ng-qubee 2.1.0 → 3.0.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.
- package/README.md +301 -54
- package/fesm2022/ng-qubee.mjs +1257 -264
- package/fesm2022/ng-qubee.mjs.map +1 -1
- package/package.json +4 -4
- package/types/ng-qubee.d.ts +1302 -0
- package/index.d.ts +0 -5
- package/lib/enums/sort.enum.d.ts +0 -4
- package/lib/errors/invalid-limit.error.d.ts +0 -3
- package/lib/errors/invalid-model-name.error.d.ts +0 -3
- package/lib/errors/invalid-page-number.error.d.ts +0 -3
- package/lib/errors/key-not-found.error.d.ts +0 -3
- package/lib/errors/unselectable-model.error.d.ts +0 -3
- package/lib/interfaces/config.interface.d.ts +0 -6
- package/lib/interfaces/fields.interface.d.ts +0 -3
- package/lib/interfaces/filters.interface.d.ts +0 -3
- package/lib/interfaces/nest-state.interface.d.ts +0 -4
- package/lib/interfaces/normalized.interface.d.ts +0 -3
- package/lib/interfaces/page.interface.d.ts +0 -2
- package/lib/interfaces/paginated-object.interface.d.ts +0 -3
- package/lib/interfaces/pagination-config.interface.d.ts +0 -14
- package/lib/interfaces/query-builder-config.interface.d.ts +0 -9
- package/lib/interfaces/query-builder-state.interface.d.ts +0 -13
- package/lib/interfaces/sort.interface.d.ts +0 -5
- package/lib/models/paginated-collection.d.ts +0 -30
- package/lib/models/query-builder-options.d.ts +0 -11
- package/lib/models/response-options.d.ts +0 -16
- package/lib/ng-qubee.module.d.ts +0 -9
- package/lib/provide-ngqubee.d.ts +0 -21
- package/lib/services/nest.service.d.ts +0 -182
- package/lib/services/ng-qubee.service.d.ts +0 -147
- package/lib/services/pagination.service.d.ts +0 -13
- 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**: 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,58 @@ Install NgQubee via NPM
|
|
|
38
39
|
npm i ng-qubee
|
|
39
40
|
```
|
|
40
41
|
|
|
42
|
+
## Drivers
|
|
43
|
+
|
|
44
|
+
NgQubee supports three drivers out of the box. A driver **must** be specified in the configuration:
|
|
45
|
+
|
|
46
|
+
| Driver | Backend | Request Format | Response Format |
|
|
47
|
+
|---|---|---|---|
|
|
48
|
+
| **Laravel** | Plain Laravel pagination | `limit=N&page=N` (pagination only) | Flat: `{ data, current_page, total, ... }` |
|
|
49
|
+
| **Spatie** | Spatie Query Builder | `filter[field]=value`, `sort=-field` | Flat: `{ data, current_page, total, ... }` |
|
|
50
|
+
| **NestJS** | nestjs-paginate | `filter.field=$operator:value`, `sortBy=field:DESC` | Nested: `{ data, meta: {...}, links: {...} }` |
|
|
51
|
+
|
|
41
52
|
## Usage
|
|
42
|
-
|
|
53
|
+
|
|
54
|
+
### Laravel Driver (pagination-only)
|
|
55
|
+
|
|
56
|
+
The Laravel driver provides basic pagination — limit and page parameters only. No filters, sorts, fields, or includes are supported.
|
|
43
57
|
|
|
44
58
|
```typescript
|
|
59
|
+
import { DriverEnum } from 'ng-qubee';
|
|
60
|
+
|
|
61
|
+
// Standalone approach
|
|
62
|
+
bootstrapApplication(AppComponent, {
|
|
63
|
+
providers: [provideNgQubee({ driver: DriverEnum.LARAVEL })]
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Module approach
|
|
45
67
|
@NgModule({
|
|
46
68
|
imports: [
|
|
47
|
-
NgQubeeModule.forRoot({
|
|
69
|
+
NgQubeeModule.forRoot({ driver: DriverEnum.LARAVEL })
|
|
48
70
|
]
|
|
49
71
|
})
|
|
50
|
-
export class AppModule
|
|
72
|
+
export class AppModule {}
|
|
51
73
|
```
|
|
52
74
|
|
|
53
|
-
|
|
75
|
+
### Spatie Driver
|
|
76
|
+
|
|
77
|
+
The Spatie driver generates URIs compatible with [Spatie Laravel Query Builder](https://spatie.be/docs/laravel-query-builder):
|
|
78
|
+
|
|
54
79
|
```typescript
|
|
55
|
-
|
|
80
|
+
import { DriverEnum } from 'ng-qubee';
|
|
56
81
|
|
|
82
|
+
// Standalone approach
|
|
57
83
|
bootstrapApplication(AppComponent, {
|
|
58
|
-
providers: [provideNgQubee(
|
|
84
|
+
providers: [provideNgQubee({ driver: DriverEnum.SPATIE })]
|
|
59
85
|
});
|
|
86
|
+
|
|
87
|
+
// Module approach
|
|
88
|
+
@NgModule({
|
|
89
|
+
imports: [
|
|
90
|
+
NgQubeeModule.forRoot({ driver: DriverEnum.SPATIE })
|
|
91
|
+
]
|
|
92
|
+
})
|
|
93
|
+
export class AppModule {}
|
|
60
94
|
```
|
|
61
95
|
|
|
62
96
|
The object given to the _forRoot_ method allows to customize the query param keys. Following, the default behaviour:
|
|
@@ -72,6 +106,7 @@ As you can easily imagine, everything that regards the URI composition is placed
|
|
|
72
106
|
|
|
73
107
|
```typescript
|
|
74
108
|
NgQubeeModule.forRoot({
|
|
109
|
+
driver: DriverEnum.SPATIE,
|
|
75
110
|
request: {
|
|
76
111
|
filters: 'custom-filter-key',
|
|
77
112
|
fields: 'custom-fields-key',
|
|
@@ -80,6 +115,39 @@ NgQubeeModule.forRoot({
|
|
|
80
115
|
})
|
|
81
116
|
```
|
|
82
117
|
|
|
118
|
+
### NestJS Driver
|
|
119
|
+
|
|
120
|
+
To use the NestJS driver, specify the driver in your configuration:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import { DriverEnum } from 'ng-qubee';
|
|
124
|
+
|
|
125
|
+
// Standalone approach
|
|
126
|
+
bootstrapApplication(AppComponent, {
|
|
127
|
+
providers: [provideNgQubee({ driver: DriverEnum.NESTJS })]
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Module approach
|
|
131
|
+
@NgModule({
|
|
132
|
+
imports: [
|
|
133
|
+
NgQubeeModule.forRoot({ driver: DriverEnum.NESTJS })
|
|
134
|
+
]
|
|
135
|
+
})
|
|
136
|
+
export class AppModule {}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The NestJS driver generates URIs compatible with [nestjs-paginate](https://github.com/ppetzold/nestjs-paginate):
|
|
140
|
+
|
|
141
|
+
- **Filters** are composed as `filter.field=value`
|
|
142
|
+
- **Filter operators** are composed as `filter.field=$operator:value`
|
|
143
|
+
- **Sorts** are composed as `sortBy=field:ASC,field2:DESC`
|
|
144
|
+
- **Select** is composed as `select=col1,col2`
|
|
145
|
+
- **Search** is composed as `search=term`
|
|
146
|
+
- **Limit** is composed as `limit=15`
|
|
147
|
+
- **Page** is composed as `page=1`
|
|
148
|
+
|
|
149
|
+
## Query Builder API
|
|
150
|
+
|
|
83
151
|
For composing queries, the first step is to inject the proper NgQubeeService:
|
|
84
152
|
|
|
85
153
|
```typescript
|
|
@@ -89,16 +157,16 @@ export class YourService {
|
|
|
89
157
|
}
|
|
90
158
|
```
|
|
91
159
|
|
|
92
|
-
Set the **
|
|
160
|
+
Set the **resource** to run the query against:
|
|
93
161
|
|
|
94
162
|
```typescript
|
|
95
|
-
this._ngQubeeService.
|
|
163
|
+
this._ngQubeeService.setResource('users');
|
|
96
164
|
```
|
|
97
165
|
|
|
98
166
|
This is necessary to build the prefix of the URI (/users)
|
|
99
167
|
|
|
100
168
|
|
|
101
|
-
### Fields
|
|
169
|
+
### Fields (Spatie only)
|
|
102
170
|
Fields can be selected as following:
|
|
103
171
|
|
|
104
172
|
```typescript
|
|
@@ -107,14 +175,25 @@ this._ngQubeeService.addFields('users', ['id', 'email']);
|
|
|
107
175
|
|
|
108
176
|
Will output _/users?fields[users]=id,email_
|
|
109
177
|
|
|
110
|
-
###
|
|
178
|
+
### Select (NestJS only)
|
|
179
|
+
Flat field selection for the NestJS driver:
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
this._ngQubeeService.addSelect('id', 'name', 'email');
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Will output _/users?select=id,name,email_
|
|
186
|
+
|
|
187
|
+
### Filters (Spatie + NestJS)
|
|
111
188
|
Filters are applied as following:
|
|
112
189
|
|
|
113
190
|
```typescript
|
|
114
191
|
this._ngQubeeService.addFilter('id', 5);
|
|
115
192
|
```
|
|
116
193
|
|
|
117
|
-
Will output
|
|
194
|
+
Will output:
|
|
195
|
+
- Spatie: _/users?filter[id]=5_
|
|
196
|
+
- NestJS: _/users?filter.id=5_
|
|
118
197
|
|
|
119
198
|
Multiple values are allowed too:
|
|
120
199
|
|
|
@@ -122,11 +201,40 @@ Multiple values are allowed too:
|
|
|
122
201
|
this._ngQubeeService.addFilter('id', 5, 7, 10);
|
|
123
202
|
```
|
|
124
203
|
|
|
125
|
-
Will output
|
|
204
|
+
Will output:
|
|
205
|
+
- Spatie: _/users?filter[id]=5,7,10_
|
|
206
|
+
- NestJS: _/users?filter.id=5,7,10_
|
|
207
|
+
|
|
208
|
+
### Filter Operators (NestJS only)
|
|
209
|
+
The NestJS driver supports explicit filter operators:
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
import { FilterOperatorEnum } from 'ng-qubee';
|
|
213
|
+
|
|
214
|
+
// Equality
|
|
215
|
+
this._ngQubeeService.addFilterOperator('status', FilterOperatorEnum.EQ, 'active');
|
|
216
|
+
// Output: filter.status=$eq:active
|
|
217
|
+
|
|
218
|
+
// Greater than or equal
|
|
219
|
+
this._ngQubeeService.addFilterOperator('age', FilterOperatorEnum.GTE, 18);
|
|
220
|
+
// Output: filter.age=$gte:18
|
|
126
221
|
|
|
127
|
-
|
|
222
|
+
// In (multiple values)
|
|
223
|
+
this._ngQubeeService.addFilterOperator('id', FilterOperatorEnum.IN, 1, 2, 3);
|
|
224
|
+
// Output: filter.id=$in:1,2,3
|
|
128
225
|
|
|
129
|
-
|
|
226
|
+
// Between
|
|
227
|
+
this._ngQubeeService.addFilterOperator('price', FilterOperatorEnum.BTW, 10, 100);
|
|
228
|
+
// Output: filter.price=$btw:10,100
|
|
229
|
+
|
|
230
|
+
// Case-insensitive like
|
|
231
|
+
this._ngQubeeService.addFilterOperator('name', FilterOperatorEnum.ILIKE, 'john');
|
|
232
|
+
// Output: filter.name=$ilike:john
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**Available operators:** `$eq`, `$not`, `$null`, `$in`, `$gt`, `$gte`, `$lt`, `$lte`, `$btw`, `$ilike`, `$sw`, `$contains`
|
|
236
|
+
|
|
237
|
+
### Includes (Spatie only)
|
|
130
238
|
Ask to include related models with:
|
|
131
239
|
|
|
132
240
|
```typescript
|
|
@@ -135,7 +243,16 @@ this._ngQubeeService.addIncludes('profile', 'settings');
|
|
|
135
243
|
|
|
136
244
|
Will output _/users?include=profile,settings_
|
|
137
245
|
|
|
138
|
-
###
|
|
246
|
+
### Search (NestJS only)
|
|
247
|
+
Full-text search for the NestJS driver:
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
this._ngQubeeService.setSearch('john doe');
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Will output _/users?search=john doe_
|
|
254
|
+
|
|
255
|
+
### Sort (Spatie + NestJS)
|
|
139
256
|
Sort elements as following:
|
|
140
257
|
|
|
141
258
|
```typescript
|
|
@@ -144,7 +261,9 @@ import { SortEnum } from 'ng-qubee';
|
|
|
144
261
|
this._ngQubeeService.addSort('fieldName', SortEnum.ASC);
|
|
145
262
|
```
|
|
146
263
|
|
|
147
|
-
Will output
|
|
264
|
+
Will output:
|
|
265
|
+
- Spatie: _/users?sort=fieldName_ (or _/users?sort=-fieldName_ if DESC)
|
|
266
|
+
- NestJS: _/users?sortBy=fieldName:ASC_ (or _/users?sortBy=fieldName:DESC_ if DESC)
|
|
148
267
|
|
|
149
268
|
The `SortEnum` provides two ordering options:
|
|
150
269
|
- `SortEnum.ASC` - Ascending order
|
|
@@ -173,13 +292,47 @@ URI is generated invoking the _generateUri_ method of the NgQubeeService. An obs
|
|
|
173
292
|
this._ngQubeeService.generateUri().subscribe(uri => console.log(uri));
|
|
174
293
|
```
|
|
175
294
|
|
|
295
|
+
### Deleting State
|
|
296
|
+
|
|
297
|
+
All query features have corresponding delete methods:
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
// Spatie + NestJS
|
|
301
|
+
this._ngQubeeService.deleteFilters('status', 'role');
|
|
302
|
+
this._ngQubeeService.deleteSorts('created_at');
|
|
303
|
+
|
|
304
|
+
// Spatie only
|
|
305
|
+
this._ngQubeeService.deleteFields({ users: ['email'] });
|
|
306
|
+
this._ngQubeeService.deleteFieldsByModel('users', 'email');
|
|
307
|
+
this._ngQubeeService.deleteIncludes('profile');
|
|
308
|
+
|
|
309
|
+
// NestJS only
|
|
310
|
+
this._ngQubeeService.deleteOperatorFilters('age');
|
|
311
|
+
this._ngQubeeService.deleteSelect('email');
|
|
312
|
+
this._ngQubeeService.deleteSearch();
|
|
313
|
+
```
|
|
314
|
+
|
|
176
315
|
### Reset state
|
|
177
|
-
Query Builder state can be cleaned with the reset method. This will clean up everything set up previously, including the current
|
|
316
|
+
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
317
|
|
|
179
318
|
```typescript
|
|
180
319
|
this._ngQubeeService.reset();
|
|
181
320
|
```
|
|
182
321
|
|
|
322
|
+
### Driver Validation
|
|
323
|
+
|
|
324
|
+
Calling a method that is not supported by the active driver throws a descriptive error immediately:
|
|
325
|
+
|
|
326
|
+
| Method | Laravel | Spatie | NestJS |
|
|
327
|
+
|---|---|---|---|
|
|
328
|
+
| `addFilter()` / `deleteFilters()` | throws `UnsupportedFilterError` | supported | supported |
|
|
329
|
+
| `addSort()` / `deleteSorts()` | throws `UnsupportedSortError` | supported | supported |
|
|
330
|
+
| `addFields()` / `deleteFields()` / `deleteFieldsByModel()` | throws `UnsupportedFieldSelectionError` | supported | throws `UnsupportedFieldSelectionError` |
|
|
331
|
+
| `addIncludes()` / `deleteIncludes()` | throws `UnsupportedIncludesError` | supported | throws `UnsupportedIncludesError` |
|
|
332
|
+
| `addFilterOperator()` / `deleteOperatorFilters()` | throws `UnsupportedFilterOperatorError` | throws `UnsupportedFilterOperatorError` | supported |
|
|
333
|
+
| `addSelect()` / `deleteSelect()` | throws `UnsupportedSelectError` | throws `UnsupportedSelectError` | supported |
|
|
334
|
+
| `setSearch()` / `deleteSearch()` | throws `UnsupportedSearchError` | throws `UnsupportedSearchError` | supported |
|
|
335
|
+
|
|
183
336
|
## Pagination
|
|
184
337
|
If you are working with an API that supports pagination, we have got you covered 😉 NgQubee provides:
|
|
185
338
|
- A PaginatedCollection class that holds paginated data
|
|
@@ -199,31 +352,69 @@ this._pg.paginate<Model>({ ...response, data: response.data.map(e => new Mo
|
|
|
199
352
|
|
|
200
353
|
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
354
|
|
|
202
|
-
|
|
355
|
+
### Laravel / Spatie Response Format
|
|
356
|
+
|
|
357
|
+
When using the Laravel or Spatie driver, the paginated collection will check for the following keys in the response:
|
|
203
358
|
|
|
204
359
|
- data - the key that holds the response data
|
|
205
|
-
-
|
|
206
|
-
- from - Showing items from n
|
|
207
|
-
- to - Showing items
|
|
208
|
-
- total - Count of the items available in
|
|
209
|
-
-
|
|
210
|
-
-
|
|
211
|
-
-
|
|
212
|
-
-
|
|
213
|
-
-
|
|
214
|
-
-
|
|
215
|
-
|
|
216
|
-
|
|
360
|
+
- current_page - requested page for the pagination
|
|
361
|
+
- from - Showing items from n
|
|
362
|
+
- to - Showing items to n
|
|
363
|
+
- total - Count of the items available in the whole pagination
|
|
364
|
+
- per_page - Items per page
|
|
365
|
+
- prev_page_url - URL to the previous page
|
|
366
|
+
- next_page_url - URL to the next page
|
|
367
|
+
- last_page - Last page number
|
|
368
|
+
- first_page_url - URL to the first page
|
|
369
|
+
- last_page_url - URL to the last page
|
|
370
|
+
|
|
371
|
+
### NestJS Response Format
|
|
372
|
+
|
|
373
|
+
When using the NestJS driver, the PaginationService automatically parses nested responses:
|
|
374
|
+
|
|
375
|
+
```json
|
|
376
|
+
{
|
|
377
|
+
"data": [...],
|
|
378
|
+
"meta": {
|
|
379
|
+
"currentPage": 1,
|
|
380
|
+
"totalItems": 100,
|
|
381
|
+
"itemsPerPage": 10,
|
|
382
|
+
"totalPages": 10
|
|
383
|
+
},
|
|
384
|
+
"links": {
|
|
385
|
+
"first": "http://api.com/users?page=1",
|
|
386
|
+
"previous": null,
|
|
387
|
+
"next": "http://api.com/users?page=2",
|
|
388
|
+
"last": "http://api.com/users?page=10",
|
|
389
|
+
"current": "http://api.com/users?page=1"
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
The `from` and `to` values are computed automatically from `currentPage` and `itemsPerPage` when not present in the response.
|
|
395
|
+
|
|
396
|
+
### Customizing Response Keys
|
|
397
|
+
|
|
398
|
+
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
399
|
|
|
218
400
|
```typescript
|
|
401
|
+
// Spatie
|
|
219
402
|
NgQubeeModule.forRoot({
|
|
403
|
+
driver: DriverEnum.SPATIE,
|
|
220
404
|
response: {
|
|
221
405
|
currentPage: 'pg'
|
|
222
406
|
}
|
|
223
407
|
})
|
|
224
|
-
```
|
|
225
408
|
|
|
226
|
-
|
|
409
|
+
// NestJS (use dot-notation for nested paths)
|
|
410
|
+
NgQubeeModule.forRoot({
|
|
411
|
+
driver: DriverEnum.NESTJS,
|
|
412
|
+
response: {
|
|
413
|
+
currentPage: 'pagination.page',
|
|
414
|
+
total: 'pagination.total'
|
|
415
|
+
}
|
|
416
|
+
})
|
|
417
|
+
```
|
|
227
418
|
|
|
228
419
|
## TypeScript Support
|
|
229
420
|
|
|
@@ -232,11 +423,30 @@ NgQubee is fully typed and exports all public interfaces, enums, and types for T
|
|
|
232
423
|
### Available Enums
|
|
233
424
|
|
|
234
425
|
```typescript
|
|
235
|
-
import { SortEnum } from 'ng-qubee';
|
|
426
|
+
import { DriverEnum, FilterOperatorEnum, SortEnum } from 'ng-qubee';
|
|
427
|
+
|
|
428
|
+
// Driver options
|
|
429
|
+
DriverEnum.LARAVEL // 'laravel' (pagination only)
|
|
430
|
+
DriverEnum.SPATIE // 'spatie'
|
|
431
|
+
DriverEnum.NESTJS // 'nestjs'
|
|
236
432
|
|
|
237
433
|
// Sorting options
|
|
238
434
|
SortEnum.ASC // 'asc'
|
|
239
435
|
SortEnum.DESC // 'desc'
|
|
436
|
+
|
|
437
|
+
// Filter operators (NestJS only)
|
|
438
|
+
FilterOperatorEnum.EQ // '$eq'
|
|
439
|
+
FilterOperatorEnum.NOT // '$not'
|
|
440
|
+
FilterOperatorEnum.NULL // '$null'
|
|
441
|
+
FilterOperatorEnum.IN // '$in'
|
|
442
|
+
FilterOperatorEnum.GT // '$gt'
|
|
443
|
+
FilterOperatorEnum.GTE // '$gte'
|
|
444
|
+
FilterOperatorEnum.LT // '$lt'
|
|
445
|
+
FilterOperatorEnum.LTE // '$lte'
|
|
446
|
+
FilterOperatorEnum.BTW // '$btw'
|
|
447
|
+
FilterOperatorEnum.ILIKE // '$ilike'
|
|
448
|
+
FilterOperatorEnum.SW // '$sw'
|
|
449
|
+
FilterOperatorEnum.CONTAINS // '$contains'
|
|
240
450
|
```
|
|
241
451
|
|
|
242
452
|
### Available Interfaces
|
|
@@ -252,8 +462,9 @@ import {
|
|
|
252
462
|
IPaginationConfig
|
|
253
463
|
} from 'ng-qubee';
|
|
254
464
|
|
|
255
|
-
// Main configuration interface
|
|
465
|
+
// Main configuration interface (driver is required)
|
|
256
466
|
const config: IConfig = {
|
|
467
|
+
driver: DriverEnum.NESTJS,
|
|
257
468
|
request: {
|
|
258
469
|
filters: 'custom-filter-key',
|
|
259
470
|
fields: 'custom-fields-key',
|
|
@@ -277,7 +488,8 @@ const config: IConfig = {
|
|
|
277
488
|
import {
|
|
278
489
|
IFilters,
|
|
279
490
|
IFields,
|
|
280
|
-
ISort
|
|
491
|
+
ISort,
|
|
492
|
+
IOperatorFilter
|
|
281
493
|
} from 'ng-qubee';
|
|
282
494
|
|
|
283
495
|
// Filters interface - key-value pairs with array values
|
|
@@ -297,30 +509,25 @@ const sort: ISort = {
|
|
|
297
509
|
field: 'created_at',
|
|
298
510
|
order: SortEnum.DESC
|
|
299
511
|
};
|
|
512
|
+
|
|
513
|
+
// Operator filter interface (NestJS only)
|
|
514
|
+
const operatorFilter: IOperatorFilter = {
|
|
515
|
+
field: 'age',
|
|
516
|
+
operator: FilterOperatorEnum.GTE,
|
|
517
|
+
values: [18]
|
|
518
|
+
};
|
|
300
519
|
```
|
|
301
520
|
|
|
302
|
-
####
|
|
521
|
+
#### Strategy Interfaces
|
|
303
522
|
|
|
304
523
|
```typescript
|
|
305
|
-
import {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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
|
-
};
|
|
524
|
+
import {
|
|
525
|
+
IRequestStrategy,
|
|
526
|
+
IResponseStrategy
|
|
527
|
+
} from 'ng-qubee';
|
|
321
528
|
```
|
|
322
529
|
|
|
323
|
-
### Usage Example
|
|
530
|
+
### Spatie Usage Example
|
|
324
531
|
|
|
325
532
|
```typescript
|
|
326
533
|
import { Component, OnInit } from '@angular/core';
|
|
@@ -340,7 +547,7 @@ export class UsersComponent implements OnInit {
|
|
|
340
547
|
|
|
341
548
|
ngOnInit(): void {
|
|
342
549
|
// Set up the query with type safety
|
|
343
|
-
this.ngQubee.
|
|
550
|
+
this.ngQubee.setResource('users');
|
|
344
551
|
|
|
345
552
|
// Define fields with type checking
|
|
346
553
|
const userFields: IFields = {
|
|
@@ -368,6 +575,46 @@ export class UsersComponent implements OnInit {
|
|
|
368
575
|
}
|
|
369
576
|
```
|
|
370
577
|
|
|
578
|
+
### NestJS Usage Example
|
|
579
|
+
|
|
580
|
+
```typescript
|
|
581
|
+
import { Component, OnInit } from '@angular/core';
|
|
582
|
+
import {
|
|
583
|
+
NgQubeeService,
|
|
584
|
+
PaginationService,
|
|
585
|
+
FilterOperatorEnum,
|
|
586
|
+
SortEnum
|
|
587
|
+
} from 'ng-qubee';
|
|
588
|
+
|
|
589
|
+
@Component({
|
|
590
|
+
selector: 'app-users',
|
|
591
|
+
template: '...'
|
|
592
|
+
})
|
|
593
|
+
export class UsersComponent implements OnInit {
|
|
594
|
+
constructor(
|
|
595
|
+
private ngQubee: NgQubeeService,
|
|
596
|
+
private pagination: PaginationService
|
|
597
|
+
) {}
|
|
598
|
+
|
|
599
|
+
ngOnInit(): void {
|
|
600
|
+
this.ngQubee
|
|
601
|
+
.setResource('users')
|
|
602
|
+
.addFilterOperator('age', FilterOperatorEnum.GTE, 18)
|
|
603
|
+
.addFilter('status', 'active')
|
|
604
|
+
.addSelect('id', 'name', 'email')
|
|
605
|
+
.addSort('name', SortEnum.ASC)
|
|
606
|
+
.setSearch('john')
|
|
607
|
+
.setLimit(10)
|
|
608
|
+
.setPage(1);
|
|
609
|
+
|
|
610
|
+
this.ngQubee.generateUri().subscribe(uri => {
|
|
611
|
+
console.log(uri);
|
|
612
|
+
// Output: /users?filter.status=active&filter.age=$gte:18&sortBy=name:ASC&select=id,name,email&search=john&limit=10&page=1
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
```
|
|
617
|
+
|
|
371
618
|
[ng-qubee]: <https://github.com/AndreaAlhena/ng-qubee>
|
|
372
619
|
[rxjs]: <https://reactivex.io>
|
|
373
620
|
[qs]: <https://github.com/ljharb/qs>
|