ng-qubee 2.1.0 → 3.1.0

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 (32) hide show
  1. package/README.md +378 -54
  2. package/fesm2022/ng-qubee.mjs +1791 -419
  3. package/fesm2022/ng-qubee.mjs.map +1 -1
  4. package/package.json +4 -4
  5. package/types/ng-qubee.d.ts +1544 -0
  6. package/index.d.ts +0 -5
  7. package/lib/enums/sort.enum.d.ts +0 -4
  8. package/lib/errors/invalid-limit.error.d.ts +0 -3
  9. package/lib/errors/invalid-model-name.error.d.ts +0 -3
  10. package/lib/errors/invalid-page-number.error.d.ts +0 -3
  11. package/lib/errors/key-not-found.error.d.ts +0 -3
  12. package/lib/errors/unselectable-model.error.d.ts +0 -3
  13. package/lib/interfaces/config.interface.d.ts +0 -6
  14. package/lib/interfaces/fields.interface.d.ts +0 -3
  15. package/lib/interfaces/filters.interface.d.ts +0 -3
  16. package/lib/interfaces/nest-state.interface.d.ts +0 -4
  17. package/lib/interfaces/normalized.interface.d.ts +0 -3
  18. package/lib/interfaces/page.interface.d.ts +0 -2
  19. package/lib/interfaces/paginated-object.interface.d.ts +0 -3
  20. package/lib/interfaces/pagination-config.interface.d.ts +0 -14
  21. package/lib/interfaces/query-builder-config.interface.d.ts +0 -9
  22. package/lib/interfaces/query-builder-state.interface.d.ts +0 -13
  23. package/lib/interfaces/sort.interface.d.ts +0 -5
  24. package/lib/models/paginated-collection.d.ts +0 -30
  25. package/lib/models/query-builder-options.d.ts +0 -11
  26. package/lib/models/response-options.d.ts +0 -16
  27. package/lib/ng-qubee.module.d.ts +0 -9
  28. package/lib/provide-ngqubee.d.ts +0 -21
  29. package/lib/services/nest.service.d.ts +0 -182
  30. package/lib/services/ng-qubee.service.d.ts +0 -147
  31. package/lib/services/pagination.service.d.ts +0 -13
  32. package/public-api.d.ts +0 -20
package/README.md CHANGED
@@ -15,6 +15,7 @@ NgQubee is a Query Builder for Angular. Easily compose your API requests without
15
15
  - Pagination ready
16
16
  - Reactive, as the results are emitted with a RxJS Observable
17
17
  - Developed with a test-driven approach
18
+ - **Multi-driver support**: JSON:API, Laravel (pagination-only), Spatie Query Builder, and NestJS (nestjs-paginate)
18
19
 
19
20
  ## We love it, we use it ❤️
20
21
  NgQubee uses some open source projects to work properly:
@@ -38,25 +39,88 @@ Install NgQubee via NPM
38
39
  npm i ng-qubee
39
40
  ```
40
41
 
42
+ ## Drivers
43
+
44
+ NgQubee supports four drivers out of the box. A driver **must** be specified in the configuration:
45
+
46
+ | Driver | Backend | Request Format | Response Format |
47
+ |---|---|---|---|
48
+ | **JSON:API** | Any JSON:API-compliant backend | `filter[field]=value`, `sort=-field`, `page[number]=N&page[size]=N` | Nested: `{ data, meta: {...}, links: {...} }` |
49
+ | **Laravel** | Plain Laravel pagination | `limit=N&page=N` (pagination only) | Flat: `{ data, current_page, total, ... }` |
50
+ | **Spatie** | Spatie Query Builder | `filter[field]=value`, `sort=-field` | Flat: `{ data, current_page, total, ... }` |
51
+ | **NestJS** | nestjs-paginate | `filter.field=$operator:value`, `sortBy=field:DESC` | Nested: `{ data, meta: {...}, links: {...} }` |
52
+
41
53
  ## Usage
42
- Import the module in your Angular app:
54
+
55
+ ### JSON:API Driver
56
+
57
+ The JSON:API driver generates URIs compatible with any [JSON:API](https://jsonapi.org/format/)-compliant backend (Rails, Django, .NET, Java, Elixir, etc.):
43
58
 
44
59
  ```typescript
60
+ import { DriverEnum } from 'ng-qubee';
61
+
62
+ // Standalone approach
63
+ bootstrapApplication(AppComponent, {
64
+ providers: [provideNgQubee({ driver: DriverEnum.JSON_API })]
65
+ });
66
+
67
+ // Module approach
45
68
  @NgModule({
46
69
  imports: [
47
- NgQubeeModule.forRoot({}) // You can omit the empty object as it is an optional argument
70
+ NgQubeeModule.forRoot({ driver: DriverEnum.JSON_API })
48
71
  ]
49
72
  })
50
- export class AppModule {}
73
+ export class AppModule {}
51
74
  ```
52
75
 
53
- Or if you are working with Angular 15 or greater, use the provide function:
76
+ The JSON:API driver supports:
77
+
78
+ - **Filters** are composed as `filter[field]=value`
79
+ - **Fields** are composed as `fields[type]=col1,col2`
80
+ - **Includes** are composed as `include=author,comments.author`
81
+ - **Sort** is composed as `sort=-created_at,name` (`-` prefix = DESC)
82
+ - **Pagination** uses bracket notation: `page[number]=1&page[size]=15`
83
+
84
+ ### Laravel Driver (pagination-only)
85
+
86
+ The Laravel driver provides basic pagination — limit and page parameters only. No filters, sorts, fields, or includes are supported.
87
+
54
88
  ```typescript
55
- const config = {};
89
+ import { DriverEnum } from 'ng-qubee';
56
90
 
91
+ // Standalone approach
57
92
  bootstrapApplication(AppComponent, {
58
- providers: [provideNgQubee(config)]
93
+ providers: [provideNgQubee({ driver: DriverEnum.LARAVEL })]
59
94
  });
95
+
96
+ // Module approach
97
+ @NgModule({
98
+ imports: [
99
+ NgQubeeModule.forRoot({ driver: DriverEnum.LARAVEL })
100
+ ]
101
+ })
102
+ export class AppModule {}
103
+ ```
104
+
105
+ ### Spatie Driver
106
+
107
+ The Spatie driver generates URIs compatible with [Spatie Laravel Query Builder](https://spatie.be/docs/laravel-query-builder):
108
+
109
+ ```typescript
110
+ import { DriverEnum } from 'ng-qubee';
111
+
112
+ // Standalone approach
113
+ bootstrapApplication(AppComponent, {
114
+ providers: [provideNgQubee({ driver: DriverEnum.SPATIE })]
115
+ });
116
+
117
+ // Module approach
118
+ @NgModule({
119
+ imports: [
120
+ NgQubeeModule.forRoot({ driver: DriverEnum.SPATIE })
121
+ ]
122
+ })
123
+ export class AppModule {}
60
124
  ```
61
125
 
62
126
  The object given to the _forRoot_ method allows to customize the query param keys. Following, the default behaviour:
@@ -72,6 +136,7 @@ As you can easily imagine, everything that regards the URI composition is placed
72
136
 
73
137
  ```typescript
74
138
  NgQubeeModule.forRoot({
139
+ driver: DriverEnum.SPATIE,
75
140
  request: {
76
141
  filters: 'custom-filter-key',
77
142
  fields: 'custom-fields-key',
@@ -80,6 +145,39 @@ NgQubeeModule.forRoot({
80
145
  })
81
146
  ```
82
147
 
148
+ ### NestJS Driver
149
+
150
+ To use the NestJS driver, specify the driver in your configuration:
151
+
152
+ ```typescript
153
+ import { DriverEnum } from 'ng-qubee';
154
+
155
+ // Standalone approach
156
+ bootstrapApplication(AppComponent, {
157
+ providers: [provideNgQubee({ driver: DriverEnum.NESTJS })]
158
+ });
159
+
160
+ // Module approach
161
+ @NgModule({
162
+ imports: [
163
+ NgQubeeModule.forRoot({ driver: DriverEnum.NESTJS })
164
+ ]
165
+ })
166
+ export class AppModule {}
167
+ ```
168
+
169
+ The NestJS driver generates URIs compatible with [nestjs-paginate](https://github.com/ppetzold/nestjs-paginate):
170
+
171
+ - **Filters** are composed as `filter.field=value`
172
+ - **Filter operators** are composed as `filter.field=$operator:value`
173
+ - **Sorts** are composed as `sortBy=field:ASC,field2:DESC`
174
+ - **Select** is composed as `select=col1,col2`
175
+ - **Search** is composed as `search=term`
176
+ - **Limit** is composed as `limit=15`
177
+ - **Page** is composed as `page=1`
178
+
179
+ ## Query Builder API
180
+
83
181
  For composing queries, the first step is to inject the proper NgQubeeService:
84
182
 
85
183
  ```typescript
@@ -89,16 +187,16 @@ export class YourService {
89
187
  }
90
188
  ```
91
189
 
92
- Set the **model** to run the query against:
190
+ Set the **resource** to run the query against:
93
191
 
94
192
  ```typescript
95
- this._ngQubeeService.setModel('users');
193
+ this._ngQubeeService.setResource('users');
96
194
  ```
97
195
 
98
196
  This is necessary to build the prefix of the URI (/users)
99
197
 
100
198
 
101
- ### Fields
199
+ ### Fields (JSON:API + Spatie)
102
200
  Fields can be selected as following:
103
201
 
104
202
  ```typescript
@@ -107,14 +205,25 @@ this._ngQubeeService.addFields('users', ['id', 'email']);
107
205
 
108
206
  Will output _/users?fields[users]=id,email_
109
207
 
110
- ### Filters
208
+ ### Select (NestJS only)
209
+ Flat field selection for the NestJS driver:
210
+
211
+ ```typescript
212
+ this._ngQubeeService.addSelect('id', 'name', 'email');
213
+ ```
214
+
215
+ Will output _/users?select=id,name,email_
216
+
217
+ ### Filters (JSON:API + Spatie + NestJS)
111
218
  Filters are applied as following:
112
219
 
113
220
  ```typescript
114
221
  this._ngQubeeService.addFilter('id', 5);
115
222
  ```
116
223
 
117
- Will output _/users?filter[id]=5_
224
+ Will output:
225
+ - Spatie: _/users?filter[id]=5_
226
+ - NestJS: _/users?filter.id=5_
118
227
 
119
228
  Multiple values are allowed too:
120
229
 
@@ -122,11 +231,40 @@ Multiple values are allowed too:
122
231
  this._ngQubeeService.addFilter('id', 5, 7, 10);
123
232
  ```
124
233
 
125
- Will output _/users?filter[id]=5,7,10_
234
+ Will output:
235
+ - Spatie: _/users?filter[id]=5,7,10_
236
+ - NestJS: _/users?filter.id=5,7,10_
126
237
 
127
-
238
+ ### Filter Operators (NestJS only)
239
+ The NestJS driver supports explicit filter operators:
128
240
 
129
- ### Includes
241
+ ```typescript
242
+ import { FilterOperatorEnum } from 'ng-qubee';
243
+
244
+ // Equality
245
+ this._ngQubeeService.addFilterOperator('status', FilterOperatorEnum.EQ, 'active');
246
+ // Output: filter.status=$eq:active
247
+
248
+ // Greater than or equal
249
+ this._ngQubeeService.addFilterOperator('age', FilterOperatorEnum.GTE, 18);
250
+ // Output: filter.age=$gte:18
251
+
252
+ // In (multiple values)
253
+ this._ngQubeeService.addFilterOperator('id', FilterOperatorEnum.IN, 1, 2, 3);
254
+ // Output: filter.id=$in:1,2,3
255
+
256
+ // Between
257
+ this._ngQubeeService.addFilterOperator('price', FilterOperatorEnum.BTW, 10, 100);
258
+ // Output: filter.price=$btw:10,100
259
+
260
+ // Case-insensitive like
261
+ this._ngQubeeService.addFilterOperator('name', FilterOperatorEnum.ILIKE, 'john');
262
+ // Output: filter.name=$ilike:john
263
+ ```
264
+
265
+ **Available operators:** `$eq`, `$not`, `$null`, `$in`, `$gt`, `$gte`, `$lt`, `$lte`, `$btw`, `$ilike`, `$sw`, `$contains`
266
+
267
+ ### Includes (JSON:API + Spatie)
130
268
  Ask to include related models with:
131
269
 
132
270
  ```typescript
@@ -135,7 +273,16 @@ this._ngQubeeService.addIncludes('profile', 'settings');
135
273
 
136
274
  Will output _/users?include=profile,settings_
137
275
 
138
- ### Sort
276
+ ### Search (NestJS only)
277
+ Full-text search for the NestJS driver:
278
+
279
+ ```typescript
280
+ this._ngQubeeService.setSearch('john doe');
281
+ ```
282
+
283
+ Will output _/users?search=john doe_
284
+
285
+ ### Sort (JSON:API + Spatie + NestJS)
139
286
  Sort elements as following:
140
287
 
141
288
  ```typescript
@@ -144,7 +291,9 @@ import { SortEnum } from 'ng-qubee';
144
291
  this._ngQubeeService.addSort('fieldName', SortEnum.ASC);
145
292
  ```
146
293
 
147
- Will output _/users?sort=fieldName_ (or _/users?sort=-fieldName_ if DESC)
294
+ Will output:
295
+ - Spatie: _/users?sort=fieldName_ (or _/users?sort=-fieldName_ if DESC)
296
+ - NestJS: _/users?sortBy=fieldName:ASC_ (or _/users?sortBy=fieldName:DESC_ if DESC)
148
297
 
149
298
  The `SortEnum` provides two ordering options:
150
299
  - `SortEnum.ASC` - Ascending order
@@ -166,6 +315,28 @@ Default values are automatically added to the query:
166
315
 
167
316
  Always expect your query to include _limit=15&page=1_
168
317
 
318
+ #### Fetch all (NestJS only)
319
+
320
+ When the active driver is NestJS, `setLimit(-1)` is accepted as a "fetch all items" sentinel, following the [nestjs-paginate](https://github.com/ppetzold/nestjs-paginate) convention (the server must opt in via `maxLimit: -1`):
321
+
322
+ ```typescript
323
+ // NestJS driver only
324
+ this._ngQubeeService.setLimit(-1);
325
+ ```
326
+
327
+ JSON:API, Laravel, and Spatie drivers reject `-1` and throw `InvalidLimitError`.
328
+
329
+ #### Limit validation
330
+
331
+ Limit validation is driver-scoped — each request strategy enforces its own accepted range and invalid values throw `InvalidLimitError` immediately when passed to `setLimit()`:
332
+
333
+ | Driver | Accepted limit values |
334
+ |---|---|
335
+ | NestJS | integer `-1` (fetch all) or `>= 1` |
336
+ | JSON:API / Laravel / Spatie | integer `>= 1` |
337
+
338
+ Non-integer values, zero, negative numbers (other than `-1` for NestJS), `NaN`, and `Infinity` are all rejected.
339
+
169
340
  ### Retrieving data
170
341
  URI is generated invoking the _generateUri_ method of the NgQubeeService. An observable is returned and the URI will be emitted:
171
342
 
@@ -173,13 +344,47 @@ URI is generated invoking the _generateUri_ method of the NgQubeeService. An obs
173
344
  this._ngQubeeService.generateUri().subscribe(uri => console.log(uri));
174
345
  ```
175
346
 
347
+ ### Deleting State
348
+
349
+ All query features have corresponding delete methods:
350
+
351
+ ```typescript
352
+ // JSON:API + Spatie + NestJS
353
+ this._ngQubeeService.deleteFilters('status', 'role');
354
+ this._ngQubeeService.deleteSorts('created_at');
355
+
356
+ // JSON:API + Spatie only
357
+ this._ngQubeeService.deleteFields({ users: ['email'] });
358
+ this._ngQubeeService.deleteFieldsByModel('users', 'email');
359
+ this._ngQubeeService.deleteIncludes('profile');
360
+
361
+ // NestJS only
362
+ this._ngQubeeService.deleteOperatorFilters('age');
363
+ this._ngQubeeService.deleteSelect('email');
364
+ this._ngQubeeService.deleteSearch();
365
+ ```
366
+
176
367
  ### Reset state
177
- Query Builder state can be cleaned with the reset method. This will clean up everything set up previously, including the current model, filters, includes and so on...
368
+ Query Builder state can be cleaned with the reset method. This will clean up everything set up previously, including the current resource, filters, includes and so on...
178
369
 
179
370
  ```typescript
180
371
  this._ngQubeeService.reset();
181
372
  ```
182
373
 
374
+ ### Driver Validation
375
+
376
+ Calling a method that is not supported by the active driver throws a descriptive error immediately:
377
+
378
+ | Method | JSON:API | Laravel | Spatie | NestJS |
379
+ |---|---|---|---|---|
380
+ | `addFilter()` / `deleteFilters()` | supported | throws `UnsupportedFilterError` | supported | supported |
381
+ | `addSort()` / `deleteSorts()` | supported | throws `UnsupportedSortError` | supported | supported |
382
+ | `addFields()` / `deleteFields()` / `deleteFieldsByModel()` | supported | throws `UnsupportedFieldSelectionError` | supported | throws `UnsupportedFieldSelectionError` |
383
+ | `addIncludes()` / `deleteIncludes()` | supported | throws `UnsupportedIncludesError` | supported | throws `UnsupportedIncludesError` |
384
+ | `addFilterOperator()` / `deleteOperatorFilters()` | throws `UnsupportedFilterOperatorError` | throws `UnsupportedFilterOperatorError` | throws `UnsupportedFilterOperatorError` | supported |
385
+ | `addSelect()` / `deleteSelect()` | throws `UnsupportedSelectError` | throws `UnsupportedSelectError` | throws `UnsupportedSelectError` | supported |
386
+ | `setSearch()` / `deleteSearch()` | throws `UnsupportedSearchError` | throws `UnsupportedSearchError` | throws `UnsupportedSearchError` | supported |
387
+
183
388
  ## Pagination
184
389
  If you are working with an API that supports pagination, we have got you covered 😉 NgQubee provides:
185
390
  - A PaginatedCollection class that holds paginated data
@@ -199,31 +404,93 @@ this._pg.paginate<Model>({ ...response, data: response.data.map(e => new Mo
199
404
 
200
405
  The "paginate" method returns a PaginatedCollection that helps handling paginated data. Additionally, if you are dealing with a state library in your application, you can use the "normalize" method of the collection to normalize the data.
201
406
 
202
- As you can see from the example, the paginate method requires a generic type: put there your model and you'll be provided with a PaginatedCollection<Model>. By default, the paginated collection will check for the following keys in the response:
407
+ ### Laravel / Spatie Response Format
408
+
409
+ When using the Laravel or Spatie driver, the paginated collection will check for the following keys in the response:
203
410
 
204
411
  - data - the key that holds the response data
205
- - currentPage - requested page for the pagination
206
- - from - Showing items from n (where n is a number)
207
- - to - Showing items from n (where n is a number)
208
- - total - Count of the items available in thw whole pagination
209
- - perPage - Items per page
210
- - prevPageUrl - Url to the previous page
211
- - nextPageUrl - Url to the next page
212
- - lastPage - Last page number
213
- - firstPageUrl - Url to the first page
214
- - lastPageUrl - Url to the last page
215
-
216
- Just like the query builder, the pagination service supports customizable keys. While invoking the forRoot method of the module, use the response key to look for different keys in the API response. Let's assume that the "currentPage" key is named "pg" in your API responseL your forRoot configuration will look as following:
412
+ - current_page - requested page for the pagination
413
+ - from - Showing items from n
414
+ - to - Showing items to n
415
+ - total - Count of the items available in the whole pagination
416
+ - per_page - Items per page
417
+ - prev_page_url - URL to the previous page
418
+ - next_page_url - URL to the next page
419
+ - last_page - Last page number
420
+ - first_page_url - URL to the first page
421
+ - last_page_url - URL to the last page
422
+
423
+ ### JSON:API Response Format
424
+
425
+ When using the JSON:API driver, the PaginationService automatically parses nested responses:
426
+
427
+ ```json
428
+ {
429
+ "data": [...],
430
+ "meta": {
431
+ "current-page": 1,
432
+ "per-page": 10,
433
+ "total": 100,
434
+ "page-count": 10
435
+ },
436
+ "links": {
437
+ "first": "http://api.com/articles?page[number]=1&page[size]=10",
438
+ "prev": null,
439
+ "next": "http://api.com/articles?page[number]=2&page[size]=10",
440
+ "last": "http://api.com/articles?page[number]=10&page[size]=10"
441
+ }
442
+ }
443
+ ```
444
+
445
+ The `from` and `to` values are computed automatically from `current-page` and `per-page` when not present in the response. JSON:API meta key names vary by implementation; defaults can be fully customised via response configuration.
446
+
447
+ ### NestJS Response Format
448
+
449
+ When using the NestJS driver, the PaginationService automatically parses nested responses:
450
+
451
+ ```json
452
+ {
453
+ "data": [...],
454
+ "meta": {
455
+ "currentPage": 1,
456
+ "totalItems": 100,
457
+ "itemsPerPage": 10,
458
+ "totalPages": 10
459
+ },
460
+ "links": {
461
+ "first": "http://api.com/users?page=1",
462
+ "previous": null,
463
+ "next": "http://api.com/users?page=2",
464
+ "last": "http://api.com/users?page=10",
465
+ "current": "http://api.com/users?page=1"
466
+ }
467
+ }
468
+ ```
469
+
470
+ The `from` and `to` values are computed automatically from `currentPage` and `itemsPerPage` when not present in the response.
471
+
472
+ ### Customizing Response Keys
473
+
474
+ Just like the query builder, the pagination service supports customizable keys. While invoking the forRoot method of the module, use the response key to look for different keys in the API response:
217
475
 
218
476
  ```typescript
477
+ // Spatie
219
478
  NgQubeeModule.forRoot({
479
+ driver: DriverEnum.SPATIE,
220
480
  response: {
221
481
  currentPage: 'pg'
222
482
  }
223
483
  })
224
- ```
225
484
 
226
- Feel free to customize your PaginationService as you need, using the keys shown in the upper list.
485
+ // NestJS (use dot-notation for nested paths)
486
+ NgQubeeModule.forRoot({
487
+ driver: DriverEnum.NESTJS,
488
+ response: {
489
+ currentPage: 'pagination.page',
490
+ total: 'pagination.total'
491
+ }
492
+ })
493
+ ```
227
494
 
228
495
  ## TypeScript Support
229
496
 
@@ -232,11 +499,31 @@ NgQubee is fully typed and exports all public interfaces, enums, and types for T
232
499
  ### Available Enums
233
500
 
234
501
  ```typescript
235
- import { SortEnum } from 'ng-qubee';
502
+ import { DriverEnum, FilterOperatorEnum, SortEnum } from 'ng-qubee';
503
+
504
+ // Driver options
505
+ DriverEnum.JSON_API // 'json-api'
506
+ DriverEnum.LARAVEL // 'laravel' (pagination only)
507
+ DriverEnum.SPATIE // 'spatie'
508
+ DriverEnum.NESTJS // 'nestjs'
236
509
 
237
510
  // Sorting options
238
511
  SortEnum.ASC // 'asc'
239
512
  SortEnum.DESC // 'desc'
513
+
514
+ // Filter operators (NestJS only)
515
+ FilterOperatorEnum.EQ // '$eq'
516
+ FilterOperatorEnum.NOT // '$not'
517
+ FilterOperatorEnum.NULL // '$null'
518
+ FilterOperatorEnum.IN // '$in'
519
+ FilterOperatorEnum.GT // '$gt'
520
+ FilterOperatorEnum.GTE // '$gte'
521
+ FilterOperatorEnum.LT // '$lt'
522
+ FilterOperatorEnum.LTE // '$lte'
523
+ FilterOperatorEnum.BTW // '$btw'
524
+ FilterOperatorEnum.ILIKE // '$ilike'
525
+ FilterOperatorEnum.SW // '$sw'
526
+ FilterOperatorEnum.CONTAINS // '$contains'
240
527
  ```
241
528
 
242
529
  ### Available Interfaces
@@ -252,8 +539,9 @@ import {
252
539
  IPaginationConfig
253
540
  } from 'ng-qubee';
254
541
 
255
- // Main configuration interface
542
+ // Main configuration interface (driver is required)
256
543
  const config: IConfig = {
544
+ driver: DriverEnum.NESTJS,
257
545
  request: {
258
546
  filters: 'custom-filter-key',
259
547
  fields: 'custom-fields-key',
@@ -277,7 +565,8 @@ const config: IConfig = {
277
565
  import {
278
566
  IFilters,
279
567
  IFields,
280
- ISort
568
+ ISort,
569
+ IOperatorFilter
281
570
  } from 'ng-qubee';
282
571
 
283
572
  // Filters interface - key-value pairs with array values
@@ -297,30 +586,25 @@ const sort: ISort = {
297
586
  field: 'created_at',
298
587
  order: SortEnum.DESC
299
588
  };
589
+
590
+ // Operator filter interface (NestJS only)
591
+ const operatorFilter: IOperatorFilter = {
592
+ field: 'age',
593
+ operator: FilterOperatorEnum.GTE,
594
+ values: [18]
595
+ };
300
596
  ```
301
597
 
302
- #### Pagination Interfaces
598
+ #### Strategy Interfaces
303
599
 
304
600
  ```typescript
305
- import { IPaginatedObject } from 'ng-qubee';
306
-
307
- // Use with your model type
308
- interface User {
309
- id: number;
310
- email: string;
311
- username: string;
312
- }
313
-
314
- // The paginated object can contain any additional keys
315
- const paginatedData: IPaginatedObject = {
316
- data: [/* users */],
317
- currentPage: 1,
318
- total: 100,
319
- perPage: 15
320
- };
601
+ import {
602
+ IRequestStrategy,
603
+ IResponseStrategy
604
+ } from 'ng-qubee';
321
605
  ```
322
606
 
323
- ### Usage Example with Full Types
607
+ ### Spatie Usage Example
324
608
 
325
609
  ```typescript
326
610
  import { Component, OnInit } from '@angular/core';
@@ -340,7 +624,7 @@ export class UsersComponent implements OnInit {
340
624
 
341
625
  ngOnInit(): void {
342
626
  // Set up the query with type safety
343
- this.ngQubee.setModel('users');
627
+ this.ngQubee.setResource('users');
344
628
 
345
629
  // Define fields with type checking
346
630
  const userFields: IFields = {
@@ -368,6 +652,46 @@ export class UsersComponent implements OnInit {
368
652
  }
369
653
  ```
370
654
 
655
+ ### NestJS Usage Example
656
+
657
+ ```typescript
658
+ import { Component, OnInit } from '@angular/core';
659
+ import {
660
+ NgQubeeService,
661
+ PaginationService,
662
+ FilterOperatorEnum,
663
+ SortEnum
664
+ } from 'ng-qubee';
665
+
666
+ @Component({
667
+ selector: 'app-users',
668
+ template: '...'
669
+ })
670
+ export class UsersComponent implements OnInit {
671
+ constructor(
672
+ private ngQubee: NgQubeeService,
673
+ private pagination: PaginationService
674
+ ) {}
675
+
676
+ ngOnInit(): void {
677
+ this.ngQubee
678
+ .setResource('users')
679
+ .addFilterOperator('age', FilterOperatorEnum.GTE, 18)
680
+ .addFilter('status', 'active')
681
+ .addSelect('id', 'name', 'email')
682
+ .addSort('name', SortEnum.ASC)
683
+ .setSearch('john')
684
+ .setLimit(10)
685
+ .setPage(1);
686
+
687
+ this.ngQubee.generateUri().subscribe(uri => {
688
+ console.log(uri);
689
+ // Output: /users?filter.status=active&filter.age=$gte:18&sortBy=name:ASC&select=id,name,email&search=john&limit=10&page=1
690
+ });
691
+ }
692
+ }
693
+ ```
694
+
371
695
  [ng-qubee]: <https://github.com/AndreaAlhena/ng-qubee>
372
696
  [rxjs]: <https://reactivex.io>
373
697
  [qs]: <https://github.com/ljharb/qs>