@nextplus/js-sdk 0.0.10 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +404 -35
- package/dist/{chunk-GMJM2AK6.js → chunk-ASHZA665.js} +1 -1
- package/dist/{chunk-O65NPNYE.js → chunk-PEBCO4EJ.js} +79 -78
- package/dist/{index-DP-keAMv.d.ts → index-9b6z3K2x.d.cts} +1 -1
- package/dist/{index-Dwy0Oyyf.d.cts → index-NQKQN8wR.d.ts} +1 -1
- package/dist/index.cjs +426 -112
- package/dist/index.d.cts +41 -27
- package/dist/index.d.ts +41 -27
- package/dist/index.js +348 -36
- package/dist/sdk/index.cjs +78 -78
- package/dist/sdk/index.d.cts +1 -1
- package/dist/sdk/index.d.ts +1 -1
- package/dist/sdk/index.js +2 -2
- package/dist/sdk/sdk.gen.cjs +78 -78
- package/dist/sdk/sdk.gen.d.cts +1 -1
- package/dist/sdk/sdk.gen.d.ts +1 -1
- package/dist/sdk/sdk.gen.js +1 -1
- package/dist/{sdk.gen-BntcMIIs.d.cts → sdk.gen-P3Z3oO-Q.d.ts} +559 -434
- package/dist/{sdk.gen-k17BtAsz.d.ts → sdk.gen-kGvktS0r.d.cts} +559 -434
- package/package.json +12 -4
- package/src/index.ts +256 -76
- package/src/sdk/sdk.gen.ts +117 -117
- package/src/sdk/types.gen.ts +518 -393
- package/src/smoke.ts +582 -71
package/package.json
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextplus/js-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"generate": "npm run clean && npm run prepare-spec && npm run openapi-ts && npm run build",
|
|
7
|
-
"build": "tsup
|
|
7
|
+
"build": "tsup",
|
|
8
8
|
"clean": "rm -rf dist && rm -rf .generated",
|
|
9
|
-
"prepublishOnly": "npm run clean && tsup
|
|
9
|
+
"prepublishOnly": "npm run clean && SKIP_SMOKE=1 tsup",
|
|
10
10
|
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
|
11
11
|
"openapi-ts": "openapi-ts",
|
|
12
12
|
"prepare-spec": "node scripts/prepare-spec.js",
|
|
13
|
-
"test": "npm run build && node dist/smoke.js"
|
|
13
|
+
"test": "npm run build && node --test dist/smoke.js",
|
|
14
|
+
"test:watch": "tsx watch --test src/smoke.ts",
|
|
15
|
+
"test:dev": "tsx --test src/smoke.ts"
|
|
14
16
|
},
|
|
15
17
|
"files": [
|
|
16
18
|
"dist",
|
|
@@ -24,6 +26,11 @@
|
|
|
24
26
|
"import": "./dist/index.js",
|
|
25
27
|
"require": "./dist/index.cjs"
|
|
26
28
|
},
|
|
29
|
+
"./services": {
|
|
30
|
+
"types": "./dist/sdk/sdk.gen.d.ts",
|
|
31
|
+
"import": "./dist/sdk/sdk.gen.js",
|
|
32
|
+
"require": "./dist/sdk/sdk.gen.cjs"
|
|
33
|
+
},
|
|
27
34
|
"./sdk": {
|
|
28
35
|
"types": "./dist/sdk/index.d.ts",
|
|
29
36
|
"import": "./dist/sdk/index.js",
|
|
@@ -52,6 +59,7 @@
|
|
|
52
59
|
"eslint": "^9.32.0",
|
|
53
60
|
"prettier": "^3.6.2",
|
|
54
61
|
"tsup": "^8.5.0",
|
|
62
|
+
"tsx": "^4.21.0",
|
|
55
63
|
"typescript": "^5.9.2"
|
|
56
64
|
},
|
|
57
65
|
"dependencies": {
|
package/src/index.ts
CHANGED
|
@@ -1,18 +1,43 @@
|
|
|
1
1
|
import debug from 'debug';
|
|
2
|
-
import { createClient } from './sdk/client';
|
|
2
|
+
import { createClient, createConfig } from './sdk/client';
|
|
3
3
|
import { UserModelService } from './sdk';
|
|
4
4
|
import * as AllServices from './sdk';
|
|
5
5
|
import type * as AllServiceTypes from './sdk';
|
|
6
6
|
|
|
7
7
|
const log = debug('nextplus:sdk');
|
|
8
8
|
|
|
9
|
+
// Configuration types for token-based authentication
|
|
10
|
+
export type TokenConfig = {
|
|
11
|
+
baseURL?: string;
|
|
12
|
+
accessToken: string;
|
|
13
|
+
returnType?: 'raw' | 'data';
|
|
14
|
+
throwOnError?: boolean; // For tree-shakeable imports
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// Configuration types for credential-based authentication
|
|
18
|
+
export type CredentialConfig = {
|
|
19
|
+
baseURL?: string;
|
|
20
|
+
email?: string;
|
|
21
|
+
username?: string;
|
|
22
|
+
password: string;
|
|
23
|
+
returnType?: 'raw' | 'data';
|
|
24
|
+
throwOnError?: boolean; // For tree-shakeable imports
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// Union type for SDK configuration
|
|
28
|
+
export type SDKConfig = TokenConfig | CredentialConfig;
|
|
29
|
+
|
|
9
30
|
const accessToken = {
|
|
10
31
|
token: null as string | null,
|
|
11
32
|
created: null as Date | null,
|
|
12
33
|
ttl: 0,
|
|
13
34
|
};
|
|
14
35
|
|
|
15
|
-
const setAccessToken = (
|
|
36
|
+
const setAccessToken = (
|
|
37
|
+
token: string,
|
|
38
|
+
created: Date = new Date(),
|
|
39
|
+
ttl: number = 1209600,
|
|
40
|
+
) => {
|
|
16
41
|
accessToken.token = token;
|
|
17
42
|
accessToken.created = created;
|
|
18
43
|
accessToken.ttl = ttl;
|
|
@@ -34,17 +59,18 @@ const isTokenValid = (): boolean => {
|
|
|
34
59
|
return tokenAge < tokenTtlMs;
|
|
35
60
|
};
|
|
36
61
|
|
|
37
|
-
|
|
38
|
-
|
|
39
62
|
export class NextPlusSDK {
|
|
40
|
-
|
|
41
|
-
private credentials
|
|
63
|
+
public client: any; // Exposed for tree-shakeable service imports
|
|
64
|
+
private credentials?: { email?: string; username?: string; password: string };
|
|
65
|
+
private providedAccessToken?: string;
|
|
42
66
|
private returnType: 'raw' | 'data' = 'data';
|
|
67
|
+
private authMode: 'token' | 'credentials';
|
|
43
68
|
|
|
44
69
|
// Wrap plain developer inputs into the right container (body/query)
|
|
45
70
|
// and stringify complex query params when required by LoopBack (filter/where)
|
|
46
71
|
private normalizeOptions(methodName: string, rawOptions: any): any {
|
|
47
|
-
const options: any =
|
|
72
|
+
const options: any =
|
|
73
|
+
rawOptions && typeof rawOptions === 'object' ? { ...rawOptions } : {};
|
|
48
74
|
|
|
49
75
|
// Always ensure client is set (will be set by caller afterwards if missing)
|
|
50
76
|
// We avoid mutating the original object to keep predictable behavior
|
|
@@ -54,10 +80,22 @@ export class NextPlusSDK {
|
|
|
54
80
|
const method = methodName.toString().toLowerCase();
|
|
55
81
|
const isFind = method.includes('find') && !method.includes('count');
|
|
56
82
|
const isCount = method.includes('count');
|
|
57
|
-
const shouldUseBody = /(create|update|replace|patch|login|upsert)/i.test(
|
|
83
|
+
const shouldUseBody = /(create|update|replace|patch|login|upsert)/i.test(
|
|
84
|
+
methodName.toString(),
|
|
85
|
+
);
|
|
58
86
|
|
|
59
|
-
const topLevelKeys = [
|
|
60
|
-
|
|
87
|
+
const topLevelKeys = [
|
|
88
|
+
'filter',
|
|
89
|
+
'where',
|
|
90
|
+
'fields',
|
|
91
|
+
'order',
|
|
92
|
+
'limit',
|
|
93
|
+
'offset',
|
|
94
|
+
'include',
|
|
95
|
+
];
|
|
96
|
+
const hasTopLevelFilterBits = topLevelKeys.some((k) =>
|
|
97
|
+
Object.prototype.hasOwnProperty.call(options, k),
|
|
98
|
+
);
|
|
61
99
|
|
|
62
100
|
// Only create query if relevant for this method
|
|
63
101
|
if (isFind) {
|
|
@@ -73,9 +111,13 @@ export class NextPlusSDK {
|
|
|
73
111
|
if (options.order !== undefined) filterObject.order = options.order;
|
|
74
112
|
if (options.limit !== undefined) filterObject.limit = options.limit;
|
|
75
113
|
if (options.offset !== undefined) filterObject.offset = options.offset;
|
|
76
|
-
if (options.include !== undefined)
|
|
114
|
+
if (options.include !== undefined)
|
|
115
|
+
filterObject.include = options.include;
|
|
77
116
|
if (Object.keys(filterObject).length > 0) {
|
|
78
|
-
options.query.filter =
|
|
117
|
+
options.query.filter =
|
|
118
|
+
typeof filterObject === 'string'
|
|
119
|
+
? filterObject
|
|
120
|
+
: JSON.stringify(filterObject);
|
|
79
121
|
}
|
|
80
122
|
// Clean moved keys from top-level
|
|
81
123
|
topLevelKeys.forEach((k) => delete options[k]);
|
|
@@ -85,7 +127,8 @@ export class NextPlusSDK {
|
|
|
85
127
|
// Allow top-level where or query.where as object → stringify
|
|
86
128
|
if (options.where !== undefined) {
|
|
87
129
|
const whereVal = options.where;
|
|
88
|
-
options.query.where =
|
|
130
|
+
options.query.where =
|
|
131
|
+
typeof whereVal === 'string' ? whereVal : JSON.stringify(whereVal);
|
|
89
132
|
delete options.where;
|
|
90
133
|
}
|
|
91
134
|
} else if (shouldUseBody) {
|
|
@@ -99,7 +142,8 @@ export class NextPlusSDK {
|
|
|
99
142
|
options.body = bodyCandidate;
|
|
100
143
|
// Keep only body/client/query/path at root
|
|
101
144
|
Object.keys(options).forEach((k) => {
|
|
102
|
-
if (!['body', 'client', 'query', 'path'].includes(k))
|
|
145
|
+
if (!['body', 'client', 'query', 'path'].includes(k))
|
|
146
|
+
delete options[k];
|
|
103
147
|
});
|
|
104
148
|
}
|
|
105
149
|
}
|
|
@@ -118,41 +162,83 @@ export class NextPlusSDK {
|
|
|
118
162
|
return options;
|
|
119
163
|
}
|
|
120
164
|
|
|
121
|
-
constructor(options: {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
165
|
+
constructor(options: SDKConfig) {
|
|
166
|
+
// Determine authentication mode
|
|
167
|
+
const hasToken = 'accessToken' in options && options.accessToken;
|
|
168
|
+
const hasPassword = 'password' in options && options.password;
|
|
169
|
+
|
|
170
|
+
// Validate mutually exclusive authentication
|
|
171
|
+
if (hasToken && hasPassword) {
|
|
172
|
+
throw new Error(
|
|
173
|
+
'Provide either accessToken or credentials (email/username + password), not both',
|
|
174
|
+
);
|
|
131
175
|
}
|
|
132
|
-
|
|
133
|
-
|
|
176
|
+
|
|
177
|
+
if (!hasToken && !hasPassword) {
|
|
178
|
+
throw new Error(
|
|
179
|
+
'Either accessToken or credentials (email/username + password) must be provided',
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Set authentication mode
|
|
184
|
+
if (hasToken) {
|
|
185
|
+
this.authMode = 'token';
|
|
186
|
+
this.providedAccessToken = (options as TokenConfig).accessToken;
|
|
187
|
+
// Set the token immediately for token-based auth
|
|
188
|
+
setAccessToken(this.providedAccessToken, new Date(), 1209600);
|
|
189
|
+
} else {
|
|
190
|
+
this.authMode = 'credentials';
|
|
191
|
+
const credConfig = options as CredentialConfig;
|
|
192
|
+
|
|
193
|
+
// Validate that either email or username is provided
|
|
194
|
+
if (!credConfig.email && !credConfig.username) {
|
|
195
|
+
throw new Error(
|
|
196
|
+
'Either email or username must be provided with password',
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
if (credConfig.email && credConfig.username) {
|
|
200
|
+
throw new Error('Provide either email or username, not both');
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
this.credentials = {
|
|
204
|
+
email: credConfig.email,
|
|
205
|
+
username: credConfig.username,
|
|
206
|
+
password: credConfig.password,
|
|
207
|
+
};
|
|
134
208
|
}
|
|
135
209
|
|
|
136
|
-
this.credentials = {
|
|
137
|
-
email: options.email,
|
|
138
|
-
username: options.username,
|
|
139
|
-
password: options.password
|
|
140
|
-
};
|
|
141
210
|
this.returnType = options.returnType || 'data';
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
211
|
+
|
|
212
|
+
// Handle baseURL with smart defaults
|
|
213
|
+
let baseURL = options.baseURL;
|
|
214
|
+
if (!baseURL) {
|
|
215
|
+
// Try to detect browser environment
|
|
216
|
+
if (typeof window !== 'undefined' && window.location) {
|
|
217
|
+
baseURL = window.location.origin + '/api';
|
|
218
|
+
} else {
|
|
219
|
+
throw new Error('baseURL is required in non-browser environments');
|
|
220
|
+
}
|
|
145
221
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
222
|
+
|
|
223
|
+
// Normalize baseURL
|
|
224
|
+
if (baseURL.endsWith('/')) {
|
|
225
|
+
baseURL = baseURL.slice(0, -1);
|
|
149
226
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
227
|
+
if (!baseURL.endsWith('/api')) {
|
|
228
|
+
baseURL = baseURL + '/api';
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
this.client = createClient(
|
|
232
|
+
createConfig({
|
|
233
|
+
baseUrl: baseURL,
|
|
234
|
+
throwOnError: options.throwOnError ?? false,
|
|
235
|
+
}),
|
|
236
|
+
);
|
|
153
237
|
|
|
154
238
|
// Add authentication interceptor
|
|
155
|
-
this.client.interceptors.request.use(
|
|
239
|
+
this.client.interceptors.request.use(
|
|
240
|
+
this.authRequestInterceptor.bind(this),
|
|
241
|
+
);
|
|
156
242
|
|
|
157
243
|
// Create service proxies dynamically
|
|
158
244
|
this.createServiceProxies();
|
|
@@ -164,24 +250,37 @@ export class NextPlusSDK {
|
|
|
164
250
|
return request;
|
|
165
251
|
}
|
|
166
252
|
|
|
167
|
-
//
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
253
|
+
// Handle authentication based on mode
|
|
254
|
+
if (this.authMode === 'token') {
|
|
255
|
+
// For token mode, use the provided token directly
|
|
256
|
+
if (this.providedAccessToken) {
|
|
257
|
+
request.headers.set('Authorization', this.providedAccessToken);
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
// For credentials mode, ensure we have a valid token
|
|
261
|
+
await this.ensureValidToken();
|
|
262
|
+
const token = getAccessToken();
|
|
263
|
+
if (token.token) {
|
|
264
|
+
request.headers.set('Authorization', token.token);
|
|
265
|
+
}
|
|
173
266
|
}
|
|
267
|
+
|
|
174
268
|
return request;
|
|
175
269
|
}
|
|
176
270
|
|
|
177
271
|
private async ensureValidToken(): Promise<void> {
|
|
178
|
-
|
|
272
|
+
// Only validate token for credentials mode
|
|
273
|
+
if (this.authMode === 'credentials' && !isTokenValid()) {
|
|
179
274
|
log('Token expired or missing, refreshing...');
|
|
180
275
|
await this.login();
|
|
181
276
|
}
|
|
182
277
|
}
|
|
183
278
|
|
|
184
279
|
private async login(): Promise<boolean> {
|
|
280
|
+
if (this.authMode !== 'credentials' || !this.credentials) {
|
|
281
|
+
throw new Error('Login is only available in credentials mode');
|
|
282
|
+
}
|
|
283
|
+
|
|
185
284
|
try {
|
|
186
285
|
const loginBody: any = {
|
|
187
286
|
password: this.credentials.password,
|
|
@@ -219,11 +318,13 @@ export class NextPlusSDK {
|
|
|
219
318
|
|
|
220
319
|
private createServiceProxies() {
|
|
221
320
|
// Get all service classes from the SDK
|
|
222
|
-
const serviceNames = Object.keys(AllServices).filter(
|
|
223
|
-
key
|
|
321
|
+
const serviceNames = Object.keys(AllServices).filter(
|
|
322
|
+
(key) =>
|
|
323
|
+
key.endsWith('Service') &&
|
|
324
|
+
typeof (AllServices as any)[key] === 'function',
|
|
224
325
|
);
|
|
225
326
|
|
|
226
|
-
serviceNames.forEach(serviceName => {
|
|
327
|
+
serviceNames.forEach((serviceName) => {
|
|
227
328
|
const ServiceClass = (AllServices as any)[serviceName];
|
|
228
329
|
|
|
229
330
|
// Create a proxy for each service
|
|
@@ -236,7 +337,7 @@ export class NextPlusSDK {
|
|
|
236
337
|
return new Proxy(ServiceClass, {
|
|
237
338
|
get(target, prop) {
|
|
238
339
|
if (typeof target[prop] === 'function') {
|
|
239
|
-
return async function(...args: any[]) {
|
|
340
|
+
return async function (...args: any[]) {
|
|
240
341
|
// Automatically inject client if not provided
|
|
241
342
|
if (!args[0]) args[0] = {};
|
|
242
343
|
// Normalize developer-friendly input into OpenAPI options
|
|
@@ -246,11 +347,25 @@ export class NextPlusSDK {
|
|
|
246
347
|
const result = await target[prop].apply(target, args);
|
|
247
348
|
|
|
248
349
|
// Return based on returnType setting
|
|
249
|
-
if (
|
|
350
|
+
if (
|
|
351
|
+
self.returnType === 'data' &&
|
|
352
|
+
result &&
|
|
353
|
+
typeof result === 'object' &&
|
|
354
|
+
'data' in result
|
|
355
|
+
) {
|
|
250
356
|
return result.data;
|
|
251
357
|
}
|
|
252
|
-
if (
|
|
253
|
-
|
|
358
|
+
if (
|
|
359
|
+
self.returnType === 'data' &&
|
|
360
|
+
result &&
|
|
361
|
+
typeof result === 'object' &&
|
|
362
|
+
'error' in result
|
|
363
|
+
) {
|
|
364
|
+
const error = new Error(
|
|
365
|
+
result.error.error.message ||
|
|
366
|
+
result.error.error.code ||
|
|
367
|
+
'Unknown error',
|
|
368
|
+
) as any;
|
|
254
369
|
if (result.error.error.details) {
|
|
255
370
|
error.details = result.error.error.details;
|
|
256
371
|
}
|
|
@@ -261,46 +376,111 @@ export class NextPlusSDK {
|
|
|
261
376
|
};
|
|
262
377
|
}
|
|
263
378
|
return target[prop];
|
|
264
|
-
}
|
|
379
|
+
},
|
|
265
380
|
});
|
|
266
381
|
}
|
|
267
382
|
|
|
268
|
-
// Manual login method (optional, for explicit control)
|
|
383
|
+
// Manual login method (optional, for explicit control in credentials mode)
|
|
269
384
|
async manualLogin(): Promise<boolean> {
|
|
385
|
+
if (this.authMode !== 'credentials') {
|
|
386
|
+
throw new Error('manualLogin is only available in credentials mode');
|
|
387
|
+
}
|
|
270
388
|
return this.login();
|
|
271
389
|
}
|
|
390
|
+
|
|
391
|
+
// Bind a service to this SDK's client for tree-shakeable imports
|
|
392
|
+
// This eliminates the need to pass client on every call
|
|
393
|
+
service<T extends Record<string, any>>(ServiceClass: T): T {
|
|
394
|
+
const client = this.client;
|
|
395
|
+
const boundService = Object.create(ServiceClass);
|
|
396
|
+
|
|
397
|
+
// Get all property names including static methods
|
|
398
|
+
const properties = Object.getOwnPropertyNames(ServiceClass);
|
|
399
|
+
|
|
400
|
+
properties.forEach((key) => {
|
|
401
|
+
const descriptor = Object.getOwnPropertyDescriptor(ServiceClass, key);
|
|
402
|
+
if (
|
|
403
|
+
descriptor &&
|
|
404
|
+
typeof descriptor.value === 'function' &&
|
|
405
|
+
key !== 'constructor'
|
|
406
|
+
) {
|
|
407
|
+
// Bind static methods to auto-inject client
|
|
408
|
+
boundService[key] = (options: any = {}) => {
|
|
409
|
+
return descriptor.value.call(ServiceClass, { ...options, client });
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
return boundService;
|
|
415
|
+
}
|
|
272
416
|
}
|
|
273
417
|
|
|
274
418
|
// Expose accurate static service method types on the SDK instance for IDE/type safety
|
|
275
419
|
type ServiceStatics = {
|
|
276
|
-
[K in keyof typeof AllServiceTypes as K extends `${string}Service`
|
|
420
|
+
[K in keyof typeof AllServiceTypes as K extends `${string}Service`
|
|
421
|
+
? K
|
|
422
|
+
: never]: (typeof AllServiceTypes)[K];
|
|
277
423
|
};
|
|
278
424
|
|
|
279
425
|
export interface NextPlusSDK extends ServiceStatics {}
|
|
280
426
|
|
|
281
|
-
//
|
|
427
|
+
// SDK instance type
|
|
282
428
|
type SDKInstance = NextPlusSDK & ServiceStatics;
|
|
283
429
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
430
|
+
// Import the generated default client to update it
|
|
431
|
+
import { client as generatedClient } from './sdk/client.gen';
|
|
432
|
+
|
|
433
|
+
// Configure function - creates a full SDK instance with service proxies
|
|
434
|
+
// Automatically sets the client as global default for tree-shakeable imports
|
|
435
|
+
const configure = (options: SDKConfig): SDKInstance => {
|
|
436
|
+
const sdk = new NextPlusSDK(options) as SDKInstance;
|
|
437
|
+
// Automatically set as global default
|
|
438
|
+
setDefaultClient(sdk.client);
|
|
439
|
+
// Update the generated SDK's default client so services work without passing client
|
|
440
|
+
Object.assign(generatedClient, sdk.client);
|
|
441
|
+
return sdk;
|
|
292
442
|
};
|
|
293
443
|
|
|
294
|
-
// Create SDK instance
|
|
295
|
-
const createSDK = (options: {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
return new NextPlusSDK(options) as SDKInstance;
|
|
444
|
+
// Create SDK instance - alias for configure
|
|
445
|
+
const createSDK = (options: SDKConfig): SDKInstance => {
|
|
446
|
+
const sdk = new NextPlusSDK(options) as SDKInstance;
|
|
447
|
+
// Automatically set as global default
|
|
448
|
+
setDefaultClient(sdk.client);
|
|
449
|
+
// Update the generated SDK's default client so services work without passing client
|
|
450
|
+
Object.assign(generatedClient, sdk.client);
|
|
451
|
+
return sdk;
|
|
303
452
|
};
|
|
304
453
|
|
|
454
|
+
// Global default client for tree-shakeable imports
|
|
455
|
+
// Automatically set when configure() or createSDK() is called
|
|
456
|
+
let globalClient: any = null;
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Set a global default client for all service calls
|
|
460
|
+
* Note: This is automatically called by configure() and createSDK()
|
|
461
|
+
* You usually don't need to call this manually
|
|
462
|
+
*/
|
|
463
|
+
export function setDefaultClient(client: any): void {
|
|
464
|
+
globalClient = client;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Get the current global default client
|
|
469
|
+
*/
|
|
470
|
+
export function getDefaultClient(): any {
|
|
471
|
+
return globalClient;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Clear the global default client (useful for logout)
|
|
476
|
+
*/
|
|
477
|
+
export function clearDefaultClient(): void {
|
|
478
|
+
globalClient = null;
|
|
479
|
+
}
|
|
480
|
+
|
|
305
481
|
export type { SDKInstance };
|
|
306
482
|
export { configure, createSDK };
|
|
483
|
+
|
|
484
|
+
// Re-export SDK types and generated services
|
|
485
|
+
// Services will automatically use global client as fallback via the generated code's default client
|
|
486
|
+
export * from './sdk';
|