ng-qubee 3.0.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.
- package/README.md +94 -17
- package/fesm2022/ng-qubee.mjs +944 -565
- package/fesm2022/ng-qubee.mjs.map +1 -1
- package/package.json +1 -1
- package/types/ng-qubee.d.ts +269 -27
package/README.md
CHANGED
|
@@ -15,7 +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
|
+
- **Multi-driver support**: JSON:API, Laravel (pagination-only), Spatie Query Builder, and NestJS (nestjs-paginate)
|
|
19
19
|
|
|
20
20
|
## We love it, we use it ❤️
|
|
21
21
|
NgQubee uses some open source projects to work properly:
|
|
@@ -41,16 +41,46 @@ npm i ng-qubee
|
|
|
41
41
|
|
|
42
42
|
## Drivers
|
|
43
43
|
|
|
44
|
-
NgQubee supports
|
|
44
|
+
NgQubee supports four drivers out of the box. A driver **must** be specified in the configuration:
|
|
45
45
|
|
|
46
46
|
| Driver | Backend | Request Format | Response Format |
|
|
47
47
|
|---|---|---|---|
|
|
48
|
+
| **JSON:API** | Any JSON:API-compliant backend | `filter[field]=value`, `sort=-field`, `page[number]=N&page[size]=N` | Nested: `{ data, meta: {...}, links: {...} }` |
|
|
48
49
|
| **Laravel** | Plain Laravel pagination | `limit=N&page=N` (pagination only) | Flat: `{ data, current_page, total, ... }` |
|
|
49
50
|
| **Spatie** | Spatie Query Builder | `filter[field]=value`, `sort=-field` | Flat: `{ data, current_page, total, ... }` |
|
|
50
51
|
| **NestJS** | nestjs-paginate | `filter.field=$operator:value`, `sortBy=field:DESC` | Nested: `{ data, meta: {...}, links: {...} }` |
|
|
51
52
|
|
|
52
53
|
## Usage
|
|
53
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.):
|
|
58
|
+
|
|
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
|
|
68
|
+
@NgModule({
|
|
69
|
+
imports: [
|
|
70
|
+
NgQubeeModule.forRoot({ driver: DriverEnum.JSON_API })
|
|
71
|
+
]
|
|
72
|
+
})
|
|
73
|
+
export class AppModule {}
|
|
74
|
+
```
|
|
75
|
+
|
|
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
|
+
|
|
54
84
|
### Laravel Driver (pagination-only)
|
|
55
85
|
|
|
56
86
|
The Laravel driver provides basic pagination — limit and page parameters only. No filters, sorts, fields, or includes are supported.
|
|
@@ -166,7 +196,7 @@ this._ngQubeeService.setResource('users');
|
|
|
166
196
|
This is necessary to build the prefix of the URI (/users)
|
|
167
197
|
|
|
168
198
|
|
|
169
|
-
### Fields (Spatie
|
|
199
|
+
### Fields (JSON:API + Spatie)
|
|
170
200
|
Fields can be selected as following:
|
|
171
201
|
|
|
172
202
|
```typescript
|
|
@@ -184,7 +214,7 @@ this._ngQubeeService.addSelect('id', 'name', 'email');
|
|
|
184
214
|
|
|
185
215
|
Will output _/users?select=id,name,email_
|
|
186
216
|
|
|
187
|
-
### Filters (Spatie + NestJS)
|
|
217
|
+
### Filters (JSON:API + Spatie + NestJS)
|
|
188
218
|
Filters are applied as following:
|
|
189
219
|
|
|
190
220
|
```typescript
|
|
@@ -234,7 +264,7 @@ this._ngQubeeService.addFilterOperator('name', FilterOperatorEnum.ILIKE, 'john')
|
|
|
234
264
|
|
|
235
265
|
**Available operators:** `$eq`, `$not`, `$null`, `$in`, `$gt`, `$gte`, `$lt`, `$lte`, `$btw`, `$ilike`, `$sw`, `$contains`
|
|
236
266
|
|
|
237
|
-
### Includes (Spatie
|
|
267
|
+
### Includes (JSON:API + Spatie)
|
|
238
268
|
Ask to include related models with:
|
|
239
269
|
|
|
240
270
|
```typescript
|
|
@@ -252,7 +282,7 @@ this._ngQubeeService.setSearch('john doe');
|
|
|
252
282
|
|
|
253
283
|
Will output _/users?search=john doe_
|
|
254
284
|
|
|
255
|
-
### Sort (Spatie + NestJS)
|
|
285
|
+
### Sort (JSON:API + Spatie + NestJS)
|
|
256
286
|
Sort elements as following:
|
|
257
287
|
|
|
258
288
|
```typescript
|
|
@@ -285,6 +315,28 @@ Default values are automatically added to the query:
|
|
|
285
315
|
|
|
286
316
|
Always expect your query to include _limit=15&page=1_
|
|
287
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
|
+
|
|
288
340
|
### Retrieving data
|
|
289
341
|
URI is generated invoking the _generateUri_ method of the NgQubeeService. An observable is returned and the URI will be emitted:
|
|
290
342
|
|
|
@@ -297,11 +349,11 @@ this._ngQubeeService.generateUri().subscribe(uri => console.log(uri));
|
|
|
297
349
|
All query features have corresponding delete methods:
|
|
298
350
|
|
|
299
351
|
```typescript
|
|
300
|
-
// Spatie + NestJS
|
|
352
|
+
// JSON:API + Spatie + NestJS
|
|
301
353
|
this._ngQubeeService.deleteFilters('status', 'role');
|
|
302
354
|
this._ngQubeeService.deleteSorts('created_at');
|
|
303
355
|
|
|
304
|
-
// Spatie only
|
|
356
|
+
// JSON:API + Spatie only
|
|
305
357
|
this._ngQubeeService.deleteFields({ users: ['email'] });
|
|
306
358
|
this._ngQubeeService.deleteFieldsByModel('users', 'email');
|
|
307
359
|
this._ngQubeeService.deleteIncludes('profile');
|
|
@@ -323,15 +375,15 @@ this._ngQubeeService.reset();
|
|
|
323
375
|
|
|
324
376
|
Calling a method that is not supported by the active driver throws a descriptive error immediately:
|
|
325
377
|
|
|
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 |
|
|
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 |
|
|
335
387
|
|
|
336
388
|
## Pagination
|
|
337
389
|
If you are working with an API that supports pagination, we have got you covered 😉 NgQubee provides:
|
|
@@ -368,6 +420,30 @@ When using the Laravel or Spatie driver, the paginated collection will check for
|
|
|
368
420
|
- first_page_url - URL to the first page
|
|
369
421
|
- last_page_url - URL to the last page
|
|
370
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
|
+
|
|
371
447
|
### NestJS Response Format
|
|
372
448
|
|
|
373
449
|
When using the NestJS driver, the PaginationService automatically parses nested responses:
|
|
@@ -426,6 +502,7 @@ NgQubee is fully typed and exports all public interfaces, enums, and types for T
|
|
|
426
502
|
import { DriverEnum, FilterOperatorEnum, SortEnum } from 'ng-qubee';
|
|
427
503
|
|
|
428
504
|
// Driver options
|
|
505
|
+
DriverEnum.JSON_API // 'json-api'
|
|
429
506
|
DriverEnum.LARAVEL // 'laravel' (pagination only)
|
|
430
507
|
DriverEnum.SPATIE // 'spatie'
|
|
431
508
|
DriverEnum.NESTJS // 'nestjs'
|