@nextplus/js-sdk 0.0.11 → 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 CHANGED
@@ -10,55 +10,22 @@ npm install @nextplus/js-sdk
10
10
 
11
11
  ## Usage
12
12
 
13
- ### Authentication Methods
14
-
15
- The SDK supports two authentication methods:
16
-
17
- 1. **Token-based authentication** - Use an existing access token (recommended for React/browser apps)
18
- 2. **Credential-based authentication** - Provide email/username + password (SDK handles login automatically)
19
-
20
- ### Token-Based Authentication (Recommended for React/Browser Apps)
21
-
22
- Perfect for apps where authentication is handled separately (e.g., OAuth, Firebase Auth, custom auth):
23
-
24
- ```typescript
25
- import { configure } from '@nextplus/js-sdk';
26
-
27
- // With explicit baseURL
28
- const sdk = configure({
29
- baseURL: 'https://your-nextplus-instance.com',
30
- accessToken: 'your-existing-token',
31
- returnType: 'data', // 'data' | 'raw'
32
- });
33
-
34
- // Auto-detect baseURL in browser (uses window.location.origin + '/api')
35
- const sdk = configure({
36
- accessToken: userToken, // from your auth provider
37
- returnType: 'data',
38
- });
39
-
40
- // Use the SDK
41
- const tables = await sdk.TableService.find({});
42
- ```
43
-
44
- ### Credential-Based Authentication
45
-
46
- The SDK automatically handles login and token refresh:
13
+ ### Basic Configuration
47
14
 
48
15
  ```typescript
49
16
  import { configure } from '@nextplus/js-sdk';
50
17
 
51
- // With email
18
+ // Configure with email authentication
52
19
  const sdk = configure({
53
- baseURL: 'https://your-nextplus-instance.com',
20
+ baseURL: 'https://your-nextplus-instance.com/api',
54
21
  email: 'your-email@example.com',
55
22
  password: 'your-password',
56
- returnType: 'data',
23
+ returnType: 'data', // 'data' | 'raw'
57
24
  });
58
25
 
59
- // With username
26
+ // Or configure with username authentication
60
27
  const sdk = configure({
61
- baseURL: 'https://your-nextplus-instance.com',
28
+ baseURL: 'https://your-nextplus-instance.com/api',
62
29
  username: 'your-username',
63
30
  password: 'your-password',
64
31
  returnType: 'data',
@@ -70,348 +37,65 @@ const sdk = configure({
70
37
  - **`'data'`**: Returns only the response data (default behavior)
71
38
  - **`'raw'`**: Returns the full response object with `{ data, request, response }`
72
39
 
73
- **Important:** The `returnType` setting only applies when using service methods through the SDK instance (e.g., `sdk.TableService.find()`). When using `sdk.client` directly with individual service imports, responses are always in raw format (`{ data, request, response }`).
74
-
75
- ### Error Handling
76
-
77
- **By default**, non-OK responses return `{ error: ... }` instead of throwing:
78
-
79
- ```typescript
80
- const response = await TableService.find({ limit: 10 });
81
-
82
- if ('error' in response) {
83
- console.error('API Error:', response.error);
84
- } else {
85
- console.log('Success:', response.data);
86
- }
87
- ```
88
-
89
- **To make errors throw automatically**, use `throwOnError: true`:
90
-
91
- ```typescript
92
- configure({
93
- accessToken: token,
94
- throwOnError: true, // Errors will throw
95
- });
96
-
97
- try {
98
- const response = await TableService.find({ limit: 10 });
99
- // Only success responses reach here
100
- } catch (error) {
101
- // All API errors throw here
102
- console.error('API Error:', error);
103
- }
104
- ```
105
-
106
- | Configuration | Error Behavior |
107
- | ------------------------------- | --------------------------- |
108
- | `returnType: 'data'` (Full SDK) | ✅ Throws errors |
109
- | `returnType: 'raw'` (Full SDK) | ❌ Returns `{ error: ... }` |
110
- | `throwOnError: true` | ✅ Throws errors |
111
- | Default (tree-shakeable) | ❌ Returns `{ error: ... }` |
112
-
113
- ### Usage Patterns
114
-
115
- **All patterns use the same `configure()` function!**
116
-
117
- #### Pattern 1: Full SDK (Convenient, with return type control)
118
-
119
- ```typescript
120
- import { configure } from '@nextplus/js-sdk';
121
-
122
- const sdk = configure({
123
- accessToken: userToken,
124
- returnType: 'data', // Returns just the data
125
- });
126
-
127
- // Use service methods through SDK - returns transformed data
128
- const tables = await sdk.TableService.find({ limit: 10 });
129
- // tables = [{ ... }, { ... }] - just the array
130
- ```
131
-
132
- #### Pattern 2a: Automatic Global Client (Cleanest - Recommended)
133
-
134
- ```typescript
135
- import { configure, TableService, UserModelService } from '@nextplus/js-sdk';
136
-
137
- // Configure once - automatically becomes global default!
138
- configure({
139
- accessToken: userToken,
140
- throwOnError: true, // Make errors throw (optional)
141
- });
142
-
143
- // Use anywhere in your app - no client parameter needed!
144
- try {
145
- const response = await TableService.find({ limit: 10 });
146
- const user = await UserModelService.findById({ path: { id: '123' } });
147
-
148
- // Returns raw response format
149
- console.log(response.data); // The actual data
150
- } catch (error) {
151
- // With throwOnError: true, errors are thrown
152
- console.error('API Error:', error);
153
- }
154
- ```
155
-
156
- **Benefits:**
157
-
158
- - ✅ Automatic - `configure()` sets global client automatically
159
- - ✅ No client parameter needed anywhere
160
- - ✅ Tree-shakeable - only import services you use
161
- - ✅ Optional error throwing with `throwOnError: true`
162
- - ✅ Clean code everywhere in your app
163
-
164
- #### Pattern 2b: Bound Services (Per-component)
165
-
166
- ```typescript
167
- import { configure, TableService, UserModelService } from '@nextplus/js-sdk';
168
-
169
- // Configure once
170
- const sdk = configure({ accessToken: userToken });
171
-
172
- // Bind services - no need to pass client every time!
173
- const Tables = sdk.service(TableService);
174
- const Users = sdk.service(UserModelService);
175
-
176
- // Use bound services
177
- const response = await Tables.find({ limit: 10 });
178
- const user = await Users.findById({ path: { id: '123' } });
179
- ```
180
-
181
- #### Pattern 2c: Manual Client (Explicit control)
182
-
183
- ```typescript
184
- const sdk = configure({ accessToken: userToken });
185
-
186
- // Pass client explicitly each time
187
- const response = await TableService.find({
188
- client: sdk.client,
189
- limit: 10,
190
- });
191
- ```
192
-
193
- #### Pattern 3: Manual Client Setup (Maximum control)
194
-
195
- ```typescript
196
- import { TableService } from '@nextplus/js-sdk/services';
197
- import { createClient } from '@nextplus/js-sdk/sdk/client';
198
-
199
- const client = createClient({
200
- baseUrl: window.location.origin + '/api',
201
- });
202
-
203
- // Add auth interceptor manually
204
- client.interceptors.request.use((req) => {
205
- req.headers.set('Authorization', myToken);
206
- return req;
207
- });
208
-
209
- const response = await TableService.find({ client });
210
- ```
211
-
212
- **Comparison:**
213
-
214
- | Feature | Pattern 1: Full SDK | Pattern 2: Tree-shakeable | Pattern 3: Manual |
215
- | ------------------- | ------------------- | ------------------------- | ----------------- |
216
- | Function | `configure()` | `configure()` | `createClient()` |
217
- | Service access | `sdk.ServiceName.*` | Direct `ServiceName.*` | Direct |
218
- | Bundle size | Larger | Smaller | Smallest |
219
- | Return type control | ✅ `'data'`/`'raw'` | ❌ Always raw | ❌ Always raw |
220
- | Auto-login | ✅ (credentials) | ✅ (credentials) | ❌ |
221
- | Complexity | Simple | Simple | More control |
222
- | Best for | Full apps | Modern bundlers | Advanced use |
223
-
224
- ### Automatic Global Client
225
-
226
- **`configure()` automatically sets the global default client** - no manual setup needed!
227
-
228
- ```typescript
229
- import { configure, TableService, UserModelService } from '@nextplus/js-sdk';
230
-
231
- // Configure once - automatically becomes global default!
232
- configure({ accessToken: token });
233
-
234
- // Use anywhere in your app - no client needed!
235
- const tables = await TableService.find({ limit: 10 });
236
- const users = await UserModelService.find({ limit: 10 });
237
-
238
- // No client parameter needed! ✨
239
- ```
240
-
241
- **Use Cases:**
242
-
243
- ```typescript
244
- // React app initialization
245
- function App() {
246
- useEffect(() => {
247
- // configure() automatically sets global client
248
- configure({ accessToken: getAuthToken() });
249
-
250
- return () => clearDefaultClient(); // Cleanup on unmount
251
- }, []);
252
-
253
- return <Routes />;
254
- }
255
-
256
- // Any component can now use services
257
- function TableList() {
258
- const [tables, setTables] = useState([]);
259
-
260
- useEffect(() => {
261
- // No client parameter needed!
262
- TableService.find({ limit: 100 }).then(res => setTables(res.data));
263
- }, []);
264
-
265
- return <div>{/* render tables */}</div>;
266
- }
267
- ```
268
-
269
- **Manual Control (Optional):**
270
-
271
- ```typescript
272
- // Set global client manually
273
- setDefaultClient(client);
274
-
275
- // Get current global client
276
- const client = getDefaultClient();
277
-
278
- // Clear global client (useful for logout)
279
- clearDefaultClient();
280
- ```
281
-
282
- **Client Override:**
283
-
284
- You can still pass a `client` parameter to override the global default:
285
-
286
- ```typescript
287
- configure({ accessToken: token1 }); // Sets global client
288
-
289
- // Uses global client
290
- await TableService.find({ limit: 10 });
291
-
292
- // Uses specific client (overrides global)
293
- await TableService.find({ client: customClient, limit: 10 });
294
- ```
295
-
296
- ### Interceptors (Request/Response Middleware)
297
-
298
- Add custom logic to all requests and responses:
299
-
300
- ```typescript
301
- import { configure } from '@nextplus/js-sdk';
302
-
303
- const sdk = configure({ accessToken: token });
304
-
305
- // Request interceptor - runs before every request
306
- sdk.client.interceptors.request.use((request) => {
307
- console.log('Request:', request.url);
308
- // Add custom headers
309
- request.headers.set('X-Custom-Header', 'value');
310
- // Modify request
311
- return request;
312
- });
313
-
314
- // Response interceptor - runs after every successful response
315
- sdk.client.interceptors.response.use((response) => {
316
- console.log('Response:', response.status);
317
- // Log or transform responses
318
- return response;
319
- });
320
-
321
- // Error interceptor - runs on any error
322
- sdk.client.interceptors.error.use((error) => {
323
- console.error('API Error:', error);
324
- // Custom error handling, logging, etc.
325
- throw error; // Re-throw or handle
326
- });
327
- ```
328
-
329
- **Common Use Cases:**
330
-
331
- ```typescript
332
- // Add request ID to all requests
333
- sdk.client.interceptors.request.use((request) => {
334
- request.headers.set('X-Request-ID', crypto.randomUUID());
335
- return request;
336
- });
337
-
338
- // Add retry logic
339
- sdk.client.interceptors.error.use(async (error) => {
340
- if (error.response?.status === 429) {
341
- // Rate limited - wait and retry
342
- await new Promise((resolve) => setTimeout(resolve, 1000));
343
- // Retry logic here
344
- }
345
- throw error;
346
- });
347
-
348
- // Log all API calls
349
- sdk.client.interceptors.request.use((request) => {
350
- console.log(`[API] ${request.method} ${request.url}`);
351
- return request;
352
- });
353
- ```
354
-
355
- **Works with all patterns:**
356
-
357
- ```typescript
358
- // Pattern 1: Full SDK
359
- const sdk = configure({ accessToken: token });
360
- sdk.client.interceptors.request.use(/* ... */);
361
- await sdk.TableService.find({});
362
-
363
- // Pattern 2: Tree-shakeable
364
- const Tables = sdk.service(TableService);
365
- await Tables.find({}); // Interceptors still apply!
366
-
367
- // Pattern 3: Manual
368
- await TableService.find({ client: sdk.client }); // Interceptors apply!
369
- ```
370
-
371
40
  ### API Usage Examples
372
41
 
373
42
  ```typescript
374
- // Find with filters
375
- const tables = await sdk.TableService.find({
376
- where: { name: 'my-table' },
377
- limit: 10,
378
- order: 'createdAt DESC',
379
- });
380
-
381
- // Find with filter object
43
+ // Find tables with filters
382
44
  const tables = await sdk.TableService.find({
383
45
  filter: {
384
- where: { name: 'my-table' },
385
- limit: 10,
386
- },
46
+ name: {
47
+ eq: 'my-table'
48
+ }
49
+ }
387
50
  });
388
51
 
389
- // Create a record
52
+ // Create a new table
390
53
  const newTable = await sdk.TableService.create({
391
- name: 'New Table',
392
- description: 'Table description',
393
- });
394
-
395
- // Update a record
396
- const updated = await sdk.TableService.prototypePatchAttributes({
397
- path: { id: 'table-id' },
398
- name: 'Updated Name',
54
+ body: {
55
+ name: 'New Table',
56
+ // ... other table properties
57
+ }
399
58
  });
400
59
 
401
60
  // With raw response type
402
61
  const sdk = configure({
403
- accessToken: 'token',
404
- returnType: 'raw',
62
+ baseURL: 'https://api.example.com',
63
+ email: 'user@example.com',
64
+ password: 'password',
65
+ returnType: 'raw'
405
66
  });
406
67
 
407
68
  const response = await sdk.TableService.find({});
408
- console.log(response.data); // Response data
409
- console.log(response.request); // Request object
410
- console.log(response.response); // Full HTTP response
69
+ console.log(response.data); // Response data
70
+ console.log(response.request); // Request object
71
+ console.log(response.response); // Full HTTP response
411
72
  ```
412
73
 
413
74
  ## Development
414
75
 
76
+ ### Releases
77
+
78
+ Jenkins generates the SDK from the API models in the NextPlus release image on
79
+ `master`. The npm version is taken from the repository's root `package.json`.
80
+ After the release pipeline succeeds, Jenkins publishes the verified tarball to
81
+ npm. Rebuilding an already published version skips publishing it again.
82
+
83
+ To validate a release locally, from the repository root with dependencies installed:
84
+
85
+ ```bash
86
+ node CI/update-manifest.js
87
+ node CI/export-js-sdk-spec.js
88
+ sh CI/build-js-sdk.sh
89
+ npm publish sdk-artifacts/nextplus-js-sdk-$(node -p 'require("./package.json").version').tgz --dry-run --access public
90
+ ```
91
+
92
+ The build updates the SDK manifest and generated sources in the build workspace.
93
+ Jenkins uses the Secret text credential `npm-js-sdk-publish`, scoped in npm to
94
+ publish `@nextplus/js-sdk` only, with bypass 2FA enabled. Renew it before its expiry
95
+ (npm allows at most 90 days). npm has announced that direct publishing with bypass
96
+ 2FA tokens ends in January 2027; migrate the publishing step to a supported trusted
97
+ publisher before then: https://docs.npmjs.com/trusted-publishers/.
98
+
415
99
  ### Prerequisites
416
100
 
417
101
  - Node.js (v18 or higher)
@@ -455,65 +139,36 @@ Generated files are located in `src/sdk/` and should not be manually edited.
455
139
 
456
140
  ## Testing
457
141
 
458
- ### Test Commands
459
-
460
- ```bash
461
- # Run full test suite (builds first, then runs tests)
462
- npm test
142
+ ### Smoke Tests
463
143
 
464
- # Run tests directly from TypeScript (faster for development)
465
- npm run test:dev
144
+ Run the smoke test to verify the SDK works correctly:
466
145
 
467
- # Run tests in watch mode (re-runs on file changes)
468
- npm run test:watch
146
+ ```bash
147
+ # Make sure your NextPlus instance is running on localhost:3000
148
+ npm run test
469
149
  ```
470
150
 
471
- ### Test Suite
472
-
473
- Make sure your NextPlus instance is running on `localhost:3000` before running tests.
474
-
475
- The test suite (`src/smoke.ts`) uses Node's built-in test runner and validates:
476
-
477
- - Token-based authentication
151
+ The smoke test (`src/smoke.ts`) demonstrates:
478
152
  - Email and username authentication
479
153
  - Different return types (`data` vs `raw`)
480
- - Tree-shakeable service imports
481
154
  - API calls to the TableService
482
- - Configuration validation and error handling
155
+ - Error handling
483
156
 
484
157
  ### Manual Testing
485
158
 
486
159
  ```typescript
487
- // Test with token authentication
160
+ // Create a test file
488
161
  import { configure } from '@nextplus/js-sdk';
489
162
 
490
163
  const sdk = configure({
491
- baseURL: 'http://localhost:3000',
492
- accessToken: 'your-test-token',
493
- });
494
-
495
- const result = await sdk.TableService.find({});
496
- console.log(result);
497
-
498
- // Test with credentials
499
- const sdk2 = configure({
500
- baseURL: 'http://localhost:3000',
164
+ baseURL: 'http://localhost:3000/api',
501
165
  email: 'test@example.com',
502
166
  password: 'password',
503
167
  });
504
168
 
505
- const result2 = await sdk2.TableService.find({});
506
- console.log(result2);
507
-
508
- // Test tree-shakeable imports
509
- import { configure, TableService } from '@nextplus/js-sdk';
510
-
511
- const sdk = configure({
512
- accessToken: 'your-test-token',
513
- });
514
-
515
- const tables = await TableService.find({ client: sdk.client });
516
- console.log(tables);
169
+ // Test your API calls
170
+ const result = await sdk.TableService.find({});
171
+ console.log(result);
517
172
  ```
518
173
 
519
174
  ## Publishing
@@ -573,7 +228,6 @@ export default {
573
228
  ### TypeScript
574
229
 
575
230
  The project uses modern TypeScript with:
576
-
577
231
  - ES2020 target
578
232
  - ESNext modules
579
233
  - Strict type checking