ng-qubee 2.0.5 → 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 +432 -30
- package/fesm2022/ng-qubee.mjs +1264 -261
- package/fesm2022/ng-qubee.mjs.map +1 -1
- package/package.json +9 -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/normalized.interface.d.ts +0 -3
- 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 -10
package/README.md
CHANGED
|
@@ -3,12 +3,19 @@
|
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
# Your next Angular Query Builder 🐝
|
|
6
|
+
|
|
7
|
+
[](https://github.com/AndreaAlhena/ng-qubee/actions)
|
|
8
|
+
[](https://codecov.io/gh/AndreaAlhena/ng-qubee)
|
|
9
|
+
[](https://www.npmjs.com/package/ng-qubee)
|
|
10
|
+
[](https://opensource.org/licenses/MIT)
|
|
11
|
+
|
|
6
12
|
NgQubee is a Query Builder for Angular. Easily compose your API requests without the hassle of writing the wheel again :)
|
|
7
13
|
|
|
8
14
|
- Easily retrieve URIs with a Service
|
|
9
15
|
- Pagination ready
|
|
10
16
|
- Reactive, as the results are emitted with a RxJS Observable
|
|
11
17
|
- Developed with a test-driven approach
|
|
18
|
+
- **Multi-driver support**: Laravel (pagination-only), Spatie Query Builder, and NestJS (nestjs-paginate)
|
|
12
19
|
|
|
13
20
|
## We love it, we use it ❤️
|
|
14
21
|
NgQubee uses some open source projects to work properly:
|
|
@@ -32,25 +39,58 @@ Install NgQubee via NPM
|
|
|
32
39
|
npm i ng-qubee
|
|
33
40
|
```
|
|
34
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
|
+
|
|
35
52
|
## Usage
|
|
36
|
-
|
|
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.
|
|
37
57
|
|
|
38
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
|
|
39
67
|
@NgModule({
|
|
40
68
|
imports: [
|
|
41
|
-
NgQubeeModule.forRoot({
|
|
69
|
+
NgQubeeModule.forRoot({ driver: DriverEnum.LARAVEL })
|
|
42
70
|
]
|
|
43
71
|
})
|
|
44
|
-
export class AppModule
|
|
72
|
+
export class AppModule {}
|
|
45
73
|
```
|
|
46
74
|
|
|
47
|
-
|
|
75
|
+
### Spatie Driver
|
|
76
|
+
|
|
77
|
+
The Spatie driver generates URIs compatible with [Spatie Laravel Query Builder](https://spatie.be/docs/laravel-query-builder):
|
|
78
|
+
|
|
48
79
|
```typescript
|
|
49
|
-
|
|
80
|
+
import { DriverEnum } from 'ng-qubee';
|
|
50
81
|
|
|
82
|
+
// Standalone approach
|
|
51
83
|
bootstrapApplication(AppComponent, {
|
|
52
|
-
providers: [provideNgQubee(
|
|
84
|
+
providers: [provideNgQubee({ driver: DriverEnum.SPATIE })]
|
|
53
85
|
});
|
|
86
|
+
|
|
87
|
+
// Module approach
|
|
88
|
+
@NgModule({
|
|
89
|
+
imports: [
|
|
90
|
+
NgQubeeModule.forRoot({ driver: DriverEnum.SPATIE })
|
|
91
|
+
]
|
|
92
|
+
})
|
|
93
|
+
export class AppModule {}
|
|
54
94
|
```
|
|
55
95
|
|
|
56
96
|
The object given to the _forRoot_ method allows to customize the query param keys. Following, the default behaviour:
|
|
@@ -66,6 +106,7 @@ As you can easily imagine, everything that regards the URI composition is placed
|
|
|
66
106
|
|
|
67
107
|
```typescript
|
|
68
108
|
NgQubeeModule.forRoot({
|
|
109
|
+
driver: DriverEnum.SPATIE,
|
|
69
110
|
request: {
|
|
70
111
|
filters: 'custom-filter-key',
|
|
71
112
|
fields: 'custom-fields-key',
|
|
@@ -74,6 +115,39 @@ NgQubeeModule.forRoot({
|
|
|
74
115
|
})
|
|
75
116
|
```
|
|
76
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
|
+
|
|
77
151
|
For composing queries, the first step is to inject the proper NgQubeeService:
|
|
78
152
|
|
|
79
153
|
```typescript
|
|
@@ -83,16 +157,16 @@ export class YourService {
|
|
|
83
157
|
}
|
|
84
158
|
```
|
|
85
159
|
|
|
86
|
-
Set the **
|
|
160
|
+
Set the **resource** to run the query against:
|
|
87
161
|
|
|
88
162
|
```typescript
|
|
89
|
-
this._ngQubeeService.
|
|
163
|
+
this._ngQubeeService.setResource('users');
|
|
90
164
|
```
|
|
91
165
|
|
|
92
166
|
This is necessary to build the prefix of the URI (/users)
|
|
93
167
|
|
|
94
168
|
|
|
95
|
-
### Fields
|
|
169
|
+
### Fields (Spatie only)
|
|
96
170
|
Fields can be selected as following:
|
|
97
171
|
|
|
98
172
|
```typescript
|
|
@@ -101,14 +175,25 @@ this._ngQubeeService.addFields('users', ['id', 'email']);
|
|
|
101
175
|
|
|
102
176
|
Will output _/users?fields[users]=id,email_
|
|
103
177
|
|
|
104
|
-
###
|
|
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)
|
|
105
188
|
Filters are applied as following:
|
|
106
189
|
|
|
107
190
|
```typescript
|
|
108
191
|
this._ngQubeeService.addFilter('id', 5);
|
|
109
192
|
```
|
|
110
193
|
|
|
111
|
-
Will output
|
|
194
|
+
Will output:
|
|
195
|
+
- Spatie: _/users?filter[id]=5_
|
|
196
|
+
- NestJS: _/users?filter.id=5_
|
|
112
197
|
|
|
113
198
|
Multiple values are allowed too:
|
|
114
199
|
|
|
@@ -116,11 +201,40 @@ Multiple values are allowed too:
|
|
|
116
201
|
this._ngQubeeService.addFilter('id', 5, 7, 10);
|
|
117
202
|
```
|
|
118
203
|
|
|
119
|
-
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
|
|
120
221
|
|
|
121
|
-
|
|
222
|
+
// In (multiple values)
|
|
223
|
+
this._ngQubeeService.addFilterOperator('id', FilterOperatorEnum.IN, 1, 2, 3);
|
|
224
|
+
// Output: filter.id=$in:1,2,3
|
|
122
225
|
|
|
123
|
-
|
|
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)
|
|
124
238
|
Ask to include related models with:
|
|
125
239
|
|
|
126
240
|
```typescript
|
|
@@ -129,14 +243,31 @@ this._ngQubeeService.addIncludes('profile', 'settings');
|
|
|
129
243
|
|
|
130
244
|
Will output _/users?include=profile,settings_
|
|
131
245
|
|
|
132
|
-
###
|
|
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)
|
|
133
256
|
Sort elements as following:
|
|
134
257
|
|
|
135
258
|
```typescript
|
|
259
|
+
import { SortEnum } from 'ng-qubee';
|
|
260
|
+
|
|
136
261
|
this._ngQubeeService.addSort('fieldName', SortEnum.ASC);
|
|
137
262
|
```
|
|
138
263
|
|
|
139
|
-
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)
|
|
267
|
+
|
|
268
|
+
The `SortEnum` provides two ordering options:
|
|
269
|
+
- `SortEnum.ASC` - Ascending order
|
|
270
|
+
- `SortEnum.DESC` - Descending order
|
|
140
271
|
|
|
141
272
|
### Page and Limit
|
|
142
273
|
NgQubee supports paginated queries:
|
|
@@ -161,13 +292,47 @@ URI is generated invoking the _generateUri_ method of the NgQubeeService. An obs
|
|
|
161
292
|
this._ngQubeeService.generateUri().subscribe(uri => console.log(uri));
|
|
162
293
|
```
|
|
163
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
|
+
|
|
164
315
|
### Reset state
|
|
165
|
-
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...
|
|
166
317
|
|
|
167
318
|
```typescript
|
|
168
319
|
this._ngQubeeService.reset();
|
|
169
320
|
```
|
|
170
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
|
+
|
|
171
336
|
## Pagination
|
|
172
337
|
If you are working with an API that supports pagination, we have got you covered 😉 NgQubee provides:
|
|
173
338
|
- A PaginatedCollection class that holds paginated data
|
|
@@ -187,31 +352,268 @@ this._pg.paginate<Model>({ ...response, data: response.data.map(e => new Mo
|
|
|
187
352
|
|
|
188
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.
|
|
189
354
|
|
|
190
|
-
|
|
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:
|
|
191
358
|
|
|
192
359
|
- data - the key that holds the response data
|
|
193
|
-
-
|
|
194
|
-
- from - Showing items from n
|
|
195
|
-
- to - Showing items
|
|
196
|
-
- total - Count of the items available in
|
|
197
|
-
-
|
|
198
|
-
-
|
|
199
|
-
-
|
|
200
|
-
-
|
|
201
|
-
-
|
|
202
|
-
-
|
|
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
|
+
```
|
|
203
393
|
|
|
204
|
-
|
|
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:
|
|
205
399
|
|
|
206
400
|
```typescript
|
|
401
|
+
// Spatie
|
|
207
402
|
NgQubeeModule.forRoot({
|
|
403
|
+
driver: DriverEnum.SPATIE,
|
|
208
404
|
response: {
|
|
209
405
|
currentPage: 'pg'
|
|
210
406
|
}
|
|
211
407
|
})
|
|
408
|
+
|
|
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
|
+
```
|
|
418
|
+
|
|
419
|
+
## TypeScript Support
|
|
420
|
+
|
|
421
|
+
NgQubee is fully typed and exports all public interfaces, enums, and types for TypeScript users.
|
|
422
|
+
|
|
423
|
+
### Available Enums
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
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'
|
|
432
|
+
|
|
433
|
+
// Sorting options
|
|
434
|
+
SortEnum.ASC // 'asc'
|
|
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'
|
|
212
450
|
```
|
|
213
451
|
|
|
214
|
-
|
|
452
|
+
### Available Interfaces
|
|
453
|
+
|
|
454
|
+
NgQubee exports the following interfaces for type-safe development:
|
|
455
|
+
|
|
456
|
+
#### Configuration Interfaces
|
|
457
|
+
|
|
458
|
+
```typescript
|
|
459
|
+
import {
|
|
460
|
+
IConfig,
|
|
461
|
+
IQueryBuilderConfig,
|
|
462
|
+
IPaginationConfig
|
|
463
|
+
} from 'ng-qubee';
|
|
464
|
+
|
|
465
|
+
// Main configuration interface (driver is required)
|
|
466
|
+
const config: IConfig = {
|
|
467
|
+
driver: DriverEnum.NESTJS,
|
|
468
|
+
request: {
|
|
469
|
+
filters: 'custom-filter-key',
|
|
470
|
+
fields: 'custom-fields-key',
|
|
471
|
+
includes: 'custom-include-key',
|
|
472
|
+
limit: 'custom-limit-key',
|
|
473
|
+
page: 'custom-page-key',
|
|
474
|
+
sort: 'custom-sort-key'
|
|
475
|
+
},
|
|
476
|
+
response: {
|
|
477
|
+
currentPage: 'pg',
|
|
478
|
+
data: 'items',
|
|
479
|
+
total: 'count',
|
|
480
|
+
perPage: 'itemsPerPage'
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
#### Query Building Interfaces
|
|
486
|
+
|
|
487
|
+
```typescript
|
|
488
|
+
import {
|
|
489
|
+
IFilters,
|
|
490
|
+
IFields,
|
|
491
|
+
ISort,
|
|
492
|
+
IOperatorFilter
|
|
493
|
+
} from 'ng-qubee';
|
|
494
|
+
|
|
495
|
+
// Filters interface - key-value pairs with array values
|
|
496
|
+
const filters: IFilters = {
|
|
497
|
+
id: [1, 2, 3],
|
|
498
|
+
status: ['active', 'pending']
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
// Fields interface - model name with array of field names
|
|
502
|
+
const fields: IFields = {
|
|
503
|
+
users: ['id', 'email', 'username'],
|
|
504
|
+
profile: ['avatar', 'bio']
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
// Sort interface - field and order
|
|
508
|
+
const sort: ISort = {
|
|
509
|
+
field: 'created_at',
|
|
510
|
+
order: SortEnum.DESC
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
// Operator filter interface (NestJS only)
|
|
514
|
+
const operatorFilter: IOperatorFilter = {
|
|
515
|
+
field: 'age',
|
|
516
|
+
operator: FilterOperatorEnum.GTE,
|
|
517
|
+
values: [18]
|
|
518
|
+
};
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
#### Strategy Interfaces
|
|
522
|
+
|
|
523
|
+
```typescript
|
|
524
|
+
import {
|
|
525
|
+
IRequestStrategy,
|
|
526
|
+
IResponseStrategy
|
|
527
|
+
} from 'ng-qubee';
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### Spatie Usage Example
|
|
531
|
+
|
|
532
|
+
```typescript
|
|
533
|
+
import { Component, OnInit } from '@angular/core';
|
|
534
|
+
import {
|
|
535
|
+
NgQubeeService,
|
|
536
|
+
SortEnum,
|
|
537
|
+
IFilters,
|
|
538
|
+
IFields
|
|
539
|
+
} from 'ng-qubee';
|
|
540
|
+
|
|
541
|
+
@Component({
|
|
542
|
+
selector: 'app-users',
|
|
543
|
+
template: '...'
|
|
544
|
+
})
|
|
545
|
+
export class UsersComponent implements OnInit {
|
|
546
|
+
constructor(private ngQubee: NgQubeeService) {}
|
|
547
|
+
|
|
548
|
+
ngOnInit(): void {
|
|
549
|
+
// Set up the query with type safety
|
|
550
|
+
this.ngQubee.setResource('users');
|
|
551
|
+
|
|
552
|
+
// Define fields with type checking
|
|
553
|
+
const userFields: IFields = {
|
|
554
|
+
users: ['id', 'email', 'username']
|
|
555
|
+
};
|
|
556
|
+
this.ngQubee.addFields('users', userFields.users);
|
|
557
|
+
|
|
558
|
+
// Define filters with type checking
|
|
559
|
+
const filters: IFilters = {
|
|
560
|
+
status: ['active'],
|
|
561
|
+
role: ['admin', 'moderator']
|
|
562
|
+
};
|
|
563
|
+
this.ngQubee.addFilter('status', ...filters.status);
|
|
564
|
+
this.ngQubee.addFilter('role', ...filters.role);
|
|
565
|
+
|
|
566
|
+
// Add sorting with enum
|
|
567
|
+
this.ngQubee.addSort('created_at', SortEnum.DESC);
|
|
568
|
+
|
|
569
|
+
// Generate URI
|
|
570
|
+
this.ngQubee.generateUri().subscribe(uri => {
|
|
571
|
+
console.log(uri);
|
|
572
|
+
// Output: /users?fields[users]=id,email,username&filter[status]=active&filter[role]=admin,moderator&sort=-created_at&limit=15&page=1
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
```
|
|
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
|
+
```
|
|
215
617
|
|
|
216
618
|
[ng-qubee]: <https://github.com/AndreaAlhena/ng-qubee>
|
|
217
619
|
[rxjs]: <https://reactivex.io>
|