@@ -20,13 +20,37 @@ import { BackendAuthClient } from '../auth/backend.js';
2020import { FrontendAuthClient } from '../auth/frontend.js' ;
2121import type { AuthConfig } from '../auth/types.js' ;
2222
23+ /**
24+ * Normalizes the base URL to ensure it includes the API path
25+ * Only applies to Enterprise instances, this does not modify the B&B URL.
26+ * @param baseUrl - The input base URL
27+ * @returns Normalized URL with /api/v3 appended if needed for Enterprise instances
28+ */
29+ function normalizeBaseUrl ( baseUrl : string ) : string {
30+ // Remove trailing slashes
31+ const cleanUrl = baseUrl . replace ( / \/ + $ / , '' ) ;
32+
33+ // Don't modify the B&B Stack Overflow Teams API URL
34+ if ( cleanUrl . startsWith ( 'https://api.stackoverflowteams.com' ) ) {
35+ return cleanUrl ;
36+ }
37+
38+ // Check if the URL already ends with /api/v3 or contains /api/v3/
39+ if ( cleanUrl . endsWith ( '/api/v3' ) || cleanUrl . includes ( '/api/v3/' ) ) {
40+ return cleanUrl ;
41+ }
42+
43+ // Append /api/v3 to enterprise/private instances only
44+ return `${ cleanUrl } /api/v3` ;
45+ }
46+
2347/**
2448 * Basic configuration for Stack Overflow SDK
2549 */
2650export interface SDKConfig {
2751 /** Optional access token for authenticated requests */
2852 accessToken ?: string ;
29- /** Base URL of the Stack Overflow Enterprise instance */
53+ /** Base URL of the Stack Overflow API V3 for your instance */
3054 baseUrl : string ;
3155 // httpApi?: HttpLibrary; // defaults to FixedIsomorphicFetchHttpLibrary
3256}
@@ -72,21 +96,24 @@ export class StackOverflowSDK {
7296 * // Basic usage with access token
7397 * const sdk = new StackOverflowSDK({
7498 * accessToken: 'your-token',
75- * baseUrl: 'https://stackoverflow.enterprise.com '
99+ * baseUrl: 'https://stackoverflow.stackenterprise.co '
76100 * });
77101 *
78102 * // With OAuth authentication setup
79103 * const sdk = new StackOverflowSDK({
80- * baseUrl: 'https://stackoverflow.enterprise.com ',
104+ * baseUrl: 'https://stackoverflow.stackenterprise.co ',
81105 * auth: {
82106 * clientId: 'your-client-id',
83107 * redirectUri: 'http://localhost:3000/callback',
84- * baseUrl: 'https://stackoverflow.enterprise.com '
108+ * baseUrl: 'https://stackoverflow.stackenterprise.co '
85109 * }
86110 * });
87111 * ```
88112 */
89113 constructor ( config : SDKConfig | AuthSDKConfig ) {
114+ // Normalize the base URL to include API path
115+ const normalizedBaseUrl = normalizeBaseUrl ( config . baseUrl ) ;
116+
90117 // Prepare auth configuration
91118 const authConfig : AuthMethodsConfiguration = { } ;
92119
@@ -96,11 +123,11 @@ export class StackOverflowSDK {
96123 } ;
97124 }
98125
99- // Create configuration parameters
126+ // Create configuration parameters with normalized URL
100127 const configParams : ConfigurationParameters = {
101128 authMethods : authConfig ,
102129 httpApi : new FixedIsomorphicFetchHttpLibrary ( ) ,
103- baseServer : new ServerConfiguration ( config . baseUrl , { } )
130+ baseServer : new ServerConfiguration ( normalizedBaseUrl , { } )
104131 } ;
105132
106133 this . config = createConfiguration ( configParams ) ;
@@ -119,9 +146,15 @@ export class StackOverflowSDK {
119146
120147 // Initialize auth clients if auth config is provided
121148 if ( 'auth' in config && config . auth ) {
149+ // Also normalize the auth config base URL
150+ const normalizedAuthConfig = {
151+ ...config . auth ,
152+ baseUrl : normalizeBaseUrl ( config . auth . baseUrl )
153+ } ;
154+
122155 this . auth = {
123- backend : new BackendAuthClient ( config . auth ) ,
124- frontend : new FrontendAuthClient ( config . auth ) ,
156+ backend : new BackendAuthClient ( normalizedAuthConfig ) ,
157+ frontend : new FrontendAuthClient ( normalizedAuthConfig ) ,
125158 } ;
126159 }
127160 }
@@ -134,7 +167,7 @@ export class StackOverflowSDK {
134167 * @returns TeamContext instance configured for the specified team
135168 * @example
136169 * ```typescript
137- * const sdk = StackOverflowSDK.fromToken('token', 'https://stackoverflow.enterprise.com ');
170+ * const sdk = StackOverflowSDK.fromToken('token', 'https://stackoverflow.stackenterprise.co ');
138171 * const teamContext = sdk.forTeam('team-123');
139172 *
140173 * // Now all operations are scoped to team-123
@@ -150,14 +183,20 @@ export class StackOverflowSDK {
150183 * Convenient factory method when you already have a valid access token
151184 *
152185 * @param accessToken - Valid Stack Overflow for Teams access token
153- * @param baseUrl - Base URL of your Stack Overflow for Teams instance
186+ * @param baseUrl - Base URL of your Stack Overflow for Teams instance (API v3 path automatically appended where needed)
154187 * @returns Configured SDK instance ready for authenticated API calls
155188 * @example
156189 * ```typescript
157- * // Create SDK with existing token (e.g., from cookies, database, etc.)
190+ * // Create SDK with existing token (API path automatically added if needed)
191+ * const sdk = StackOverflowSDK.fromToken(
192+ * 'your-access-token-here',
193+ * 'https://support-test-teams.stackenterprise.co' // becomes https://support-test-teams.stackenterprise.co/api/v3
194+ * );
195+ *
196+ * // B&B API usage
158197 * const sdk = StackOverflowSDK.fromToken(
159198 * 'your-access-token-here',
160- * 'https://stackoverflow.enterprise .com'
199+ * 'https://api.stackoverflowteams .com/v3/ '
161200 * );
162201 *
163202 * // Make authenticated requests immediately
@@ -184,7 +223,7 @@ export class StackOverflowSDK {
184223 * const sdk = StackOverflowSDK.enterpriseOAuth({
185224 * clientId: 'your-oauth-client-id',
186225 * redirectUri: 'https://yourapp.com/callback',
187- * baseUrl: 'https://stackoverflow.enterprise.com ',
226+ * baseUrl: 'https://stackoverflow.stackenterprise.co ',
188227 * scope: 'write_access'
189228 * });
190229 *
@@ -248,10 +287,8 @@ export { CommunityClient } from './communities.js';
248287export { UserClient } from './users.js' ;
249288export { TagClient } from './tags.js' ;
250289export { UserGroupClient } from './userGroups.js' ;
251-
252290export { BackendAuthClient , FrontendAuthClient } from '../auth/index.js' ;
253291export type { AuthConfig , TokenResponse , PKCETokens } from '../auth/index.js' ;
254-
255292export { FixedIsomorphicFetchHttpLibrary } from '../helper/fixedHttpLibrary.js' ;
256293
257294export default StackOverflowSDK ;
0 commit comments