@klerick/json-api-nestjs-sdk 10.0.0-beta.3 → 10.0.0-beta.5

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.
Files changed (68) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/README.md +665 -0
  3. package/cjs/src/index.d.ts +1 -1
  4. package/cjs/src/index.js +4 -13
  5. package/cjs/src/index.js.map +1 -1
  6. package/cjs/src/lib/constants/index.js +1 -4
  7. package/cjs/src/lib/constants/index.js.map +1 -1
  8. package/cjs/src/lib/json-api-angular.js +19 -26
  9. package/cjs/src/lib/json-api-angular.js.map +1 -1
  10. package/cjs/src/lib/json-api-js.js +14 -18
  11. package/cjs/src/lib/json-api-js.js.map +1 -1
  12. package/cjs/src/lib/service/atomic-operations.service.js +8 -12
  13. package/cjs/src/lib/service/atomic-operations.service.js.map +1 -1
  14. package/cjs/src/lib/service/fetch-inner-client.js +13 -11
  15. package/cjs/src/lib/service/fetch-inner-client.js.map +1 -1
  16. package/cjs/src/lib/service/index.js +3 -6
  17. package/cjs/src/lib/service/index.js.map +1 -1
  18. package/cjs/src/lib/service/json-api-sdk.service.js +41 -38
  19. package/cjs/src/lib/service/json-api-sdk.service.js.map +1 -1
  20. package/cjs/src/lib/service/json-api-utils.service.js +58 -51
  21. package/cjs/src/lib/service/json-api-utils.service.js.map +1 -1
  22. package/cjs/src/lib/token/index.js +3 -6
  23. package/cjs/src/lib/token/index.js.map +1 -1
  24. package/cjs/src/lib/types/atomic-operation.js +0 -2
  25. package/cjs/src/lib/types/atomic-type.js +1 -3
  26. package/cjs/src/lib/types/atomic-type.js.map +1 -1
  27. package/cjs/src/lib/types/config.js +0 -2
  28. package/cjs/src/lib/types/filter-operand.js +1 -3
  29. package/cjs/src/lib/types/filter-operand.js.map +1 -1
  30. package/cjs/src/lib/types/http-inner-client.js +0 -2
  31. package/cjs/src/lib/types/http-request-params.js +0 -2
  32. package/cjs/src/lib/types/index.js +9 -12
  33. package/cjs/src/lib/types/index.js.map +1 -1
  34. package/cjs/src/lib/types/promise-json-api-sdk.js +0 -2
  35. package/cjs/src/lib/types/query-params.d.ts +3 -3
  36. package/cjs/src/lib/types/query-params.js +1 -3
  37. package/cjs/src/lib/types/query-params.js.map +1 -1
  38. package/cjs/src/lib/types/utils.js +0 -2
  39. package/cjs/src/lib/utils/adapter-for-axios.d.ts +2 -2
  40. package/cjs/src/lib/utils/adapter-for-axios.js +5 -8
  41. package/cjs/src/lib/utils/adapter-for-axios.js.map +1 -1
  42. package/cjs/src/lib/utils/entity-array.js +1 -5
  43. package/cjs/src/lib/utils/entity-array.js.map +1 -1
  44. package/cjs/src/lib/utils/generate-atomic-body.js +24 -16
  45. package/cjs/src/lib/utils/generate-atomic-body.js.map +1 -1
  46. package/cjs/src/lib/utils/http-params.js +3 -8
  47. package/cjs/src/lib/utils/http-params.js.map +1 -1
  48. package/cjs/src/lib/utils/index.js +5 -8
  49. package/cjs/src/lib/utils/index.js.map +1 -1
  50. package/cjs/src/lib/utils/utils.js +14 -14
  51. package/cjs/src/lib/utils/utils.js.map +1 -1
  52. package/cjs/src/ngModule.js +3 -13
  53. package/cjs/src/ngModule.js.map +1 -1
  54. package/mjs/src/index.d.ts +1 -1
  55. package/mjs/src/lib/types/atomic-operation.js +0 -1
  56. package/mjs/src/lib/types/config.js +0 -1
  57. package/mjs/src/lib/types/http-inner-client.js +0 -1
  58. package/mjs/src/lib/types/http-request-params.js +0 -1
  59. package/mjs/src/lib/types/promise-json-api-sdk.js +0 -1
  60. package/mjs/src/lib/types/query-params.d.ts +3 -3
  61. package/mjs/src/lib/types/utils.js +0 -1
  62. package/mjs/src/lib/utils/adapter-for-axios.d.ts +2 -2
  63. package/mjs/src/lib/utils/adapter-for-axios.js.map +1 -1
  64. package/mjs/src/lib/utils/generate-atomic-body.js +3 -0
  65. package/mjs/src/lib/utils/generate-atomic-body.js.map +1 -1
  66. package/package.json +6 -9
  67. package/cjs/package.json +0 -55
  68. package/mjs/package.json +0 -57
package/README.md ADDED
@@ -0,0 +1,665 @@
1
+ <p align='center'>
2
+ <a href="https://www.npmjs.com/package/@klerick/json-api-nestjs-sdk" target="_blank"><img src="https://img.shields.io/npm/v/@klerick/json-api-nestjs-sdk.svg" alt="NPM Version" /></a>
3
+ <a href="https://www.npmjs.com/package/@klerick/json-api-nestjs-sdk" target="_blank"><img src="https://img.shields.io/npm/l/@klerick/json-api-nestjs-sdk.svg" alt="Package License" /></a>
4
+ <a href="https://www.npmjs.com/package/@klerick/json-api-nestjs-sdk" target="_blank"><img src="https://img.shields.io/npm/dm/json-api-nestjs-sdk.svg" alt="NPM Downloads" /></a>
5
+ <a href="http://commitizen.github.io/cz-cli/" target="_blank"><img src="https://img.shields.io/badge/commitizen-friendly-brightgreen.svg" alt="Commitizen friendly" /></a>
6
+ <img src="https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/klerick/02a4c98cf7008fea2af70dc2d50f4cb7/raw/json-api-nestjs-sdk.json" alt="Coverage Badge" />
7
+ </p>
8
+
9
+ # JSON:API Client SDK
10
+
11
+ Type-safe TypeScript/JavaScript client for consuming [JSON:API](https://jsonapi.org/) endpoints built with [@klerick/json-api-nestjs](https://www.npmjs.com/package/@klerick/json-api-nestjs).
12
+
13
+ ## ✨ Features
14
+
15
+ - 🎯 **Full Type Safety** - Complete TypeScript support with type inference from your entities
16
+ - 🔍 **Advanced Filtering** - Rich query builder with operators (eq, ne, in, like, gt, lt, etc.)
17
+ - 📦 **Relationship Handling** - Easy include, sparse fieldsets, and relationship management
18
+ - ⚡ **Atomic Operations** - Batch multiple operations in a single request with rollback support
19
+ - 🌐 **Multiple HTTP Clients** - Works with Axios, Fetch API, and Angular HttpClient
20
+ - 📄 **Pagination & Sorting** - Built-in support for pagination and multi-field sorting
21
+ - 🔄 **Observable or Promise** - Choose your async style (RxJS Observable or native Promise)
22
+ - 🔗 **Relationship Operations** - Post, patch, and delete relationships independently
23
+
24
+ ## 📚 Table of Contents
25
+
26
+ - [Installation](#installation)
27
+ - [Quick Start](#-quick-start)
28
+ - [Basic Setup (Axios)](#basic-setup-axios)
29
+ - [Angular Setup](#angular-setup)
30
+ - [Configuration](#-configuration)
31
+ - [API Methods](#-api-methods)
32
+ - [Fetching Resources](#fetching-resources)
33
+ - [Creating Resources](#creating-resources)
34
+ - [Updating Resources](#updating-resources)
35
+ - [Deleting Resources](#deleting-resources)
36
+ - [Relationship Operations](#relationship-operations)
37
+ - [Query Options](#-query-options)
38
+ - [Filtering](#filtering)
39
+ - [Sorting](#sorting)
40
+ - [Pagination](#pagination)
41
+ - [Including Relationships](#including-relationships)
42
+ - [Sparse Fieldsets](#sparse-fieldsets)
43
+ - [Atomic Operations](#-atomic-operations)
44
+ - [Examples](#-examples)
45
+
46
+
47
+ ## Installation
48
+
49
+ ```bash
50
+ npm install @klerick/json-api-nestjs-sdk
51
+ ```
52
+
53
+ ---
54
+
55
+ ## 🚀 Quick Start
56
+
57
+ ### Basic Setup (Axios)
58
+
59
+ ```typescript
60
+ import { JsonApiJs, adapterForAxios, FilterOperand } from '@klerick/json-api-nestjs-sdk';
61
+ import axios from 'axios';
62
+ import { Users } from './entities'; // Your entity classes
63
+
64
+ // 1. Create adapter
65
+ const axiosAdapter = adapterForAxios(axios);
66
+
67
+ // 2. Configure SDK
68
+ const jsonSdk = JsonApiJs(
69
+ {
70
+ adapter: axiosAdapter,
71
+ apiHost: 'http://localhost:3000',
72
+ apiPrefix: 'api',
73
+ dateFields: ['createdAt', 'updatedAt'],
74
+ operationUrl: 'operation',
75
+ },
76
+ true // true = return Promises, false = return Observables
77
+ );
78
+
79
+ // 3. Use SDK
80
+ // Fetch all users
81
+ const users = await jsonSdk.jonApiSdkService.getAll(Users);
82
+
83
+ // Fetch with filtering and relationships
84
+ const activeUsers = await jsonSdk.jonApiSdkService.getAll(Users, {
85
+ filter: {
86
+ target: {
87
+ isActive: { [FilterOperand.eq]: 'true' }
88
+ }
89
+ },
90
+ include: ['addresses', 'roles']
91
+ });
92
+
93
+ // Get one user
94
+ const user = await jsonSdk.jonApiSdkService.getOne(Users, '1', {
95
+ include: ['addresses', 'comments', 'roles', 'manager']
96
+ });
97
+
98
+ // Create a user
99
+ const newUser = new Users();
100
+ newUser.firstName = 'John';
101
+ newUser.lastName = 'Doe';
102
+ newUser.login = 'johndoe';
103
+ newUser.isActive = true;
104
+
105
+ const createdUser = await jsonSdk.jonApiSdkService.postOne(newUser);
106
+
107
+ // Update a user
108
+ createdUser.firstName = 'Jane';
109
+ const updatedUser = await jsonSdk.jonApiSdkService.patchOne(createdUser);
110
+
111
+ // Delete a user
112
+ await jsonSdk.jonApiSdkService.deleteOne(createdUser);
113
+ ```
114
+
115
+ ### Angular Setup
116
+
117
+ ```typescript
118
+ import {
119
+ provideJsonApi,
120
+ AtomicFactory,
121
+ JsonApiSdkService
122
+ } from '@klerick/json-api-nestjs-sdk/ngModule';
123
+ import {
124
+ provideHttpClient,
125
+ withFetch,
126
+ } from '@angular/common/http';
127
+ import { Component, inject } from '@angular/core';
128
+ import { bootstrapApplication } from '@angular/platform-browser';
129
+
130
+ // 1. Configure in your main.ts or app.config.ts
131
+ const angularConfig = {
132
+ apiHost: 'http://localhost:3000',
133
+ idKey: 'id',
134
+ apiPrefix: 'api',
135
+ operationUrl: 'operation',
136
+ dateFields: ['createdAt', 'updatedAt']
137
+ };
138
+
139
+ bootstrapApplication(AppComponent, {
140
+ providers: [
141
+ provideHttpClient(withFetch()),
142
+ provideJsonApi(angularConfig)
143
+ ],
144
+ }).catch((err) => console.error(err));
145
+
146
+ // 2. Use in your components
147
+ @Component({
148
+ standalone: true,
149
+ selector: 'app-users',
150
+ templateUrl: './users.component.html',
151
+ })
152
+ export class UsersComponent {
153
+ private jsonApiService = inject(JsonApiSdkService);
154
+ private atomicFactory = inject(AtomicFactory);
155
+
156
+ async loadUsers() {
157
+ const users = await this.jsonApiService.getAll(Users, {
158
+ include: ['addresses']
159
+ });
160
+ return users;
161
+ }
162
+
163
+ async createMultipleResources() {
164
+ const result = await this.atomicFactory()
165
+ .postOne(newUser)
166
+ .postOne(newAddress)
167
+ .run();
168
+ }
169
+ }
170
+ ```
171
+
172
+ ## ⚙️ Configuration
173
+
174
+ ### JsonConfig Type
175
+
176
+ ```typescript
177
+ type JsonSdkConfig = {
178
+ apiHost: string; // Base URL of your API (e.g., 'http://localhost:3000')
179
+ apiPrefix?: string; // API prefix (e.g., 'api' -> '/api/users')
180
+ idKey?: string; // Name of ID field (default: 'id')
181
+ idIsNumber?: boolean; // Parse IDs as numbers (default: false)
182
+ operationUrl?: string; // URL path for atomic operations (default: 'operation')
183
+ dateFields?: string[]; // Fields to convert to Date objects (e.g., ['createdAt', 'updatedAt'])
184
+ }
185
+
186
+ type JsonConfig = JsonSdkConfig & {
187
+ adapter?: HttpInnerClient; // HTTP client adapter (default: fetch)
188
+ }
189
+ ```
190
+
191
+ ### HTTP Adapters
192
+
193
+ **Axios Adapter:**
194
+ ```typescript
195
+ import { adapterForAxios } from '@klerick/json-api-nestjs-sdk';
196
+ import axios from 'axios';
197
+
198
+ const adapter = adapterForAxios(axios);
199
+ ```
200
+
201
+ **Fetch API (default):**
202
+ ```typescript
203
+ // No adapter needed, fetch is used by default
204
+ const jsonSdk = JsonApiJs({
205
+ apiHost: 'http://localhost:3000',
206
+ apiPrefix: 'api',
207
+ }, true);
208
+ ```
209
+
210
+ **Custom Adapter:**
211
+
212
+ See [HttpInnerClient interface](https://github.com/klerick/nestjs-json-api/blob/master/libs/json-api/json-api-nestjs-sdk/src/lib/types/http-inner-client.ts) for implementation details.
213
+
214
+ ---
215
+
216
+ ## 📖 API Methods
217
+
218
+ ### Fetching Resources
219
+
220
+ #### `getAll(Entity, options?)`
221
+
222
+ Fetch all resources with optional filtering, sorting, and relationships.
223
+
224
+ ```typescript
225
+ import { FilterOperand } from '@klerick/json-api-nestjs-sdk';
226
+
227
+ // Fetch all users
228
+ const users = await jsonSdk.jonApiSdkService.getAll(Users);
229
+
230
+ // With filtering
231
+ const activeUsers = await jsonSdk.jonApiSdkService.getAll(Users, {
232
+ filter: {
233
+ target: {
234
+ isActive: { [FilterOperand.eq]: 'true' },
235
+ id: { [FilterOperand.in]: ['1', '2', '3'] }
236
+ }
237
+ },
238
+ include: ['addresses', 'roles']
239
+ });
240
+
241
+ // Filter by relationship
242
+ const usersWithRoles = await jsonSdk.jonApiSdkService.getAll(Users, {
243
+ filter: {
244
+ target: {
245
+ id: { [FilterOperand.in]: ['1', '2'] }
246
+ },
247
+ roles: {
248
+ name: { [FilterOperand.eq]: 'admin' }
249
+ }
250
+ },
251
+ include: ['roles']
252
+ });
253
+ ```
254
+
255
+ #### `getList(Entity, options)`
256
+
257
+ Fetch resources with pagination (returns paginated results).
258
+
259
+ ```typescript
260
+ const firstPage = await jsonSdk.jonApiSdkService.getList(Users, {
261
+ page: {
262
+ number: 1,
263
+ size: 10
264
+ },
265
+ sort: {
266
+ target: {
267
+ id: 'ASC'
268
+ }
269
+ }
270
+ });
271
+
272
+ const secondPage = await jsonSdk.jonApiSdkService.getList(Users, {
273
+ page: {
274
+ number: 2,
275
+ size: 10
276
+ },
277
+ sort: {
278
+ target: {
279
+ createdAt: 'DESC'
280
+ }
281
+ }
282
+ });
283
+ ```
284
+
285
+ #### `getOne(Entity, id, options?)`
286
+
287
+ Fetch a single resource by ID.
288
+
289
+ ```typescript
290
+ // Simple fetch
291
+ const user = await jsonSdk.jonApiSdkService.getOne(Users, '1');
292
+
293
+ // With relationships
294
+ const userWithRelations = await jsonSdk.jonApiSdkService.getOne(Users, '1', {
295
+ include: ['addresses', 'comments', 'roles', 'manager']
296
+ });
297
+
298
+ // With sparse fieldsets
299
+ const userPartial = await jsonSdk.jonApiSdkService.getOne(Users, '1', {
300
+ fields: {
301
+ users: ['firstName', 'lastName', 'email']
302
+ }
303
+ });
304
+ ```
305
+
306
+ ### Creating Resources
307
+
308
+ #### `postOne(entity, options?)`
309
+
310
+ Create a new resource.
311
+
312
+ ```typescript
313
+ // Simple create
314
+ const newUser = new Users();
315
+ newUser.firstName = 'John';
316
+ newUser.lastName = 'Doe';
317
+ newUser.login = 'johndoe';
318
+ newUser.isActive = true;
319
+
320
+ const createdUser = await jsonSdk.jonApiSdkService.postOne(newUser);
321
+
322
+ // Create with relationships
323
+ const newAddress = new Addresses();
324
+ newAddress.city = 'New York';
325
+ newAddress.state = 'NY';
326
+ newAddress.country = 'USA';
327
+
328
+ const savedAddress = await jsonSdk.jonApiSdkService.postOne(newAddress);
329
+
330
+ const user = new Users();
331
+ user.firstName = 'Jane';
332
+ user.lastName = 'Doe';
333
+ user.login = 'janedoe';
334
+ user.addresses = savedAddress; // Set relationship
335
+
336
+ const createdUser = await jsonSdk.jonApiSdkService.postOne(user);
337
+ ```
338
+
339
+ ### Updating Resources
340
+
341
+ #### `patchOne(entity, options?)`
342
+
343
+ Update an existing resource.
344
+
345
+ ```typescript
346
+ // Update attributes
347
+ user.firstName = 'Updated Name';
348
+ const updatedUser = await jsonSdk.jonApiSdkService.patchOne(user);
349
+
350
+ // Update relationships
351
+ const newAddress = await jsonSdk.jonApiSdkService.postOne(addressEntity);
352
+ user.addresses = newAddress;
353
+
354
+ const updatedUser = await jsonSdk.jonApiSdkService.patchOne(user);
355
+ ```
356
+
357
+ ### Deleting Resources
358
+
359
+ #### `deleteOne(entity)`
360
+
361
+ Delete a resource.
362
+
363
+ ```typescript
364
+ await jsonSdk.jonApiSdkService.deleteOne(user);
365
+ ```
366
+
367
+ ### Relationship Operations
368
+
369
+ #### `deleteRelationships(entity, relationshipName)`
370
+
371
+ Remove relationships without deleting the related resources.
372
+
373
+ ```typescript
374
+ // Remove all roles from user
375
+ await jsonSdk.jonApiSdkService.deleteRelationships(user, 'roles');
376
+
377
+ // Remove manager from user
378
+ await jsonSdk.jonApiSdkService.deleteRelationships(user, 'manager');
379
+
380
+ // Remove all comments from user
381
+ await jsonSdk.jonApiSdkService.deleteRelationships(user, 'comments');
382
+ ```
383
+
384
+ ---
385
+
386
+ ## 🔍 Query Options
387
+
388
+ ### Filtering
389
+
390
+ Available operators:
391
+
392
+ ```typescript
393
+ enum FilterOperand {
394
+ eq = 'eq', // Equal
395
+ ne = 'ne', // Not equal
396
+ in = 'in', // In array
397
+ nin = 'nin', // Not in array
398
+ lt = 'lt', // Less than
399
+ lte = 'lte', // Less than or equal
400
+ gt = 'gt', // Greater than
401
+ gte = 'gte', // Greater than or equal
402
+ like = 'like', // SQL LIKE
403
+ re = 'regexp', // Regular expression
404
+ }
405
+ ```
406
+
407
+ **Examples:**
408
+
409
+ ```typescript
410
+ // Equal
411
+ const users = await jsonSdk.jonApiSdkService.getAll(Users, {
412
+ filter: {
413
+ target: {
414
+ isActive: { [FilterOperand.eq]: 'true' }
415
+ }
416
+ }
417
+ });
418
+
419
+ // Not equal
420
+ const inactiveUsers = await jsonSdk.jonApiSdkService.getAll(Users, {
421
+ filter: {
422
+ target: {
423
+ isActive: { [FilterOperand.ne]: 'true' }
424
+ }
425
+ }
426
+ });
427
+
428
+ // In array
429
+ const specificUsers = await jsonSdk.jonApiSdkService.getAll(Users, {
430
+ filter: {
431
+ target: {
432
+ id: { [FilterOperand.in]: ['1', '2', '3'] }
433
+ }
434
+ }
435
+ });
436
+
437
+ // LIKE search
438
+ const searchUsers = await jsonSdk.jonApiSdkService.getAll(Users, {
439
+ filter: {
440
+ target: {
441
+ login: { [FilterOperand.like]: 'john' }
442
+ }
443
+ }
444
+ });
445
+
446
+ // Check null/not null
447
+ const usersWithManager = await jsonSdk.jonApiSdkService.getAll(Users, {
448
+ filter: {
449
+ target: {
450
+ manager: { [FilterOperand.ne]: null }
451
+ }
452
+ }
453
+ });
454
+
455
+ const usersWithoutManager = await jsonSdk.jonApiSdkService.getAll(Users, {
456
+ filter: {
457
+ target: {
458
+ manager: { [FilterOperand.eq]: null }
459
+ }
460
+ }
461
+ });
462
+ ```
463
+
464
+ ### Sorting
465
+
466
+ ```typescript
467
+ // Sort by single field
468
+ const users = await jsonSdk.jonApiSdkService.getList(Users, {
469
+ sort: {
470
+ target: {
471
+ id: 'ASC'
472
+ }
473
+ }
474
+ });
475
+
476
+ // Sort by multiple fields
477
+ const sortedUsers = await jsonSdk.jonApiSdkService.getList(Users, {
478
+ sort: {
479
+ target: {
480
+ createdAt: 'DESC',
481
+ lastName: 'ASC'
482
+ }
483
+ }
484
+ });
485
+ ```
486
+
487
+ ### Pagination
488
+
489
+ ```typescript
490
+ const paginatedUsers = await jsonSdk.jonApiSdkService.getList(Users, {
491
+ page: {
492
+ number: 1, // Page number (1-indexed)
493
+ size: 20 // Items per page
494
+ }
495
+ });
496
+ ```
497
+
498
+ ### Including Relationships
499
+
500
+ ```typescript
501
+ // Include single relationship
502
+ const users = await jsonSdk.jonApiSdkService.getAll(Users, {
503
+ include: ['addresses']
504
+ });
505
+
506
+ // Include multiple relationships
507
+ const usersWithAll = await jsonSdk.jonApiSdkService.getAll(Users, {
508
+ include: ['addresses', 'roles', 'comments', 'manager']
509
+ });
510
+
511
+ // Include nested relationships
512
+ const usersWithNested = await jsonSdk.jonApiSdkService.getAll(Users, {
513
+ include: ['addresses', 'manager.addresses', 'roles']
514
+ });
515
+ ```
516
+
517
+ ### Sparse Fieldsets
518
+
519
+ Request only specific fields to reduce payload size.
520
+
521
+ ```typescript
522
+ const users = await jsonSdk.jonApiSdkService.getAll(Users, {
523
+ fields: {
524
+ users: ['firstName', 'lastName', 'email'],
525
+ addresses: ['city', 'country']
526
+ },
527
+ include: ['addresses']
528
+ });
529
+ ```
530
+
531
+ ---
532
+
533
+ ## ⚡ Atomic Operations
534
+
535
+ Execute multiple operations in a single HTTP request. All operations succeed or fail together.
536
+
537
+ ### Basic Atomic Operation
538
+
539
+ ```typescript
540
+ const newUser = new Users();
541
+ newUser.firstName = 'John';
542
+ newUser.lastName = 'Doe';
543
+ newUser.login = 'johndoe';
544
+
545
+ const result = await jsonSdk.atomicFactory()
546
+ .postOne(newUser)
547
+ .run();
548
+
549
+ console.log(result[0]); // Created user
550
+ ```
551
+
552
+ ### Multiple Operations
553
+
554
+ ```typescript
555
+ // Create multiple related resources
556
+ const address = new Addresses();
557
+ address.city = 'New York';
558
+ address.state = 'NY';
559
+ address.country = 'USA';
560
+
561
+ const role = new Roles();
562
+ role.name = 'Admin';
563
+ role.key = 'admin';
564
+
565
+ const user = new Users();
566
+ user.firstName = 'Jane';
567
+ user.lastName = 'Doe';
568
+ user.login = 'janedoe';
569
+ user.addresses = address;
570
+ user.roles = [role];
571
+
572
+ const [createdAddress, createdRole, createdUser] = await jsonSdk
573
+ .atomicFactory()
574
+ .postOne(address)
575
+ .postOne(role)
576
+ .postOne(user)
577
+ .run();
578
+ ```
579
+
580
+ ### Mixed Operations (POST, PATCH, Relationships)
581
+
582
+ ```typescript
583
+ // Create user first
584
+ const newUser = new Users();
585
+ newUser.firstName = 'John';
586
+ newUser.login = 'john';
587
+
588
+ const [createdUser] = await jsonSdk.atomicFactory()
589
+ .postOne(newUser)
590
+ .run();
591
+
592
+ // Then update and manage relationships atomically
593
+ const patchUser = Object.assign(new Users(), createdUser);
594
+ patchUser.firstName = 'John Updated';
595
+ patchUser.roles = [role1];
596
+
597
+ const patchUser2 = Object.assign(new Users(), createdUser);
598
+ patchUser2.comments = [comment1];
599
+
600
+ const patchUser3 = Object.assign(new Users(), createdUser);
601
+ patchUser3.comments = [comment2];
602
+
603
+ const result = await jsonSdk
604
+ .atomicFactory()
605
+ .patchOne(patchUser) // Update user attributes and set roles
606
+ .patchOne(patchUser2) // Set comments
607
+ .patchRelationships(patchUser2, 'comments') // Replace comments (keep only comment1)
608
+ .postRelationships(patchUser3, 'comments') // Add comment2 to existing comments
609
+ .run();
610
+
611
+ // result[0] - updated user
612
+ // result[1] - updated user with comments
613
+ // result[2] - array of comment IDs after replacement
614
+ // result[3] - array of all comment IDs after addition
615
+ ```
616
+
617
+ ### Using Temporary IDs (lid)
618
+
619
+ Reference resources created within the same atomic request using temporary IDs.
620
+
621
+ ```typescript
622
+ const address = new Addresses();
623
+ address.city = 'Boston';
624
+ address.id = 10000; // Temporary ID
625
+
626
+ const user = new Users();
627
+ user.firstName = 'Alice';
628
+ user.addresses = address; // Reference by temp ID
629
+
630
+ const [createdAddress, createdUser] = await jsonSdk
631
+ .atomicFactory()
632
+ .postOne(address)
633
+ .postOne(user)
634
+ .run();
635
+
636
+ // Server assigns real IDs
637
+ console.log(createdAddress.id); // Real ID (e.g., 1)
638
+ console.log(createdUser.addresses.id); // Same real ID
639
+ ```
640
+
641
+ ---
642
+
643
+ ## 💡 Examples
644
+
645
+ For comprehensive real-world examples, see the [E2E test suite](https://github.com/klerick/nestjs-json-api/tree/master/apps/json-api-server-e2e/src/json-api/json-api-sdk):
646
+
647
+ - **[GET Operations](https://github.com/klerick/nestjs-json-api/blob/master/apps/json-api-server-e2e/src/json-api/json-api-sdk/get-method.spec.ts)** - Fetching, filtering, pagination, sparse fieldsets
648
+ - **[POST Operations](https://github.com/klerick/nestjs-json-api/blob/master/apps/json-api-server-e2e/src/json-api/json-api-sdk/post-method.spec.ts)** - Creating resources with relationships
649
+ - **[PATCH Operations](https://github.com/klerick/nestjs-json-api/blob/master/apps/json-api-server-e2e/src/json-api/json-api-sdk/patch-methode.spec.ts)** - Updating resources and relationships
650
+ - **[Atomic Operations](https://github.com/klerick/nestjs-json-api/blob/master/apps/json-api-server-e2e/src/json-api/json-api-sdk/atomic-sdk.spec.ts)** - Batch requests with rollback
651
+ - **[Common Decorators](https://github.com/klerick/nestjs-json-api/blob/master/apps/json-api-server-e2e/src/json-api/json-api-sdk/check-common-decorator.spec.ts)** - Guards, interceptors, custom behavior
652
+
653
+ ---
654
+
655
+ ## 📝 License
656
+
657
+ MIT
658
+
659
+ ---
660
+
661
+ ## 🔗 Related Packages
662
+
663
+ - [@klerick/json-api-nestjs](https://www.npmjs.com/package/@klerick/json-api-nestjs) - JSON:API server implementation for NestJS
664
+ - [@klerick/json-api-nestjs-typeorm](https://www.npmjs.com/package/@klerick/json-api-nestjs-typeorm) - TypeORM adapter
665
+ - [@klerick/json-api-nestjs-microorm](https://www.npmjs.com/package/@klerick/json-api-nestjs-microorm) - MikroORM adapter
@@ -2,4 +2,4 @@ export { FilterOperand, ResourceObject, QueryField, } from '@klerick/json-api-ne
2
2
  export { JsonApiUtilsService, JsonApiSdkService } from './lib/service';
3
3
  export * from './lib/json-api-js';
4
4
  export { adapterForAxios } from './lib/utils';
5
- export { AtomicOperations, Operands, QueryParams } from './lib/types';
5
+ export { AtomicOperations, Operands, QueryParams, JsonConfig, Filter, Includes, Sort, Pagination, Fields } from './lib/types';
package/cjs/src/index.js CHANGED
@@ -1,14 +1,5 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.adapterForAxios = exports.JsonApiSdkService = exports.JsonApiUtilsService = exports.QueryField = exports.FilterOperand = void 0;
4
- const tslib_1 = require("tslib");
5
- var json_api_nestjs_shared_1 = require("@klerick/json-api-nestjs-shared");
6
- Object.defineProperty(exports, "FilterOperand", { enumerable: true, get: function () { return json_api_nestjs_shared_1.FilterOperand; } });
7
- Object.defineProperty(exports, "QueryField", { enumerable: true, get: function () { return json_api_nestjs_shared_1.QueryField; } });
8
- var service_1 = require("./lib/service");
9
- Object.defineProperty(exports, "JsonApiUtilsService", { enumerable: true, get: function () { return service_1.JsonApiUtilsService; } });
10
- Object.defineProperty(exports, "JsonApiSdkService", { enumerable: true, get: function () { return service_1.JsonApiSdkService; } });
11
- tslib_1.__exportStar(require("./lib/json-api-js"), exports);
12
- var utils_1 = require("./lib/utils");
13
- Object.defineProperty(exports, "adapterForAxios", { enumerable: true, get: function () { return utils_1.adapterForAxios; } });
1
+ export { FilterOperand, QueryField, } from '@klerick/json-api-nestjs-shared';
2
+ export { JsonApiUtilsService, JsonApiSdkService } from './lib/service';
3
+ export * from './lib/json-api-js';
4
+ export { adapterForAxios } from './lib/utils';
14
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/json-api/json-api-nestjs-sdk/src/index.ts"],"names":[],"mappings":";;;;AAAA,0EAIyC;AAHvC,uHAAA,aAAa,OAAA;AAEb,oHAAA,UAAU,OAAA;AAGZ,yCAAuE;AAA9D,8GAAA,mBAAmB,OAAA;AAAE,4GAAA,iBAAiB,OAAA;AAC/C,4DAAkC;AAClC,qCAA8C;AAArC,wGAAA,eAAe,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/json-api/json-api-nestjs-sdk/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAEb,UAAU,GACX,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvE,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
@@ -1,5 +1,2 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ID_KEY = void 0;
4
- exports.ID_KEY = 'id';
1
+ export const ID_KEY = 'id';
5
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../libs/json-api/json-api-nestjs-sdk/src/lib/constants/index.ts"],"names":[],"mappings":";;;AAAa,QAAA,MAAM,GAAG,IAAI,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../libs/json-api/json-api-nestjs-sdk/src/lib/constants/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC"}