@nextplus/js-sdk 0.0.9 → 0.0.11

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,22 +10,55 @@ npm install @nextplus/js-sdk
10
10
 
11
11
  ## Usage
12
12
 
13
- ### Basic Configuration
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):
14
23
 
15
24
  ```typescript
16
25
  import { configure } from '@nextplus/js-sdk';
17
26
 
18
- // Configure with email authentication
27
+ // With explicit baseURL
19
28
  const sdk = configure({
20
- baseURL: 'https://your-nextplus-instance.com/api',
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:
47
+
48
+ ```typescript
49
+ import { configure } from '@nextplus/js-sdk';
50
+
51
+ // With email
52
+ const sdk = configure({
53
+ baseURL: 'https://your-nextplus-instance.com',
21
54
  email: 'your-email@example.com',
22
55
  password: 'your-password',
23
- returnType: 'data', // 'data' | 'raw'
56
+ returnType: 'data',
24
57
  });
25
58
 
26
- // Or configure with username authentication
59
+ // With username
27
60
  const sdk = configure({
28
- baseURL: 'https://your-nextplus-instance.com/api',
61
+ baseURL: 'https://your-nextplus-instance.com',
29
62
  username: 'your-username',
30
63
  password: 'your-password',
31
64
  returnType: 'data',
@@ -37,38 +70,344 @@ const sdk = configure({
37
70
  - **`'data'`**: Returns only the response data (default behavior)
38
71
  - **`'raw'`**: Returns the full response object with `{ data, request, response }`
39
72
 
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
+
40
371
  ### API Usage Examples
41
372
 
42
373
  ```typescript
43
- // Find tables with filters
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
44
382
  const tables = await sdk.TableService.find({
45
383
  filter: {
46
- name: {
47
- eq: 'my-table'
48
- }
49
- }
384
+ where: { name: 'my-table' },
385
+ limit: 10,
386
+ },
50
387
  });
51
388
 
52
- // Create a new table
389
+ // Create a record
53
390
  const newTable = await sdk.TableService.create({
54
- body: {
55
- name: 'New Table',
56
- // ... other table properties
57
- }
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',
58
399
  });
59
400
 
60
401
  // With raw response type
61
402
  const sdk = configure({
62
- baseURL: 'https://api.example.com',
63
- email: 'user@example.com',
64
- password: 'password',
65
- returnType: 'raw'
403
+ accessToken: 'token',
404
+ returnType: 'raw',
66
405
  });
67
406
 
68
407
  const response = await sdk.TableService.find({});
69
- console.log(response.data); // Response data
70
- console.log(response.request); // Request object
71
- console.log(response.response); // Full HTTP response
408
+ console.log(response.data); // Response data
409
+ console.log(response.request); // Request object
410
+ console.log(response.response); // Full HTTP response
72
411
  ```
73
412
 
74
413
  ## Development
@@ -116,36 +455,65 @@ Generated files are located in `src/sdk/` and should not be manually edited.
116
455
 
117
456
  ## Testing
118
457
 
119
- ### Smoke Tests
120
-
121
- Run the smoke test to verify the SDK works correctly:
458
+ ### Test Commands
122
459
 
123
460
  ```bash
124
- # Make sure your NextPlus instance is running on localhost:3000
125
- npm run test
461
+ # Run full test suite (builds first, then runs tests)
462
+ npm test
463
+
464
+ # Run tests directly from TypeScript (faster for development)
465
+ npm run test:dev
466
+
467
+ # Run tests in watch mode (re-runs on file changes)
468
+ npm run test:watch
126
469
  ```
127
470
 
128
- The smoke test (`src/smoke.ts`) demonstrates:
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
129
478
  - Email and username authentication
130
479
  - Different return types (`data` vs `raw`)
480
+ - Tree-shakeable service imports
131
481
  - API calls to the TableService
132
- - Error handling
482
+ - Configuration validation and error handling
133
483
 
134
484
  ### Manual Testing
135
485
 
136
486
  ```typescript
137
- // Create a test file
487
+ // Test with token authentication
138
488
  import { configure } from '@nextplus/js-sdk';
139
489
 
140
490
  const sdk = configure({
141
- baseURL: 'http://localhost:3000/api',
142
- email: 'test@example.com',
143
- password: 'password',
491
+ baseURL: 'http://localhost:3000',
492
+ accessToken: 'your-test-token',
144
493
  });
145
494
 
146
- // Test your API calls
147
495
  const result = await sdk.TableService.find({});
148
496
  console.log(result);
497
+
498
+ // Test with credentials
499
+ const sdk2 = configure({
500
+ baseURL: 'http://localhost:3000',
501
+ email: 'test@example.com',
502
+ password: 'password',
503
+ });
504
+
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);
149
517
  ```
150
518
 
151
519
  ## Publishing
@@ -205,6 +573,7 @@ export default {
205
573
  ### TypeScript
206
574
 
207
575
  The project uses modern TypeScript with:
576
+
208
577
  - ES2020 target
209
578
  - ESNext modules
210
579
  - Strict type checking
@@ -13,6 +13,8 @@ import {
13
13
  CertificateMappingService,
14
14
  CertificateService,
15
15
  ChapterService,
16
+ ChatThreadService,
17
+ CommandPaletteHistoryService,
16
18
  CommentService,
17
19
  ConfigurationService,
18
20
  ConnectionService,
@@ -71,6 +73,7 @@ import {
71
73
  SettingService,
72
74
  ShiftService,
73
75
  ShiftTypeService,
76
+ SqlServerService,
74
77
  StationService,
75
78
  StockService,
76
79
  SyncClientsService,
@@ -99,8 +102,9 @@ import {
99
102
  WorkflowTypeService,
100
103
  WorkorderService,
101
104
  WorkorderStatusService,
105
+ WorkorderStatusTransitionService,
102
106
  WorkorderTemplateService
103
- } from "./chunk-VAV5HKXV.js";
107
+ } from "./chunk-QDNBVWJS.js";
104
108
  import {
105
109
  __export
106
110
  } from "./chunk-FXXZNC42.js";
@@ -122,6 +126,8 @@ __export(sdk_exports, {
122
126
  CertificateMappingService: () => CertificateMappingService,
123
127
  CertificateService: () => CertificateService,
124
128
  ChapterService: () => ChapterService,
129
+ ChatThreadService: () => ChatThreadService,
130
+ CommandPaletteHistoryService: () => CommandPaletteHistoryService,
125
131
  CommentService: () => CommentService,
126
132
  ConfigurationService: () => ConfigurationService,
127
133
  ConnectionService: () => ConnectionService,
@@ -180,6 +186,7 @@ __export(sdk_exports, {
180
186
  SettingService: () => SettingService,
181
187
  ShiftService: () => ShiftService,
182
188
  ShiftTypeService: () => ShiftTypeService,
189
+ SqlServerService: () => SqlServerService,
183
190
  StationService: () => StationService,
184
191
  StockService: () => StockService,
185
192
  SyncClientsService: () => SyncClientsService,
@@ -208,6 +215,7 @@ __export(sdk_exports, {
208
215
  WorkflowTypeService: () => WorkflowTypeService,
209
216
  WorkorderService: () => WorkorderService,
210
217
  WorkorderStatusService: () => WorkorderStatusService,
218
+ WorkorderStatusTransitionService: () => WorkorderStatusTransitionService,
211
219
  WorkorderTemplateService: () => WorkorderTemplateService
212
220
  });
213
221