@nextplus/js-sdk 0.0.12 → 1.14.46
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 +58 -404
- package/dist/chunk-SFE3EXIE.js +41872 -0
- package/dist/chunk-SUTLUR6L.js +224 -0
- package/dist/{chunk-ASHZA665.js → chunk-UNVS4USV.js} +17 -1
- package/dist/index-BWjz-kSr.d.ts +9110 -0
- package/dist/index-K-vpX3En.d.cts +9110 -0
- package/dist/index.cjs +29232 -8721
- package/dist/index.d.cts +27 -41
- package/dist/index.d.ts +27 -41
- package/dist/index.js +8 -530
- package/dist/sdk/index.cjs +29580 -8747
- package/dist/sdk/index.d.cts +1 -1
- package/dist/sdk/index.d.ts +1 -1
- package/dist/sdk/index.js +18 -2
- package/dist/sdk/sdk.gen.cjs +29580 -8747
- package/dist/sdk/sdk.gen.d.cts +1 -1
- package/dist/sdk/sdk.gen.d.ts +1 -1
- package/dist/sdk/sdk.gen.js +17 -1
- package/dist/sdk.gen-BTtG06KM.d.ts +72538 -0
- package/dist/sdk.gen-HriFOrth.d.cts +72538 -0
- package/dist/smoke.cjs +42761 -0
- package/dist/smoke.d.cts +2 -0
- package/dist/smoke.d.ts +2 -0
- package/dist/smoke.js +79 -0
- package/package.json +4 -12
- package/src/index.ts +76 -256
- package/src/sdk/schemas.gen.ts +2932 -2167
- package/src/sdk/sdk.gen.ts +45935 -10503
- package/src/sdk/transformers.gen.ts +9032 -2705
- package/src/sdk/types.gen.ts +52692 -16449
- package/src/smoke.ts +71 -582
- package/dist/chunk-PEBCO4EJ.js +0 -21048
- package/dist/index-9b6z3K2x.d.cts +0 -4683
- package/dist/index-NQKQN8wR.d.ts +0 -4683
- package/dist/sdk.gen-P3Z3oO-Q.d.ts +0 -36063
- package/dist/sdk.gen-kGvktS0r.d.cts +0 -36063
package/dist/smoke.d.cts
ADDED
package/dist/smoke.d.ts
ADDED
package/dist/smoke.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import {
|
|
2
|
+
configure
|
|
3
|
+
} from "./chunk-SUTLUR6L.js";
|
|
4
|
+
import "./chunk-UNVS4USV.js";
|
|
5
|
+
import "./chunk-SFE3EXIE.js";
|
|
6
|
+
import "./chunk-FXXZNC42.js";
|
|
7
|
+
|
|
8
|
+
// src/smoke.ts
|
|
9
|
+
async function main() {
|
|
10
|
+
console.log("=== Testing with email and returnType: data ===");
|
|
11
|
+
const sdk = configure({
|
|
12
|
+
baseURL: "http://127.0.0.1:3000/api",
|
|
13
|
+
email: "operator@operator.com",
|
|
14
|
+
password: "operator@operator.com",
|
|
15
|
+
returnType: "data"
|
|
16
|
+
// Only return data, not full response
|
|
17
|
+
});
|
|
18
|
+
console.log("SDK configured (email)");
|
|
19
|
+
const tables = await sdk.TableService.find({
|
|
20
|
+
query: {
|
|
21
|
+
filter: JSON.stringify({
|
|
22
|
+
language: "he",
|
|
23
|
+
limit: 10,
|
|
24
|
+
order: "created DESC",
|
|
25
|
+
fields: {
|
|
26
|
+
id: true,
|
|
27
|
+
name: true,
|
|
28
|
+
created: true
|
|
29
|
+
},
|
|
30
|
+
where: {
|
|
31
|
+
name: "no-such-table!"
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
console.log(
|
|
37
|
+
"Tables found (data only):",
|
|
38
|
+
Array.isArray(tables) ? `Array with ${tables.length} items` : tables
|
|
39
|
+
);
|
|
40
|
+
try {
|
|
41
|
+
const newTable = await sdk.TableService.create({ body: {} });
|
|
42
|
+
console.log("New table created:", newTable);
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.log("Expected validation error caught:", error.message);
|
|
45
|
+
}
|
|
46
|
+
console.log("\n=== Testing with username and returnType: raw ===");
|
|
47
|
+
const sdk2 = configure({
|
|
48
|
+
baseURL: "http://127.0.0.1:3000/api",
|
|
49
|
+
username: "operator",
|
|
50
|
+
// Using username instead of email
|
|
51
|
+
password: "operator@operator.com",
|
|
52
|
+
returnType: "raw"
|
|
53
|
+
// Return full response object
|
|
54
|
+
});
|
|
55
|
+
console.log("SDK configured (username)");
|
|
56
|
+
const tablesRaw = await sdk2.TableService.find({
|
|
57
|
+
query: {
|
|
58
|
+
filter: JSON.stringify({
|
|
59
|
+
where: {
|
|
60
|
+
name: "test"
|
|
61
|
+
},
|
|
62
|
+
limit: 5
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
console.log("Tables found (raw response):", {
|
|
67
|
+
hasData: "data" in tablesRaw,
|
|
68
|
+
hasRequest: "request" in tablesRaw,
|
|
69
|
+
hasResponse: "response" in tablesRaw,
|
|
70
|
+
dataLength: tablesRaw.data ? tablesRaw.data.length : "no data"
|
|
71
|
+
});
|
|
72
|
+
try {
|
|
73
|
+
const createTable = await sdk2.TableService.create({ body: {} });
|
|
74
|
+
console.log("Table created:", createTable);
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.log("Expected validation error caught (raw mode):", error.message);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
main().catch(console.error);
|
package/package.json
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextplus/js-sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.14.46",
|
|
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 src/index.ts src/sdk/index.ts src/sdk/client/index.ts src/sdk/sdk.gen.ts src/smoke.ts --dts --format esm,cjs --outDir dist --clean",
|
|
8
8
|
"clean": "rm -rf dist && rm -rf .generated",
|
|
9
|
-
"prepublishOnly": "npm run clean &&
|
|
9
|
+
"prepublishOnly": "npm run clean && tsup src/index.ts src/sdk/index.ts src/sdk/client/index.ts src/sdk/sdk.gen.ts --dts --format esm,cjs --outDir dist --clean",
|
|
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
|
|
14
|
-
"test:watch": "tsx watch --test src/smoke.ts",
|
|
15
|
-
"test:dev": "tsx --test src/smoke.ts"
|
|
13
|
+
"test": "npm run build && node dist/smoke.js"
|
|
16
14
|
},
|
|
17
15
|
"files": [
|
|
18
16
|
"dist",
|
|
@@ -26,11 +24,6 @@
|
|
|
26
24
|
"import": "./dist/index.js",
|
|
27
25
|
"require": "./dist/index.cjs"
|
|
28
26
|
},
|
|
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
|
-
},
|
|
34
27
|
"./sdk": {
|
|
35
28
|
"types": "./dist/sdk/index.d.ts",
|
|
36
29
|
"import": "./dist/sdk/index.js",
|
|
@@ -59,7 +52,6 @@
|
|
|
59
52
|
"eslint": "^9.32.0",
|
|
60
53
|
"prettier": "^3.6.2",
|
|
61
54
|
"tsup": "^8.5.0",
|
|
62
|
-
"tsx": "^4.21.0",
|
|
63
55
|
"typescript": "^5.9.2"
|
|
64
56
|
},
|
|
65
57
|
"dependencies": {
|
package/src/index.ts
CHANGED
|
@@ -1,43 +1,18 @@
|
|
|
1
1
|
import debug from 'debug';
|
|
2
|
-
import { createClient
|
|
2
|
+
import { createClient } 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
|
-
|
|
30
9
|
const accessToken = {
|
|
31
10
|
token: null as string | null,
|
|
32
11
|
created: null as Date | null,
|
|
33
12
|
ttl: 0,
|
|
34
13
|
};
|
|
35
14
|
|
|
36
|
-
const setAccessToken = (
|
|
37
|
-
token: string,
|
|
38
|
-
created: Date = new Date(),
|
|
39
|
-
ttl: number = 1209600,
|
|
40
|
-
) => {
|
|
15
|
+
const setAccessToken = (token: string, created: Date = new Date(), ttl: number = 1209600) => {
|
|
41
16
|
accessToken.token = token;
|
|
42
17
|
accessToken.created = created;
|
|
43
18
|
accessToken.ttl = ttl;
|
|
@@ -59,18 +34,17 @@ const isTokenValid = (): boolean => {
|
|
|
59
34
|
return tokenAge < tokenTtlMs;
|
|
60
35
|
};
|
|
61
36
|
|
|
37
|
+
|
|
38
|
+
|
|
62
39
|
export class NextPlusSDK {
|
|
63
|
-
|
|
64
|
-
private credentials
|
|
65
|
-
private providedAccessToken?: string;
|
|
40
|
+
private client: any;
|
|
41
|
+
private credentials: { email?: string; username?: string; password: string };
|
|
66
42
|
private returnType: 'raw' | 'data' = 'data';
|
|
67
|
-
private authMode: 'token' | 'credentials';
|
|
68
43
|
|
|
69
44
|
// Wrap plain developer inputs into the right container (body/query)
|
|
70
45
|
// and stringify complex query params when required by LoopBack (filter/where)
|
|
71
46
|
private normalizeOptions(methodName: string, rawOptions: any): any {
|
|
72
|
-
const options: any =
|
|
73
|
-
rawOptions && typeof rawOptions === 'object' ? { ...rawOptions } : {};
|
|
47
|
+
const options: any = rawOptions && typeof rawOptions === 'object' ? { ...rawOptions } : {};
|
|
74
48
|
|
|
75
49
|
// Always ensure client is set (will be set by caller afterwards if missing)
|
|
76
50
|
// We avoid mutating the original object to keep predictable behavior
|
|
@@ -80,22 +54,10 @@ export class NextPlusSDK {
|
|
|
80
54
|
const method = methodName.toString().toLowerCase();
|
|
81
55
|
const isFind = method.includes('find') && !method.includes('count');
|
|
82
56
|
const isCount = method.includes('count');
|
|
83
|
-
const shouldUseBody = /(create|update|replace|patch|login|upsert)/i.test(
|
|
84
|
-
methodName.toString(),
|
|
85
|
-
);
|
|
57
|
+
const shouldUseBody = /(create|update|replace|patch|login|upsert)/i.test(methodName.toString());
|
|
86
58
|
|
|
87
|
-
const topLevelKeys = [
|
|
88
|
-
|
|
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
|
-
);
|
|
59
|
+
const topLevelKeys = ['filter', 'where', 'fields', 'order', 'limit', 'offset', 'include'];
|
|
60
|
+
const hasTopLevelFilterBits = topLevelKeys.some((k) => Object.prototype.hasOwnProperty.call(options, k));
|
|
99
61
|
|
|
100
62
|
// Only create query if relevant for this method
|
|
101
63
|
if (isFind) {
|
|
@@ -111,13 +73,9 @@ export class NextPlusSDK {
|
|
|
111
73
|
if (options.order !== undefined) filterObject.order = options.order;
|
|
112
74
|
if (options.limit !== undefined) filterObject.limit = options.limit;
|
|
113
75
|
if (options.offset !== undefined) filterObject.offset = options.offset;
|
|
114
|
-
if (options.include !== undefined)
|
|
115
|
-
filterObject.include = options.include;
|
|
76
|
+
if (options.include !== undefined) filterObject.include = options.include;
|
|
116
77
|
if (Object.keys(filterObject).length > 0) {
|
|
117
|
-
options.query.filter =
|
|
118
|
-
typeof filterObject === 'string'
|
|
119
|
-
? filterObject
|
|
120
|
-
: JSON.stringify(filterObject);
|
|
78
|
+
options.query.filter = typeof filterObject === 'string' ? filterObject : JSON.stringify(filterObject);
|
|
121
79
|
}
|
|
122
80
|
// Clean moved keys from top-level
|
|
123
81
|
topLevelKeys.forEach((k) => delete options[k]);
|
|
@@ -127,8 +85,7 @@ export class NextPlusSDK {
|
|
|
127
85
|
// Allow top-level where or query.where as object → stringify
|
|
128
86
|
if (options.where !== undefined) {
|
|
129
87
|
const whereVal = options.where;
|
|
130
|
-
options.query.where =
|
|
131
|
-
typeof whereVal === 'string' ? whereVal : JSON.stringify(whereVal);
|
|
88
|
+
options.query.where = typeof whereVal === 'string' ? whereVal : JSON.stringify(whereVal);
|
|
132
89
|
delete options.where;
|
|
133
90
|
}
|
|
134
91
|
} else if (shouldUseBody) {
|
|
@@ -142,8 +99,7 @@ export class NextPlusSDK {
|
|
|
142
99
|
options.body = bodyCandidate;
|
|
143
100
|
// Keep only body/client/query/path at root
|
|
144
101
|
Object.keys(options).forEach((k) => {
|
|
145
|
-
if (!['body', 'client', 'query', 'path'].includes(k))
|
|
146
|
-
delete options[k];
|
|
102
|
+
if (!['body', 'client', 'query', 'path'].includes(k)) delete options[k];
|
|
147
103
|
});
|
|
148
104
|
}
|
|
149
105
|
}
|
|
@@ -162,83 +118,41 @@ export class NextPlusSDK {
|
|
|
162
118
|
return options;
|
|
163
119
|
}
|
|
164
120
|
|
|
165
|
-
constructor(options:
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
);
|
|
121
|
+
constructor(options: {
|
|
122
|
+
baseURL: string;
|
|
123
|
+
email?: string;
|
|
124
|
+
username?: string;
|
|
125
|
+
password: string;
|
|
126
|
+
returnType?: 'raw' | 'data';
|
|
127
|
+
}) {
|
|
128
|
+
// Validate that either email or username is provided
|
|
129
|
+
if (!options.email && !options.username) {
|
|
130
|
+
throw new Error('Either email or username must be provided');
|
|
175
131
|
}
|
|
176
|
-
|
|
177
|
-
|
|
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
|
-
};
|
|
132
|
+
if (options.email && options.username) {
|
|
133
|
+
throw new Error('Provide either email or username, not both');
|
|
208
134
|
}
|
|
209
135
|
|
|
136
|
+
this.credentials = {
|
|
137
|
+
email: options.email,
|
|
138
|
+
username: options.username,
|
|
139
|
+
password: options.password
|
|
140
|
+
};
|
|
210
141
|
this.returnType = options.returnType || 'data';
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// Normalize baseURL
|
|
224
|
-
if (baseURL.endsWith('/')) {
|
|
225
|
-
baseURL = baseURL.slice(0, -1);
|
|
142
|
+
// remove trailing slash from baseURL
|
|
143
|
+
if (options.baseURL.endsWith('/')) {
|
|
144
|
+
options.baseURL = options.baseURL.slice(0, -1);
|
|
226
145
|
}
|
|
227
|
-
if
|
|
228
|
-
|
|
146
|
+
// if baseURL does not end with /api, add it
|
|
147
|
+
if (!options.baseURL.endsWith('/api')) {
|
|
148
|
+
options.baseURL = options.baseURL + '/api';
|
|
229
149
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
baseUrl: baseURL,
|
|
234
|
-
throwOnError: options.throwOnError ?? false,
|
|
235
|
-
}),
|
|
236
|
-
);
|
|
150
|
+
this.client = createClient({
|
|
151
|
+
baseUrl: options.baseURL,
|
|
152
|
+
});
|
|
237
153
|
|
|
238
154
|
// Add authentication interceptor
|
|
239
|
-
this.client.interceptors.request.use(
|
|
240
|
-
this.authRequestInterceptor.bind(this),
|
|
241
|
-
);
|
|
155
|
+
this.client.interceptors.request.use(this.authRequestInterceptor.bind(this));
|
|
242
156
|
|
|
243
157
|
// Create service proxies dynamically
|
|
244
158
|
this.createServiceProxies();
|
|
@@ -250,37 +164,24 @@ export class NextPlusSDK {
|
|
|
250
164
|
return request;
|
|
251
165
|
}
|
|
252
166
|
|
|
253
|
-
//
|
|
254
|
-
|
|
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
|
-
}
|
|
266
|
-
}
|
|
167
|
+
// Ensure we have a valid token
|
|
168
|
+
await this.ensureValidToken();
|
|
267
169
|
|
|
170
|
+
const token = getAccessToken();
|
|
171
|
+
if (token.token) {
|
|
172
|
+
request.headers.set('Authorization', token.token);
|
|
173
|
+
}
|
|
268
174
|
return request;
|
|
269
175
|
}
|
|
270
176
|
|
|
271
177
|
private async ensureValidToken(): Promise<void> {
|
|
272
|
-
|
|
273
|
-
if (this.authMode === 'credentials' && !isTokenValid()) {
|
|
178
|
+
if (!isTokenValid()) {
|
|
274
179
|
log('Token expired or missing, refreshing...');
|
|
275
180
|
await this.login();
|
|
276
181
|
}
|
|
277
182
|
}
|
|
278
183
|
|
|
279
184
|
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
|
-
|
|
284
185
|
try {
|
|
285
186
|
const loginBody: any = {
|
|
286
187
|
password: this.credentials.password,
|
|
@@ -318,13 +219,11 @@ export class NextPlusSDK {
|
|
|
318
219
|
|
|
319
220
|
private createServiceProxies() {
|
|
320
221
|
// Get all service classes from the SDK
|
|
321
|
-
const serviceNames = Object.keys(AllServices).filter(
|
|
322
|
-
(
|
|
323
|
-
key.endsWith('Service') &&
|
|
324
|
-
typeof (AllServices as any)[key] === 'function',
|
|
222
|
+
const serviceNames = Object.keys(AllServices).filter(key =>
|
|
223
|
+
key.endsWith('Service') && typeof (AllServices as any)[key] === 'function'
|
|
325
224
|
);
|
|
326
225
|
|
|
327
|
-
serviceNames.forEach(
|
|
226
|
+
serviceNames.forEach(serviceName => {
|
|
328
227
|
const ServiceClass = (AllServices as any)[serviceName];
|
|
329
228
|
|
|
330
229
|
// Create a proxy for each service
|
|
@@ -337,7 +236,7 @@ export class NextPlusSDK {
|
|
|
337
236
|
return new Proxy(ServiceClass, {
|
|
338
237
|
get(target, prop) {
|
|
339
238
|
if (typeof target[prop] === 'function') {
|
|
340
|
-
return async function
|
|
239
|
+
return async function(...args: any[]) {
|
|
341
240
|
// Automatically inject client if not provided
|
|
342
241
|
if (!args[0]) args[0] = {};
|
|
343
242
|
// Normalize developer-friendly input into OpenAPI options
|
|
@@ -347,25 +246,11 @@ export class NextPlusSDK {
|
|
|
347
246
|
const result = await target[prop].apply(target, args);
|
|
348
247
|
|
|
349
248
|
// Return based on returnType setting
|
|
350
|
-
if (
|
|
351
|
-
self.returnType === 'data' &&
|
|
352
|
-
result &&
|
|
353
|
-
typeof result === 'object' &&
|
|
354
|
-
'data' in result
|
|
355
|
-
) {
|
|
249
|
+
if (self.returnType === 'data' && result && typeof result === 'object' && 'data' in result) {
|
|
356
250
|
return result.data;
|
|
357
251
|
}
|
|
358
|
-
if (
|
|
359
|
-
|
|
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;
|
|
252
|
+
if (self.returnType === 'data' && result && typeof result === 'object' && 'error' in result) {
|
|
253
|
+
const error = new Error(result.error.error.message || result.error.error.code || 'Unknown error') as any;
|
|
369
254
|
if (result.error.error.details) {
|
|
370
255
|
error.details = result.error.error.details;
|
|
371
256
|
}
|
|
@@ -376,111 +261,46 @@ export class NextPlusSDK {
|
|
|
376
261
|
};
|
|
377
262
|
}
|
|
378
263
|
return target[prop];
|
|
379
|
-
}
|
|
264
|
+
}
|
|
380
265
|
});
|
|
381
266
|
}
|
|
382
267
|
|
|
383
|
-
// Manual login method (optional, for explicit control
|
|
268
|
+
// Manual login method (optional, for explicit control)
|
|
384
269
|
async manualLogin(): Promise<boolean> {
|
|
385
|
-
if (this.authMode !== 'credentials') {
|
|
386
|
-
throw new Error('manualLogin is only available in credentials mode');
|
|
387
|
-
}
|
|
388
270
|
return this.login();
|
|
389
271
|
}
|
|
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
|
-
}
|
|
416
272
|
}
|
|
417
273
|
|
|
418
274
|
// Expose accurate static service method types on the SDK instance for IDE/type safety
|
|
419
275
|
type ServiceStatics = {
|
|
420
|
-
[K in keyof typeof AllServiceTypes as K extends `${string}Service`
|
|
421
|
-
? K
|
|
422
|
-
: never]: (typeof AllServiceTypes)[K];
|
|
276
|
+
[K in keyof typeof AllServiceTypes as K extends `${string}Service` ? K : never]: typeof AllServiceTypes[K];
|
|
423
277
|
};
|
|
424
278
|
|
|
425
279
|
export interface NextPlusSDK extends ServiceStatics {}
|
|
426
280
|
|
|
427
|
-
//
|
|
281
|
+
// Legacy function for backward compatibility
|
|
428
282
|
type SDKInstance = NextPlusSDK & ServiceStatics;
|
|
429
283
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
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;
|
|
284
|
+
const configure = (options: {
|
|
285
|
+
baseURL: string;
|
|
286
|
+
email?: string;
|
|
287
|
+
username?: string;
|
|
288
|
+
password: string;
|
|
289
|
+
returnType?: 'raw' | 'data';
|
|
290
|
+
}): SDKInstance => {
|
|
291
|
+
return new NextPlusSDK(options) as SDKInstance;
|
|
442
292
|
};
|
|
443
293
|
|
|
444
|
-
// Create SDK instance
|
|
445
|
-
const createSDK = (options:
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
294
|
+
// Create SDK instance
|
|
295
|
+
const createSDK = (options: {
|
|
296
|
+
baseURL: string;
|
|
297
|
+
email?: string;
|
|
298
|
+
username?: string;
|
|
299
|
+
password: string;
|
|
300
|
+
returnType?: 'raw' | 'data';
|
|
301
|
+
}): SDKInstance => {
|
|
302
|
+
return new NextPlusSDK(options) as SDKInstance;
|
|
452
303
|
};
|
|
453
304
|
|
|
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
|
-
|
|
481
305
|
export type { SDKInstance };
|
|
482
306
|
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';
|