ng-qubee 3.1.0 → 3.3.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 +225 -1
- package/fesm2022/ng-qubee.mjs +2180 -1579
- package/fesm2022/ng-qubee.mjs.map +1 -1
- package/package.json +4 -3
- package/types/ng-qubee.d.ts +835 -265
package/types/ng-qubee.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { ModuleWithProviders, EnvironmentProviders, Signal } from '@angular/core';
|
|
2
|
+
import { ModuleWithProviders, Provider, EnvironmentProviders, Signal, InjectionToken } from '@angular/core';
|
|
3
3
|
import { Observable } from 'rxjs';
|
|
4
4
|
|
|
5
5
|
interface INormalized {
|
|
@@ -49,9 +49,27 @@ declare enum DriverEnum {
|
|
|
49
49
|
JSON_API = "json-api",
|
|
50
50
|
LARAVEL = "laravel",
|
|
51
51
|
NESTJS = "nestjs",
|
|
52
|
+
POSTGREST = "postgrest",
|
|
52
53
|
SPATIE = "spatie"
|
|
53
54
|
}
|
|
54
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Enum representing the wire-level pagination mechanism
|
|
58
|
+
*
|
|
59
|
+
* `QUERY` (default) — the request strategy emits `limit` and `offset` (or
|
|
60
|
+
* equivalent) query parameters on the URL.
|
|
61
|
+
*
|
|
62
|
+
* `RANGE` — the request strategy omits URL-based pagination and the
|
|
63
|
+
* consumer instead applies HTTP request headers returned by
|
|
64
|
+
* `NgQubeeService.paginationHeaders()`. Currently honoured only by the
|
|
65
|
+
* PostgREST driver, which maps it to `Range-Unit: items` + `Range: 0-9`.
|
|
66
|
+
* Other drivers ignore the setting.
|
|
67
|
+
*/
|
|
68
|
+
declare enum PaginationModeEnum {
|
|
69
|
+
QUERY = "query",
|
|
70
|
+
RANGE = "range"
|
|
71
|
+
}
|
|
72
|
+
|
|
55
73
|
/**
|
|
56
74
|
* Configuration interface for customizing response field key names
|
|
57
75
|
*
|
|
@@ -135,6 +153,12 @@ interface IQueryBuilderConfig {
|
|
|
135
153
|
interface IConfig {
|
|
136
154
|
/** The pagination driver to use */
|
|
137
155
|
driver: DriverEnum;
|
|
156
|
+
/**
|
|
157
|
+
* Wire-level pagination mechanism. Defaults to `PaginationModeEnum.QUERY`
|
|
158
|
+
* when omitted. Currently honoured only by the PostgREST driver; other
|
|
159
|
+
* drivers ignore it.
|
|
160
|
+
*/
|
|
161
|
+
pagination?: PaginationModeEnum;
|
|
138
162
|
/** Custom key names for request query parameters */
|
|
139
163
|
request?: IQueryBuilderConfig;
|
|
140
164
|
/** Custom key names for response field mapping */
|
|
@@ -154,6 +178,23 @@ declare class NgQubeeModule {
|
|
|
154
178
|
static ɵinj: i0.ɵɵInjectorDeclaration<NgQubeeModule>;
|
|
155
179
|
}
|
|
156
180
|
|
|
181
|
+
/**
|
|
182
|
+
* Build the core provider list shared by `provideNgQubee()` and
|
|
183
|
+
* `NgQubeeModule.forRoot()`
|
|
184
|
+
*
|
|
185
|
+
* Looks up the driver definition from the registry and calls its three
|
|
186
|
+
* factories — request strategy, response strategy, response options.
|
|
187
|
+
* Adding a driver means adding one entry to `DRIVERS`; this function
|
|
188
|
+
* does not change.
|
|
189
|
+
*
|
|
190
|
+
* Exposes the driver, strategies, and options via injection tokens so that
|
|
191
|
+
* consumers can request a component-scoped instance of the services through
|
|
192
|
+
* `provideNgQubeeInstance()`.
|
|
193
|
+
*
|
|
194
|
+
* @param config - Configuration object compliant to the IConfig interface
|
|
195
|
+
* @returns An array of Providers for the environment injector
|
|
196
|
+
*/
|
|
197
|
+
declare function buildNgQubeeProviders(config: IConfig): Provider[];
|
|
157
198
|
/**
|
|
158
199
|
* Sets up providers necessary to enable `NgQubee` functionality for the application.
|
|
159
200
|
*
|
|
@@ -198,19 +239,57 @@ declare class NgQubeeModule {
|
|
|
198
239
|
* @returns A set of providers to setup NgQubee
|
|
199
240
|
*/
|
|
200
241
|
declare function provideNgQubee(config: IConfig): EnvironmentProviders;
|
|
242
|
+
/**
|
|
243
|
+
* Providers for a component-scoped NgQubee instance
|
|
244
|
+
*
|
|
245
|
+
* Use this inside a standalone component's `providers: [...]` to get a
|
|
246
|
+
* dedicated `NgQubeeService` (and its `NestService` / `PaginationService`
|
|
247
|
+
* collaborators) whose query-builder and pagination state does not bleed
|
|
248
|
+
* with the app-wide shared instance provided by `provideNgQubee()`.
|
|
249
|
+
*
|
|
250
|
+
* @usageNotes
|
|
251
|
+
*
|
|
252
|
+
* ```
|
|
253
|
+
* @Component({
|
|
254
|
+
* standalone: true,
|
|
255
|
+
* providers: [...provideNgQubeeInstance()]
|
|
256
|
+
* })
|
|
257
|
+
* export class MyFeatureComponent {
|
|
258
|
+
* constructor(private _qb: NgQubeeService) {}
|
|
259
|
+
* }
|
|
260
|
+
* ```
|
|
261
|
+
*
|
|
262
|
+
* The driver, strategies, and options are inherited from the environment
|
|
263
|
+
* injector (`provideNgQubee()` at root), so only the service instances are
|
|
264
|
+
* re-created at the component level.
|
|
265
|
+
*
|
|
266
|
+
* @publicApi
|
|
267
|
+
* @returns A provider array to spread into a component's `providers`
|
|
268
|
+
*/
|
|
269
|
+
declare function provideNgQubeeInstance(): Provider[];
|
|
201
270
|
|
|
202
271
|
/**
|
|
203
|
-
* Enum representing the available filter operators for
|
|
272
|
+
* Enum representing the available filter operators for explicit operator
|
|
273
|
+
* filters
|
|
204
274
|
*
|
|
205
|
-
*
|
|
206
|
-
* `filter.field=$operator:value`
|
|
275
|
+
* NestJS encodes these with the `$` prefix at the wire level
|
|
276
|
+
* (`filter.field=$operator:value`); PostgREST translates them to its own
|
|
277
|
+
* prefix notation (`col=eq.val`, `col=is.null`, etc.). The enum values are
|
|
278
|
+
* intentionally the NestJS form; each driver's request strategy is
|
|
279
|
+
* responsible for mapping them into its own shape.
|
|
280
|
+
*
|
|
281
|
+
* `FTS`, `PLFTS`, `PHFTS`, `WFTS` are PostgREST-native full-text search
|
|
282
|
+
* variants; they throw `UnsupportedFilterOperatorError` on every other
|
|
283
|
+
* driver that does not recognise them.
|
|
207
284
|
*
|
|
208
285
|
* @see https://github.com/ppetzold/nestjs-paginate
|
|
286
|
+
* @see https://postgrest.org/en/stable/api.html#operators
|
|
209
287
|
*/
|
|
210
288
|
declare enum FilterOperatorEnum {
|
|
211
289
|
BTW = "$btw",
|
|
212
290
|
CONTAINS = "$contains",
|
|
213
291
|
EQ = "$eq",
|
|
292
|
+
FTS = "$fts",
|
|
214
293
|
GT = "$gt",
|
|
215
294
|
GTE = "$gte",
|
|
216
295
|
ILIKE = "$ilike",
|
|
@@ -219,7 +298,10 @@ declare enum FilterOperatorEnum {
|
|
|
219
298
|
LTE = "$lte",
|
|
220
299
|
NOT = "$not",
|
|
221
300
|
NULL = "$null",
|
|
222
|
-
|
|
301
|
+
PHFTS = "$phfts",
|
|
302
|
+
PLFTS = "$plfts",
|
|
303
|
+
SW = "$sw",
|
|
304
|
+
WFTS = "$wfts"
|
|
223
305
|
}
|
|
224
306
|
|
|
225
307
|
declare enum SortEnum {
|
|
@@ -280,6 +362,10 @@ interface IQueryBuilderState {
|
|
|
280
362
|
filters: IFilters;
|
|
281
363
|
/** Related models to include (Spatie only) */
|
|
282
364
|
includes: string[];
|
|
365
|
+
/** Whether the last paginated response has synced `lastPage` into state */
|
|
366
|
+
isLastPageKnown: boolean;
|
|
367
|
+
/** Last page number known from the most recent paginated response; only meaningful when `isLastPageKnown` is true */
|
|
368
|
+
lastPage: number;
|
|
283
369
|
/** Number of items per page (all drivers) */
|
|
284
370
|
limit: number;
|
|
285
371
|
/** Filters with explicit operators (NestJS only) */
|
|
@@ -296,6 +382,33 @@ interface IQueryBuilderState {
|
|
|
296
382
|
sorts: ISort[];
|
|
297
383
|
}
|
|
298
384
|
|
|
385
|
+
/**
|
|
386
|
+
* Capability flags declared by an `IRequestStrategy`
|
|
387
|
+
*
|
|
388
|
+
* Single source of truth for what a driver supports. Replaces the inline
|
|
389
|
+
* `DriverEnum` allowlists previously scattered across `NgQubeeService`'s
|
|
390
|
+
* `_assertDriver(...)` call sites.
|
|
391
|
+
*
|
|
392
|
+
* Adding a new driver means defining one of these objects on the new
|
|
393
|
+
* strategy class — `NgQubeeService` does not need to be touched.
|
|
394
|
+
*/
|
|
395
|
+
interface IStrategyCapabilities {
|
|
396
|
+
/** Per-model field selection (e.g. JSON:API `fields[type]=col1,col2`) */
|
|
397
|
+
readonly fields: boolean;
|
|
398
|
+
/** Simple key-value filters (e.g. `filter.status=active`) */
|
|
399
|
+
readonly filters: boolean;
|
|
400
|
+
/** Related-resource includes (e.g. JSON:API/Spatie `include=author`) */
|
|
401
|
+
readonly includes: boolean;
|
|
402
|
+
/** Filters with explicit operators (e.g. NestJS `$gte`, PostgREST `gte.`) */
|
|
403
|
+
readonly operatorFilters: boolean;
|
|
404
|
+
/** Global full-text search via a single term (NestJS `search=…`) */
|
|
405
|
+
readonly search: boolean;
|
|
406
|
+
/** Flat column-list selection (NestJS / PostgREST `select=col1,col2`) */
|
|
407
|
+
readonly select: boolean;
|
|
408
|
+
/** Sort ordering on one or more fields */
|
|
409
|
+
readonly sort: boolean;
|
|
410
|
+
}
|
|
411
|
+
|
|
299
412
|
/**
|
|
300
413
|
* Resolved query parameter key names with defaults applied
|
|
301
414
|
*
|
|
@@ -323,6 +436,14 @@ declare class QueryBuilderOptions {
|
|
|
323
436
|
* in the format expected by the corresponding backend.
|
|
324
437
|
*/
|
|
325
438
|
interface IRequestStrategy {
|
|
439
|
+
/**
|
|
440
|
+
* Capability flags declared by this driver
|
|
441
|
+
*
|
|
442
|
+
* Read by `NgQubeeService` to gate feature methods (e.g. `addFilter`)
|
|
443
|
+
* without hardcoding `DriverEnum` checks. Each strategy returns a
|
|
444
|
+
* static, immutable capability map.
|
|
445
|
+
*/
|
|
446
|
+
readonly capabilities: IStrategyCapabilities;
|
|
326
447
|
/**
|
|
327
448
|
* Build a URI string from the given query builder state
|
|
328
449
|
*
|
|
@@ -331,6 +452,23 @@ interface IRequestStrategy {
|
|
|
331
452
|
* @returns The composed URI string
|
|
332
453
|
*/
|
|
333
454
|
buildUri(state: IQueryBuilderState, options: QueryBuilderOptions): string;
|
|
455
|
+
/**
|
|
456
|
+
* Compute HTTP request headers carrying pagination metadata
|
|
457
|
+
*
|
|
458
|
+
* Honoured only by drivers that support header-based pagination (the
|
|
459
|
+
* PostgREST driver configured with `PaginationModeEnum.RANGE`). All
|
|
460
|
+
* other drivers should return `null` — which is also the default when
|
|
461
|
+
* a driver does not override this method.
|
|
462
|
+
*
|
|
463
|
+
* When the method returns a non-null object, `NgQubeeService.buildUri`
|
|
464
|
+
* is expected to have already omitted URL-level pagination params for
|
|
465
|
+
* that request; the consumer then merges these headers into the HTTP
|
|
466
|
+
* call so the server knows the requested range.
|
|
467
|
+
*
|
|
468
|
+
* @param state - The current query builder state
|
|
469
|
+
* @returns A map of header name → value, or `null` when not applicable
|
|
470
|
+
*/
|
|
471
|
+
buildPaginationHeaders?(state: IQueryBuilderState): Record<string, string> | null;
|
|
334
472
|
/**
|
|
335
473
|
* Assert that the given limit value is valid for this driver
|
|
336
474
|
*
|
|
@@ -560,6 +698,19 @@ declare class NestService {
|
|
|
560
698
|
* service.setSearch('john doe');
|
|
561
699
|
*/
|
|
562
700
|
setSearch(search: string): void;
|
|
701
|
+
/**
|
|
702
|
+
* Atomically record the `lastPage` value from a paginated response and
|
|
703
|
+
* flip `isLastPageKnown` to `true`
|
|
704
|
+
*
|
|
705
|
+
* Called exclusively by `PaginationService.paginate()` as part of the
|
|
706
|
+
* auto-sync contract; not intended to be invoked by consumers directly.
|
|
707
|
+
* Keeping the two fields under a single write guarantees they cannot
|
|
708
|
+
* drift out of sync.
|
|
709
|
+
*
|
|
710
|
+
* @param {number} lastPage - The last page number parsed from the most recent paginated response
|
|
711
|
+
* @return {void}
|
|
712
|
+
*/
|
|
713
|
+
syncLastPage(lastPage: number): void;
|
|
563
714
|
/**
|
|
564
715
|
* Reset the query builder state to initial values
|
|
565
716
|
* Clears all fields, filters, includes, sorts, and resets pagination
|
|
@@ -595,15 +746,19 @@ declare class NgQubeeService {
|
|
|
595
746
|
* Observable that emits non-empty generated URIs
|
|
596
747
|
*/
|
|
597
748
|
uri$: Observable<string>;
|
|
598
|
-
constructor(_nestService: NestService, requestStrategy: IRequestStrategy, driver: DriverEnum, options?:
|
|
749
|
+
constructor(_nestService: NestService, requestStrategy: IRequestStrategy, driver: DriverEnum, options?: QueryBuilderOptions);
|
|
599
750
|
/**
|
|
600
|
-
* Assert that the active
|
|
751
|
+
* Assert that the active strategy declares support for a capability
|
|
752
|
+
*
|
|
753
|
+
* Reads from `IRequestStrategy.capabilities` rather than the driver
|
|
754
|
+
* enum so adding a new driver only requires declaring its capability
|
|
755
|
+
* map — this method does not change.
|
|
601
756
|
*
|
|
602
|
-
* @param
|
|
603
|
-
* @param error - The error to throw if the
|
|
604
|
-
* @throws The provided error if the active
|
|
757
|
+
* @param flag - The capability key to check
|
|
758
|
+
* @param error - The error to throw if the capability is unsupported
|
|
759
|
+
* @throws The provided error if the active strategy lacks the capability
|
|
605
760
|
*/
|
|
606
|
-
private
|
|
761
|
+
private _assertCapability;
|
|
607
762
|
/**
|
|
608
763
|
* Add fields to the select statement for the given model (JSON:API and Spatie only)
|
|
609
764
|
*
|
|
@@ -614,7 +769,7 @@ declare class NgQubeeService {
|
|
|
614
769
|
*/
|
|
615
770
|
addFields(model: string, fields: string[]): this;
|
|
616
771
|
/**
|
|
617
|
-
* Add a filter with the given value(s) (JSON:API, NestJS, and Spatie)
|
|
772
|
+
* Add a filter with the given value(s) (JSON:API, NestJS, PostgREST, and Spatie)
|
|
618
773
|
*
|
|
619
774
|
* Produces: `filter[field]=value` (JSON:API / Spatie) or `filter.field=value` (NestJS)
|
|
620
775
|
*
|
|
@@ -625,7 +780,7 @@ declare class NgQubeeService {
|
|
|
625
780
|
*/
|
|
626
781
|
addFilter(field: string, ...values: (string | number | boolean)[]): this;
|
|
627
782
|
/**
|
|
628
|
-
* Add a filter with an explicit operator (NestJS
|
|
783
|
+
* Add a filter with an explicit operator (NestJS and PostgREST)
|
|
629
784
|
*
|
|
630
785
|
* Produces: `filter.field=$operator:value`
|
|
631
786
|
*
|
|
@@ -645,7 +800,7 @@ declare class NgQubeeService {
|
|
|
645
800
|
*/
|
|
646
801
|
addIncludes(...models: string[]): this;
|
|
647
802
|
/**
|
|
648
|
-
* Add flat field selection (NestJS
|
|
803
|
+
* Add flat field selection (NestJS and PostgREST)
|
|
649
804
|
*
|
|
650
805
|
* Produces: `select=col1,col2`
|
|
651
806
|
*
|
|
@@ -655,7 +810,7 @@ declare class NgQubeeService {
|
|
|
655
810
|
*/
|
|
656
811
|
addSelect(...fields: string[]): this;
|
|
657
812
|
/**
|
|
658
|
-
* Add a field with a sort criteria (JSON:API, NestJS, and Spatie)
|
|
813
|
+
* Add a field with a sort criteria (JSON:API, NestJS, PostgREST, and Spatie)
|
|
659
814
|
*
|
|
660
815
|
* @param field - Field to use for sorting
|
|
661
816
|
* @param {SortEnum} order - A value from the SortEnum enumeration
|
|
@@ -663,6 +818,13 @@ declare class NgQubeeService {
|
|
|
663
818
|
* @throws {UnsupportedSortError} If the active driver does not support sorts
|
|
664
819
|
*/
|
|
665
820
|
addSort(field: string, order: SortEnum): this;
|
|
821
|
+
/**
|
|
822
|
+
* Get the current page number
|
|
823
|
+
*
|
|
824
|
+
* @remarks Always safe to call. Thin accessor over the internal state's `page` field.
|
|
825
|
+
* @returns The current page number
|
|
826
|
+
*/
|
|
827
|
+
currentPage(): number;
|
|
666
828
|
/**
|
|
667
829
|
* Delete selected fields for the given models in the current query builder state (JSON:API and Spatie only)
|
|
668
830
|
*
|
|
@@ -692,7 +854,7 @@ declare class NgQubeeService {
|
|
|
692
854
|
*/
|
|
693
855
|
deleteFieldsByModel(model: string, ...fields: string[]): this;
|
|
694
856
|
/**
|
|
695
|
-
* Remove given filters from the query builder state (JSON:API, NestJS, and Spatie)
|
|
857
|
+
* Remove given filters from the query builder state (JSON:API, NestJS, PostgREST, and Spatie)
|
|
696
858
|
*
|
|
697
859
|
* @param {string[]} filters - Filters to remove
|
|
698
860
|
* @returns {this}
|
|
@@ -708,7 +870,7 @@ declare class NgQubeeService {
|
|
|
708
870
|
*/
|
|
709
871
|
deleteIncludes(...includes: string[]): this;
|
|
710
872
|
/**
|
|
711
|
-
* Remove operator filters by field name (NestJS
|
|
873
|
+
* Remove operator filters by field name (NestJS and PostgREST)
|
|
712
874
|
*
|
|
713
875
|
* @param {string[]} fields - Field names of operator filters to remove
|
|
714
876
|
* @returns {this}
|
|
@@ -723,7 +885,7 @@ declare class NgQubeeService {
|
|
|
723
885
|
*/
|
|
724
886
|
deleteSearch(): this;
|
|
725
887
|
/**
|
|
726
|
-
* Remove flat field selections from the query builder state (NestJS
|
|
888
|
+
* Remove flat field selections from the query builder state (NestJS and PostgREST)
|
|
727
889
|
*
|
|
728
890
|
* @param {string[]} fields - Fields to remove from selection
|
|
729
891
|
* @returns {this}
|
|
@@ -731,19 +893,101 @@ declare class NgQubeeService {
|
|
|
731
893
|
*/
|
|
732
894
|
deleteSelect(...fields: string[]): this;
|
|
733
895
|
/**
|
|
734
|
-
* Remove sort rules from the query builder state (JSON:API, NestJS, and Spatie)
|
|
896
|
+
* Remove sort rules from the query builder state (JSON:API, NestJS, PostgREST, and Spatie)
|
|
735
897
|
*
|
|
736
898
|
* @param sorts - Fields used for sorting to remove
|
|
737
899
|
* @returns {this}
|
|
738
900
|
* @throws {UnsupportedSortError} If the active driver does not support sorts
|
|
739
901
|
*/
|
|
740
902
|
deleteSorts(...sorts: string[]): this;
|
|
903
|
+
/**
|
|
904
|
+
* Navigate to the first page (page 1)
|
|
905
|
+
*
|
|
906
|
+
* @remarks Never throws. Idempotent when already on page 1.
|
|
907
|
+
* @returns {this}
|
|
908
|
+
*/
|
|
909
|
+
firstPage(): this;
|
|
741
910
|
/**
|
|
742
911
|
* Generate a URI accordingly to the given data and active driver
|
|
743
912
|
*
|
|
744
913
|
* @returns {Observable<string>} An observable that emits the generated URI
|
|
745
914
|
*/
|
|
746
915
|
generateUri(): Observable<string>;
|
|
916
|
+
/**
|
|
917
|
+
* Navigate directly to the specified page
|
|
918
|
+
*
|
|
919
|
+
* Validates integer/positive via the existing `setPage` path, and
|
|
920
|
+
* additionally rejects values that exceed `state.lastPage` when
|
|
921
|
+
* pagination bounds are known.
|
|
922
|
+
*
|
|
923
|
+
* @param n - Target page number
|
|
924
|
+
* @returns {this}
|
|
925
|
+
* @throws {InvalidPageNumberError} If `n` is not a positive integer, or if `n > state.lastPage` when `state.isLastPageKnown` is true
|
|
926
|
+
*/
|
|
927
|
+
goToPage(n: number): this;
|
|
928
|
+
/**
|
|
929
|
+
* Check whether a next page exists
|
|
930
|
+
*
|
|
931
|
+
* @remarks Template-safe. Returns `true` when pagination bounds are unknown (conservative default — keeps a "Next" button enabled before the first `paginate()` call).
|
|
932
|
+
* @returns `true` if `state.page < state.lastPage` when bounds are known, or `true` when bounds are unknown
|
|
933
|
+
*/
|
|
934
|
+
hasNextPage(): boolean;
|
|
935
|
+
/**
|
|
936
|
+
* Check whether a previous page exists
|
|
937
|
+
*
|
|
938
|
+
* @remarks Always safe. Does not require a synced paginated response.
|
|
939
|
+
* @returns `true` if `state.page > 1`
|
|
940
|
+
*/
|
|
941
|
+
hasPreviousPage(): boolean;
|
|
942
|
+
/**
|
|
943
|
+
* Check whether the current page is the first page
|
|
944
|
+
*
|
|
945
|
+
* @remarks Always safe. Does not require a synced paginated response.
|
|
946
|
+
* @returns `true` if `state.page === 1`
|
|
947
|
+
*/
|
|
948
|
+
isFirstPage(): boolean;
|
|
949
|
+
/**
|
|
950
|
+
* Check whether the current page is the last page
|
|
951
|
+
*
|
|
952
|
+
* @remarks Template-safe. Returns `false` when pagination bounds are unknown (no paginated response has been synced yet) — keeps "Next" navigation unblocked until the first `paginate()` call syncs.
|
|
953
|
+
* @returns `true` only when `state.isLastPageKnown` and `state.page === state.lastPage`
|
|
954
|
+
*/
|
|
955
|
+
isLastPage(): boolean;
|
|
956
|
+
/**
|
|
957
|
+
* Navigate to the last page known from the most recent paginated response
|
|
958
|
+
*
|
|
959
|
+
* @remarks Requires at least one `PaginationService.paginate()` call to have synced `state.lastPage`. Before that, the bound is unknown and this method throws.
|
|
960
|
+
* @returns {this}
|
|
961
|
+
* @throws {PaginationNotSyncedError} If `state.isLastPageKnown` is false (no paginated response has been synced yet)
|
|
962
|
+
*/
|
|
963
|
+
lastPage(): this;
|
|
964
|
+
/**
|
|
965
|
+
* Navigate to the next page
|
|
966
|
+
*
|
|
967
|
+
* @remarks Never throws. Idempotent at the known last page (no-op). Pair with `hasNextPage()` for a disable-state binding.
|
|
968
|
+
* @returns {this}
|
|
969
|
+
*/
|
|
970
|
+
nextPage(): this;
|
|
971
|
+
/**
|
|
972
|
+
* HTTP request headers the active driver wants the consumer to apply
|
|
973
|
+
*
|
|
974
|
+
* Returns `null` for drivers that pass all pagination metadata on the
|
|
975
|
+
* URL (Laravel, Spatie, JSON:API, NestJS, and PostgREST in its default
|
|
976
|
+
* QUERY mode). Returns a map of header name → value when the active
|
|
977
|
+
* driver uses HTTP headers instead — today, only the PostgREST driver
|
|
978
|
+
* configured with `PaginationModeEnum.RANGE`, which yields
|
|
979
|
+
* `{ 'Range-Unit': 'items', 'Range': 'from-to' }`.
|
|
980
|
+
*
|
|
981
|
+
* @returns Map of headers to apply to the HTTP request, or `null` when not needed
|
|
982
|
+
*/
|
|
983
|
+
paginationHeaders(): Record<string, string> | null;
|
|
984
|
+
/**
|
|
985
|
+
* Navigate to the previous page
|
|
986
|
+
*
|
|
987
|
+
* @remarks Never throws. Idempotent at page 1 (floored). Pair with `hasPreviousPage()` for a disable-state binding.
|
|
988
|
+
* @returns {this}
|
|
989
|
+
*/
|
|
990
|
+
previousPage(): this;
|
|
747
991
|
/**
|
|
748
992
|
* Clear the current state and reset the Query Builder to a fresh, clean condition
|
|
749
993
|
*
|
|
@@ -794,8 +1038,39 @@ declare class NgQubeeService {
|
|
|
794
1038
|
* @throws {UnsupportedSearchError} If the active driver does not support search
|
|
795
1039
|
*/
|
|
796
1040
|
setSearch(search: string): this;
|
|
1041
|
+
/**
|
|
1042
|
+
* Get the total number of pages reported by the most recent paginated response
|
|
1043
|
+
*
|
|
1044
|
+
* @remarks Throws when called before any `paginate()` has synced a value. For a non-throwing read in a template, read `nest().isLastPageKnown` first as a guard.
|
|
1045
|
+
* @returns The last page number
|
|
1046
|
+
* @throws {PaginationNotSyncedError} If `state.isLastPageKnown` is false (no paginated response has been synced yet)
|
|
1047
|
+
*/
|
|
1048
|
+
totalPages(): number;
|
|
1049
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<NgQubeeService, never>;
|
|
1050
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<NgQubeeService>;
|
|
797
1051
|
}
|
|
798
1052
|
|
|
1053
|
+
/**
|
|
1054
|
+
* A minimal bag of HTTP response headers that a response strategy can read
|
|
1055
|
+
* by name.
|
|
1056
|
+
*
|
|
1057
|
+
* Accepts anything that exposes a `.get(name): string | null` method
|
|
1058
|
+
* (Angular's `HttpHeaders`, the DOM `Headers` class) or a plain object
|
|
1059
|
+
* keyed by header name. Consumers should not need to convert between them.
|
|
1060
|
+
*/
|
|
1061
|
+
type HeaderBag = {
|
|
1062
|
+
get(name: string): string | null;
|
|
1063
|
+
} | Record<string, string | null | undefined>;
|
|
1064
|
+
/**
|
|
1065
|
+
* Read a header value by name from a `HeaderBag`, regardless of whether the
|
|
1066
|
+
* bag exposes a `.get()` accessor or plain property access.
|
|
1067
|
+
*
|
|
1068
|
+
* @param bag - The header bag to read from
|
|
1069
|
+
* @param name - The header name (case-sensitivity follows the underlying bag)
|
|
1070
|
+
* @returns The header value, or `null` if absent or the bag itself is falsy
|
|
1071
|
+
*/
|
|
1072
|
+
declare function readHeader(bag: HeaderBag | null | undefined, name: string): string | null;
|
|
1073
|
+
|
|
799
1074
|
/**
|
|
800
1075
|
* Resolved response field key names with defaults applied
|
|
801
1076
|
*
|
|
@@ -836,14 +1111,25 @@ interface IResponseStrategy {
|
|
|
836
1111
|
/**
|
|
837
1112
|
* Parse a raw API response into a typed PaginatedCollection
|
|
838
1113
|
*
|
|
839
|
-
* @param response - The raw API response object
|
|
1114
|
+
* @param response - The raw API response object (body). For drivers that
|
|
1115
|
+
* emit a bare array body (e.g. PostgREST), pass the array here.
|
|
840
1116
|
* @param options - The response key name configuration
|
|
1117
|
+
* @param headers - Optional HTTP response headers. Drivers that carry
|
|
1118
|
+
* pagination metadata in headers (PostgREST's `Content-Range`) read from
|
|
1119
|
+
* this bag; body-only drivers ignore it. Accepts anything with a `.get()`
|
|
1120
|
+
* accessor (`HttpHeaders`, `Headers`) or a plain `Record<string, string>`.
|
|
841
1121
|
* @returns A typed PaginatedCollection instance
|
|
842
1122
|
*/
|
|
843
|
-
paginate<T extends IPaginatedObject>(response: Record<string, unknown>, options: ResponseOptions): PaginatedCollection<T>;
|
|
1123
|
+
paginate<T extends IPaginatedObject>(response: Record<string, unknown>, options: ResponseOptions, headers?: HeaderBag): PaginatedCollection<T>;
|
|
844
1124
|
}
|
|
845
1125
|
|
|
846
1126
|
declare class PaginationService {
|
|
1127
|
+
/**
|
|
1128
|
+
* The NestService instance that owns the query-builder state for this
|
|
1129
|
+
* PaginationService's scope (environment-level by default, or
|
|
1130
|
+
* component-level when used via `provideNgQubeeInstance()`)
|
|
1131
|
+
*/
|
|
1132
|
+
private _nestService;
|
|
847
1133
|
/**
|
|
848
1134
|
* Resolved response key name options
|
|
849
1135
|
*/
|
|
@@ -852,18 +1138,56 @@ declare class PaginationService {
|
|
|
852
1138
|
* The response strategy that parses responses for the active driver
|
|
853
1139
|
*/
|
|
854
1140
|
private _responseStrategy;
|
|
855
|
-
constructor(responseStrategy: IResponseStrategy, options?:
|
|
1141
|
+
constructor(nestService: NestService, responseStrategy: IResponseStrategy, options?: ResponseOptions);
|
|
856
1142
|
/**
|
|
857
1143
|
* Transform a raw API response into a typed PaginatedCollection
|
|
858
1144
|
*
|
|
859
|
-
* Delegates to the active driver's response strategy for parsing
|
|
860
|
-
*
|
|
861
|
-
*
|
|
1145
|
+
* Delegates to the active driver's response strategy for parsing, then
|
|
1146
|
+
* auto-syncs the parsed `page` and `lastPage` back into `NestService`
|
|
1147
|
+
* so pagination navigation helpers on `NgQubeeService` can operate
|
|
1148
|
+
* against the live server-reported bounds without consumer bookkeeping.
|
|
1149
|
+
*
|
|
1150
|
+
* @remarks
|
|
1151
|
+
* `lastPage` is only synced when the response yields a positive integer.
|
|
1152
|
+
* Server-emitted `0` (empty collection edge case) and absent fields are
|
|
1153
|
+
* treated as "no useful info" and leave `isLastPageKnown: false`.
|
|
1154
|
+
*
|
|
1155
|
+
* @param response - The raw API response body. For drivers that emit a
|
|
1156
|
+
* bare array (PostgREST), pass the array.
|
|
1157
|
+
* @param headers - Optional HTTP response headers. Required by the
|
|
1158
|
+
* PostgREST driver (reads `Content-Range` for pagination metadata);
|
|
1159
|
+
* body-only drivers ignore it. Accepts Angular's `HttpHeaders`, the
|
|
1160
|
+
* native `Headers` class, or a plain `Record<string, string>`.
|
|
862
1161
|
* @returns A typed PaginatedCollection instance
|
|
863
1162
|
*/
|
|
864
1163
|
paginate<T extends IPaginatedObject>(response: {
|
|
865
1164
|
[key: string]: any;
|
|
866
|
-
}): PaginatedCollection<T>;
|
|
1165
|
+
}, headers?: HeaderBag): PaginatedCollection<T>;
|
|
1166
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<PaginationService, never>;
|
|
1167
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<PaginationService>;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
/**
|
|
1171
|
+
* Thrown when a filter operator receives a value array of the wrong shape
|
|
1172
|
+
*
|
|
1173
|
+
* Some operators have arity or type constraints that the library enforces
|
|
1174
|
+
* at call time so misuse fails loudly instead of silently emitting invalid
|
|
1175
|
+
* server requests:
|
|
1176
|
+
*
|
|
1177
|
+
* - `BTW` requires exactly two values (min, max).
|
|
1178
|
+
* - `NULL` requires exactly one boolean value (`true` for `IS NULL`,
|
|
1179
|
+
* `false` for `IS NOT NULL`).
|
|
1180
|
+
*
|
|
1181
|
+
* Operators with looser shape rules leave validation to the server; this
|
|
1182
|
+
* error is reserved for cases where the library itself can detect the
|
|
1183
|
+
* problem unambiguously from the call site.
|
|
1184
|
+
*/
|
|
1185
|
+
declare class InvalidFilterOperatorValueError extends Error {
|
|
1186
|
+
/**
|
|
1187
|
+
* @param operator - The operator that rejected the values
|
|
1188
|
+
* @param reason - Short human-readable explanation of the constraint
|
|
1189
|
+
*/
|
|
1190
|
+
constructor(operator: FilterOperatorEnum, reason: string);
|
|
867
1191
|
}
|
|
868
1192
|
|
|
869
1193
|
/**
|
|
@@ -899,6 +1223,24 @@ declare class KeyNotFoundError extends Error {
|
|
|
899
1223
|
constructor(key: string);
|
|
900
1224
|
}
|
|
901
1225
|
|
|
1226
|
+
/**
|
|
1227
|
+
* Thrown when a pagination helper that needs `state.lastPage` is called
|
|
1228
|
+
* before `PaginationService.paginate()` has ever synced a value.
|
|
1229
|
+
*
|
|
1230
|
+
* Examples: `NgQubeeService.lastPage()`, `NgQubeeService.totalPages()`.
|
|
1231
|
+
*
|
|
1232
|
+
* Safe-for-templates predicates (`isLastPage`, `hasNextPage`, etc.) do not
|
|
1233
|
+
* throw and return conservative defaults instead.
|
|
1234
|
+
*/
|
|
1235
|
+
declare class PaginationNotSyncedError extends Error {
|
|
1236
|
+
/**
|
|
1237
|
+
* @param action - Short imperative describing what the caller was trying
|
|
1238
|
+
* to do (e.g. "navigate to last page", "read totalPages"). Surfaced in
|
|
1239
|
+
* the error message so the cause is obvious at the call site.
|
|
1240
|
+
*/
|
|
1241
|
+
constructor(action: string);
|
|
1242
|
+
}
|
|
1243
|
+
|
|
902
1244
|
declare class UnselectableModelError extends Error {
|
|
903
1245
|
constructor(model: string);
|
|
904
1246
|
}
|
|
@@ -977,185 +1319,303 @@ interface IPage {
|
|
|
977
1319
|
}
|
|
978
1320
|
|
|
979
1321
|
/**
|
|
980
|
-
*
|
|
1322
|
+
* Injection token for the active pagination driver
|
|
981
1323
|
*
|
|
982
|
-
*
|
|
983
|
-
* -
|
|
984
|
-
*
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
1324
|
+
* Provided by `provideNgQubee()` / `NgQubeeModule.forRoot()` from the
|
|
1325
|
+
* user-supplied `IConfig.driver`. Services read it to gate driver-specific
|
|
1326
|
+
* behavior (e.g. `NgQubeeService._assertDriver`).
|
|
1327
|
+
*/
|
|
1328
|
+
declare const NG_QUBEE_DRIVER: InjectionToken<DriverEnum>;
|
|
1329
|
+
/**
|
|
1330
|
+
* Injection token for the resolved request URI strategy
|
|
988
1331
|
*
|
|
989
|
-
*
|
|
1332
|
+
* Provided by `provideNgQubee()` / `NgQubeeModule.forRoot()` based on the
|
|
1333
|
+
* active driver. Used by `NgQubeeService` to build request URIs.
|
|
1334
|
+
*/
|
|
1335
|
+
declare const NG_QUBEE_REQUEST_STRATEGY: InjectionToken<IRequestStrategy>;
|
|
1336
|
+
/**
|
|
1337
|
+
* Injection token for the resolved request query-parameter key options
|
|
1338
|
+
*
|
|
1339
|
+
* Provided as a fully-built `QueryBuilderOptions` instance. `provideNgQubee()`
|
|
1340
|
+
* constructs it from `IConfig.request`; consumers don't interact with this
|
|
1341
|
+
* token directly.
|
|
990
1342
|
*/
|
|
991
|
-
declare
|
|
1343
|
+
declare const NG_QUBEE_REQUEST_OPTIONS: InjectionToken<QueryBuilderOptions>;
|
|
1344
|
+
/**
|
|
1345
|
+
* Injection token for the resolved response parsing strategy
|
|
1346
|
+
*
|
|
1347
|
+
* Provided by `provideNgQubee()` / `NgQubeeModule.forRoot()` based on the
|
|
1348
|
+
* active driver. Used by `PaginationService` to parse paginated responses.
|
|
1349
|
+
*/
|
|
1350
|
+
declare const NG_QUBEE_RESPONSE_STRATEGY: InjectionToken<IResponseStrategy>;
|
|
1351
|
+
/**
|
|
1352
|
+
* Injection token for the resolved response field-key options
|
|
1353
|
+
*
|
|
1354
|
+
* Provided as a fully-built `ResponseOptions` instance (or a driver-specific
|
|
1355
|
+
* subclass like `JsonApiResponseOptions` / `NestjsResponseOptions`).
|
|
1356
|
+
* `provideNgQubee()` constructs the correct variant from `IConfig.response`.
|
|
1357
|
+
*/
|
|
1358
|
+
declare const NG_QUBEE_RESPONSE_OPTIONS: InjectionToken<ResponseOptions>;
|
|
1359
|
+
|
|
1360
|
+
/**
|
|
1361
|
+
* Base class for request strategies
|
|
1362
|
+
*
|
|
1363
|
+
* Concentrates the glue every concrete strategy used to copy: the
|
|
1364
|
+
* resource-required guard, the `?`/`&` URL composition, and the default
|
|
1365
|
+
* positive-integer `validateLimit`. Concrete strategies override only
|
|
1366
|
+
* the parts that differ — the per-driver wire format goes into a single
|
|
1367
|
+
* `protected parts(state, options): string[]` method that returns the
|
|
1368
|
+
* ordered query-string segments the base then joins.
|
|
1369
|
+
*
|
|
1370
|
+
* Drivers that need a non-default `validateLimit` (e.g. NestJS, which
|
|
1371
|
+
* accepts `-1` as a fetch-all sentinel) override that method directly.
|
|
1372
|
+
*/
|
|
1373
|
+
declare abstract class AbstractRequestStrategy implements IRequestStrategy {
|
|
992
1374
|
/**
|
|
993
|
-
*
|
|
1375
|
+
* Capability declaration for this driver
|
|
1376
|
+
*
|
|
1377
|
+
* Concrete strategies must provide a static, immutable capability map
|
|
1378
|
+
* so `NgQubeeService._assertCapability(...)` can read it.
|
|
994
1379
|
*/
|
|
995
|
-
|
|
1380
|
+
abstract readonly capabilities: IStrategyCapabilities;
|
|
996
1381
|
/**
|
|
997
|
-
*
|
|
1382
|
+
* Compose the full request URI from the given state
|
|
1383
|
+
*
|
|
1384
|
+
* Template method: validates the resource, computes the base path,
|
|
1385
|
+
* delegates the per-driver query-string segments to `parts(...)`, and
|
|
1386
|
+
* joins them with the conventional `?`/`&` separators.
|
|
998
1387
|
*
|
|
999
1388
|
* @param state - The current query builder state
|
|
1000
1389
|
* @param options - The query parameter key name configuration
|
|
1001
1390
|
* @returns The composed URI string
|
|
1002
|
-
* @throws Error if resource is not set
|
|
1391
|
+
* @throws Error if the resource is not set
|
|
1003
1392
|
*/
|
|
1004
1393
|
buildUri(state: IQueryBuilderState, options: QueryBuilderOptions): string;
|
|
1005
1394
|
/**
|
|
1006
|
-
* Validate that
|
|
1395
|
+
* Validate that a limit value is acceptable for this driver
|
|
1007
1396
|
*
|
|
1008
|
-
*
|
|
1009
|
-
*
|
|
1010
|
-
* accepted.
|
|
1397
|
+
* Default policy: positive integer. Drivers that recognise a sentinel
|
|
1398
|
+
* (NestJS treats `-1` as "fetch all") override this method.
|
|
1011
1399
|
*
|
|
1012
1400
|
* @param limit - The limit value to validate
|
|
1013
1401
|
* @throws {InvalidLimitError} If the value is not a positive integer
|
|
1014
1402
|
*/
|
|
1015
1403
|
validateLimit(limit: number): void;
|
|
1016
1404
|
/**
|
|
1017
|
-
*
|
|
1405
|
+
* Per-driver query-string segments, in emission order
|
|
1018
1406
|
*
|
|
1019
|
-
*
|
|
1020
|
-
*
|
|
1407
|
+
* Each entry is one `key=value` (or `key=v1&key=v2` for compound
|
|
1408
|
+
* params like PostgREST's `BTW`). Empty arrays are valid and produce
|
|
1409
|
+
* a URI containing only the resource path.
|
|
1021
1410
|
*
|
|
1022
1411
|
* @param state - The current query builder state
|
|
1023
1412
|
* @param options - The query parameter key name configuration
|
|
1024
|
-
* @returns
|
|
1025
|
-
* @throws Error if resource is required but not set
|
|
1026
|
-
* @throws UnselectableModelError if a field model is not in resource or includes
|
|
1413
|
+
* @returns Ordered list of query-string fragments
|
|
1027
1414
|
*/
|
|
1028
|
-
|
|
1415
|
+
protected abstract parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
1029
1416
|
/**
|
|
1030
|
-
*
|
|
1417
|
+
* Throw if the resource is not set on the state
|
|
1031
1418
|
*
|
|
1032
|
-
*
|
|
1419
|
+
* Centralises the message that was previously copy-pasted across four
|
|
1420
|
+
* of the five concrete strategies.
|
|
1033
1421
|
*
|
|
1034
1422
|
* @param state - The current query builder state
|
|
1035
|
-
* @
|
|
1036
|
-
* @returns The generated filter parameter string
|
|
1423
|
+
* @throws Error if `state.resource` is empty
|
|
1037
1424
|
*/
|
|
1038
|
-
|
|
1425
|
+
protected assertResource(state: IQueryBuilderState): void;
|
|
1039
1426
|
/**
|
|
1040
|
-
*
|
|
1427
|
+
* Compute the base path (no query string)
|
|
1041
1428
|
*
|
|
1042
|
-
*
|
|
1429
|
+
* @param state - The current query builder state
|
|
1430
|
+
* @returns The base URI without the query separator (e.g. `/users` or `https://api.example.com/users`)
|
|
1431
|
+
*/
|
|
1432
|
+
protected baseUri(state: IQueryBuilderState): string;
|
|
1433
|
+
/**
|
|
1434
|
+
* Glue the base URI and the per-driver query-string segments
|
|
1435
|
+
*
|
|
1436
|
+
* Returns the bare base when no segments were emitted (e.g. PostgREST
|
|
1437
|
+
* in RANGE mode with no filters), otherwise joins with `?` + `&`.
|
|
1438
|
+
*
|
|
1439
|
+
* @param base - The base URI from `_baseUri`
|
|
1440
|
+
* @param segments - The query-string fragments from `parts(...)`
|
|
1441
|
+
* @returns The full URI
|
|
1442
|
+
*/
|
|
1443
|
+
protected join(base: string, segments: string[]): string;
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
/**
|
|
1447
|
+
* Request strategy for the JSON:API driver
|
|
1448
|
+
*
|
|
1449
|
+
* Generates URIs in the JSON:API format:
|
|
1450
|
+
* - Fields: `fields[articles]=title,body&fields[people]=name`
|
|
1451
|
+
* - Filters: `filter[status]=active`
|
|
1452
|
+
* - Includes: `include=author,comments.author`
|
|
1453
|
+
* - Pagination: `page[number]=1&page[size]=15`
|
|
1454
|
+
* - Sort: `sort=-created_at,name` (- prefix = DESC)
|
|
1455
|
+
*
|
|
1456
|
+
* @see https://jsonapi.org/format/
|
|
1457
|
+
*/
|
|
1458
|
+
declare class JsonApiRequestStrategy extends AbstractRequestStrategy {
|
|
1459
|
+
/**
|
|
1460
|
+
* Filters, sorts, includes, per-model fields — same shape as Spatie
|
|
1461
|
+
* but with bracket-style pagination
|
|
1462
|
+
*/
|
|
1463
|
+
readonly capabilities: IStrategyCapabilities;
|
|
1464
|
+
/**
|
|
1465
|
+
* Emit JSON:API-format query-string segments in canonical order:
|
|
1466
|
+
* include → fields → filters → pagination → sort
|
|
1043
1467
|
*
|
|
1044
1468
|
* @param state - The current query builder state
|
|
1045
1469
|
* @param options - The query parameter key name configuration
|
|
1046
|
-
* @returns
|
|
1470
|
+
* @returns Ordered query-string fragments
|
|
1047
1471
|
*/
|
|
1048
|
-
|
|
1472
|
+
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
1049
1473
|
/**
|
|
1050
|
-
*
|
|
1051
|
-
*
|
|
1052
|
-
* Generates: `page[number]=1&page[size]=15`
|
|
1474
|
+
* Append per-type field selection in bracket notation
|
|
1053
1475
|
*
|
|
1054
1476
|
* @param state - The current query builder state
|
|
1055
1477
|
* @param options - The query parameter key name configuration
|
|
1056
|
-
* @
|
|
1478
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1479
|
+
* @throws Error if the resource is missing from the fields object
|
|
1480
|
+
* @throws UnselectableModelError if a field type is not the resource or in includes
|
|
1057
1481
|
*/
|
|
1058
|
-
private
|
|
1482
|
+
private _appendFields;
|
|
1059
1483
|
/**
|
|
1060
|
-
*
|
|
1484
|
+
* Append filter parameters in bracket notation: `filter[key]=value`
|
|
1061
1485
|
*
|
|
1062
|
-
*
|
|
1486
|
+
* @param state - The current query builder state
|
|
1487
|
+
* @param options - The query parameter key name configuration
|
|
1488
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1489
|
+
*/
|
|
1490
|
+
private _appendFilters;
|
|
1491
|
+
/**
|
|
1492
|
+
* Append include parameter as `include=author,comments.author`
|
|
1063
1493
|
*
|
|
1064
1494
|
* @param state - The current query builder state
|
|
1065
1495
|
* @param options - The query parameter key name configuration
|
|
1066
|
-
* @
|
|
1496
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1067
1497
|
*/
|
|
1068
|
-
private
|
|
1498
|
+
private _appendIncludes;
|
|
1069
1499
|
/**
|
|
1070
|
-
*
|
|
1500
|
+
* Append JSON:API bracket pagination as `page[number]=1&page[size]=15`
|
|
1501
|
+
*
|
|
1502
|
+
* `qs.stringify` already returns the two segments joined with `&`, so we
|
|
1503
|
+
* push the whole string as one accumulator entry — `_join` will glue
|
|
1504
|
+
* it onto the rest with the same separator.
|
|
1071
1505
|
*
|
|
1072
|
-
*
|
|
1073
|
-
*
|
|
1506
|
+
* @param state - The current query builder state
|
|
1507
|
+
* @param options - The query parameter key name configuration
|
|
1508
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1509
|
+
*/
|
|
1510
|
+
private _appendPagination;
|
|
1511
|
+
/**
|
|
1512
|
+
* Append sort parameter as `sort=-field1,field2` (`-` prefix = DESC)
|
|
1074
1513
|
*
|
|
1075
1514
|
* @param state - The current query builder state
|
|
1076
|
-
* @
|
|
1515
|
+
* @param options - The query parameter key name configuration
|
|
1516
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1077
1517
|
*/
|
|
1078
|
-
private
|
|
1518
|
+
private _appendSort;
|
|
1079
1519
|
}
|
|
1080
1520
|
|
|
1081
1521
|
/**
|
|
1082
|
-
*
|
|
1522
|
+
* Base class for response strategies whose pagination metadata lives at
|
|
1523
|
+
* dot-notation paths inside the response body
|
|
1083
1524
|
*
|
|
1084
|
-
*
|
|
1085
|
-
*
|
|
1086
|
-
*
|
|
1087
|
-
*
|
|
1088
|
-
*
|
|
1089
|
-
*
|
|
1090
|
-
*
|
|
1091
|
-
* "total": 100,
|
|
1092
|
-
* "page-count": 10,
|
|
1093
|
-
* "from": 1,
|
|
1094
|
-
* "to": 10
|
|
1095
|
-
* },
|
|
1096
|
-
* "links": {
|
|
1097
|
-
* "first": "url",
|
|
1098
|
-
* "prev": "url",
|
|
1099
|
-
* "next": "url",
|
|
1100
|
-
* "last": "url"
|
|
1101
|
-
* }
|
|
1102
|
-
* }
|
|
1103
|
-
* ```
|
|
1525
|
+
* JSON:API and NestJS share an identical body-traversal algorithm: the
|
|
1526
|
+
* total / current-page / etc. live at nested keys like `meta.total`, and
|
|
1527
|
+
* `from`/`to` are either present directly or must be derived from
|
|
1528
|
+
* `currentPage` × `perPage`. Both strategies were duplicating this
|
|
1529
|
+
* verbatim before this base existed; concrete classes now extend and
|
|
1530
|
+
* provide only the docstring describing their driver's specific path
|
|
1531
|
+
* conventions (see `JsonApiResponseStrategy`, `NestjsResponseStrategy`).
|
|
1104
1532
|
*
|
|
1105
|
-
*
|
|
1533
|
+
* Drivers whose pagination metadata travels via HTTP headers (PostgREST)
|
|
1534
|
+
* or whose body has a flat shape with no dot paths (Laravel, Spatie) do
|
|
1535
|
+
* not extend this class — they implement `IResponseStrategy` directly.
|
|
1106
1536
|
*/
|
|
1107
|
-
declare class
|
|
1537
|
+
declare abstract class AbstractDotPathResponseStrategy implements IResponseStrategy {
|
|
1108
1538
|
/**
|
|
1109
|
-
* Parse a
|
|
1110
|
-
*
|
|
1111
|
-
* Supports dot-notation key paths for accessing nested values.
|
|
1112
|
-
* Computes `from` and `to` from `currentPage` and `perPage` when
|
|
1113
|
-
* they are not directly available in the response.
|
|
1539
|
+
* Parse a nested-envelope pagination response into a PaginatedCollection
|
|
1114
1540
|
*
|
|
1115
1541
|
* @param response - The raw API response object
|
|
1116
|
-
* @param options - The response key name configuration
|
|
1542
|
+
* @param options - The response key name configuration (dot-notation paths supported)
|
|
1117
1543
|
* @returns A typed PaginatedCollection instance
|
|
1118
1544
|
*/
|
|
1119
1545
|
paginate<T extends IPaginatedObject>(response: Record<string, any>, options: ResponseOptions): PaginatedCollection<T>;
|
|
1120
1546
|
/**
|
|
1121
1547
|
* Resolve a value from a response object using a dot-notation path
|
|
1122
1548
|
*
|
|
1123
|
-
* Supports both flat keys ('data') and nested paths ('meta.
|
|
1549
|
+
* Supports both flat keys (`'data'`) and nested paths (`'meta.totalItems'`).
|
|
1124
1550
|
*
|
|
1125
1551
|
* @param response - The raw response object
|
|
1126
1552
|
* @param path - The dot-notation path to resolve
|
|
1127
|
-
* @returns The resolved value, or undefined if
|
|
1553
|
+
* @returns The resolved value, or undefined if any segment is missing
|
|
1128
1554
|
*/
|
|
1129
|
-
|
|
1555
|
+
protected resolve(response: Record<string, any>, path: string): unknown;
|
|
1130
1556
|
/**
|
|
1131
1557
|
* Resolve the "from" index value
|
|
1132
1558
|
*
|
|
1133
|
-
* If
|
|
1134
|
-
* Otherwise
|
|
1135
|
-
* `(currentPage - 1) * perPage + 1`
|
|
1559
|
+
* If `options.from` resolves to a value in the response, use it.
|
|
1560
|
+
* Otherwise compute `(currentPage - 1) * perPage + 1` when both are known.
|
|
1136
1561
|
*
|
|
1137
1562
|
* @param response - The raw response object
|
|
1138
1563
|
* @param options - The response key name configuration
|
|
1139
1564
|
* @param currentPage - The current page number
|
|
1140
1565
|
* @param perPage - The number of items per page
|
|
1141
|
-
* @returns The
|
|
1566
|
+
* @returns The "from" index, or `undefined` when neither path nor inputs suffice
|
|
1142
1567
|
*/
|
|
1143
|
-
|
|
1568
|
+
protected resolveFrom(response: Record<string, any>, options: ResponseOptions, currentPage: number, perPage?: number): number | undefined;
|
|
1144
1569
|
/**
|
|
1145
1570
|
* Resolve the "to" index value
|
|
1146
1571
|
*
|
|
1147
|
-
* If
|
|
1148
|
-
* Otherwise
|
|
1149
|
-
*
|
|
1572
|
+
* If `options.to` resolves to a value in the response, use it.
|
|
1573
|
+
* Otherwise compute `Math.min(currentPage * perPage, total)` when all
|
|
1574
|
+
* three are known.
|
|
1150
1575
|
*
|
|
1151
1576
|
* @param response - The raw response object
|
|
1152
1577
|
* @param options - The response key name configuration
|
|
1153
1578
|
* @param currentPage - The current page number
|
|
1154
1579
|
* @param perPage - The number of items per page
|
|
1155
1580
|
* @param total - The total number of items
|
|
1156
|
-
* @returns The
|
|
1581
|
+
* @returns The "to" index, or `undefined` when neither path nor inputs suffice
|
|
1157
1582
|
*/
|
|
1158
|
-
|
|
1583
|
+
protected resolveTo(response: Record<string, any>, options: ResponseOptions, currentPage: number, perPage?: number, total?: number): number | undefined;
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
/**
|
|
1587
|
+
* Response strategy for the JSON:API driver
|
|
1588
|
+
*
|
|
1589
|
+
* Parses JSON:API pagination responses:
|
|
1590
|
+
* ```json
|
|
1591
|
+
* {
|
|
1592
|
+
* "data": [...],
|
|
1593
|
+
* "meta": {
|
|
1594
|
+
* "current-page": 1,
|
|
1595
|
+
* "per-page": 10,
|
|
1596
|
+
* "total": 100,
|
|
1597
|
+
* "page-count": 10,
|
|
1598
|
+
* "from": 1,
|
|
1599
|
+
* "to": 10
|
|
1600
|
+
* },
|
|
1601
|
+
* "links": {
|
|
1602
|
+
* "first": "url",
|
|
1603
|
+
* "prev": "url",
|
|
1604
|
+
* "next": "url",
|
|
1605
|
+
* "last": "url"
|
|
1606
|
+
* }
|
|
1607
|
+
* }
|
|
1608
|
+
* ```
|
|
1609
|
+
*
|
|
1610
|
+
* Default key paths are configured in `JsonApiResponseOptions`. The
|
|
1611
|
+
* traversal algorithm (dot-notation resolution + computed `from`/`to`) is
|
|
1612
|
+
* inherited from `AbstractDotPathResponseStrategy`; this class exists so
|
|
1613
|
+
* `DriverEnum.JSON_API` resolves to a distinct identity at the DI layer
|
|
1614
|
+
* even though the parsing logic is shared with NestJS.
|
|
1615
|
+
*
|
|
1616
|
+
* @see https://jsonapi.org/format/
|
|
1617
|
+
*/
|
|
1618
|
+
declare class JsonApiResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
1159
1619
|
}
|
|
1160
1620
|
|
|
1161
1621
|
/**
|
|
@@ -1166,26 +1626,19 @@ declare class JsonApiResponseStrategy implements IResponseStrategy {
|
|
|
1166
1626
|
*
|
|
1167
1627
|
* Filters, sorts, fields, includes, search, and select in state are ignored.
|
|
1168
1628
|
*/
|
|
1169
|
-
declare class LaravelRequestStrategy
|
|
1629
|
+
declare class LaravelRequestStrategy extends AbstractRequestStrategy {
|
|
1170
1630
|
/**
|
|
1171
|
-
*
|
|
1172
|
-
*
|
|
1173
|
-
* @param state - The current query builder state
|
|
1174
|
-
* @param options - The query parameter key name configuration
|
|
1175
|
-
* @returns The composed URI string
|
|
1176
|
-
* @throws Error if resource is not set
|
|
1631
|
+
* Pagination-only driver — no filtering, sorting, or column selection
|
|
1177
1632
|
*/
|
|
1178
|
-
|
|
1633
|
+
readonly capabilities: IStrategyCapabilities;
|
|
1179
1634
|
/**
|
|
1180
|
-
*
|
|
1181
|
-
*
|
|
1182
|
-
* Laravel pagination does not recognize `-1` as a "fetch all" sentinel,
|
|
1183
|
-
* so only positive integers are accepted.
|
|
1635
|
+
* Emit only the pagination params; filters/sorts/etc. are ignored
|
|
1184
1636
|
*
|
|
1185
|
-
* @param
|
|
1186
|
-
* @
|
|
1637
|
+
* @param state - The current query builder state
|
|
1638
|
+
* @param options - The query parameter key name configuration
|
|
1639
|
+
* @returns The two pagination query-string fragments
|
|
1187
1640
|
*/
|
|
1188
|
-
|
|
1641
|
+
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
1189
1642
|
}
|
|
1190
1643
|
|
|
1191
1644
|
/**
|
|
@@ -1228,20 +1681,12 @@ declare class LaravelResponseStrategy implements IResponseStrategy {
|
|
|
1228
1681
|
*
|
|
1229
1682
|
* @see https://github.com/ppetzold/nestjs-paginate
|
|
1230
1683
|
*/
|
|
1231
|
-
declare class NestjsRequestStrategy
|
|
1684
|
+
declare class NestjsRequestStrategy extends AbstractRequestStrategy {
|
|
1232
1685
|
/**
|
|
1233
|
-
*
|
|
1686
|
+
* Filters, operator filters, sorts, flat select, global search — no
|
|
1687
|
+
* per-model fields, no includes
|
|
1234
1688
|
*/
|
|
1235
|
-
|
|
1236
|
-
/**
|
|
1237
|
-
* Build a URI string from the given state using the NestJS paginate format
|
|
1238
|
-
*
|
|
1239
|
-
* @param state - The current query builder state
|
|
1240
|
-
* @param options - The query parameter key name configuration
|
|
1241
|
-
* @returns The composed URI string
|
|
1242
|
-
* @throws Error if model is not set
|
|
1243
|
-
*/
|
|
1244
|
-
buildUri(state: IQueryBuilderState, options: QueryBuilderOptions): string;
|
|
1689
|
+
readonly capabilities: IStrategyCapabilities;
|
|
1245
1690
|
/**
|
|
1246
1691
|
* Validate that the given limit is accepted by nestjs-paginate
|
|
1247
1692
|
*
|
|
@@ -1253,76 +1698,72 @@ declare class NestjsRequestStrategy implements IRequestStrategy {
|
|
|
1253
1698
|
*/
|
|
1254
1699
|
validateLimit(limit: number): void;
|
|
1255
1700
|
/**
|
|
1256
|
-
*
|
|
1257
|
-
*
|
|
1258
|
-
* Generates: `filter.field=value1,value2` for each filter
|
|
1701
|
+
* Emit NestJS-format query-string segments in canonical order:
|
|
1702
|
+
* filters → operator filters → sortBy → select → search → limit → page
|
|
1259
1703
|
*
|
|
1260
1704
|
* @param state - The current query builder state
|
|
1261
1705
|
* @param options - The query parameter key name configuration
|
|
1706
|
+
* @returns Ordered query-string fragments
|
|
1262
1707
|
*/
|
|
1263
|
-
|
|
1708
|
+
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
1264
1709
|
/**
|
|
1265
|
-
*
|
|
1710
|
+
* Append simple filter parameters as `filter.field=value1,value2`
|
|
1266
1711
|
*
|
|
1267
1712
|
* @param state - The current query builder state
|
|
1268
1713
|
* @param options - The query parameter key name configuration
|
|
1714
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1269
1715
|
*/
|
|
1270
|
-
private
|
|
1716
|
+
private _appendFilters;
|
|
1271
1717
|
/**
|
|
1272
|
-
*
|
|
1273
|
-
*
|
|
1274
|
-
* Groups operator filters by field and generates:
|
|
1275
|
-
* - Single value: `filter.field=$operator:value`
|
|
1276
|
-
* - Multiple values ($in, $btw): `filter.field=$operator:val1,val2`
|
|
1718
|
+
* Append the limit parameter
|
|
1277
1719
|
*
|
|
1278
1720
|
* @param state - The current query builder state
|
|
1279
1721
|
* @param options - The query parameter key name configuration
|
|
1722
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1280
1723
|
*/
|
|
1281
|
-
private
|
|
1724
|
+
private _appendLimit;
|
|
1282
1725
|
/**
|
|
1283
|
-
*
|
|
1726
|
+
* Append operator-filter parameters as `filter.field=$op:value`
|
|
1727
|
+
*
|
|
1728
|
+
* Groups by field; multi-value operators ($in, $btw) join values with commas.
|
|
1284
1729
|
*
|
|
1285
1730
|
* @param state - The current query builder state
|
|
1286
1731
|
* @param options - The query parameter key name configuration
|
|
1732
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1287
1733
|
*/
|
|
1288
|
-
private
|
|
1734
|
+
private _appendOperatorFilters;
|
|
1289
1735
|
/**
|
|
1290
|
-
*
|
|
1291
|
-
*
|
|
1292
|
-
* Generates: `search=term`
|
|
1736
|
+
* Append the page parameter
|
|
1293
1737
|
*
|
|
1294
1738
|
* @param state - The current query builder state
|
|
1295
1739
|
* @param options - The query parameter key name configuration
|
|
1740
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1296
1741
|
*/
|
|
1297
|
-
private
|
|
1742
|
+
private _appendPage;
|
|
1298
1743
|
/**
|
|
1299
|
-
*
|
|
1300
|
-
*
|
|
1301
|
-
* Generates: `select=col1,col2`
|
|
1744
|
+
* Append the search parameter as `search=term`
|
|
1302
1745
|
*
|
|
1303
1746
|
* @param state - The current query builder state
|
|
1304
1747
|
* @param options - The query parameter key name configuration
|
|
1748
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1305
1749
|
*/
|
|
1306
|
-
private
|
|
1750
|
+
private _appendSearch;
|
|
1307
1751
|
/**
|
|
1308
|
-
*
|
|
1309
|
-
*
|
|
1310
|
-
* Generates: `sortBy=field1:DESC,field2:ASC`
|
|
1752
|
+
* Append the select parameter as `select=col1,col2`
|
|
1311
1753
|
*
|
|
1312
1754
|
* @param state - The current query builder state
|
|
1313
1755
|
* @param options - The query parameter key name configuration
|
|
1756
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1314
1757
|
*/
|
|
1315
|
-
private
|
|
1758
|
+
private _appendSelect;
|
|
1316
1759
|
/**
|
|
1317
|
-
*
|
|
1318
|
-
*
|
|
1319
|
-
* Returns the full base path with `?` for the first parameter,
|
|
1320
|
-
* or `&` for subsequent parameters.
|
|
1760
|
+
* Append sort parameter as `sortBy=field1:DESC,field2:ASC`
|
|
1321
1761
|
*
|
|
1322
1762
|
* @param state - The current query builder state
|
|
1323
|
-
* @
|
|
1763
|
+
* @param options - The query parameter key name configuration
|
|
1764
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1324
1765
|
*/
|
|
1325
|
-
private
|
|
1766
|
+
private _appendSort;
|
|
1326
1767
|
}
|
|
1327
1768
|
|
|
1328
1769
|
/**
|
|
@@ -1348,60 +1789,214 @@ declare class NestjsRequestStrategy implements IRequestStrategy {
|
|
|
1348
1789
|
* }
|
|
1349
1790
|
* ```
|
|
1350
1791
|
*
|
|
1792
|
+
* Default key paths are configured in `NestjsResponseOptions`. The
|
|
1793
|
+
* traversal algorithm (dot-notation resolution + computed `from`/`to`) is
|
|
1794
|
+
* inherited from `AbstractDotPathResponseStrategy`; this class exists so
|
|
1795
|
+
* `DriverEnum.NESTJS` resolves to a distinct identity at the DI layer
|
|
1796
|
+
* even though the parsing logic is shared with JSON:API.
|
|
1797
|
+
*
|
|
1351
1798
|
* @see https://github.com/ppetzold/nestjs-paginate
|
|
1352
1799
|
*/
|
|
1353
|
-
declare class NestjsResponseStrategy
|
|
1800
|
+
declare class NestjsResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
/**
|
|
1804
|
+
* Request strategy for the PostgREST driver
|
|
1805
|
+
*
|
|
1806
|
+
* PostgREST auto-generates REST APIs from PostgreSQL schemas and is the
|
|
1807
|
+
* backbone of Supabase's data API. This strategy produces URIs in
|
|
1808
|
+
* PostgREST's native query-string format:
|
|
1809
|
+
*
|
|
1810
|
+
* - Filters: `col=eq.val` (single value) / `col=in.(v1,v2,v3)` (multi-value)
|
|
1811
|
+
* - Order: `order=col1.asc,col2.desc`
|
|
1812
|
+
* - Select: `select=col1,col2`
|
|
1813
|
+
* - Pagination: `limit=N&offset=M` (offset derived from state.page)
|
|
1814
|
+
*
|
|
1815
|
+
* The `order` and `offset` query-parameter names are PostgREST conventions
|
|
1816
|
+
* and are intentionally not configurable via `QueryBuilderOptions` (see
|
|
1817
|
+
* issue #50 MVP scope). `limit`, `select`, and `filters` (per-column name)
|
|
1818
|
+
* honour the existing option keys.
|
|
1819
|
+
*
|
|
1820
|
+
* @see https://postgrest.org/en/stable/api.html
|
|
1821
|
+
* @see https://supabase.com/docs/reference/javascript/select
|
|
1822
|
+
*/
|
|
1823
|
+
declare class PostgrestRequestStrategy extends AbstractRequestStrategy {
|
|
1354
1824
|
/**
|
|
1355
|
-
*
|
|
1825
|
+
* Filters, operator filters (incl. FTS), sorts, flat select — no
|
|
1826
|
+
* per-model fields, no JSON:API/Spatie-style includes, no global
|
|
1827
|
+
* search (per-column FTS via the operator family covers it)
|
|
1828
|
+
*/
|
|
1829
|
+
readonly capabilities: IStrategyCapabilities;
|
|
1830
|
+
private static readonly _offsetKey;
|
|
1831
|
+
private static readonly _orderKey;
|
|
1832
|
+
/**
|
|
1833
|
+
* Active pagination mode
|
|
1356
1834
|
*
|
|
1357
|
-
*
|
|
1358
|
-
*
|
|
1359
|
-
*
|
|
1835
|
+
* QUERY (default) → URL emits limit/offset.
|
|
1836
|
+
* RANGE → URL omits them; `buildPaginationHeaders()` returns the
|
|
1837
|
+
* `Range-Unit` / `Range` HTTP headers instead.
|
|
1838
|
+
*/
|
|
1839
|
+
private readonly _paginationMode;
|
|
1840
|
+
/**
|
|
1841
|
+
* @param paginationMode - Wire-level pagination mechanism. Defaults to
|
|
1842
|
+
* `PaginationModeEnum.QUERY`; `provideNgQubee` wires this from
|
|
1843
|
+
* `IConfig.pagination`.
|
|
1844
|
+
*/
|
|
1845
|
+
constructor(paginationMode?: PaginationModeEnum);
|
|
1846
|
+
/**
|
|
1847
|
+
* Compute `Range-Unit` / `Range` HTTP headers for RANGE pagination mode
|
|
1360
1848
|
*
|
|
1361
|
-
*
|
|
1362
|
-
*
|
|
1363
|
-
*
|
|
1849
|
+
* In QUERY mode this returns `null` so `NgQubeeService.paginationHeaders()`
|
|
1850
|
+
* conveys "no headers needed" to the consumer. In RANGE mode the method
|
|
1851
|
+
* converts the 1-indexed `state.page` + `state.limit` into PostgREST's
|
|
1852
|
+
* 0-indexed inclusive range (`from = (page - 1) * limit`,
|
|
1853
|
+
* `to = from + limit - 1`) and returns both header values.
|
|
1854
|
+
*
|
|
1855
|
+
* @param state - The current query builder state
|
|
1856
|
+
* @returns `{ 'Range-Unit': 'items', 'Range': 'from-to' }` or `null`
|
|
1364
1857
|
*/
|
|
1365
|
-
|
|
1858
|
+
buildPaginationHeaders(state: IQueryBuilderState): Record<string, string> | null;
|
|
1366
1859
|
/**
|
|
1367
|
-
*
|
|
1860
|
+
* Emit PostgREST-format query-string segments in canonical order:
|
|
1861
|
+
* filters → operator filters → order → select → (limit + offset in
|
|
1862
|
+
* QUERY mode only — RANGE mode passes pagination via headers instead)
|
|
1368
1863
|
*
|
|
1369
|
-
*
|
|
1864
|
+
* @param state - The current query builder state
|
|
1865
|
+
* @param options - The query parameter key name configuration
|
|
1866
|
+
* @returns Ordered query-string fragments
|
|
1867
|
+
*/
|
|
1868
|
+
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
1869
|
+
/**
|
|
1870
|
+
* Append filter parameters in PostgREST format
|
|
1370
1871
|
*
|
|
1371
|
-
*
|
|
1372
|
-
*
|
|
1373
|
-
*
|
|
1872
|
+
* Every filter is operator-prefixed (PostgREST has no implicit equality):
|
|
1873
|
+
* a single value yields `col=eq.val`; multiple values collapse into
|
|
1874
|
+
* PostgREST's native IN-list syntax `col=in.(v1,v2,v3)`.
|
|
1875
|
+
*
|
|
1876
|
+
* @param state - The current query builder state
|
|
1877
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1374
1878
|
*/
|
|
1375
|
-
private
|
|
1879
|
+
private _appendFilters;
|
|
1376
1880
|
/**
|
|
1377
|
-
*
|
|
1881
|
+
* Append the limit parameter
|
|
1378
1882
|
*
|
|
1379
|
-
*
|
|
1380
|
-
*
|
|
1381
|
-
*
|
|
1883
|
+
* @param state - The current query builder state
|
|
1884
|
+
* @param options - The query parameter key name configuration
|
|
1885
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1886
|
+
*/
|
|
1887
|
+
private _appendLimit;
|
|
1888
|
+
/**
|
|
1889
|
+
* Append the offset parameter, derived from state.page
|
|
1382
1890
|
*
|
|
1383
|
-
*
|
|
1384
|
-
*
|
|
1385
|
-
*
|
|
1386
|
-
*
|
|
1387
|
-
*
|
|
1891
|
+
* PostgREST uses offset-based pagination, not page-based. The offset is
|
|
1892
|
+
* computed as `(page - 1) * limit`. Omitted when offset would be 0
|
|
1893
|
+
* (i.e. page 1) since PostgREST defaults to offset=0 anyway and dropping
|
|
1894
|
+
* it keeps the URI shorter.
|
|
1895
|
+
*
|
|
1896
|
+
* @param state - The current query builder state
|
|
1897
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1388
1898
|
*/
|
|
1389
|
-
private
|
|
1899
|
+
private _appendOffset;
|
|
1390
1900
|
/**
|
|
1391
|
-
*
|
|
1901
|
+
* Append explicit operator filters
|
|
1392
1902
|
*
|
|
1393
|
-
*
|
|
1394
|
-
*
|
|
1395
|
-
* `
|
|
1903
|
+
* Maps each `FilterOperatorEnum` value to PostgREST's prefix-operator
|
|
1904
|
+
* syntax. `BTW` expands to two query params (`gte` + `lte`); `NULL`
|
|
1905
|
+
* emits `is.null` / `is.not.null` based on the boolean value; `NOT`
|
|
1906
|
+
* picks its inner operator by arity (`not.eq.val` for single values,
|
|
1907
|
+
* `not.in.(v1,v2)` for multi-value).
|
|
1396
1908
|
*
|
|
1397
|
-
* @param
|
|
1398
|
-
* @param
|
|
1399
|
-
* @
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1909
|
+
* @param state - The current query builder state
|
|
1910
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1911
|
+
* @throws {InvalidFilterOperatorValueError} If `BTW` does not receive exactly 2 values, or `NULL` does not receive exactly 1 boolean
|
|
1912
|
+
*/
|
|
1913
|
+
private _appendOperatorFilters;
|
|
1914
|
+
/**
|
|
1915
|
+
* Append a `BTW` operator filter as two PostgREST segments
|
|
1916
|
+
*
|
|
1917
|
+
* Produces: `col=gte.min` and `col=lte.max`. Values must be exactly
|
|
1918
|
+
* `[min, max]`.
|
|
1919
|
+
*
|
|
1920
|
+
* @param filter - The operator filter carrying the BTW bounds
|
|
1921
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1922
|
+
* @throws {InvalidFilterOperatorValueError} If values.length !== 2
|
|
1923
|
+
*/
|
|
1924
|
+
private _appendBetweenFilter;
|
|
1925
|
+
/**
|
|
1926
|
+
* Build the right-hand-side of a PostgREST filter param for the given operator
|
|
1927
|
+
*
|
|
1928
|
+
* Kept as a separate helper so each operator's shape is visible in one
|
|
1929
|
+
* place and the dispatch is exhaustively typed against
|
|
1930
|
+
* `FilterOperatorEnum`.
|
|
1931
|
+
*
|
|
1932
|
+
* @param filter - The operator filter (field, operator, values)
|
|
1933
|
+
* @returns The PostgREST-formatted value portion (right of the `=` sign)
|
|
1934
|
+
* @throws {InvalidFilterOperatorValueError} If NULL receives a non-boolean or wrong arity
|
|
1935
|
+
*/
|
|
1936
|
+
private _formatOperatorRhs;
|
|
1937
|
+
/**
|
|
1938
|
+
* Append the order parameter as `order=col1.asc,col2.desc`
|
|
1939
|
+
*
|
|
1940
|
+
* @param state - The current query builder state
|
|
1941
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1403
1942
|
*/
|
|
1404
|
-
private
|
|
1943
|
+
private _appendOrder;
|
|
1944
|
+
/**
|
|
1945
|
+
* Append the select parameter as `select=col1,col2`
|
|
1946
|
+
*
|
|
1947
|
+
* PostgREST uses a `select` query param for column pruning, matching
|
|
1948
|
+
* NestJS semantics.
|
|
1949
|
+
*
|
|
1950
|
+
* @param state - The current query builder state
|
|
1951
|
+
* @param options - The query parameter key name configuration
|
|
1952
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1953
|
+
*/
|
|
1954
|
+
private _appendSelect;
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
/**
|
|
1958
|
+
* Response strategy for the PostgREST driver
|
|
1959
|
+
*
|
|
1960
|
+
* PostgREST (and Supabase, which wraps it) returns a bare array body for
|
|
1961
|
+
* collection endpoints. Pagination metadata is carried in the
|
|
1962
|
+
* `Content-Range` HTTP response header, e.g. `0-9/50` meaning "items 0–9
|
|
1963
|
+
* out of 50 total". Consumers opt into totals by sending the
|
|
1964
|
+
* `Prefer: count=exact` request header.
|
|
1965
|
+
*
|
|
1966
|
+
* This strategy expects the consumer to pass the array body as `response`
|
|
1967
|
+
* (or a plain object with `response[options.data]` pointing at the array)
|
|
1968
|
+
* and the response headers via the optional `headers` bag. See
|
|
1969
|
+
* `PaginationService.paginate()` for the call-site shape.
|
|
1970
|
+
*
|
|
1971
|
+
* @see https://postgrest.org/en/stable/references/api/pagination_count.html
|
|
1972
|
+
*/
|
|
1973
|
+
declare class PostgrestResponseStrategy implements IResponseStrategy {
|
|
1974
|
+
private static readonly _contentRangeHeader;
|
|
1975
|
+
private static readonly _contentRangeRegex;
|
|
1976
|
+
/**
|
|
1977
|
+
* Parse a PostgREST response into a typed PaginatedCollection
|
|
1978
|
+
*
|
|
1979
|
+
* @param response - The raw response. Either the array body directly, or
|
|
1980
|
+
* an object with the array at `response[options.data]`.
|
|
1981
|
+
* @param options - The response key configuration (only `options.data` is
|
|
1982
|
+
* consulted; all pagination metadata comes from the Content-Range header).
|
|
1983
|
+
* @param headers - Optional HTTP response headers. The `Content-Range`
|
|
1984
|
+
* header drives page/total derivation; omission is tolerated and yields
|
|
1985
|
+
* a collection with `undefined` bounds (auto-sync will leave
|
|
1986
|
+
* `isLastPageKnown` at `false`).
|
|
1987
|
+
* @returns A typed PaginatedCollection instance
|
|
1988
|
+
*/
|
|
1989
|
+
paginate<T extends IPaginatedObject>(response: Record<string, unknown>, options: ResponseOptions, headers?: HeaderBag): PaginatedCollection<T>;
|
|
1990
|
+
/**
|
|
1991
|
+
* Extract `{from, to, total}` from a PostgREST `Content-Range` value
|
|
1992
|
+
*
|
|
1993
|
+
* Expected format: `<from>-<to>/<total|*>`. Any shape mismatch returns
|
|
1994
|
+
* an empty object; `*` as the total yields `total: undefined`.
|
|
1995
|
+
*
|
|
1996
|
+
* @param value - Raw header value (possibly null/undefined)
|
|
1997
|
+
* @returns Parsed integers; missing fields indicate an unparseable header
|
|
1998
|
+
*/
|
|
1999
|
+
private _parseContentRange;
|
|
1405
2000
|
}
|
|
1406
2001
|
|
|
1407
2002
|
/**
|
|
@@ -1416,99 +2011,74 @@ declare class NestjsResponseStrategy implements IResponseStrategy {
|
|
|
1416
2011
|
*
|
|
1417
2012
|
* @see https://spatie.be/docs/laravel-query-builder
|
|
1418
2013
|
*/
|
|
1419
|
-
declare class SpatieRequestStrategy
|
|
2014
|
+
declare class SpatieRequestStrategy extends AbstractRequestStrategy {
|
|
1420
2015
|
/**
|
|
1421
|
-
*
|
|
2016
|
+
* Filters, sorts, includes, per-model fields — no operators, no flat
|
|
2017
|
+
* select, no global search
|
|
1422
2018
|
*/
|
|
1423
|
-
|
|
2019
|
+
readonly capabilities: IStrategyCapabilities;
|
|
1424
2020
|
/**
|
|
1425
|
-
*
|
|
2021
|
+
* Emit Spatie-format query-string segments in canonical order:
|
|
2022
|
+
* include → fields → filters → limit → page → sort
|
|
1426
2023
|
*
|
|
1427
2024
|
* @param state - The current query builder state
|
|
1428
2025
|
* @param options - The query parameter key name configuration
|
|
1429
|
-
* @returns
|
|
1430
|
-
* @throws Error if resource is not set
|
|
1431
|
-
*/
|
|
1432
|
-
buildUri(state: IQueryBuilderState, options: QueryBuilderOptions): string;
|
|
1433
|
-
/**
|
|
1434
|
-
* Validate that the given limit is accepted by the Spatie driver
|
|
1435
|
-
*
|
|
1436
|
-
* Spatie query-builder does not recognize `-1` as a "fetch all" sentinel,
|
|
1437
|
-
* so only positive integers are accepted.
|
|
1438
|
-
*
|
|
1439
|
-
* @param limit - The limit value to validate
|
|
1440
|
-
* @throws {InvalidLimitError} If the value is not a positive integer
|
|
2026
|
+
* @returns Ordered query-string fragments
|
|
1441
2027
|
*/
|
|
1442
|
-
|
|
2028
|
+
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
1443
2029
|
/**
|
|
1444
|
-
*
|
|
2030
|
+
* Append per-model field selection in bracket notation
|
|
1445
2031
|
*
|
|
1446
2032
|
* Validates that each field model exists either as the main resource
|
|
1447
|
-
* or in the includes list.
|
|
2033
|
+
* or in the includes list.
|
|
1448
2034
|
*
|
|
1449
2035
|
* @param state - The current query builder state
|
|
1450
2036
|
* @param options - The query parameter key name configuration
|
|
1451
|
-
* @
|
|
1452
|
-
* @throws Error if resource is required but not set
|
|
2037
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2038
|
+
* @throws Error if the resource is required but not set
|
|
1453
2039
|
* @throws UnselectableModelError if a field model is not in resource or includes
|
|
1454
2040
|
*/
|
|
1455
|
-
private
|
|
2041
|
+
private _appendFields;
|
|
1456
2042
|
/**
|
|
1457
|
-
*
|
|
1458
|
-
*
|
|
1459
|
-
* Generates filter parameters in bracket notation: `filter[key]=value1,value2`
|
|
2043
|
+
* Append filter parameters in bracket notation: `filter[key]=value`
|
|
1460
2044
|
*
|
|
1461
2045
|
* @param state - The current query builder state
|
|
1462
2046
|
* @param options - The query parameter key name configuration
|
|
1463
|
-
* @
|
|
2047
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1464
2048
|
*/
|
|
1465
|
-
private
|
|
2049
|
+
private _appendFilters;
|
|
1466
2050
|
/**
|
|
1467
|
-
*
|
|
1468
|
-
*
|
|
1469
|
-
* Generates: `include=model1,model2`
|
|
2051
|
+
* Append include parameter as `include=model1,model2`
|
|
1470
2052
|
*
|
|
1471
2053
|
* @param state - The current query builder state
|
|
1472
2054
|
* @param options - The query parameter key name configuration
|
|
1473
|
-
* @
|
|
2055
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1474
2056
|
*/
|
|
1475
|
-
private
|
|
2057
|
+
private _appendIncludes;
|
|
1476
2058
|
/**
|
|
1477
|
-
*
|
|
2059
|
+
* Append the limit parameter
|
|
1478
2060
|
*
|
|
1479
2061
|
* @param state - The current query builder state
|
|
1480
2062
|
* @param options - The query parameter key name configuration
|
|
1481
|
-
* @
|
|
2063
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1482
2064
|
*/
|
|
1483
|
-
private
|
|
2065
|
+
private _appendLimit;
|
|
1484
2066
|
/**
|
|
1485
|
-
*
|
|
2067
|
+
* Append the page parameter
|
|
1486
2068
|
*
|
|
1487
2069
|
* @param state - The current query builder state
|
|
1488
2070
|
* @param options - The query parameter key name configuration
|
|
1489
|
-
* @
|
|
2071
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1490
2072
|
*/
|
|
1491
|
-
private
|
|
2073
|
+
private _appendPage;
|
|
1492
2074
|
/**
|
|
1493
|
-
*
|
|
1494
|
-
*
|
|
1495
|
-
* Generates: `sort=-field1,field2` where `-` prefix indicates DESC order
|
|
2075
|
+
* Append sort parameter as `sort=-field1,field2` (`-` prefix = DESC)
|
|
1496
2076
|
*
|
|
1497
2077
|
* @param state - The current query builder state
|
|
1498
2078
|
* @param options - The query parameter key name configuration
|
|
1499
|
-
* @
|
|
1500
|
-
*/
|
|
1501
|
-
private _parseSort;
|
|
1502
|
-
/**
|
|
1503
|
-
* Determine the appropriate URI prefix based on the current accumulator state
|
|
1504
|
-
*
|
|
1505
|
-
* Returns the full base path with `?` for the first parameter,
|
|
1506
|
-
* or `&` for subsequent parameters.
|
|
1507
|
-
*
|
|
1508
|
-
* @param state - The current query builder state
|
|
1509
|
-
* @returns The prefix string to prepend to the next parameter
|
|
2079
|
+
* @param out - The accumulator the caller joins into the URI
|
|
1510
2080
|
*/
|
|
1511
|
-
private
|
|
2081
|
+
private _appendSort;
|
|
1512
2082
|
}
|
|
1513
2083
|
|
|
1514
2084
|
/**
|
|
@@ -1540,5 +2110,5 @@ declare class SpatieResponseStrategy implements IResponseStrategy {
|
|
|
1540
2110
|
paginate<T extends IPaginatedObject>(response: Record<string, any>, options: ResponseOptions): PaginatedCollection<T>;
|
|
1541
2111
|
}
|
|
1542
2112
|
|
|
1543
|
-
export { DriverEnum, FilterOperatorEnum, InvalidLimitError, InvalidPageNumberError, InvalidResourceNameError, JsonApiRequestStrategy, JsonApiResponseStrategy, KeyNotFoundError, LaravelRequestStrategy, LaravelResponseStrategy, NestjsRequestStrategy, NestjsResponseStrategy, NgQubeeModule, NgQubeeService, PaginatedCollection, PaginationService, SortEnum, SpatieRequestStrategy, SpatieResponseStrategy, UnselectableModelError, UnsupportedFieldSelectionError, UnsupportedFilterError, UnsupportedFilterOperatorError, UnsupportedIncludesError, UnsupportedSearchError, UnsupportedSelectError, UnsupportedSortError, provideNgQubee };
|
|
1544
|
-
export type { IConfig, IFields, IFilters, INestState, IOperatorFilter, IPage, IPaginatedObject, IPaginationConfig, IQueryBuilderConfig, IQueryBuilderState, IRequestStrategy, IResponseStrategy, ISort };
|
|
2113
|
+
export { DriverEnum, FilterOperatorEnum, InvalidFilterOperatorValueError, InvalidLimitError, InvalidPageNumberError, InvalidResourceNameError, JsonApiRequestStrategy, JsonApiResponseStrategy, KeyNotFoundError, LaravelRequestStrategy, LaravelResponseStrategy, NG_QUBEE_DRIVER, NG_QUBEE_REQUEST_OPTIONS, NG_QUBEE_REQUEST_STRATEGY, NG_QUBEE_RESPONSE_OPTIONS, NG_QUBEE_RESPONSE_STRATEGY, NestjsRequestStrategy, NestjsResponseStrategy, NgQubeeModule, NgQubeeService, PaginatedCollection, PaginationModeEnum, PaginationNotSyncedError, PaginationService, PostgrestRequestStrategy, PostgrestResponseStrategy, SortEnum, SpatieRequestStrategy, SpatieResponseStrategy, UnselectableModelError, UnsupportedFieldSelectionError, UnsupportedFilterError, UnsupportedFilterOperatorError, UnsupportedIncludesError, UnsupportedSearchError, UnsupportedSelectError, UnsupportedSortError, buildNgQubeeProviders, provideNgQubee, provideNgQubeeInstance, readHeader };
|
|
2114
|
+
export type { HeaderBag, IConfig, IFields, IFilters, INestState, IOperatorFilter, IPage, IPaginatedObject, IPaginationConfig, IQueryBuilderConfig, IQueryBuilderState, IRequestStrategy, IResponseStrategy, ISort };
|