ng-qubee 3.6.0 → 3.7.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 +11 -3
- package/fesm2022/ng-qubee.mjs +4113 -931
- package/fesm2022/ng-qubee.mjs.map +1 -1
- package/package.json +17 -2
- package/types/ng-qubee.d.ts +2695 -599
package/types/ng-qubee.d.ts
CHANGED
|
@@ -40,39 +40,52 @@ declare class PaginatedCollection<T extends IPaginatedObject> {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
*
|
|
43
|
+
* Configuration interface for customizing request query parameter key names
|
|
44
44
|
*
|
|
45
|
-
* Each
|
|
46
|
-
*
|
|
45
|
+
* Each property maps a logical query concept to the actual query parameter name
|
|
46
|
+
* used in the generated URI. The defaults depend on the selected driver.
|
|
47
47
|
*/
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
48
|
+
interface IQueryBuilderConfig {
|
|
49
|
+
/** Key for the appends parameter (Laravel only, default: 'append') */
|
|
50
|
+
appends?: string;
|
|
51
|
+
/** Key for the fields parameter (Laravel: 'fields', NestJS: 'select') */
|
|
52
|
+
fields?: string;
|
|
53
|
+
/** Key for the filters parameter (default: 'filter') */
|
|
54
|
+
filters?: string;
|
|
55
|
+
/** Key for the includes parameter (Laravel only, default: 'include') */
|
|
56
|
+
includes?: string;
|
|
57
|
+
/** Key for the limit parameter (default: 'limit') */
|
|
58
|
+
limit?: string;
|
|
59
|
+
/** Key for the page parameter (default: 'page') */
|
|
60
|
+
page?: string;
|
|
61
|
+
/** Key for the search parameter (NestJS only, default: 'search') */
|
|
62
|
+
search?: string;
|
|
63
|
+
/** Key for the select parameter (NestJS only, default: 'select') */
|
|
64
|
+
select?: string;
|
|
65
|
+
/** Key for the sort parameter (Laravel: 'sort', NestJS: 'sortBy') */
|
|
66
|
+
sort?: string;
|
|
67
|
+
/** Key for the sortBy parameter (NestJS only, default: 'sortBy') */
|
|
68
|
+
sortBy?: string;
|
|
59
69
|
}
|
|
60
70
|
|
|
61
71
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* `QUERY` (default) — the request strategy emits `limit` and `offset` (or
|
|
65
|
-
* equivalent) query parameters on the URL.
|
|
72
|
+
* Resolved query parameter key names with defaults applied
|
|
66
73
|
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* `NgQubeeService.paginationHeaders()`. Currently honoured only by the
|
|
70
|
-
* PostgREST driver, which maps it to `Range-Unit: items` + `Range: 0-9`.
|
|
71
|
-
* Other drivers ignore the setting.
|
|
74
|
+
* Maps logical query concepts to the actual query parameter names
|
|
75
|
+
* used in the generated URI. Unset values fall back to defaults.
|
|
72
76
|
*/
|
|
73
|
-
declare
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
declare class QueryBuilderOptions {
|
|
78
|
+
readonly appends: string;
|
|
79
|
+
readonly fields: string;
|
|
80
|
+
readonly filters: string;
|
|
81
|
+
readonly includes: string;
|
|
82
|
+
readonly limit: string;
|
|
83
|
+
readonly page: string;
|
|
84
|
+
readonly search: string;
|
|
85
|
+
readonly select: string;
|
|
86
|
+
readonly sort: string;
|
|
87
|
+
readonly sortBy: string;
|
|
88
|
+
constructor(options: IQueryBuilderConfig);
|
|
76
89
|
}
|
|
77
90
|
|
|
78
91
|
/**
|
|
@@ -112,32 +125,264 @@ interface IPaginationConfig {
|
|
|
112
125
|
}
|
|
113
126
|
|
|
114
127
|
/**
|
|
115
|
-
*
|
|
128
|
+
* Resolved response field key names with defaults applied
|
|
116
129
|
*
|
|
117
|
-
*
|
|
118
|
-
* used in the
|
|
130
|
+
* Maps logical pagination concepts to the actual key names
|
|
131
|
+
* used in the API response. Unset values fall back to Laravel defaults.
|
|
132
|
+
*
|
|
133
|
+
* For NestJS responses, use dot-notation paths:
|
|
134
|
+
* ```typescript
|
|
135
|
+
* new ResponseOptions({
|
|
136
|
+
* currentPage: 'meta.currentPage',
|
|
137
|
+
* total: 'meta.totalItems'
|
|
138
|
+
* });
|
|
139
|
+
* ```
|
|
119
140
|
*/
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
+
declare class ResponseOptions {
|
|
142
|
+
readonly currentPage: string;
|
|
143
|
+
readonly data: string;
|
|
144
|
+
readonly firstPageUrl: string;
|
|
145
|
+
readonly from: string;
|
|
146
|
+
readonly lastPage: string;
|
|
147
|
+
readonly lastPageUrl: string;
|
|
148
|
+
readonly nextPageUrl: string;
|
|
149
|
+
readonly path: string;
|
|
150
|
+
readonly perPage: string;
|
|
151
|
+
readonly prevPageUrl: string;
|
|
152
|
+
readonly to: string;
|
|
153
|
+
readonly total: string;
|
|
154
|
+
constructor(options: IPaginationConfig);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Pre-configured ResponseOptions for the API Platform (Symfony) driver
|
|
158
|
+
*
|
|
159
|
+
* Uses dot-notation paths into the Hydra/JSON-LD envelope — the Hydra
|
|
160
|
+
* keys contain colons but no dots, so `hydra:view.hydra:next` traverses
|
|
161
|
+
* `response['hydra:view']['hydra:next']`. The `path` slot points at the
|
|
162
|
+
* view's `@id`, which the strategy parses for the current page and page
|
|
163
|
+
* size; `currentPage` / `perPage` / `lastPage` have no body field and
|
|
164
|
+
* default to empty paths (derived from the view URLs instead).
|
|
165
|
+
*/
|
|
166
|
+
declare class ApiPlatformResponseOptions extends ResponseOptions {
|
|
167
|
+
constructor(options: IPaginationConfig);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Pre-configured ResponseOptions for the Directus driver
|
|
171
|
+
*
|
|
172
|
+
* The Directus envelope is `{ data, meta: { total_count, filter_count } }`
|
|
173
|
+
* (with `meta=total_count,filter_count` requested — the request strategy
|
|
174
|
+
* always emits it). `total` defaults to `meta.filter_count`, the count of
|
|
175
|
+
* items matching the current filter; point it at `meta.total_count` via
|
|
176
|
+
* `IPaginationConfig` for the unfiltered collection size. The envelope
|
|
177
|
+
* names no current page, page size, or navigation URLs, so those paths
|
|
178
|
+
* default to empty strings — the strategy falls back to page 1 and
|
|
179
|
+
* derives `lastPage`/`from`/`to` only when the response provably holds
|
|
180
|
+
* the whole filtered set. All paths are overridable (dot notation
|
|
181
|
+
* supported) for custom wrappers that do include paging fields.
|
|
182
|
+
*/
|
|
183
|
+
declare class DirectusResponseOptions extends ResponseOptions {
|
|
184
|
+
constructor(options: IPaginationConfig);
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Pre-configured ResponseOptions for the Django REST Framework (DRF) driver
|
|
188
|
+
*
|
|
189
|
+
* DRF's `PageNumberPagination` envelope is `{ count, next, previous,
|
|
190
|
+
* results }`, with no body field naming the current page, per-page, or
|
|
191
|
+
* last-page. The strategy parses those from the `next` / `previous`
|
|
192
|
+
* URLs, so the corresponding key paths default to empty strings; the
|
|
193
|
+
* strategy ignores `options.currentPage`, `options.perPage`,
|
|
194
|
+
* `options.lastPage`, `options.from`, `options.to`, `options.path`,
|
|
195
|
+
* `options.firstPageUrl`, and `options.lastPageUrl`.
|
|
196
|
+
*/
|
|
197
|
+
declare class DrfResponseOptions extends ResponseOptions {
|
|
198
|
+
constructor(options: IPaginationConfig);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Pre-configured ResponseOptions for the FeathersJS driver
|
|
202
|
+
*
|
|
203
|
+
* The Feathers adapter envelope is `{ total, limit, skip, data }` —
|
|
204
|
+
* offset-based, with no page number and no navigation URLs. `perPage`
|
|
205
|
+
* maps to the envelope's `limit` key and `total` to `total`; the
|
|
206
|
+
* strategy derives `currentPage` / `lastPage` / `from` / `to` from
|
|
207
|
+
* `skip` and `limit`, so the corresponding key paths default to empty
|
|
208
|
+
* strings (the `skip` key itself is fixed by the envelope and read
|
|
209
|
+
* directly by the strategy).
|
|
210
|
+
*/
|
|
211
|
+
declare class FeathersResponseOptions extends ResponseOptions {
|
|
212
|
+
constructor(options: IPaginationConfig);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Pre-configured ResponseOptions for the JSON:API driver
|
|
216
|
+
*
|
|
217
|
+
* Uses dot-notation paths to access nested values in the JSON:API response format.
|
|
218
|
+
* JSON:API meta key names vary by implementation; these defaults cover the most
|
|
219
|
+
* common conventions and can be fully customised via `IPaginationConfig`.
|
|
220
|
+
*/
|
|
221
|
+
declare class JsonApiResponseOptions extends ResponseOptions {
|
|
222
|
+
constructor(options: IPaginationConfig);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Pre-configured ResponseOptions for the json-server driver
|
|
226
|
+
*
|
|
227
|
+
* The json-server v1 envelope is `{ first, prev, next, last, pages,
|
|
228
|
+
* items, data }`, where `first`/`prev`/`next`/`last` are **page
|
|
229
|
+
* numbers**, not URLs — the strategy reads `prev`/`next` directly for
|
|
230
|
+
* position derivation and leaves the URL slots `undefined`, so the
|
|
231
|
+
* navigation-URL paths default to empty strings. `total` maps to
|
|
232
|
+
* `items` and `lastPage` to `pages`; `currentPage` and `perPage` have
|
|
233
|
+
* no body field and are derived.
|
|
234
|
+
*/
|
|
235
|
+
declare class JsonServerResponseOptions extends ResponseOptions {
|
|
236
|
+
constructor(options: IPaginationConfig);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Pre-configured ResponseOptions for the NestJS driver
|
|
240
|
+
*
|
|
241
|
+
* Uses dot-notation paths to access nested values in the NestJS response format.
|
|
242
|
+
*/
|
|
243
|
+
declare class NestjsResponseOptions extends ResponseOptions {
|
|
244
|
+
constructor(options: IPaginationConfig);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Pre-configured ResponseOptions for the @nestjsx/crud driver
|
|
248
|
+
*
|
|
249
|
+
* The `getMany` envelope is flat: `{ data, count, total, page,
|
|
250
|
+
* pageCount }`. `perPage` defaults to the `count` field — the number of
|
|
251
|
+
* entities on the **current** page, which equals the requested limit on
|
|
252
|
+
* every page except a partial last one. The envelope carries no
|
|
253
|
+
* `from`/`to` indices and no navigation links, so those paths default to
|
|
254
|
+
* empty strings (the strategy derives `from`/`to` and leaves the URLs
|
|
255
|
+
* `undefined`); consumers can override any path via `IPaginationConfig`.
|
|
256
|
+
*/
|
|
257
|
+
declare class NestjsxCrudResponseOptions extends ResponseOptions {
|
|
258
|
+
constructor(options: IPaginationConfig);
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Pre-configured ResponseOptions for the OData v4 driver
|
|
262
|
+
*
|
|
263
|
+
* The OData collection envelope is `{ "@odata.count", "@odata.nextLink",
|
|
264
|
+
* "value" }` — flat keys that contain **literal dots**, so the strategy
|
|
265
|
+
* reads them with flat bracket access (never dot-path traversal). No body
|
|
266
|
+
* field names the current page, per-page, or last-page; the strategy
|
|
267
|
+
* derives those from the `@odata.nextLink` URL's `$skip` / `$top`
|
|
268
|
+
* params, so the corresponding key paths default to empty strings and
|
|
269
|
+
* are ignored.
|
|
270
|
+
*/
|
|
271
|
+
declare class OdataResponseOptions extends ResponseOptions {
|
|
272
|
+
constructor(options: IPaginationConfig);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Pre-configured ResponseOptions for the Payload CMS driver
|
|
276
|
+
*
|
|
277
|
+
* The envelope is the flat `mongoose-paginate-v2` shape: `{ docs,
|
|
278
|
+
* totalDocs, limit, totalPages, page, pagingCounter, hasPrevPage,
|
|
279
|
+
* hasNextPage, prevPage, nextPage }`. `pagingCounter` is the 1-indexed
|
|
280
|
+
* offset of the first doc on the page and maps onto `from`; `to` has no
|
|
281
|
+
* body field and is derived. `prevPage`/`nextPage` are page numbers,
|
|
282
|
+
* not URLs, so the navigation-URL paths default to empty strings. All
|
|
283
|
+
* paths are overridable via `IPaginationConfig` (dot notation
|
|
284
|
+
* supported) for custom wrappers.
|
|
285
|
+
*/
|
|
286
|
+
declare class PayloadResponseOptions extends ResponseOptions {
|
|
287
|
+
constructor(options: IPaginationConfig);
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Pre-configured ResponseOptions for the PocketBase driver
|
|
291
|
+
*
|
|
292
|
+
* The records-list envelope is flat: `{ page, perPage, totalItems,
|
|
293
|
+
* totalPages, items }`. The envelope carries no `from`/`to` indices and
|
|
294
|
+
* no navigation links, so those paths default to empty strings (the
|
|
295
|
+
* strategy derives `from`/`to` from `page` × `perPage` and leaves the
|
|
296
|
+
* URLs `undefined`); all paths are overridable via `IPaginationConfig`
|
|
297
|
+
* (dot notation supported) for custom wrappers.
|
|
298
|
+
*/
|
|
299
|
+
declare class PocketbaseResponseOptions extends ResponseOptions {
|
|
300
|
+
constructor(options: IPaginationConfig);
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Pre-configured ResponseOptions for the Sieve (.NET) driver
|
|
304
|
+
*
|
|
305
|
+
* Sieve defines no response envelope (it returns an `IQueryable` the
|
|
306
|
+
* developer wraps), so these defaults target the common hand-rolled
|
|
307
|
+
* `PagedResult<T>` shape: `{ data, page, pageSize, total, totalPages }`.
|
|
308
|
+
* Every path is overridable via `IPaginationConfig` — dot notation is
|
|
309
|
+
* supported, so nested wrappers (`meta.page`, `pagination.total`) map
|
|
310
|
+
* without subclassing. `from`/`to` default to empty paths and are
|
|
311
|
+
* derived; the navigation-URL slots resolve to `undefined` unless paths
|
|
312
|
+
* are provided.
|
|
313
|
+
*/
|
|
314
|
+
declare class SieveResponseOptions extends ResponseOptions {
|
|
315
|
+
constructor(options: IPaginationConfig);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Pre-configured ResponseOptions for the Spring Data REST driver
|
|
319
|
+
*
|
|
320
|
+
* Uses dot-notation paths into the HAL envelope: pagination metadata
|
|
321
|
+
* lives under `page.*` and navigation links under `_links.*.href`.
|
|
322
|
+
* `currentPage` points at the **0-indexed** `page.number`; the strategy
|
|
323
|
+
* adds 1 when reading it. `data` defaults to plain `_embedded` because
|
|
324
|
+
* the collection key underneath is the resource rel name (e.g.
|
|
325
|
+
* `_embedded.users`) and cannot be known statically — the strategy picks
|
|
326
|
+
* the first array inside; pin an exact path via `IPaginationConfig` when
|
|
327
|
+
* needed. `from`/`to` default to empty paths and are derived.
|
|
328
|
+
*/
|
|
329
|
+
declare class SpringResponseOptions extends ResponseOptions {
|
|
330
|
+
constructor(options: IPaginationConfig);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Pre-configured ResponseOptions for the Strapi driver
|
|
334
|
+
*
|
|
335
|
+
* Uses dot-notation paths to access the nested `meta.pagination.*` envelope
|
|
336
|
+
* Strapi v4/v5 emits. Strapi does not include navigation links by default,
|
|
337
|
+
* so the URL paths point at locations that will resolve to `undefined`
|
|
338
|
+
* unless the consumer overrides them.
|
|
339
|
+
*/
|
|
340
|
+
declare class StrapiResponseOptions extends ResponseOptions {
|
|
341
|
+
constructor(options: IPaginationConfig);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Enum representing the available pagination driver types
|
|
346
|
+
*
|
|
347
|
+
* Each driver encapsulates the full format knowledge for both
|
|
348
|
+
* request building (URI generation) and response parsing.
|
|
349
|
+
*/
|
|
350
|
+
declare enum DriverEnum {
|
|
351
|
+
API_PLATFORM = "api-platform",
|
|
352
|
+
DIRECTUS = "directus",
|
|
353
|
+
DRF = "drf",
|
|
354
|
+
FEATHERS = "feathers",
|
|
355
|
+
JSON_API = "json-api",
|
|
356
|
+
JSON_SERVER = "json-server",
|
|
357
|
+
LARAVEL = "laravel",
|
|
358
|
+
NESTJS = "nestjs",
|
|
359
|
+
NESTJSX_CRUD = "nestjsx-crud",
|
|
360
|
+
ODATA = "odata",
|
|
361
|
+
PAYLOAD = "payload",
|
|
362
|
+
POCKETBASE = "pocketbase",
|
|
363
|
+
POSTGREST = "postgrest",
|
|
364
|
+
SIEVE = "sieve",
|
|
365
|
+
SPATIE = "spatie",
|
|
366
|
+
SPRING = "spring",
|
|
367
|
+
STRAPI = "strapi",
|
|
368
|
+
WORDPRESS = "wordpress"
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Enum representing the wire-level pagination mechanism
|
|
373
|
+
*
|
|
374
|
+
* `QUERY` (default) — the request strategy emits `limit` and `offset` (or
|
|
375
|
+
* equivalent) query parameters on the URL.
|
|
376
|
+
*
|
|
377
|
+
* `RANGE` — the request strategy omits URL-based pagination and the
|
|
378
|
+
* consumer instead applies HTTP request headers returned by
|
|
379
|
+
* `NgQubeeService.paginationHeaders()`. Currently honoured only by the
|
|
380
|
+
* PostgREST driver, which maps it to `Range-Unit: items` + `Range: 0-9`.
|
|
381
|
+
* Other drivers ignore the setting.
|
|
382
|
+
*/
|
|
383
|
+
declare enum PaginationModeEnum {
|
|
384
|
+
QUERY = "query",
|
|
385
|
+
RANGE = "range"
|
|
141
386
|
}
|
|
142
387
|
|
|
143
388
|
/**
|
|
@@ -352,6 +597,19 @@ interface ISort {
|
|
|
352
597
|
order: SortEnum;
|
|
353
598
|
}
|
|
354
599
|
|
|
600
|
+
/**
|
|
601
|
+
* Embedded-resource selection map (PostgREST only)
|
|
602
|
+
*
|
|
603
|
+
* Maps a related table / foreign-key name (as PostgREST sees it) to the
|
|
604
|
+
* columns to project from it. An empty array means "all columns" and
|
|
605
|
+
* emits `relation(*)`; a non-empty array emits `relation(col1,col2)`.
|
|
606
|
+
* The PostgREST request strategy splices these fragments into the single
|
|
607
|
+
* `select=` query parameter alongside flat columns from `addSelect`.
|
|
608
|
+
*/
|
|
609
|
+
type Embedded = {
|
|
610
|
+
[relation: string]: string[];
|
|
611
|
+
};
|
|
612
|
+
|
|
355
613
|
/**
|
|
356
614
|
* Represents the complete query builder state
|
|
357
615
|
*
|
|
@@ -361,6 +619,8 @@ interface ISort {
|
|
|
361
619
|
interface IQueryBuilderState {
|
|
362
620
|
/** The base URL to prepend to generated URIs */
|
|
363
621
|
baseUrl: string;
|
|
622
|
+
/** Embedded-resource selection (PostgREST only) */
|
|
623
|
+
embedded: Embedded;
|
|
364
624
|
/** Per-model field selection (Spatie only) */
|
|
365
625
|
fields: IFields;
|
|
366
626
|
/** Simple key-value filters (Spatie and NestJS) */
|
|
@@ -398,6 +658,8 @@ interface IQueryBuilderState {
|
|
|
398
658
|
* strategy class — `NgQubeeService` does not need to be touched.
|
|
399
659
|
*/
|
|
400
660
|
interface IStrategyCapabilities {
|
|
661
|
+
/** Embedded-resource selection inside `select` (PostgREST `select=col,rel(col1)`) */
|
|
662
|
+
readonly embedded: boolean;
|
|
401
663
|
/** Per-model field selection (e.g. JSON:API `fields[type]=col1,col2`) */
|
|
402
664
|
readonly fields: boolean;
|
|
403
665
|
/** Simple key-value filters (e.g. `filter.status=active`) */
|
|
@@ -414,26 +676,6 @@ interface IStrategyCapabilities {
|
|
|
414
676
|
readonly sort: boolean;
|
|
415
677
|
}
|
|
416
678
|
|
|
417
|
-
/**
|
|
418
|
-
* Resolved query parameter key names with defaults applied
|
|
419
|
-
*
|
|
420
|
-
* Maps logical query concepts to the actual query parameter names
|
|
421
|
-
* used in the generated URI. Unset values fall back to defaults.
|
|
422
|
-
*/
|
|
423
|
-
declare class QueryBuilderOptions {
|
|
424
|
-
readonly appends: string;
|
|
425
|
-
readonly fields: string;
|
|
426
|
-
readonly filters: string;
|
|
427
|
-
readonly includes: string;
|
|
428
|
-
readonly limit: string;
|
|
429
|
-
readonly page: string;
|
|
430
|
-
readonly search: string;
|
|
431
|
-
readonly select: string;
|
|
432
|
-
readonly sort: string;
|
|
433
|
-
readonly sortBy: string;
|
|
434
|
-
constructor(options: IQueryBuilderConfig);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
679
|
/**
|
|
438
680
|
* Strategy interface for building request URIs
|
|
439
681
|
*
|
|
@@ -559,6 +801,21 @@ declare class NestService {
|
|
|
559
801
|
* @private
|
|
560
802
|
*/
|
|
561
803
|
private _validateResourceName;
|
|
804
|
+
/**
|
|
805
|
+
* Add embedded-resource selections to the request (PostgREST only)
|
|
806
|
+
* Automatically prevents duplicate columns for each relation
|
|
807
|
+
*
|
|
808
|
+
* An empty column array means "all columns" (`relation(*)`); merging an
|
|
809
|
+
* empty array into a relation that already has explicit columns keeps
|
|
810
|
+
* the explicit columns.
|
|
811
|
+
*
|
|
812
|
+
* @param {Embedded} embedded - Object mapping relation names to arrays of columns to project
|
|
813
|
+
* @return {void}
|
|
814
|
+
* @example
|
|
815
|
+
* service.addEmbedded({ author: ['id', 'name'] });
|
|
816
|
+
* service.addEmbedded({ comments: [] });
|
|
817
|
+
*/
|
|
818
|
+
addEmbedded(embedded: Embedded): void;
|
|
562
819
|
/**
|
|
563
820
|
* Add selectable fields for the given model to the request
|
|
564
821
|
* Automatically prevents duplicate fields for each model
|
|
@@ -624,6 +881,18 @@ declare class NestService {
|
|
|
624
881
|
* service.addSort({ field: 'name', order: SortEnum.ASC });
|
|
625
882
|
*/
|
|
626
883
|
addSort(sort: ISort): void;
|
|
884
|
+
/**
|
|
885
|
+
* Remove embedded-resource relations from the state (PostgREST only)
|
|
886
|
+
*
|
|
887
|
+
* Removes the whole relation entry, columns included.
|
|
888
|
+
*
|
|
889
|
+
* @param {...string[]} relations - Relation names to remove
|
|
890
|
+
* @return {void}
|
|
891
|
+
* @example
|
|
892
|
+
* service.deleteEmbedded('author');
|
|
893
|
+
* service.deleteEmbedded('comments', 'tags');
|
|
894
|
+
*/
|
|
895
|
+
deleteEmbedded(...relations: string[]): void;
|
|
627
896
|
/**
|
|
628
897
|
* Remove fields for the given model
|
|
629
898
|
* Uses deep cloning to prevent mutations to the original state
|
|
@@ -764,6 +1033,29 @@ declare class NgQubeeService {
|
|
|
764
1033
|
* @throws The provided error if the active strategy lacks the capability
|
|
765
1034
|
*/
|
|
766
1035
|
private _assertCapability;
|
|
1036
|
+
/**
|
|
1037
|
+
* Add an embedded resource to the select statement (PostgREST only)
|
|
1038
|
+
*
|
|
1039
|
+
* Splices `relation(col1,col2)` into the single `select=` query
|
|
1040
|
+
* parameter alongside flat columns from `addSelect`. Omit the columns
|
|
1041
|
+
* to project all of them (`relation(*)`):
|
|
1042
|
+
*
|
|
1043
|
+
* ```
|
|
1044
|
+
* qb.addEmbedded('author', 'id', 'name')
|
|
1045
|
+
* .addEmbedded('comments')
|
|
1046
|
+
* .addSelect('title');
|
|
1047
|
+
* // → select=title,author(id,name),comments(*)
|
|
1048
|
+
* ```
|
|
1049
|
+
*
|
|
1050
|
+
* Calling repeatedly with the same relation merge-dedups the columns.
|
|
1051
|
+
* Does not reset the page (column shape change, not record-set change).
|
|
1052
|
+
*
|
|
1053
|
+
* @param {string} relation - The related table / foreign-key name as PostgREST sees it
|
|
1054
|
+
* @param {string[]} columns - Optional column projection; omit for `relation(*)`
|
|
1055
|
+
* @returns {this}
|
|
1056
|
+
* @throws {UnsupportedEmbeddedError} If the active driver does not support embedded resources
|
|
1057
|
+
*/
|
|
1058
|
+
addEmbedded(relation: string, ...columns: string[]): this;
|
|
767
1059
|
/**
|
|
768
1060
|
* Add fields to the select statement for the given model (JSON:API and Spatie only)
|
|
769
1061
|
*
|
|
@@ -831,11 +1123,21 @@ declare class NgQubeeService {
|
|
|
831
1123
|
*/
|
|
832
1124
|
currentPage(): number;
|
|
833
1125
|
/**
|
|
834
|
-
*
|
|
1126
|
+
* Remove embedded resources from the current query builder state (PostgREST only)
|
|
835
1127
|
*
|
|
836
|
-
*
|
|
837
|
-
*
|
|
838
|
-
*
|
|
1128
|
+
* Removes the whole relation entry, columns included.
|
|
1129
|
+
*
|
|
1130
|
+
* @param {string[]} relations - Relation names to remove
|
|
1131
|
+
* @returns {this}
|
|
1132
|
+
* @throws {UnsupportedEmbeddedError} If the active driver does not support embedded resources
|
|
1133
|
+
*/
|
|
1134
|
+
deleteEmbedded(...relations: string[]): this;
|
|
1135
|
+
/**
|
|
1136
|
+
* Delete selected fields for the given models in the current query builder state (JSON:API and Spatie only)
|
|
1137
|
+
*
|
|
1138
|
+
* ```
|
|
1139
|
+
* ngQubeeService.deleteFields({
|
|
1140
|
+
* users: ['email', 'password'],
|
|
839
1141
|
* address: ['zipcode']
|
|
840
1142
|
* });
|
|
841
1143
|
* ```
|
|
@@ -1076,36 +1378,6 @@ type HeaderBag = {
|
|
|
1076
1378
|
*/
|
|
1077
1379
|
declare function readHeader(bag: HeaderBag | null | undefined, name: string): string | null;
|
|
1078
1380
|
|
|
1079
|
-
/**
|
|
1080
|
-
* Resolved response field key names with defaults applied
|
|
1081
|
-
*
|
|
1082
|
-
* Maps logical pagination concepts to the actual key names
|
|
1083
|
-
* used in the API response. Unset values fall back to Laravel defaults.
|
|
1084
|
-
*
|
|
1085
|
-
* For NestJS responses, use dot-notation paths:
|
|
1086
|
-
* ```typescript
|
|
1087
|
-
* new ResponseOptions({
|
|
1088
|
-
* currentPage: 'meta.currentPage',
|
|
1089
|
-
* total: 'meta.totalItems'
|
|
1090
|
-
* });
|
|
1091
|
-
* ```
|
|
1092
|
-
*/
|
|
1093
|
-
declare class ResponseOptions {
|
|
1094
|
-
readonly currentPage: string;
|
|
1095
|
-
readonly data: string;
|
|
1096
|
-
readonly firstPageUrl: string;
|
|
1097
|
-
readonly from: string;
|
|
1098
|
-
readonly lastPage: string;
|
|
1099
|
-
readonly lastPageUrl: string;
|
|
1100
|
-
readonly nextPageUrl: string;
|
|
1101
|
-
readonly path: string;
|
|
1102
|
-
readonly perPage: string;
|
|
1103
|
-
readonly prevPageUrl: string;
|
|
1104
|
-
readonly to: string;
|
|
1105
|
-
readonly total: string;
|
|
1106
|
-
constructor(options: IPaginationConfig);
|
|
1107
|
-
}
|
|
1108
|
-
|
|
1109
1381
|
/**
|
|
1110
1382
|
* Strategy interface for parsing paginated API responses
|
|
1111
1383
|
*
|
|
@@ -1250,6 +1522,19 @@ declare class UnselectableModelError extends Error {
|
|
|
1250
1522
|
constructor(model: string);
|
|
1251
1523
|
}
|
|
1252
1524
|
|
|
1525
|
+
/**
|
|
1526
|
+
* Error thrown when embedded resources are attempted with a driver that
|
|
1527
|
+
* does not support them
|
|
1528
|
+
*
|
|
1529
|
+
* Embedded-resource fetching (`select=col,relation(col1,col2)`) is a
|
|
1530
|
+
* PostgREST-native join mechanism and is only supported by the PostgREST
|
|
1531
|
+
* driver. Drivers with a standalone relation parameter expose it through
|
|
1532
|
+
* `addIncludes()` instead (JSON:API, Spatie, Strapi, @nestjsx/crud).
|
|
1533
|
+
*/
|
|
1534
|
+
declare class UnsupportedEmbeddedError extends Error {
|
|
1535
|
+
constructor();
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1253
1538
|
/**
|
|
1254
1539
|
* Error thrown when per-model field selection is attempted with a driver that does not support it
|
|
1255
1540
|
*
|
|
@@ -1449,294 +1734,382 @@ declare abstract class AbstractRequestStrategy implements IRequestStrategy {
|
|
|
1449
1734
|
}
|
|
1450
1735
|
|
|
1451
1736
|
/**
|
|
1452
|
-
* Request strategy for the
|
|
1453
|
-
*
|
|
1454
|
-
* Generates URIs in
|
|
1455
|
-
*
|
|
1456
|
-
*
|
|
1457
|
-
* -
|
|
1458
|
-
*
|
|
1459
|
-
* `
|
|
1460
|
-
*
|
|
1461
|
-
* -
|
|
1462
|
-
*
|
|
1463
|
-
* -
|
|
1464
|
-
*
|
|
1465
|
-
*
|
|
1466
|
-
*
|
|
1467
|
-
*
|
|
1468
|
-
*
|
|
1469
|
-
*
|
|
1470
|
-
* `
|
|
1471
|
-
*
|
|
1472
|
-
*
|
|
1473
|
-
*
|
|
1737
|
+
* Request strategy for the API Platform (Symfony) driver
|
|
1738
|
+
*
|
|
1739
|
+
* Generates URIs in [API Platform's filter format](https://api-platform.com/docs/core/filters/):
|
|
1740
|
+
* - Filters: `field=value` (exact); multi-value uses the array syntax
|
|
1741
|
+
* (`field[]=v1&field[]=v2`, OR semantics)
|
|
1742
|
+
* - Operator filters: bracket syntax `field[op]=value` — RangeFilter
|
|
1743
|
+
* (`gt`/`gte`/`lt`/`lte`/`between`), SearchFilter strategies
|
|
1744
|
+
* (`partial`/`ipartial`/`start`), ExistsFilter (`exists`) — see the
|
|
1745
|
+
* mapping on `_formatOperatorSegments`
|
|
1746
|
+
* - Relation filtering: dot paths pass through (`author.name=John` via
|
|
1747
|
+
* `addFilter('author.name', 'John')`)
|
|
1748
|
+
* - Sorts: `order[field]=asc` / `order[field]=desc` (one param per rule)
|
|
1749
|
+
* - Pagination: `page=N&itemsPerPage=M`
|
|
1750
|
+
*
|
|
1751
|
+
* The `order` and `itemsPerPage` keys are API Platform conventions and
|
|
1752
|
+
* intentionally not configurable through `QueryBuilderOptions`; `page`
|
|
1753
|
+
* honours the existing option key (its default matches the wire format).
|
|
1754
|
+
*
|
|
1755
|
+
* Date fields use API Platform's DateFilter (`field[after]=…`,
|
|
1756
|
+
* `field[before]=…`) — there is no `FilterOperatorEnum` counterpart, but
|
|
1757
|
+
* the bracket key passes through `addFilter` directly:
|
|
1758
|
+
* `addFilter('createdAt[after]', '2023-01-01')`.
|
|
1759
|
+
*
|
|
1760
|
+
* `NOT` (no negation filter in API Platform core) and the
|
|
1761
|
+
* PostgREST-native full-text operators (`FTS`, `PHFTS`, `PLFTS`,
|
|
1762
|
+
* `WFTS`) throw `UnsupportedFilterOperatorError`.
|
|
1763
|
+
*
|
|
1764
|
+
* @see https://api-platform.com/docs/core/filters/
|
|
1474
1765
|
*/
|
|
1475
|
-
declare class
|
|
1766
|
+
declare class ApiPlatformRequestStrategy extends AbstractRequestStrategy {
|
|
1476
1767
|
/**
|
|
1477
|
-
*
|
|
1478
|
-
*
|
|
1479
|
-
*
|
|
1768
|
+
* Filters, operator filters, sorts — no per-model fields, no
|
|
1769
|
+
* includes (relations embed via serialization groups server-side),
|
|
1770
|
+
* no flat select, no global search parameter
|
|
1480
1771
|
*/
|
|
1481
1772
|
readonly capabilities: IStrategyCapabilities;
|
|
1482
1773
|
/**
|
|
1483
|
-
*
|
|
1774
|
+
* API Platform-native names of the two hardcoded query keys
|
|
1484
1775
|
*
|
|
1485
|
-
* `
|
|
1486
|
-
*
|
|
1487
|
-
*
|
|
1488
|
-
*
|
|
1489
|
-
* shared options object.
|
|
1776
|
+
* `order[...]` and `itemsPerPage` are fixed conventions of API
|
|
1777
|
+
* Platform's OrderFilter and pagination; they are intentionally not
|
|
1778
|
+
* configurable through `QueryBuilderOptions` and live as private
|
|
1779
|
+
* statics so they are visible in one place.
|
|
1490
1780
|
*/
|
|
1491
|
-
private static readonly
|
|
1492
|
-
private static readonly
|
|
1781
|
+
private static readonly _itemsPerPageKey;
|
|
1782
|
+
private static readonly _orderKey;
|
|
1493
1783
|
/**
|
|
1494
|
-
* Emit
|
|
1495
|
-
* filters → operator filters →
|
|
1784
|
+
* Emit API Platform-format query-string segments in canonical order:
|
|
1785
|
+
* filters → operator filters → order → page → itemsPerPage
|
|
1496
1786
|
*
|
|
1497
1787
|
* @param state - The current query builder state
|
|
1498
|
-
* @param options - The query parameter key name configuration
|
|
1788
|
+
* @param options - The query parameter key name configuration (used
|
|
1789
|
+
* for `page`, whose default matches the wire format)
|
|
1499
1790
|
* @returns Ordered query-string fragments
|
|
1500
1791
|
*/
|
|
1501
1792
|
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
1502
1793
|
/**
|
|
1503
1794
|
* Append simple filter parameters
|
|
1504
1795
|
*
|
|
1505
|
-
*
|
|
1506
|
-
*
|
|
1507
|
-
* `
|
|
1508
|
-
* "value in list" in DRF.
|
|
1796
|
+
* A single value emits the bare exact-match form (`field=value`);
|
|
1797
|
+
* multiple values use API Platform's array syntax with OR semantics
|
|
1798
|
+
* (`field[]=v1&field[]=v2`).
|
|
1509
1799
|
*
|
|
1510
1800
|
* @param state - The current query builder state
|
|
1511
1801
|
* @param out - The accumulator the caller joins into the URI
|
|
1512
1802
|
*/
|
|
1513
1803
|
private _appendFilters;
|
|
1514
1804
|
/**
|
|
1515
|
-
* Append
|
|
1516
|
-
*
|
|
1517
|
-
* Maps each `FilterOperatorEnum` value to a django-filter lookup
|
|
1518
|
-
* suffix. `BTW` expands to `field__range=min,max`; `NULL` emits
|
|
1519
|
-
* `field__isnull=true|false`; the generic `NOT` and PostgREST-only
|
|
1520
|
-
* FTS operators are unsupported.
|
|
1805
|
+
* Append the itemsPerPage parameter
|
|
1521
1806
|
*
|
|
1522
1807
|
* @param state - The current query builder state
|
|
1523
1808
|
* @param out - The accumulator the caller joins into the URI
|
|
1524
|
-
* @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
|
|
1525
|
-
* exactly two values, or `NULL` does not receive exactly one boolean
|
|
1526
|
-
* @throws {UnsupportedFilterOperatorError} If the operator has no
|
|
1527
|
-
* django-filter equivalent
|
|
1528
1809
|
*/
|
|
1529
|
-
private
|
|
1810
|
+
private _appendItemsPerPage;
|
|
1530
1811
|
/**
|
|
1531
|
-
* Append
|
|
1812
|
+
* Append explicit operator filters in the bracket syntax
|
|
1532
1813
|
*
|
|
1533
1814
|
* @param state - The current query builder state
|
|
1534
1815
|
* @param out - The accumulator the caller joins into the URI
|
|
1535
1816
|
*/
|
|
1536
|
-
private
|
|
1817
|
+
private _appendOperatorFilters;
|
|
1537
1818
|
/**
|
|
1538
|
-
* Append `
|
|
1539
|
-
*
|
|
1540
|
-
* `page` follows `options.page` (default `page`, matching DRF); the
|
|
1541
|
-
* size key is hardcoded to DRF's idiomatic `page_size`.
|
|
1819
|
+
* Append `order[field]=asc` / `order[field]=desc` params, one per rule
|
|
1542
1820
|
*
|
|
1543
1821
|
* @param state - The current query builder state
|
|
1544
|
-
* @param options - The query parameter key name configuration
|
|
1545
1822
|
* @param out - The accumulator the caller joins into the URI
|
|
1546
1823
|
*/
|
|
1547
|
-
private
|
|
1824
|
+
private _appendOrder;
|
|
1548
1825
|
/**
|
|
1549
|
-
* Append
|
|
1826
|
+
* Append the page parameter
|
|
1550
1827
|
*
|
|
1551
1828
|
* @param state - The current query builder state
|
|
1552
1829
|
* @param options - The query parameter key name configuration
|
|
1553
1830
|
* @param out - The accumulator the caller joins into the URI
|
|
1554
1831
|
*/
|
|
1555
|
-
private
|
|
1832
|
+
private _appendPage;
|
|
1556
1833
|
/**
|
|
1557
|
-
* Translate a `FilterOperatorEnum` operator filter into
|
|
1558
|
-
*
|
|
1559
|
-
*
|
|
1560
|
-
* The
|
|
1561
|
-
*
|
|
1562
|
-
*
|
|
1563
|
-
*
|
|
1564
|
-
*
|
|
1565
|
-
* - `
|
|
1566
|
-
*
|
|
1567
|
-
* - `
|
|
1568
|
-
* - `IN` → `
|
|
1569
|
-
* - `
|
|
1570
|
-
*
|
|
1571
|
-
*
|
|
1572
|
-
*
|
|
1573
|
-
*
|
|
1574
|
-
* - `FTS
|
|
1834
|
+
* Translate a `FilterOperatorEnum` operator filter into one or more
|
|
1835
|
+
* API Platform bracket segments
|
|
1836
|
+
*
|
|
1837
|
+
* The mapping is library-canonical → API Platform-native:
|
|
1838
|
+
* - `EQ` → bare exact match (`field=value`, SearchFilter exact)
|
|
1839
|
+
* - `GT`/`GTE`/`LT`/`LTE` → RangeFilter (`field[gt]=v`, …)
|
|
1840
|
+
* - `BTW` → RangeFilter `field[between]=min..max` (arity-checked)
|
|
1841
|
+
* - `CONTAINS` → SearchFilter partial (`field[partial]=v`)
|
|
1842
|
+
* - `ILIKE` → SearchFilter ipartial (`field[ipartial]=v`,
|
|
1843
|
+
* case-insensitive)
|
|
1844
|
+
* - `SW` → SearchFilter start (`field[start]=v`)
|
|
1845
|
+
* - `IN` → array syntax (`field[]=v1&field[]=v2`)
|
|
1846
|
+
* - `NULL` → ExistsFilter — **inverted**: `true` (IS NULL) emits
|
|
1847
|
+
* `field[exists]=false`, `false` (IS NOT NULL) emits
|
|
1848
|
+
* `field[exists]=true`; arity- and type-checked
|
|
1849
|
+
*
|
|
1850
|
+
* `NOT` (API Platform core ships no negation filter) and PostgREST's
|
|
1851
|
+
* full-text-search operators (`FTS`, `PHFTS`, `PLFTS`, `WFTS`) throw
|
|
1852
|
+
* `UnsupportedFilterOperatorError`.
|
|
1575
1853
|
*
|
|
1576
1854
|
* @param filter - The operator filter to translate
|
|
1577
|
-
* @returns
|
|
1855
|
+
* @returns One or more bracket-syntax query-string segments
|
|
1578
1856
|
* @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
|
|
1579
1857
|
* exactly two values, or `NULL` does not receive exactly one boolean
|
|
1580
|
-
* @throws {UnsupportedFilterOperatorError} If the operator has no
|
|
1581
|
-
*
|
|
1858
|
+
* @throws {UnsupportedFilterOperatorError} If the operator has no API
|
|
1859
|
+
* Platform equivalent
|
|
1582
1860
|
*/
|
|
1583
|
-
private
|
|
1861
|
+
private _formatOperatorSegments;
|
|
1584
1862
|
}
|
|
1585
1863
|
|
|
1586
1864
|
/**
|
|
1587
|
-
*
|
|
1865
|
+
* Base class for response strategies whose pagination metadata lives at
|
|
1866
|
+
* dot-notation paths inside the response body
|
|
1588
1867
|
*
|
|
1589
|
-
*
|
|
1868
|
+
* JSON:API and NestJS share an identical body-traversal algorithm: the
|
|
1869
|
+
* total / current-page / etc. live at nested keys like `meta.total`, and
|
|
1870
|
+
* `from`/`to` are either present directly or must be derived from
|
|
1871
|
+
* `currentPage` × `perPage`. Both strategies were duplicating this
|
|
1872
|
+
* verbatim before this base existed; concrete classes now extend and
|
|
1873
|
+
* provide only the docstring describing their driver's specific path
|
|
1874
|
+
* conventions (see `JsonApiResponseStrategy`, `NestjsResponseStrategy`).
|
|
1875
|
+
*
|
|
1876
|
+
* Drivers whose pagination metadata travels via HTTP headers (PostgREST)
|
|
1877
|
+
* or whose body has a flat shape with no dot paths (Laravel, Spatie) do
|
|
1878
|
+
* not extend this class — they implement `IResponseStrategy` directly.
|
|
1879
|
+
*/
|
|
1880
|
+
declare abstract class AbstractDotPathResponseStrategy implements IResponseStrategy {
|
|
1881
|
+
/**
|
|
1882
|
+
* Parse a nested-envelope pagination response into a PaginatedCollection
|
|
1883
|
+
*
|
|
1884
|
+
* @param response - The raw API response object
|
|
1885
|
+
* @param options - The response key name configuration (dot-notation paths supported)
|
|
1886
|
+
* @returns A typed PaginatedCollection instance
|
|
1887
|
+
*/
|
|
1888
|
+
paginate<T extends IPaginatedObject>(response: Record<string, any>, options: ResponseOptions): PaginatedCollection<T>;
|
|
1889
|
+
/**
|
|
1890
|
+
* Resolve a value from a response object using a dot-notation path
|
|
1891
|
+
*
|
|
1892
|
+
* Supports both flat keys (`'data'`) and nested paths (`'meta.totalItems'`).
|
|
1893
|
+
*
|
|
1894
|
+
* @param response - The raw response object
|
|
1895
|
+
* @param path - The dot-notation path to resolve
|
|
1896
|
+
* @returns The resolved value, or undefined if any segment is missing
|
|
1897
|
+
*/
|
|
1898
|
+
protected resolve(response: Record<string, any>, path: string): unknown;
|
|
1899
|
+
/**
|
|
1900
|
+
* Resolve the "from" index value
|
|
1901
|
+
*
|
|
1902
|
+
* If `options.from` resolves to a value in the response, use it.
|
|
1903
|
+
* Otherwise compute `(currentPage - 1) * perPage + 1` when both are known.
|
|
1904
|
+
*
|
|
1905
|
+
* @param response - The raw response object
|
|
1906
|
+
* @param options - The response key name configuration
|
|
1907
|
+
* @param currentPage - The current page number
|
|
1908
|
+
* @param perPage - The number of items per page
|
|
1909
|
+
* @returns The "from" index, or `undefined` when neither path nor inputs suffice
|
|
1910
|
+
*/
|
|
1911
|
+
protected resolveFrom(response: Record<string, any>, options: ResponseOptions, currentPage: number, perPage?: number): number | undefined;
|
|
1912
|
+
/**
|
|
1913
|
+
* Resolve the "to" index value
|
|
1914
|
+
*
|
|
1915
|
+
* If `options.to` resolves to a value in the response, use it.
|
|
1916
|
+
* Otherwise compute `Math.min(currentPage * perPage, total)` when all
|
|
1917
|
+
* three are known.
|
|
1918
|
+
*
|
|
1919
|
+
* @param response - The raw response object
|
|
1920
|
+
* @param options - The response key name configuration
|
|
1921
|
+
* @param currentPage - The current page number
|
|
1922
|
+
* @param perPage - The number of items per page
|
|
1923
|
+
* @param total - The total number of items
|
|
1924
|
+
* @returns The "to" index, or `undefined` when neither path nor inputs suffice
|
|
1925
|
+
*/
|
|
1926
|
+
protected resolveTo(response: Record<string, any>, options: ResponseOptions, currentPage: number, perPage?: number, total?: number): number | undefined;
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1929
|
+
/**
|
|
1930
|
+
* Response strategy for the API Platform (Symfony) driver
|
|
1931
|
+
*
|
|
1932
|
+
* Parses API Platform's default Hydra/JSON-LD collection envelope:
|
|
1590
1933
|
*
|
|
1591
1934
|
* ```json
|
|
1592
1935
|
* {
|
|
1593
|
-
* "
|
|
1594
|
-
* "
|
|
1595
|
-
* "
|
|
1596
|
-
* "
|
|
1936
|
+
* "@context": "/contexts/Book",
|
|
1937
|
+
* "@type": "hydra:Collection",
|
|
1938
|
+
* "hydra:totalItems": 48,
|
|
1939
|
+
* "hydra:member": [...],
|
|
1940
|
+
* "hydra:view": {
|
|
1941
|
+
* "@id": "/books?page=3&itemsPerPage=10",
|
|
1942
|
+
* "hydra:first": "/books?page=1",
|
|
1943
|
+
* "hydra:previous": "/books?page=2",
|
|
1944
|
+
* "hydra:next": "/books?page=4",
|
|
1945
|
+
* "hydra:last": "/books?page=5"
|
|
1946
|
+
* }
|
|
1597
1947
|
* }
|
|
1598
1948
|
* ```
|
|
1599
1949
|
*
|
|
1600
|
-
*
|
|
1601
|
-
*
|
|
1602
|
-
* `next`
|
|
1603
|
-
*
|
|
1604
|
-
*
|
|
1605
|
-
*
|
|
1606
|
-
*
|
|
1607
|
-
*
|
|
1608
|
-
*
|
|
1609
|
-
*
|
|
1610
|
-
*
|
|
1611
|
-
*
|
|
1612
|
-
*
|
|
1613
|
-
*
|
|
1614
|
-
*
|
|
1615
|
-
*
|
|
1616
|
-
*
|
|
1617
|
-
*
|
|
1618
|
-
*
|
|
1619
|
-
*
|
|
1620
|
-
*
|
|
1621
|
-
* @see https://
|
|
1950
|
+
* The Hydra keys contain colons but no dots, so the inherited
|
|
1951
|
+
* dot-notation resolver traverses them cleanly (`hydra:view.hydra:next`
|
|
1952
|
+
* → `response['hydra:view']['hydra:next']`). The body names no
|
|
1953
|
+
* current-page or page-size field, so both are **derived from the
|
|
1954
|
+
* `hydra:view` URLs**:
|
|
1955
|
+
*
|
|
1956
|
+
* - `currentPage` from the `page` param of the view's `@id` (the
|
|
1957
|
+
* `path` option slot points there); missing view → page **1**.
|
|
1958
|
+
* - `perPage` from the `itemsPerPage` param of the view's `@id`
|
|
1959
|
+
* (echoed whenever the request set it — this driver's request
|
|
1960
|
+
* strategy always does), falling back to the item count of a page
|
|
1961
|
+
* that has a `hydra:next` successor.
|
|
1962
|
+
* - `lastPage` from the `page` param of `hydra:last`, falling back to
|
|
1963
|
+
* `ceil(total ÷ perPage)`; a view-less response holding the whole
|
|
1964
|
+
* collection resolves to 1.
|
|
1965
|
+
*
|
|
1966
|
+
* URLs are typically **relative** (`/books?page=4`) — parsing retries
|
|
1967
|
+
* against a placeholder base, and the links are surfaced as-is on the
|
|
1968
|
+
* collection. JSON:API and HAL serialization formats are out of scope
|
|
1969
|
+
* (use the JSON:API driver for the former).
|
|
1970
|
+
*
|
|
1971
|
+
* @see https://api-platform.com/docs/core/pagination/
|
|
1622
1972
|
*/
|
|
1623
|
-
declare class
|
|
1973
|
+
declare class ApiPlatformResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
1624
1974
|
/**
|
|
1625
|
-
* Parse a
|
|
1975
|
+
* Parse a Hydra collection response into a PaginatedCollection
|
|
1626
1976
|
*
|
|
1627
1977
|
* @param response - The raw API response body
|
|
1628
|
-
* @param options - The response key name configuration
|
|
1978
|
+
* @param options - The response key name configuration (dot-notation paths supported)
|
|
1629
1979
|
* @returns A typed PaginatedCollection instance
|
|
1630
1980
|
*/
|
|
1631
1981
|
paginate<T extends IPaginatedObject>(response: Record<string, any>, options: ResponseOptions): PaginatedCollection<T>;
|
|
1632
1982
|
/**
|
|
1633
|
-
* Derive the current page number from the `
|
|
1983
|
+
* Derive the current page number from the `hydra:view` `@id` URL
|
|
1634
1984
|
*
|
|
1635
|
-
*
|
|
1636
|
-
*
|
|
1637
|
-
*
|
|
1985
|
+
* Reads the `page` query param; a missing view (pagination disabled
|
|
1986
|
+
* or a single-page collection without a partial view) or a link
|
|
1987
|
+
* without the param resolves to page 1.
|
|
1638
1988
|
*
|
|
1639
|
-
* @param
|
|
1989
|
+
* @param viewUrl - The `hydra:view.@id` URL, or null
|
|
1640
1990
|
* @returns The current page number
|
|
1641
1991
|
*/
|
|
1642
1992
|
private _deriveCurrentPage;
|
|
1643
1993
|
/**
|
|
1644
|
-
* Derive
|
|
1645
|
-
*
|
|
1646
|
-
* @param currentPage - The current page number
|
|
1647
|
-
* @param perPage - The page size (may be undefined)
|
|
1648
|
-
* @returns The 1-indexed `from` index, or undefined when perPage is unknown
|
|
1649
|
-
*/
|
|
1650
|
-
private _deriveFrom;
|
|
1651
|
-
/**
|
|
1652
|
-
* Derive the last page number as `ceil(total / perPage)`
|
|
1994
|
+
* Derive the last page number
|
|
1653
1995
|
*
|
|
1654
|
-
*
|
|
1655
|
-
*
|
|
1656
|
-
*
|
|
1996
|
+
* Resolution order: the `page` param of `hydra:last`, then
|
|
1997
|
+
* `ceil(total ÷ perPage)`, then 1 for a view-less response that
|
|
1998
|
+
* provably holds the entire non-empty collection.
|
|
1657
1999
|
*
|
|
2000
|
+
* @param lastPageUrl - The `hydra:view.hydra:last` URL (may be undefined)
|
|
2001
|
+
* @param viewUrl - The `hydra:view.@id` URL, or null
|
|
2002
|
+
* @param data - The items on the current page
|
|
1658
2003
|
* @param total - The total item count
|
|
1659
2004
|
* @param perPage - The page size
|
|
1660
|
-
* @returns The last page number, or undefined when
|
|
2005
|
+
* @returns The last page number, or undefined when inputs insufficient
|
|
1661
2006
|
*/
|
|
1662
2007
|
private _deriveLastPage;
|
|
1663
2008
|
/**
|
|
1664
|
-
* Derive `perPage`
|
|
2009
|
+
* Derive `perPage` from the `hydra:view` `@id` URL
|
|
1665
2010
|
*
|
|
1666
|
-
*
|
|
1667
|
-
*
|
|
1668
|
-
*
|
|
1669
|
-
* the consumer is then on a single-page result with the server's
|
|
1670
|
-
* default page size, which is not introspectable from the body alone.
|
|
2011
|
+
* Reads the `itemsPerPage` query param (echoed whenever the request
|
|
2012
|
+
* set it). When absent, a page with a `hydra:next` successor is
|
|
2013
|
+
* necessarily full, so its item count equals the page size.
|
|
1671
2014
|
*
|
|
1672
|
-
* @param
|
|
1673
|
-
* @param
|
|
2015
|
+
* @param viewUrl - The `hydra:view.@id` URL, or null
|
|
2016
|
+
* @param nextPageUrl - The `hydra:view.hydra:next` URL (may be undefined)
|
|
2017
|
+
* @param data - The items on the current page
|
|
1674
2018
|
* @returns The page size, or undefined
|
|
1675
2019
|
*/
|
|
1676
2020
|
private _derivePerPage;
|
|
1677
2021
|
/**
|
|
1678
|
-
*
|
|
2022
|
+
* Extract an integer query parameter from a Hydra URL
|
|
1679
2023
|
*
|
|
1680
|
-
*
|
|
1681
|
-
*
|
|
1682
|
-
* @
|
|
1683
|
-
* @param perPage - The page size (may be undefined)
|
|
1684
|
-
* @param total - The total item count (may be undefined)
|
|
1685
|
-
* @returns The 1-indexed `to` index, or undefined when inputs insufficient
|
|
2024
|
+
* @param url - The URL to parse
|
|
2025
|
+
* @param name - The query-parameter name to look up (e.g. `page`)
|
|
2026
|
+
* @returns The integer value, or undefined
|
|
1686
2027
|
*/
|
|
1687
|
-
private
|
|
2028
|
+
private _extractNumberParam;
|
|
1688
2029
|
/**
|
|
1689
|
-
* Extract
|
|
2030
|
+
* Extract a single query parameter from a URL via the WHATWG URL parser
|
|
1690
2031
|
*
|
|
1691
|
-
*
|
|
1692
|
-
*
|
|
1693
|
-
*
|
|
2032
|
+
* Hydra links are typically **relative** (`/books?page=4`), so parsing
|
|
2033
|
+
* retries against a placeholder base before giving up. Returns
|
|
2034
|
+
* undefined when the URL is unparseable or the parameter is absent.
|
|
1694
2035
|
*
|
|
1695
2036
|
* @param url - The URL to parse
|
|
1696
|
-
* @
|
|
2037
|
+
* @param name - The query-parameter name to look up
|
|
2038
|
+
* @returns The raw string value of the parameter, or undefined
|
|
1697
2039
|
*/
|
|
1698
|
-
private
|
|
2040
|
+
private _extractQueryParam;
|
|
1699
2041
|
/**
|
|
1700
|
-
*
|
|
2042
|
+
* Derive `from` for a view-less response holding the whole collection
|
|
1701
2043
|
*
|
|
1702
|
-
* @param
|
|
1703
|
-
* @
|
|
2044
|
+
* @param viewUrl - The `hydra:view.@id` URL, or null
|
|
2045
|
+
* @param data - The items on the current page
|
|
2046
|
+
* @param total - The total item count
|
|
2047
|
+
* @returns 1 when the response provably holds all items, undefined otherwise
|
|
1704
2048
|
*/
|
|
1705
|
-
private
|
|
2049
|
+
private _wholeSetFrom;
|
|
1706
2050
|
/**
|
|
1707
|
-
*
|
|
2051
|
+
* Derive `to` for a view-less response holding the whole collection
|
|
1708
2052
|
*
|
|
1709
|
-
*
|
|
1710
|
-
*
|
|
1711
|
-
*
|
|
1712
|
-
* @
|
|
1713
|
-
* @param name - The query-parameter name to look up
|
|
1714
|
-
* @returns The raw string value of the parameter, or undefined
|
|
2053
|
+
* @param viewUrl - The `hydra:view.@id` URL, or null
|
|
2054
|
+
* @param data - The items on the current page
|
|
2055
|
+
* @param total - The total item count
|
|
2056
|
+
* @returns The item count when the response provably holds all items, undefined otherwise
|
|
1715
2057
|
*/
|
|
1716
|
-
private
|
|
2058
|
+
private _wholeSetTo;
|
|
1717
2059
|
}
|
|
1718
2060
|
|
|
1719
2061
|
/**
|
|
1720
|
-
* Request strategy for the
|
|
1721
|
-
*
|
|
1722
|
-
* Generates URIs in
|
|
1723
|
-
* -
|
|
1724
|
-
* -
|
|
1725
|
-
*
|
|
1726
|
-
*
|
|
1727
|
-
* -
|
|
1728
|
-
*
|
|
1729
|
-
*
|
|
2062
|
+
* Request strategy for the Directus driver
|
|
2063
|
+
*
|
|
2064
|
+
* Generates URIs in [Directus' query format](https://docs.directus.io/reference/query.html):
|
|
2065
|
+
* - Filters: `filter[field][_eq]=value` (multi-value collapses to `_in`)
|
|
2066
|
+
* - Operator filters: `filter[field][_op]=value` (translated from
|
|
2067
|
+
* `FilterOperatorEnum` — `BTW`→`_between`, `SW`→`_starts_with`,
|
|
2068
|
+
* `ILIKE`→`_icontains`, `NOT`→`_neq`/`_nin`, `NULL`→`_null`/`_nnull`)
|
|
2069
|
+
* - Sorts: `sort=-created_at,name` (CSV, `-` prefix = DESC)
|
|
2070
|
+
* - Field selection / relations: a single `fields=` CSV — flat columns
|
|
2071
|
+
* from `addSelect`, whole relations from `addIncludes` (`rel.*`), and
|
|
2072
|
+
* column-projected relations from `addEmbedded` (`rel.col1,rel.col2`)
|
|
2073
|
+
* - Search: `search=term` (global full-text search)
|
|
2074
|
+
* - Metadata: a constant `meta=total_count,filter_count` so responses
|
|
2075
|
+
* carry the totals the response strategy needs
|
|
2076
|
+
* - Pagination (page-based): `limit=N&page=N`
|
|
2077
|
+
*
|
|
2078
|
+
* The `filter` / `sort` / `fields` / `search` / `limit` / `page` keys
|
|
2079
|
+
* honour the existing `QueryBuilderOptions` names (their defaults match
|
|
2080
|
+
* the Directus wire format); `meta` is fixed by the server and lives as
|
|
2081
|
+
* a private static. Directus' `deep[...]` relational query options and
|
|
2082
|
+
* nested relation filtering are out of scope.
|
|
2083
|
+
*
|
|
2084
|
+
* PostgREST-native full-text search operators (`FTS`, `PHFTS`, `PLFTS`,
|
|
2085
|
+
* `WFTS`) throw `UnsupportedFilterOperatorError` — use `search` or the
|
|
2086
|
+
* `CONTAINS` / `ILIKE` operator filters instead.
|
|
2087
|
+
*
|
|
2088
|
+
* @see https://docs.directus.io/reference/query.html
|
|
2089
|
+
* @see https://docs.directus.io/reference/filter-rules.html
|
|
1730
2090
|
*/
|
|
1731
|
-
declare class
|
|
2091
|
+
declare class DirectusRequestStrategy extends AbstractRequestStrategy {
|
|
1732
2092
|
/**
|
|
1733
|
-
* Filters,
|
|
1734
|
-
*
|
|
2093
|
+
* Filters, operator filters, sorts, flat select, includes and embedded
|
|
2094
|
+
* (both folding into `fields=`), global search — no per-model fields
|
|
2095
|
+
* (Directus scopes relational projections with dot paths, not a
|
|
2096
|
+
* `fields[model]` map)
|
|
1735
2097
|
*/
|
|
1736
2098
|
readonly capabilities: IStrategyCapabilities;
|
|
1737
2099
|
/**
|
|
1738
|
-
*
|
|
1739
|
-
*
|
|
2100
|
+
* Directus-native name of the metadata query key
|
|
2101
|
+
*
|
|
2102
|
+
* `meta` has no `QueryBuilderOptions` slot and is fixed by the server,
|
|
2103
|
+
* so it lives as a private static to be visible in one place.
|
|
2104
|
+
*/
|
|
2105
|
+
private static readonly _metaKey;
|
|
2106
|
+
/**
|
|
2107
|
+
* Emit Directus-format query-string segments in canonical order:
|
|
2108
|
+
* filter (merged) → sort → fields → search → meta → limit → page
|
|
2109
|
+
*
|
|
2110
|
+
* Simple filters and operator filters share a single `filter` wrapper
|
|
2111
|
+
* so qs emits one ordered, deeply-nested bracket structure rather than
|
|
2112
|
+
* two duplicate top-level `filter[...]` blocks.
|
|
1740
2113
|
*
|
|
1741
2114
|
* @param state - The current query builder state
|
|
1742
2115
|
* @param options - The query parameter key name configuration
|
|
@@ -1744,17 +2117,31 @@ declare class JsonApiRequestStrategy extends AbstractRequestStrategy {
|
|
|
1744
2117
|
*/
|
|
1745
2118
|
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
1746
2119
|
/**
|
|
1747
|
-
* Append
|
|
2120
|
+
* Append the single `fields=` CSV combining flat columns, whole
|
|
2121
|
+
* relations, and column-projected relations
|
|
2122
|
+
*
|
|
2123
|
+
* Flat columns come from `addSelect`; relations from `addIncludes`
|
|
2124
|
+
* emit as `rel.*`; embedded relations from `addEmbedded` emit one
|
|
2125
|
+
* `rel.col` entry per column (or `rel.*` when no columns were given).
|
|
2126
|
+
* A relation present in both folds into the embedded fragment, which
|
|
2127
|
+
* carries the column information. When relations are present but no
|
|
2128
|
+
* flat columns were selected, the flat part defaults to `*` so the
|
|
2129
|
+
* base item's columns are not silently dropped from the projection.
|
|
1748
2130
|
*
|
|
1749
2131
|
* @param state - The current query builder state
|
|
1750
2132
|
* @param options - The query parameter key name configuration
|
|
1751
2133
|
* @param out - The accumulator the caller joins into the URI
|
|
1752
|
-
* @throws Error if the resource is missing from the fields object
|
|
1753
|
-
* @throws UnselectableModelError if a field type is not the resource or in includes
|
|
1754
2134
|
*/
|
|
1755
2135
|
private _appendFields;
|
|
1756
2136
|
/**
|
|
1757
|
-
* Append
|
|
2137
|
+
* Append the unified `filter[...]` wrapper combining simple filters
|
|
2138
|
+
* and operator filters
|
|
2139
|
+
*
|
|
2140
|
+
* Both kinds emit into the same nested object under the filter key so
|
|
2141
|
+
* qs produces a single deeply-bracketed block per request. Simple
|
|
2142
|
+
* single-value filters fold to `_eq`; simple multi-value filters fold
|
|
2143
|
+
* to `_in` (CSV). Operator filters then merge into the same per-field
|
|
2144
|
+
* map, potentially co-existing with a simple filter on the same field.
|
|
1758
2145
|
*
|
|
1759
2146
|
* @param state - The current query builder state
|
|
1760
2147
|
* @param options - The query parameter key name configuration
|
|
@@ -1762,523 +2149,1989 @@ declare class JsonApiRequestStrategy extends AbstractRequestStrategy {
|
|
|
1762
2149
|
*/
|
|
1763
2150
|
private _appendFilters;
|
|
1764
2151
|
/**
|
|
1765
|
-
* Append
|
|
2152
|
+
* Append the limit parameter
|
|
1766
2153
|
*
|
|
1767
2154
|
* @param state - The current query builder state
|
|
1768
2155
|
* @param options - The query parameter key name configuration
|
|
1769
2156
|
* @param out - The accumulator the caller joins into the URI
|
|
1770
2157
|
*/
|
|
1771
|
-
private
|
|
2158
|
+
private _appendLimit;
|
|
1772
2159
|
/**
|
|
1773
|
-
* Append
|
|
2160
|
+
* Append the constant `meta=total_count,filter_count` parameter
|
|
1774
2161
|
*
|
|
1775
|
-
*
|
|
1776
|
-
*
|
|
1777
|
-
*
|
|
2162
|
+
* Always emitted: the Directus response strategy reads the totals from
|
|
2163
|
+
* `meta`, which the server only includes when the request asks for it.
|
|
2164
|
+
*
|
|
2165
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2166
|
+
*/
|
|
2167
|
+
private _appendMeta;
|
|
2168
|
+
/**
|
|
2169
|
+
* Append the page parameter
|
|
2170
|
+
*
|
|
2171
|
+
* Directus pages are 1-indexed, matching the library state directly.
|
|
1778
2172
|
*
|
|
1779
2173
|
* @param state - The current query builder state
|
|
1780
2174
|
* @param options - The query parameter key name configuration
|
|
1781
2175
|
* @param out - The accumulator the caller joins into the URI
|
|
1782
2176
|
*/
|
|
1783
|
-
private
|
|
2177
|
+
private _appendPage;
|
|
1784
2178
|
/**
|
|
1785
|
-
* Append
|
|
2179
|
+
* Append the `search=` global full-text search parameter
|
|
2180
|
+
*
|
|
2181
|
+
* @param state - The current query builder state
|
|
2182
|
+
* @param options - The query parameter key name configuration
|
|
2183
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2184
|
+
*/
|
|
2185
|
+
private _appendSearch;
|
|
2186
|
+
/**
|
|
2187
|
+
* Append the `sort=-created_at,name` CSV parameter
|
|
1786
2188
|
*
|
|
1787
2189
|
* @param state - The current query builder state
|
|
1788
2190
|
* @param options - The query parameter key name configuration
|
|
1789
2191
|
* @param out - The accumulator the caller joins into the URI
|
|
1790
2192
|
*/
|
|
1791
2193
|
private _appendSort;
|
|
2194
|
+
/**
|
|
2195
|
+
* Translate a `FilterOperatorEnum` operator filter into Directus'
|
|
2196
|
+
* `_operator → value` payload shape
|
|
2197
|
+
*
|
|
2198
|
+
* The mapping is library-canonical → Directus-native:
|
|
2199
|
+
* - `EQ`/`GT`/`GTE`/`LT`/`LTE` → `_eq`/`_gt`/`_gte`/`_lt`/`_lte`
|
|
2200
|
+
* - `CONTAINS` → `_contains`; `ILIKE` → `_icontains` (case-insensitive)
|
|
2201
|
+
* - `SW` → `_starts_with`
|
|
2202
|
+
* - `IN` → `_in` (CSV)
|
|
2203
|
+
* - `BTW` → `_between` with `min,max` (arity-checked)
|
|
2204
|
+
* - `NOT` → `_neq` (single value) / `_nin` (multi-value, CSV)
|
|
2205
|
+
* - `NULL` → `_null=true` (when value is `true`) / `_nnull=true` (when
|
|
2206
|
+
* value is `false`); arity- and type-checked
|
|
2207
|
+
*
|
|
2208
|
+
* PostgREST's full-text-search operators (`FTS`, `PHFTS`, `PLFTS`,
|
|
2209
|
+
* `WFTS`) have no Directus equivalent and throw
|
|
2210
|
+
* `UnsupportedFilterOperatorError`.
|
|
2211
|
+
*
|
|
2212
|
+
* @param filter - The operator filter to translate
|
|
2213
|
+
* @returns A `{ _operator: value }` payload ready to merge under
|
|
2214
|
+
* `filter[field]`
|
|
2215
|
+
* @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
|
|
2216
|
+
* exactly two values, or `NULL` does not receive exactly one boolean
|
|
2217
|
+
* @throws {UnsupportedFilterOperatorError} If the operator is a
|
|
2218
|
+
* PostgREST-only FTS variant
|
|
2219
|
+
*/
|
|
2220
|
+
private _formatOperatorPayload;
|
|
1792
2221
|
}
|
|
1793
2222
|
|
|
1794
2223
|
/**
|
|
1795
|
-
*
|
|
1796
|
-
* dot-notation paths inside the response body
|
|
2224
|
+
* Response strategy for the Directus driver
|
|
1797
2225
|
*
|
|
1798
|
-
*
|
|
1799
|
-
*
|
|
1800
|
-
* `from`/`to` are either present directly or must be derived from
|
|
1801
|
-
* `currentPage` × `perPage`. Both strategies were duplicating this
|
|
1802
|
-
* verbatim before this base existed; concrete classes now extend and
|
|
1803
|
-
* provide only the docstring describing their driver's specific path
|
|
1804
|
-
* conventions (see `JsonApiResponseStrategy`, `NestjsResponseStrategy`).
|
|
2226
|
+
* Parses Directus collection responses (with `meta=total_count,filter_count`
|
|
2227
|
+
* requested, which the request strategy always does):
|
|
1805
2228
|
*
|
|
1806
|
-
*
|
|
1807
|
-
*
|
|
1808
|
-
*
|
|
2229
|
+
* ```json
|
|
2230
|
+
* {
|
|
2231
|
+
* "data": [{ "id": 1, "title": "Hello" }],
|
|
2232
|
+
* "meta": { "total_count": 48, "filter_count": 12 }
|
|
2233
|
+
* }
|
|
2234
|
+
* ```
|
|
2235
|
+
*
|
|
2236
|
+
* The default `total` path is `meta.filter_count` — the number of items
|
|
2237
|
+
* matching the current filter, which is the relevant total for paging a
|
|
2238
|
+
* filtered collection (`meta.total_count` ignores filters; point the
|
|
2239
|
+
* `total` path at it via `IPaginationConfig` if that is what you want).
|
|
2240
|
+
*
|
|
2241
|
+
* The envelope carries **no current-page or page-size field**, so:
|
|
2242
|
+
*
|
|
2243
|
+
* - `currentPage` falls back to **1** unless a `currentPage` path is
|
|
2244
|
+
* configured and resolves (only guaranteed correct for single-page
|
|
2245
|
+
* results — track the requested page in your own state for multi-page
|
|
2246
|
+
* UIs).
|
|
2247
|
+
* - `perPage` resolves only when a `perPage` path is configured.
|
|
2248
|
+
* - `lastPage` is `ceil(total ÷ perPage)` when both are known; on a
|
|
2249
|
+
* response that provably holds the whole filtered set it resolves
|
|
2250
|
+
* to 1.
|
|
2251
|
+
*
|
|
2252
|
+
* Every key path is overridable via `IPaginationConfig` (dot notation
|
|
2253
|
+
* supported), so custom wrappers that do include paging fields map
|
|
2254
|
+
* without subclassing.
|
|
2255
|
+
*
|
|
2256
|
+
* @see https://docs.directus.io/reference/query.html#meta
|
|
1809
2257
|
*/
|
|
1810
|
-
declare
|
|
2258
|
+
declare class DirectusResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
1811
2259
|
/**
|
|
1812
|
-
* Parse a
|
|
2260
|
+
* Parse a Directus collection response into a PaginatedCollection
|
|
1813
2261
|
*
|
|
1814
|
-
* @param response - The raw API response
|
|
2262
|
+
* @param response - The raw API response body
|
|
1815
2263
|
* @param options - The response key name configuration (dot-notation paths supported)
|
|
1816
2264
|
* @returns A typed PaginatedCollection instance
|
|
1817
2265
|
*/
|
|
1818
2266
|
paginate<T extends IPaginatedObject>(response: Record<string, any>, options: ResponseOptions): PaginatedCollection<T>;
|
|
1819
2267
|
/**
|
|
1820
|
-
*
|
|
2268
|
+
* Derive the last page number
|
|
1821
2269
|
*
|
|
1822
|
-
*
|
|
2270
|
+
* Resolution order: the configured `lastPage` path, then
|
|
2271
|
+
* `ceil(total ÷ perPage)` when both are known, then 1 when the
|
|
2272
|
+
* response provably holds the entire non-empty filtered set.
|
|
1823
2273
|
*
|
|
1824
2274
|
* @param response - The raw response object
|
|
1825
|
-
* @param
|
|
1826
|
-
* @
|
|
2275
|
+
* @param options - The response key name configuration
|
|
2276
|
+
* @param data - The items on the current page
|
|
2277
|
+
* @param total - The total item count
|
|
2278
|
+
* @param perPage - The page size
|
|
2279
|
+
* @returns The last page number, or undefined when inputs insufficient
|
|
1827
2280
|
*/
|
|
1828
|
-
|
|
2281
|
+
private _deriveLastPage;
|
|
1829
2282
|
/**
|
|
1830
|
-
*
|
|
2283
|
+
* Derive `from` for a response that holds the whole filtered set
|
|
1831
2284
|
*
|
|
1832
|
-
*
|
|
1833
|
-
*
|
|
1834
|
-
*
|
|
1835
|
-
* @param response - The raw response object
|
|
1836
|
-
* @param options - The response key name configuration
|
|
1837
|
-
* @param currentPage - The current page number
|
|
1838
|
-
* @param perPage - The number of items per page
|
|
1839
|
-
* @returns The "from" index, or `undefined` when neither path nor inputs suffice
|
|
2285
|
+
* @param data - The items on the current page
|
|
2286
|
+
* @param total - The total item count
|
|
2287
|
+
* @returns 1 when the page provably holds all items, undefined otherwise
|
|
1840
2288
|
*/
|
|
1841
|
-
|
|
2289
|
+
private _singlePageFrom;
|
|
1842
2290
|
/**
|
|
1843
|
-
*
|
|
1844
|
-
*
|
|
1845
|
-
* If `options.to` resolves to a value in the response, use it.
|
|
1846
|
-
* Otherwise compute `Math.min(currentPage * perPage, total)` when all
|
|
1847
|
-
* three are known.
|
|
2291
|
+
* Derive `to` for a response that holds the whole filtered set
|
|
1848
2292
|
*
|
|
1849
|
-
* @param
|
|
1850
|
-
* @param
|
|
1851
|
-
* @
|
|
1852
|
-
* @param perPage - The number of items per page
|
|
1853
|
-
* @param total - The total number of items
|
|
1854
|
-
* @returns The "to" index, or `undefined` when neither path nor inputs suffice
|
|
2293
|
+
* @param data - The items on the current page
|
|
2294
|
+
* @param total - The total item count
|
|
2295
|
+
* @returns The item count when the page provably holds all items, undefined otherwise
|
|
1855
2296
|
*/
|
|
1856
|
-
|
|
2297
|
+
private _singlePageTo;
|
|
1857
2298
|
}
|
|
1858
2299
|
|
|
1859
2300
|
/**
|
|
1860
|
-
*
|
|
1861
|
-
*
|
|
1862
|
-
* Parses JSON:API pagination responses:
|
|
1863
|
-
* ```json
|
|
1864
|
-
* {
|
|
1865
|
-
* "data": [...],
|
|
1866
|
-
* "meta": {
|
|
1867
|
-
* "current-page": 1,
|
|
1868
|
-
* "per-page": 10,
|
|
1869
|
-
* "total": 100,
|
|
1870
|
-
* "page-count": 10,
|
|
1871
|
-
* "from": 1,
|
|
1872
|
-
* "to": 10
|
|
1873
|
-
* },
|
|
1874
|
-
* "links": {
|
|
1875
|
-
* "first": "url",
|
|
1876
|
-
* "prev": "url",
|
|
1877
|
-
* "next": "url",
|
|
1878
|
-
* "last": "url"
|
|
1879
|
-
* }
|
|
1880
|
-
* }
|
|
1881
|
-
* ```
|
|
2301
|
+
* Request strategy for the Django REST Framework (DRF) driver
|
|
1882
2302
|
*
|
|
1883
|
-
*
|
|
1884
|
-
*
|
|
1885
|
-
* inherited from `AbstractDotPathResponseStrategy`; this class exists so
|
|
1886
|
-
* `DriverEnum.JSON_API` resolves to a distinct identity at the DI layer
|
|
1887
|
-
* even though the parsing logic is shared with NestJS.
|
|
2303
|
+
* Generates URIs in DRF's flat query-parameter format, augmented by
|
|
2304
|
+
* django-filter's double-underscore lookup convention:
|
|
1888
2305
|
*
|
|
1889
|
-
*
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
*
|
|
2306
|
+
* - Simple filters: `field=value` (multi-value collapses to `field__in=v1,v2`)
|
|
2307
|
+
* - Operator filters: `field__lookup=value` (translated from
|
|
2308
|
+
* `FilterOperatorEnum` — `GTE`→`__gte`, `ILIKE`→`__icontains`,
|
|
2309
|
+
* `BTW`→`__range`, `NULL`→`__isnull`, etc.)
|
|
2310
|
+
* - Ordering: `ordering=-field1,field2` (`-` prefix = DESC)
|
|
2311
|
+
* - Search: `search=term` (DRF's SearchFilter)
|
|
2312
|
+
* - Pagination: `page=N&page_size=M` (PageNumberPagination)
|
|
1896
2313
|
*
|
|
1897
|
-
*
|
|
1898
|
-
*
|
|
2314
|
+
* `ordering` and `page_size` are DRF-idiomatic param names and are
|
|
2315
|
+
* intentionally not configurable via `QueryBuilderOptions` — same
|
|
2316
|
+
* precedent as PostgREST's `order` and `offset`. PostgREST's full-text
|
|
2317
|
+
* search operators (`FTS`, `PHFTS`, `PLFTS`, `WFTS`) and the generic
|
|
2318
|
+
* `NOT` have no django-filter equivalent and throw
|
|
2319
|
+
* `UnsupportedFilterOperatorError`.
|
|
1899
2320
|
*
|
|
1900
|
-
*
|
|
2321
|
+
* @see https://www.django-rest-framework.org/api-guide/filtering/
|
|
2322
|
+
* @see https://django-filter.readthedocs.io/
|
|
1901
2323
|
*/
|
|
1902
|
-
declare class
|
|
2324
|
+
declare class DrfRequestStrategy extends AbstractRequestStrategy {
|
|
1903
2325
|
/**
|
|
1904
|
-
*
|
|
2326
|
+
* Simple filters, operator filters (django-filter lookups), sorts, and
|
|
2327
|
+
* global search — no per-model fields, no relation includes, no flat
|
|
2328
|
+
* select (django-restql adds it but is not core DRF)
|
|
1905
2329
|
*/
|
|
1906
2330
|
readonly capabilities: IStrategyCapabilities;
|
|
1907
2331
|
/**
|
|
1908
|
-
*
|
|
2332
|
+
* DRF-native names of the three hardcoded query keys
|
|
2333
|
+
*
|
|
2334
|
+
* `ordering` and `page_size` are DRF/django-filter conventions and are
|
|
2335
|
+
* intentionally not configurable through `QueryBuilderOptions`. `page`
|
|
2336
|
+
* matches the default `QueryBuilderOptions.page`, and `search` matches
|
|
2337
|
+
* the default `QueryBuilderOptions.search`, so those flow through the
|
|
2338
|
+
* shared options object.
|
|
2339
|
+
*/
|
|
2340
|
+
private static readonly _orderingKey;
|
|
2341
|
+
private static readonly _pageSizeKey;
|
|
2342
|
+
/**
|
|
2343
|
+
* Emit DRF-format query-string segments in canonical order:
|
|
2344
|
+
* filters → operator filters → ordering → search → pagination
|
|
1909
2345
|
*
|
|
1910
2346
|
* @param state - The current query builder state
|
|
1911
2347
|
* @param options - The query parameter key name configuration
|
|
1912
|
-
* @returns
|
|
2348
|
+
* @returns Ordered query-string fragments
|
|
1913
2349
|
*/
|
|
1914
2350
|
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
2351
|
+
/**
|
|
2352
|
+
* Append simple filter parameters
|
|
2353
|
+
*
|
|
2354
|
+
* Single-value filters emit `field=value` (django-filter's default
|
|
2355
|
+
* exact match). Multi-value filters collapse to django-filter's
|
|
2356
|
+
* `field__in=v1,v2,v3` form, which is the idiomatic way to express
|
|
2357
|
+
* "value in list" in DRF.
|
|
2358
|
+
*
|
|
2359
|
+
* @param state - The current query builder state
|
|
2360
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2361
|
+
*/
|
|
2362
|
+
private _appendFilters;
|
|
2363
|
+
/**
|
|
2364
|
+
* Append operator-filter parameters as `field__lookup=value`
|
|
2365
|
+
*
|
|
2366
|
+
* Maps each `FilterOperatorEnum` value to a django-filter lookup
|
|
2367
|
+
* suffix. `BTW` expands to `field__range=min,max`; `NULL` emits
|
|
2368
|
+
* `field__isnull=true|false`; the generic `NOT` and PostgREST-only
|
|
2369
|
+
* FTS operators are unsupported.
|
|
2370
|
+
*
|
|
2371
|
+
* @param state - The current query builder state
|
|
2372
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2373
|
+
* @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
|
|
2374
|
+
* exactly two values, or `NULL` does not receive exactly one boolean
|
|
2375
|
+
* @throws {UnsupportedFilterOperatorError} If the operator has no
|
|
2376
|
+
* django-filter equivalent
|
|
2377
|
+
*/
|
|
2378
|
+
private _appendOperatorFilters;
|
|
2379
|
+
/**
|
|
2380
|
+
* Append `ordering=-field1,field2` (django's `-` prefix = DESC)
|
|
2381
|
+
*
|
|
2382
|
+
* @param state - The current query builder state
|
|
2383
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2384
|
+
*/
|
|
2385
|
+
private _appendOrdering;
|
|
2386
|
+
/**
|
|
2387
|
+
* Append `page=N&page_size=M`
|
|
2388
|
+
*
|
|
2389
|
+
* `page` follows `options.page` (default `page`, matching DRF); the
|
|
2390
|
+
* size key is hardcoded to DRF's idiomatic `page_size`.
|
|
2391
|
+
*
|
|
2392
|
+
* @param state - The current query builder state
|
|
2393
|
+
* @param options - The query parameter key name configuration
|
|
2394
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2395
|
+
*/
|
|
2396
|
+
private _appendPagination;
|
|
2397
|
+
/**
|
|
2398
|
+
* Append `search=term` when a search term is set
|
|
2399
|
+
*
|
|
2400
|
+
* @param state - The current query builder state
|
|
2401
|
+
* @param options - The query parameter key name configuration
|
|
2402
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2403
|
+
*/
|
|
2404
|
+
private _appendSearch;
|
|
2405
|
+
/**
|
|
2406
|
+
* Translate a `FilterOperatorEnum` operator filter into a
|
|
2407
|
+
* `[suffix, serializedValue]` pair
|
|
2408
|
+
*
|
|
2409
|
+
* The suffix is appended to the field name with a `__` separator on the
|
|
2410
|
+
* wire side (`field__gte=18`). The empty string means "no suffix" —
|
|
2411
|
+
* django-filter's implicit `exact` lookup.
|
|
2412
|
+
*
|
|
2413
|
+
* Mapping:
|
|
2414
|
+
* - `EQ` → `''` (no suffix; default exact match)
|
|
2415
|
+
* - `GT`/`GTE`/`LT`/`LTE`/`CONTAINS` → identity (lowercased name)
|
|
2416
|
+
* - `ILIKE` → `icontains` (closest case-insensitive analog)
|
|
2417
|
+
* - `IN` → `in` with comma-joined values
|
|
2418
|
+
* - `SW` → `startswith`
|
|
2419
|
+
* - `BTW` → `range` with comma-joined `[min, max]` (arity-checked)
|
|
2420
|
+
* - `NULL` → `isnull` with boolean value (arity- and type-checked)
|
|
2421
|
+
* - `NOT` → `UnsupportedFilterOperatorError` (no generic negation in
|
|
2422
|
+
* django-filter; use `__exclude` on the queryset instead)
|
|
2423
|
+
* - `FTS`/`PLFTS`/`PHFTS`/`WFTS` → `UnsupportedFilterOperatorError`
|
|
2424
|
+
*
|
|
2425
|
+
* @param filter - The operator filter to translate
|
|
2426
|
+
* @returns A `[lookupSuffix, serializedValue]` tuple
|
|
2427
|
+
* @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
|
|
2428
|
+
* exactly two values, or `NULL` does not receive exactly one boolean
|
|
2429
|
+
* @throws {UnsupportedFilterOperatorError} If the operator has no
|
|
2430
|
+
* django-filter equivalent
|
|
2431
|
+
*/
|
|
2432
|
+
private _formatOperatorPayload;
|
|
2433
|
+
}
|
|
2434
|
+
|
|
2435
|
+
/**
|
|
2436
|
+
* Response strategy for the Django REST Framework (DRF) driver
|
|
2437
|
+
*
|
|
2438
|
+
* Parses DRF `PageNumberPagination` responses:
|
|
2439
|
+
*
|
|
2440
|
+
* ```json
|
|
2441
|
+
* {
|
|
2442
|
+
* "count": 100,
|
|
2443
|
+
* "next": "http://api.example.com/items/?page=3",
|
|
2444
|
+
* "previous": "http://api.example.com/items/?page=1",
|
|
2445
|
+
* "results": [...]
|
|
2446
|
+
* }
|
|
2447
|
+
* ```
|
|
2448
|
+
*
|
|
2449
|
+
* DRF emits no `current_page` field in the body, so this strategy
|
|
2450
|
+
* **derives** the current page (and the page size) by inspecting the
|
|
2451
|
+
* `next` / `previous` URLs:
|
|
2452
|
+
*
|
|
2453
|
+
* - `previous === null` → current page is **1**.
|
|
2454
|
+
* - `previous` set but has no `?page=N` param → DRF omits `page=1` from
|
|
2455
|
+
* URLs when the previous page is the first, so we infer **2**.
|
|
2456
|
+
* - `previous` has `?page=N` → current page is **N + 1**.
|
|
2457
|
+
*
|
|
2458
|
+
* Similarly, `perPage` is parsed from any `?page_size=N` query param on
|
|
2459
|
+
* `next` or `previous`, and `lastPage` is computed as
|
|
2460
|
+
* `ceil(count / perPage)`. When `perPage` cannot be discovered (e.g. on a
|
|
2461
|
+
* single-page response that emits both URLs as `null`), `perPage` and
|
|
2462
|
+
* `lastPage` are left undefined.
|
|
2463
|
+
*
|
|
2464
|
+
* Key paths are resolved through `DrfResponseOptions`, which defaults
|
|
2465
|
+
* `data → 'results'`, `total → 'count'`, `nextPageUrl → 'next'`,
|
|
2466
|
+
* `prevPageUrl → 'previous'`. The current-page / per-page / last-page
|
|
2467
|
+
* paths default to empty strings — the strategy ignores `options` for
|
|
2468
|
+
* those slots and uses URL inspection instead.
|
|
2469
|
+
*
|
|
2470
|
+
* @see https://www.django-rest-framework.org/api-guide/pagination/#pagenumberpagination
|
|
2471
|
+
*/
|
|
2472
|
+
declare class DrfResponseStrategy implements IResponseStrategy {
|
|
2473
|
+
/**
|
|
2474
|
+
* Parse a DRF pagination response into a PaginatedCollection
|
|
2475
|
+
*
|
|
2476
|
+
* @param response - The raw API response body
|
|
2477
|
+
* @param options - The response key name configuration
|
|
2478
|
+
* @returns A typed PaginatedCollection instance
|
|
2479
|
+
*/
|
|
2480
|
+
paginate<T extends IPaginatedObject>(response: Record<string, any>, options: ResponseOptions): PaginatedCollection<T>;
|
|
2481
|
+
/**
|
|
2482
|
+
* Derive the current page number from the `previous` URL
|
|
2483
|
+
*
|
|
2484
|
+
* - `null` → page 1
|
|
2485
|
+
* - URL without `?page=N` → page 2 (DRF omits `page=1` from URLs)
|
|
2486
|
+
* - URL with `?page=N` → N + 1
|
|
2487
|
+
*
|
|
2488
|
+
* @param prevPageUrl - The `previous` link from the DRF response, or null
|
|
2489
|
+
* @returns The current page number
|
|
2490
|
+
*/
|
|
2491
|
+
private _deriveCurrentPage;
|
|
2492
|
+
/**
|
|
2493
|
+
* Derive `from` as the 1-indexed offset of the first item on this page
|
|
2494
|
+
*
|
|
2495
|
+
* @param currentPage - The current page number
|
|
2496
|
+
* @param perPage - The page size (may be undefined)
|
|
2497
|
+
* @returns The 1-indexed `from` index, or undefined when perPage is unknown
|
|
2498
|
+
*/
|
|
2499
|
+
private _deriveFrom;
|
|
2500
|
+
/**
|
|
2501
|
+
* Derive the last page number as `ceil(total / perPage)`
|
|
2502
|
+
*
|
|
2503
|
+
* Both inputs must be defined; an empty result set (`total === 0`)
|
|
2504
|
+
* yields `lastPage = 0` which the caller treats as "no useful info"
|
|
2505
|
+
* and skips the sync to `NestService.lastPage`.
|
|
2506
|
+
*
|
|
2507
|
+
* @param total - The total item count
|
|
2508
|
+
* @param perPage - The page size
|
|
2509
|
+
* @returns The last page number, or undefined when either input is missing
|
|
2510
|
+
*/
|
|
2511
|
+
private _deriveLastPage;
|
|
2512
|
+
/**
|
|
2513
|
+
* Derive `perPage` by parsing `?page_size=N` from any available URL
|
|
2514
|
+
*
|
|
2515
|
+
* Tries `next` first (page 1 always has a `next` URL with `page_size`
|
|
2516
|
+
* if any non-default size was requested), then falls back to
|
|
2517
|
+
* `previous`. Returns undefined when neither URL contains the param —
|
|
2518
|
+
* the consumer is then on a single-page result with the server's
|
|
2519
|
+
* default page size, which is not introspectable from the body alone.
|
|
2520
|
+
*
|
|
2521
|
+
* @param nextPageUrl - The `next` link from the response, or null
|
|
2522
|
+
* @param prevPageUrl - The `previous` link from the response, or null
|
|
2523
|
+
* @returns The page size, or undefined
|
|
2524
|
+
*/
|
|
2525
|
+
private _derivePerPage;
|
|
2526
|
+
/**
|
|
2527
|
+
* Derive `to` as the 1-indexed offset of the last item on this page
|
|
2528
|
+
*
|
|
2529
|
+
* Clamped to `total` so the last page does not report past the end.
|
|
2530
|
+
*
|
|
2531
|
+
* @param currentPage - The current page number
|
|
2532
|
+
* @param perPage - The page size (may be undefined)
|
|
2533
|
+
* @param total - The total item count (may be undefined)
|
|
2534
|
+
* @returns The 1-indexed `to` index, or undefined when inputs insufficient
|
|
2535
|
+
*/
|
|
2536
|
+
private _deriveTo;
|
|
2537
|
+
/**
|
|
2538
|
+
* Extract the `page` query parameter from a DRF pagination URL
|
|
2539
|
+
*
|
|
2540
|
+
* Returns the integer value of `?page=N`, or undefined when the URL is
|
|
2541
|
+
* malformed or has no `page` param (which, by DRF convention, means
|
|
2542
|
+
* page 1 — the caller infers the semantics).
|
|
2543
|
+
*
|
|
2544
|
+
* @param url - The URL to parse
|
|
2545
|
+
* @returns The integer page value, or undefined
|
|
2546
|
+
*/
|
|
2547
|
+
private _extractPageParam;
|
|
2548
|
+
/**
|
|
2549
|
+
* Extract the `page_size` query parameter from a DRF pagination URL
|
|
2550
|
+
*
|
|
2551
|
+
* @param url - The URL to parse (or null)
|
|
2552
|
+
* @returns The integer page-size value, or undefined
|
|
2553
|
+
*/
|
|
2554
|
+
private _extractPageSizeParam;
|
|
2555
|
+
/**
|
|
2556
|
+
* Extract a single query parameter from a URL via the WHATWG URL parser
|
|
2557
|
+
*
|
|
2558
|
+
* Returns undefined when the URL is unparseable (relative URL without a
|
|
2559
|
+
* base, or malformed) or when the parameter is absent.
|
|
2560
|
+
*
|
|
2561
|
+
* @param url - The URL to parse
|
|
2562
|
+
* @param name - The query-parameter name to look up
|
|
2563
|
+
* @returns The raw string value of the parameter, or undefined
|
|
2564
|
+
*/
|
|
2565
|
+
private _extractQueryParam;
|
|
2566
|
+
}
|
|
2567
|
+
|
|
2568
|
+
/**
|
|
2569
|
+
* Request strategy for the FeathersJS driver
|
|
2570
|
+
*
|
|
2571
|
+
* Generates URIs in [Feathers' common database adapter query syntax](https://feathersjs.com/api/databases/querying):
|
|
2572
|
+
* - Filters: `field=value` (exact match); multi-value folds to `$in`
|
|
2573
|
+
* (`field[$in][0]=v1&field[$in][1]=v2`)
|
|
2574
|
+
* - Operator filters: `field[$op]=value` (translated from
|
|
2575
|
+
* `FilterOperatorEnum` — `BTW`→`$gte`+`$lte` pair, `NOT`→`$ne`/`$nin`)
|
|
2576
|
+
* - Sorts: `$sort[field]=1` (ASC) / `$sort[field]=-1` (DESC)
|
|
2577
|
+
* - Flat field selection: `$select[0]=col1&$select[1]=col2`
|
|
2578
|
+
* - Pagination (offset-based): `$limit=N&$skip=M` with
|
|
2579
|
+
* `skip = (page - 1) × limit`
|
|
2580
|
+
*
|
|
2581
|
+
* The dollar-prefixed query keys (`$limit`, `$skip`, `$sort`, `$select`)
|
|
2582
|
+
* are fixed by the Feathers adapter-commons parser and intentionally not
|
|
2583
|
+
* configurable through `QueryBuilderOptions`; they live as private
|
|
2584
|
+
* statics so they are visible in one place.
|
|
2585
|
+
*
|
|
2586
|
+
* Feathers' core adapter syntax has no relation includes, no per-model
|
|
2587
|
+
* field selection, and no global search — the corresponding fluent
|
|
2588
|
+
* methods throw the matching `Unsupported*Error`. `CONTAINS` / `ILIKE` /
|
|
2589
|
+
* `SW` (LIKE-style matching is adapter-specific, not core), `NULL` (no
|
|
2590
|
+
* null-check operator on the wire), and the PostgREST-native full-text
|
|
2591
|
+
* operators (`FTS`, `PHFTS`, `PLFTS`, `WFTS`) throw
|
|
2592
|
+
* `UnsupportedFilterOperatorError`.
|
|
2593
|
+
*
|
|
2594
|
+
* @see https://feathersjs.com/api/databases/querying
|
|
2595
|
+
*/
|
|
2596
|
+
declare class FeathersRequestStrategy extends AbstractRequestStrategy {
|
|
2597
|
+
/**
|
|
2598
|
+
* Filters, operator filters, sorts, flat field selection (`select`) —
|
|
2599
|
+
* no per-model fields, no includes, no global search, no embedded
|
|
2600
|
+
* resources
|
|
2601
|
+
*/
|
|
2602
|
+
readonly capabilities: IStrategyCapabilities;
|
|
2603
|
+
/**
|
|
2604
|
+
* Feathers-native names of the four hardcoded query keys
|
|
2605
|
+
*
|
|
2606
|
+
* The dollar prefix marks adapter-commons system params apart from
|
|
2607
|
+
* filter fields; these keys are fixed by the server and intentionally
|
|
2608
|
+
* not configurable through `QueryBuilderOptions`.
|
|
2609
|
+
*/
|
|
2610
|
+
private static readonly _limitKey;
|
|
2611
|
+
private static readonly _selectKey;
|
|
2612
|
+
private static readonly _skipKey;
|
|
2613
|
+
private static readonly _sortKey;
|
|
2614
|
+
/**
|
|
2615
|
+
* Emit Feathers-format query-string segments in canonical order:
|
|
2616
|
+
* filters → operator filters → $sort → $select → $limit → $skip
|
|
2617
|
+
*
|
|
2618
|
+
* @param state - The current query builder state
|
|
2619
|
+
* @param _options - The query parameter key name configuration (unused;
|
|
2620
|
+
* Feathers' system keys are fixed by the server)
|
|
2621
|
+
* @returns Ordered query-string fragments
|
|
2622
|
+
*/
|
|
2623
|
+
protected parts(state: IQueryBuilderState, _options: QueryBuilderOptions): string[];
|
|
2624
|
+
/**
|
|
2625
|
+
* Append simple filter parameters
|
|
2626
|
+
*
|
|
2627
|
+
* A single value emits the bare exact-match form (`field=value`);
|
|
2628
|
+
* multiple values fold to the `$in` list
|
|
2629
|
+
* (`field[$in][0]=v1&field[$in][1]=v2`).
|
|
2630
|
+
*
|
|
2631
|
+
* @param state - The current query builder state
|
|
2632
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2633
|
+
*/
|
|
2634
|
+
private _appendFilters;
|
|
2635
|
+
/**
|
|
2636
|
+
* Append explicit operator filters in the `field[$op]=value` syntax
|
|
2637
|
+
*
|
|
2638
|
+
* @param state - The current query builder state
|
|
2639
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2640
|
+
*/
|
|
2641
|
+
private _appendOperatorFilters;
|
|
2642
|
+
/**
|
|
2643
|
+
* Append the `$limit` / `$skip` pagination pair
|
|
2644
|
+
*
|
|
2645
|
+
* Feathers paginates by offset, so the 1-based page number from state
|
|
2646
|
+
* converts to `skip = (page - 1) × limit`.
|
|
2647
|
+
*
|
|
2648
|
+
* @param state - The current query builder state
|
|
2649
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2650
|
+
*/
|
|
2651
|
+
private _appendPagination;
|
|
2652
|
+
/**
|
|
2653
|
+
* Append the `$select[0]=col1&$select[1]=col2` array from the flat
|
|
2654
|
+
* select state
|
|
2655
|
+
*
|
|
2656
|
+
* @param state - The current query builder state
|
|
2657
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2658
|
+
*/
|
|
2659
|
+
private _appendSelect;
|
|
2660
|
+
/**
|
|
2661
|
+
* Append the `$sort[field]=1|-1` map
|
|
2662
|
+
*
|
|
2663
|
+
* @param state - The current query builder state
|
|
2664
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2665
|
+
*/
|
|
2666
|
+
private _appendSort;
|
|
2667
|
+
/**
|
|
2668
|
+
* Translate a `FilterOperatorEnum` operator filter into Feathers'
|
|
2669
|
+
* `$operator → value` payload shape (or a bare primitive for `EQ`)
|
|
2670
|
+
*
|
|
2671
|
+
* The mapping is library-canonical → Feathers-native:
|
|
2672
|
+
* - `EQ` → bare `field=value` (no operator wrapper)
|
|
2673
|
+
* - `GT`/`GTE`/`LT`/`LTE` → `$gt` / `$gte` / `$lt` / `$lte`
|
|
2674
|
+
* - `IN` → `$in` (array)
|
|
2675
|
+
* - `BTW` → `$gte` + `$lte` pair in one payload (arity-checked)
|
|
2676
|
+
* - `NOT` → `$ne` (single value) / `$nin` (multi-value)
|
|
2677
|
+
*
|
|
2678
|
+
* `CONTAINS`, `ILIKE`, and `SW` (LIKE-style matching is
|
|
2679
|
+
* adapter-specific in Feathers, not part of the common syntax),
|
|
2680
|
+
* `NULL` (no null-check operator), and PostgREST's full-text-search
|
|
2681
|
+
* operators (`FTS`, `PHFTS`, `PLFTS`, `WFTS`) throw
|
|
2682
|
+
* `UnsupportedFilterOperatorError`.
|
|
2683
|
+
*
|
|
2684
|
+
* @param filter - The operator filter to translate
|
|
2685
|
+
* @returns A `{ $operator: value }` payload ready to nest under
|
|
2686
|
+
* `field[...]`, or a bare primitive for `EQ`
|
|
2687
|
+
* @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
|
|
2688
|
+
* exactly two values
|
|
2689
|
+
* @throws {UnsupportedFilterOperatorError} If the operator has no
|
|
2690
|
+
* Feathers equivalent
|
|
2691
|
+
*/
|
|
2692
|
+
private _formatOperatorPayload;
|
|
2693
|
+
}
|
|
2694
|
+
|
|
2695
|
+
/**
|
|
2696
|
+
* Response strategy for the FeathersJS driver
|
|
2697
|
+
*
|
|
2698
|
+
* Parses the paginated envelope emitted by Feathers database adapters:
|
|
2699
|
+
*
|
|
2700
|
+
* ```json
|
|
2701
|
+
* {
|
|
2702
|
+
* "total": 48,
|
|
2703
|
+
* "limit": 10,
|
|
2704
|
+
* "skip": 10,
|
|
2705
|
+
* "data": [...]
|
|
2706
|
+
* }
|
|
2707
|
+
* ```
|
|
2708
|
+
*
|
|
2709
|
+
* The envelope is offset-based — no page number, no navigation URLs —
|
|
2710
|
+
* so position derives arithmetically:
|
|
2711
|
+
*
|
|
2712
|
+
* - `currentPage` is `skip / limit + 1` (integer division; a zero or
|
|
2713
|
+
* missing `limit` falls back to page **1**).
|
|
2714
|
+
* - `perPage` comes straight from `limit`; `lastPage` is
|
|
2715
|
+
* `ceil(total / limit)`.
|
|
2716
|
+
* - `from`/`to` are 1-indexed offsets derived from `skip` and the item
|
|
2717
|
+
* count of the current page (`from = skip + 1`,
|
|
2718
|
+
* `to = skip + data.length`); both stay `undefined` on an empty page.
|
|
2719
|
+
*
|
|
2720
|
+
* The `data` / `total` / `limit` key names are configurable through
|
|
2721
|
+
* `FeathersResponseOptions`; the `skip` key is fixed by the Feathers
|
|
2722
|
+
* envelope and lives as a private static.
|
|
2723
|
+
*
|
|
2724
|
+
* @see https://feathersjs.com/api/databases/common#pagination
|
|
2725
|
+
*/
|
|
2726
|
+
declare class FeathersResponseStrategy implements IResponseStrategy {
|
|
2727
|
+
/**
|
|
2728
|
+
* Feathers-native name of the offset key
|
|
2729
|
+
*
|
|
2730
|
+
* Fixed by the adapter envelope; read for page derivation only.
|
|
2731
|
+
*/
|
|
2732
|
+
private static readonly _skipKey;
|
|
2733
|
+
/**
|
|
2734
|
+
* Parse a Feathers pagination response into a PaginatedCollection
|
|
2735
|
+
*
|
|
2736
|
+
* @param response - The raw API response body
|
|
2737
|
+
* @param options - The response key name configuration
|
|
2738
|
+
* @returns A typed PaginatedCollection instance
|
|
2739
|
+
*/
|
|
2740
|
+
paginate<T extends IPaginatedObject>(response: Record<string, any>, options: ResponseOptions): PaginatedCollection<T>;
|
|
2741
|
+
}
|
|
2742
|
+
|
|
2743
|
+
/**
|
|
2744
|
+
* Request strategy for the JSON:API driver
|
|
2745
|
+
*
|
|
2746
|
+
* Generates URIs in the JSON:API format:
|
|
2747
|
+
* - Fields: `fields[articles]=title,body&fields[people]=name`
|
|
2748
|
+
* - Filters: `filter[status]=active`
|
|
2749
|
+
* - Includes: `include=author,comments.author`
|
|
2750
|
+
* - Pagination: `page[number]=1&page[size]=15`
|
|
2751
|
+
* - Sort: `sort=-created_at,name` (- prefix = DESC)
|
|
2752
|
+
*
|
|
2753
|
+
* @see https://jsonapi.org/format/
|
|
2754
|
+
*/
|
|
2755
|
+
declare class JsonApiRequestStrategy extends AbstractRequestStrategy {
|
|
2756
|
+
/**
|
|
2757
|
+
* Filters, sorts, includes, per-model fields — same shape as Spatie
|
|
2758
|
+
* but with bracket-style pagination
|
|
2759
|
+
*/
|
|
2760
|
+
readonly capabilities: IStrategyCapabilities;
|
|
2761
|
+
/**
|
|
2762
|
+
* Emit JSON:API-format query-string segments in canonical order:
|
|
2763
|
+
* include → fields → filters → pagination → sort
|
|
2764
|
+
*
|
|
2765
|
+
* @param state - The current query builder state
|
|
2766
|
+
* @param options - The query parameter key name configuration
|
|
2767
|
+
* @returns Ordered query-string fragments
|
|
2768
|
+
*/
|
|
2769
|
+
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
2770
|
+
/**
|
|
2771
|
+
* Append per-type field selection in bracket notation
|
|
2772
|
+
*
|
|
2773
|
+
* @param state - The current query builder state
|
|
2774
|
+
* @param options - The query parameter key name configuration
|
|
2775
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2776
|
+
* @throws Error if the resource is missing from the fields object
|
|
2777
|
+
* @throws UnselectableModelError if a field type is not the resource or in includes
|
|
2778
|
+
*/
|
|
2779
|
+
private _appendFields;
|
|
2780
|
+
/**
|
|
2781
|
+
* Append filter parameters in bracket notation: `filter[key]=value`
|
|
2782
|
+
*
|
|
2783
|
+
* @param state - The current query builder state
|
|
2784
|
+
* @param options - The query parameter key name configuration
|
|
2785
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2786
|
+
*/
|
|
2787
|
+
private _appendFilters;
|
|
2788
|
+
/**
|
|
2789
|
+
* Append include parameter as `include=author,comments.author`
|
|
2790
|
+
*
|
|
2791
|
+
* @param state - The current query builder state
|
|
2792
|
+
* @param options - The query parameter key name configuration
|
|
2793
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2794
|
+
*/
|
|
2795
|
+
private _appendIncludes;
|
|
2796
|
+
/**
|
|
2797
|
+
* Append JSON:API bracket pagination as `page[number]=1&page[size]=15`
|
|
2798
|
+
*
|
|
2799
|
+
* `qs.stringify` already returns the two segments joined with `&`, so we
|
|
2800
|
+
* push the whole string as one accumulator entry — `_join` will glue
|
|
2801
|
+
* it onto the rest with the same separator.
|
|
2802
|
+
*
|
|
2803
|
+
* @param state - The current query builder state
|
|
2804
|
+
* @param options - The query parameter key name configuration
|
|
2805
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2806
|
+
*/
|
|
2807
|
+
private _appendPagination;
|
|
2808
|
+
/**
|
|
2809
|
+
* Append sort parameter as `sort=-field1,field2` (`-` prefix = DESC)
|
|
2810
|
+
*
|
|
2811
|
+
* @param state - The current query builder state
|
|
2812
|
+
* @param options - The query parameter key name configuration
|
|
2813
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2814
|
+
*/
|
|
2815
|
+
private _appendSort;
|
|
2816
|
+
}
|
|
2817
|
+
|
|
2818
|
+
/**
|
|
2819
|
+
* Response strategy for the JSON:API driver
|
|
2820
|
+
*
|
|
2821
|
+
* Parses JSON:API pagination responses:
|
|
2822
|
+
* ```json
|
|
2823
|
+
* {
|
|
2824
|
+
* "data": [...],
|
|
2825
|
+
* "meta": {
|
|
2826
|
+
* "current-page": 1,
|
|
2827
|
+
* "per-page": 10,
|
|
2828
|
+
* "total": 100,
|
|
2829
|
+
* "page-count": 10,
|
|
2830
|
+
* "from": 1,
|
|
2831
|
+
* "to": 10
|
|
2832
|
+
* },
|
|
2833
|
+
* "links": {
|
|
2834
|
+
* "first": "url",
|
|
2835
|
+
* "prev": "url",
|
|
2836
|
+
* "next": "url",
|
|
2837
|
+
* "last": "url"
|
|
2838
|
+
* }
|
|
2839
|
+
* }
|
|
2840
|
+
* ```
|
|
2841
|
+
*
|
|
2842
|
+
* Default key paths are configured in `JsonApiResponseOptions`. The
|
|
2843
|
+
* traversal algorithm (dot-notation resolution + computed `from`/`to`) is
|
|
2844
|
+
* inherited from `AbstractDotPathResponseStrategy`; this class exists so
|
|
2845
|
+
* `DriverEnum.JSON_API` resolves to a distinct identity at the DI layer
|
|
2846
|
+
* even though the parsing logic is shared with NestJS.
|
|
2847
|
+
*
|
|
2848
|
+
* @see https://jsonapi.org/format/
|
|
2849
|
+
*/
|
|
2850
|
+
declare class JsonApiResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
2851
|
+
}
|
|
2852
|
+
|
|
2853
|
+
/**
|
|
2854
|
+
* Request strategy for the json-server driver
|
|
2855
|
+
*
|
|
2856
|
+
* Generates URIs in [json-server's](https://github.com/typicode/json-server)
|
|
2857
|
+
* query format — the de-facto standard mock REST API for prototyping:
|
|
2858
|
+
* - Filters: `field=value` (exact, no operator); multi-value folds to the
|
|
2859
|
+
* `in` list (`field:in=v1,v2`)
|
|
2860
|
+
* - Operator filters: colon syntax `field:op=value` — see the mapping on
|
|
2861
|
+
* `_formatOperatorSegments`
|
|
2862
|
+
* - Sorts: `_sort=-views,title` (CSV, `-` prefix = DESC)
|
|
2863
|
+
* - Search: `q=term` (full-text search)
|
|
2864
|
+
* - Pagination: `_page=N&_per_page=M`
|
|
2865
|
+
*
|
|
2866
|
+
* The underscore-prefixed system params (`_page`, `_per_page`, `_sort`)
|
|
2867
|
+
* and the `q` search key are fixed by the server and intentionally not
|
|
2868
|
+
* configurable through `QueryBuilderOptions`; they live as private
|
|
2869
|
+
* statics so they are visible in one place.
|
|
2870
|
+
*
|
|
2871
|
+
* json-server has no per-model field selection, no relation includes,
|
|
2872
|
+
* no column projection — the corresponding fluent methods throw the
|
|
2873
|
+
* matching `Unsupported*Error`. `ILIKE` (no case-insensitive variant),
|
|
2874
|
+
* `NULL` (no null check), and the PostgREST-native full-text operators
|
|
2875
|
+
* (`FTS`, `PHFTS`, `PLFTS`, `WFTS`) throw
|
|
2876
|
+
* `UnsupportedFilterOperatorError`.
|
|
2877
|
+
*
|
|
2878
|
+
* @see https://github.com/typicode/json-server
|
|
2879
|
+
*/
|
|
2880
|
+
declare class JsonServerRequestStrategy extends AbstractRequestStrategy {
|
|
2881
|
+
/**
|
|
2882
|
+
* Filters, operator filters, sorts, global search — no per-model
|
|
2883
|
+
* fields, no includes, no flat select, no embedded resources
|
|
2884
|
+
*/
|
|
2885
|
+
readonly capabilities: IStrategyCapabilities;
|
|
2886
|
+
/**
|
|
2887
|
+
* json-server-native names of the four hardcoded query keys
|
|
2888
|
+
*
|
|
2889
|
+
* The underscore prefix marks system params apart from filter fields;
|
|
2890
|
+
* these keys are fixed by the server and intentionally not
|
|
2891
|
+
* configurable through `QueryBuilderOptions`.
|
|
2892
|
+
*/
|
|
2893
|
+
private static readonly _pageKey;
|
|
2894
|
+
private static readonly _perPageKey;
|
|
2895
|
+
private static readonly _qKey;
|
|
2896
|
+
private static readonly _sortKey;
|
|
2897
|
+
/**
|
|
2898
|
+
* Emit json-server-format query-string segments in canonical order:
|
|
2899
|
+
* filters → operator filters → _sort → q → _page → _per_page
|
|
2900
|
+
*
|
|
2901
|
+
* @param state - The current query builder state
|
|
2902
|
+
* @param _options - The query parameter key name configuration (unused;
|
|
2903
|
+
* json-server's system keys are fixed by the server)
|
|
2904
|
+
* @returns Ordered query-string fragments
|
|
2905
|
+
*/
|
|
2906
|
+
protected parts(state: IQueryBuilderState, _options: QueryBuilderOptions): string[];
|
|
2907
|
+
/**
|
|
2908
|
+
* Append simple filter parameters
|
|
2909
|
+
*
|
|
2910
|
+
* A single value emits the bare exact-match form (`field=value`);
|
|
2911
|
+
* multiple values fold to the `in` list (`field:in=v1,v2`).
|
|
2912
|
+
*
|
|
2913
|
+
* @param state - The current query builder state
|
|
2914
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2915
|
+
*/
|
|
2916
|
+
private _appendFilters;
|
|
2917
|
+
/**
|
|
2918
|
+
* Append explicit operator filters in the colon syntax
|
|
2919
|
+
*
|
|
2920
|
+
* @param state - The current query builder state
|
|
2921
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2922
|
+
*/
|
|
2923
|
+
private _appendOperatorFilters;
|
|
2924
|
+
/**
|
|
2925
|
+
* Append the _page parameter
|
|
2926
|
+
*
|
|
2927
|
+
* @param state - The current query builder state
|
|
2928
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2929
|
+
*/
|
|
2930
|
+
private _appendPage;
|
|
2931
|
+
/**
|
|
2932
|
+
* Append the _per_page parameter
|
|
2933
|
+
*
|
|
2934
|
+
* @param state - The current query builder state
|
|
2935
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2936
|
+
*/
|
|
2937
|
+
private _appendPerPage;
|
|
2938
|
+
/**
|
|
2939
|
+
* Append the `q=` full-text search parameter
|
|
2940
|
+
*
|
|
2941
|
+
* @param state - The current query builder state
|
|
2942
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2943
|
+
*/
|
|
2944
|
+
private _appendSearch;
|
|
2945
|
+
/**
|
|
2946
|
+
* Append the `_sort=-views,title` CSV parameter
|
|
2947
|
+
*
|
|
2948
|
+
* @param state - The current query builder state
|
|
2949
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2950
|
+
*/
|
|
2951
|
+
private _appendSort;
|
|
2952
|
+
/**
|
|
2953
|
+
* Translate a `FilterOperatorEnum` operator filter into one or more
|
|
2954
|
+
* json-server `field:op=value` segments
|
|
2955
|
+
*
|
|
2956
|
+
* The mapping is library-canonical → json-server-native:
|
|
2957
|
+
* - `EQ` → `:eq`; `GT`/`GTE`/`LT`/`LTE` → `:gt` / `:gte` / `:lt` / `:lte`
|
|
2958
|
+
* - `CONTAINS` → `:contains`
|
|
2959
|
+
* - `SW` → `:startsWith`
|
|
2960
|
+
* - `IN` → `:in` (CSV)
|
|
2961
|
+
* - `BTW` → **two** AND-ed segments (`field:gte=min` and
|
|
2962
|
+
* `field:lte=max`, arity-checked)
|
|
2963
|
+
* - `NOT` → `:ne` — one segment per value, AND-ed
|
|
2964
|
+
*
|
|
2965
|
+
* `ILIKE` (json-server has no case-insensitive variant), `NULL` (no
|
|
2966
|
+
* null-check operator), and PostgREST's full-text-search operators
|
|
2967
|
+
* (`FTS`, `PHFTS`, `PLFTS`, `WFTS`) throw
|
|
2968
|
+
* `UnsupportedFilterOperatorError`.
|
|
2969
|
+
*
|
|
2970
|
+
* @param filter - The operator filter to translate
|
|
2971
|
+
* @returns One or more `field:op=value` query-string segments
|
|
2972
|
+
* @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
|
|
2973
|
+
* exactly two values
|
|
2974
|
+
* @throws {UnsupportedFilterOperatorError} If the operator has no
|
|
2975
|
+
* json-server equivalent
|
|
2976
|
+
*/
|
|
2977
|
+
private _formatOperatorSegments;
|
|
2978
|
+
}
|
|
2979
|
+
|
|
2980
|
+
/**
|
|
2981
|
+
* Response strategy for the json-server driver
|
|
2982
|
+
*
|
|
2983
|
+
* Parses json-server v1 paginated responses:
|
|
2984
|
+
*
|
|
2985
|
+
* ```json
|
|
2986
|
+
* {
|
|
2987
|
+
* "first": 1,
|
|
2988
|
+
* "prev": null,
|
|
2989
|
+
* "next": 2,
|
|
2990
|
+
* "last": 5,
|
|
2991
|
+
* "pages": 5,
|
|
2992
|
+
* "items": 48,
|
|
2993
|
+
* "data": [...]
|
|
2994
|
+
* }
|
|
2995
|
+
* ```
|
|
2996
|
+
*
|
|
2997
|
+
* Uniquely among the drivers, `first` / `prev` / `next` / `last` are
|
|
2998
|
+
* **page numbers**, not URLs — so the navigation-URL slots on
|
|
2999
|
+
* `PaginatedCollection` stay `undefined` and the strategy instead uses
|
|
3000
|
+
* the numbers to derive position:
|
|
3001
|
+
*
|
|
3002
|
+
* - `currentPage` is `prev + 1` (`prev === null` → page **1**).
|
|
3003
|
+
* - `perPage` is the item count of the current page whenever `next` is
|
|
3004
|
+
* set (a page with a successor is necessarily full); on the last page
|
|
3005
|
+
* of a multi-page set it is not introspectable and stays `undefined`.
|
|
3006
|
+
* - `lastPage` comes straight from `pages`; `from`/`to` derive from
|
|
3007
|
+
* `currentPage` × `perPage` on full pages, or count back from the
|
|
3008
|
+
* total on the last page (`from = total - items + 1`, `to = total`).
|
|
3009
|
+
*
|
|
3010
|
+
* The `data` / `items` / `pages` key paths are configurable through
|
|
3011
|
+
* `JsonServerResponseOptions`; the `prev` / `next` keys are fixed by the
|
|
3012
|
+
* json-server envelope and live as private statics.
|
|
3013
|
+
*
|
|
3014
|
+
* @see https://github.com/typicode/json-server
|
|
3015
|
+
*/
|
|
3016
|
+
declare class JsonServerResponseStrategy implements IResponseStrategy {
|
|
3017
|
+
/**
|
|
3018
|
+
* json-server-native names of the page-number navigation keys
|
|
3019
|
+
*
|
|
3020
|
+
* Fixed by the v1 envelope; read for derivation only and never
|
|
3021
|
+
* surfaced as URLs.
|
|
3022
|
+
*/
|
|
3023
|
+
private static readonly _nextKey;
|
|
3024
|
+
private static readonly _prevKey;
|
|
3025
|
+
/**
|
|
3026
|
+
* Parse a json-server pagination response into a PaginatedCollection
|
|
3027
|
+
*
|
|
3028
|
+
* @param response - The raw API response body
|
|
3029
|
+
* @param options - The response key name configuration
|
|
3030
|
+
* @returns A typed PaginatedCollection instance
|
|
3031
|
+
*/
|
|
3032
|
+
paginate<T extends IPaginatedObject>(response: Record<string, any>, options: ResponseOptions): PaginatedCollection<T>;
|
|
3033
|
+
/**
|
|
3034
|
+
* Derive `from` as the 1-indexed offset of the first item on this page
|
|
3035
|
+
*
|
|
3036
|
+
* Computed from `currentPage` × `perPage` on full pages; on the last
|
|
3037
|
+
* page (no `next`) it counts back from the total
|
|
3038
|
+
* (`total - items + 1`), which also covers single-page responses.
|
|
3039
|
+
*
|
|
3040
|
+
* @param data - The items on the current page
|
|
3041
|
+
* @param currentPage - The current page number
|
|
3042
|
+
* @param next - The next page number, or null
|
|
3043
|
+
* @param perPage - The page size (may be undefined)
|
|
3044
|
+
* @param total - The total item count (may be undefined)
|
|
3045
|
+
* @returns The 1-indexed `from` index, or undefined when inputs insufficient
|
|
3046
|
+
*/
|
|
3047
|
+
private _deriveFrom;
|
|
3048
|
+
/**
|
|
3049
|
+
* Derive `perPage` from the current page's item count
|
|
3050
|
+
*
|
|
3051
|
+
* A page with a `next` successor is necessarily full, so its item
|
|
3052
|
+
* count equals the page size. Without a successor the page may be
|
|
3053
|
+
* partial and the size is not introspectable from the body alone.
|
|
3054
|
+
*
|
|
3055
|
+
* @param next - The next page number, or null
|
|
3056
|
+
* @param data - The items on the current page
|
|
3057
|
+
* @returns The page size, or undefined
|
|
3058
|
+
*/
|
|
3059
|
+
private _derivePerPage;
|
|
3060
|
+
/**
|
|
3061
|
+
* Derive `to` as the 1-indexed offset of the last item on this page
|
|
3062
|
+
*
|
|
3063
|
+
* Clamped to `total` so the last page does not report past the end;
|
|
3064
|
+
* on the last page (no `next`) it is simply the total.
|
|
3065
|
+
*
|
|
3066
|
+
* @param data - The items on the current page
|
|
3067
|
+
* @param currentPage - The current page number
|
|
3068
|
+
* @param next - The next page number, or null
|
|
3069
|
+
* @param perPage - The page size (may be undefined)
|
|
3070
|
+
* @param total - The total item count (may be undefined)
|
|
3071
|
+
* @returns The 1-indexed `to` index, or undefined when inputs insufficient
|
|
3072
|
+
*/
|
|
3073
|
+
private _deriveTo;
|
|
3074
|
+
}
|
|
3075
|
+
|
|
3076
|
+
/**
|
|
3077
|
+
* Request strategy for the Laravel (pagination-only) driver
|
|
3078
|
+
*
|
|
3079
|
+
* Generates simple pagination URIs:
|
|
3080
|
+
* - `/{resource}?limit=N&page=N`
|
|
3081
|
+
*
|
|
3082
|
+
* Filters, sorts, fields, includes, search, and select in state are ignored.
|
|
3083
|
+
*/
|
|
3084
|
+
declare class LaravelRequestStrategy extends AbstractRequestStrategy {
|
|
3085
|
+
/**
|
|
3086
|
+
* Pagination-only driver — no filtering, sorting, or column selection
|
|
3087
|
+
*/
|
|
3088
|
+
readonly capabilities: IStrategyCapabilities;
|
|
3089
|
+
/**
|
|
3090
|
+
* Emit only the pagination params; filters/sorts/etc. are ignored
|
|
3091
|
+
*
|
|
3092
|
+
* @param state - The current query builder state
|
|
3093
|
+
* @param options - The query parameter key name configuration
|
|
3094
|
+
* @returns The two pagination query-string fragments
|
|
3095
|
+
*/
|
|
3096
|
+
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
3097
|
+
}
|
|
3098
|
+
|
|
3099
|
+
/**
|
|
3100
|
+
* Base class for response strategies whose pagination metadata is a flat
|
|
3101
|
+
* key-value envelope on the response body
|
|
3102
|
+
*
|
|
3103
|
+
* Laravel's stock pagination and Spatie's `QueryBuilder` both emit the
|
|
3104
|
+
* same flat shape — `{ data, current_page, total, per_page, from, to,
|
|
3105
|
+
* next_page_url, prev_page_url, first_page_url, last_page, last_page_url
|
|
3106
|
+
* }` — and both response strategies were duplicating the byte-identical
|
|
3107
|
+
* `new PaginatedCollection(response[options.X], ...)` body before this
|
|
3108
|
+
* base existed. Concrete classes now extend and provide only the
|
|
3109
|
+
* docstring describing their driver's specific shape (see
|
|
3110
|
+
* `LaravelResponseStrategy`, `SpatieResponseStrategy`).
|
|
3111
|
+
*
|
|
3112
|
+
* Drivers whose pagination metadata is a nested envelope (JSON:API,
|
|
1931
3113
|
* NestJS, Strapi) extend `AbstractDotPathResponseStrategy` instead.
|
|
1932
3114
|
* Drivers whose metadata comes from HTTP headers (PostgREST) or is
|
|
1933
3115
|
* derived from response URLs (DRF) implement `IResponseStrategy`
|
|
1934
3116
|
* directly.
|
|
1935
3117
|
*/
|
|
1936
|
-
declare abstract class AbstractFlatResponseStrategy implements IResponseStrategy {
|
|
3118
|
+
declare abstract class AbstractFlatResponseStrategy implements IResponseStrategy {
|
|
3119
|
+
/**
|
|
3120
|
+
* Parse a flat-envelope pagination response into a PaginatedCollection
|
|
3121
|
+
*
|
|
3122
|
+
* @param response - The raw API response object
|
|
3123
|
+
* @param options - The response key name configuration
|
|
3124
|
+
* @returns A typed PaginatedCollection instance
|
|
3125
|
+
*/
|
|
3126
|
+
paginate<T extends IPaginatedObject>(response: Record<string, any>, options: ResponseOptions): PaginatedCollection<T>;
|
|
3127
|
+
}
|
|
3128
|
+
|
|
3129
|
+
/**
|
|
3130
|
+
* Response strategy for the Laravel (pagination-only) driver
|
|
3131
|
+
*
|
|
3132
|
+
* Parses flat Laravel pagination responses:
|
|
3133
|
+
* ```json
|
|
3134
|
+
* {
|
|
3135
|
+
* "data": [...],
|
|
3136
|
+
* "current_page": 1,
|
|
3137
|
+
* "total": 100,
|
|
3138
|
+
* "per_page": 15,
|
|
3139
|
+
* "from": 1,
|
|
3140
|
+
* "to": 15,
|
|
3141
|
+
* "next_page_url": "...",
|
|
3142
|
+
* "prev_page_url": "...",
|
|
3143
|
+
* "first_page_url": "...",
|
|
3144
|
+
* "last_page": 7,
|
|
3145
|
+
* "last_page_url": "..."
|
|
3146
|
+
* }
|
|
3147
|
+
* ```
|
|
3148
|
+
*
|
|
3149
|
+
* The traversal algorithm (flat `response[options.X]` lookups) is
|
|
3150
|
+
* inherited from `AbstractFlatResponseStrategy`; this class exists so
|
|
3151
|
+
* `DriverEnum.LARAVEL` resolves to a distinct identity at the DI layer
|
|
3152
|
+
* even though the parsing logic is shared with Spatie.
|
|
3153
|
+
*/
|
|
3154
|
+
declare class LaravelResponseStrategy extends AbstractFlatResponseStrategy {
|
|
3155
|
+
}
|
|
3156
|
+
|
|
3157
|
+
/**
|
|
3158
|
+
* Request strategy for the NestJS (nestjs-paginate) driver
|
|
3159
|
+
*
|
|
3160
|
+
* Generates URIs in the NestJS paginate format:
|
|
3161
|
+
* - Simple filters: `filter.field=value`
|
|
3162
|
+
* - Operator filters: `filter.field=$operator:value`
|
|
3163
|
+
* - Sorts: `sortBy=field1:DESC,field2:ASC`
|
|
3164
|
+
* - Select: `select=col1,col2`
|
|
3165
|
+
* - Search: `search=term`
|
|
3166
|
+
* - Pagination: `limit=N&page=N`
|
|
3167
|
+
*
|
|
3168
|
+
* @see https://github.com/ppetzold/nestjs-paginate
|
|
3169
|
+
*/
|
|
3170
|
+
declare class NestjsRequestStrategy extends AbstractRequestStrategy {
|
|
1937
3171
|
/**
|
|
1938
|
-
*
|
|
3172
|
+
* Filters, operator filters, sorts, flat select, global search — no
|
|
3173
|
+
* per-model fields, no includes
|
|
3174
|
+
*/
|
|
3175
|
+
readonly capabilities: IStrategyCapabilities;
|
|
3176
|
+
/**
|
|
3177
|
+
* Validate that the given limit is accepted by nestjs-paginate
|
|
3178
|
+
*
|
|
3179
|
+
* Accepts any integer `>= 1` as a page size, plus `-1` which nestjs-paginate
|
|
3180
|
+
* interprets as "fetch all items" (server must opt-in via `maxLimit: -1`).
|
|
3181
|
+
*
|
|
3182
|
+
* @param limit - The limit value to validate
|
|
3183
|
+
* @throws {InvalidLimitError} If the value is not an integer, or is 0, or is a negative number other than -1
|
|
3184
|
+
*/
|
|
3185
|
+
validateLimit(limit: number): void;
|
|
3186
|
+
/**
|
|
3187
|
+
* Emit NestJS-format query-string segments in canonical order:
|
|
3188
|
+
* filters → operator filters → sortBy → select → search → limit → page
|
|
3189
|
+
*
|
|
3190
|
+
* @param state - The current query builder state
|
|
3191
|
+
* @param options - The query parameter key name configuration
|
|
3192
|
+
* @returns Ordered query-string fragments
|
|
3193
|
+
*/
|
|
3194
|
+
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
3195
|
+
/**
|
|
3196
|
+
* Append simple filter parameters as `filter.field=value1,value2`
|
|
3197
|
+
*
|
|
3198
|
+
* @param state - The current query builder state
|
|
3199
|
+
* @param options - The query parameter key name configuration
|
|
3200
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3201
|
+
*/
|
|
3202
|
+
private _appendFilters;
|
|
3203
|
+
/**
|
|
3204
|
+
* Append the limit parameter
|
|
3205
|
+
*
|
|
3206
|
+
* @param state - The current query builder state
|
|
3207
|
+
* @param options - The query parameter key name configuration
|
|
3208
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3209
|
+
*/
|
|
3210
|
+
private _appendLimit;
|
|
3211
|
+
/**
|
|
3212
|
+
* Append operator-filter parameters as `filter.field=$op:value`
|
|
3213
|
+
*
|
|
3214
|
+
* Groups by field; multi-value operators ($in, $btw) join values with commas.
|
|
3215
|
+
*
|
|
3216
|
+
* @param state - The current query builder state
|
|
3217
|
+
* @param options - The query parameter key name configuration
|
|
3218
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3219
|
+
*/
|
|
3220
|
+
private _appendOperatorFilters;
|
|
3221
|
+
/**
|
|
3222
|
+
* Append the page parameter
|
|
3223
|
+
*
|
|
3224
|
+
* @param state - The current query builder state
|
|
3225
|
+
* @param options - The query parameter key name configuration
|
|
3226
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3227
|
+
*/
|
|
3228
|
+
private _appendPage;
|
|
3229
|
+
/**
|
|
3230
|
+
* Append the search parameter as `search=term`
|
|
3231
|
+
*
|
|
3232
|
+
* @param state - The current query builder state
|
|
3233
|
+
* @param options - The query parameter key name configuration
|
|
3234
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3235
|
+
*/
|
|
3236
|
+
private _appendSearch;
|
|
3237
|
+
/**
|
|
3238
|
+
* Append the select parameter as `select=col1,col2`
|
|
3239
|
+
*
|
|
3240
|
+
* @param state - The current query builder state
|
|
3241
|
+
* @param options - The query parameter key name configuration
|
|
3242
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3243
|
+
*/
|
|
3244
|
+
private _appendSelect;
|
|
3245
|
+
/**
|
|
3246
|
+
* Append sort parameter as `sortBy=field1:DESC,field2:ASC`
|
|
3247
|
+
*
|
|
3248
|
+
* @param state - The current query builder state
|
|
3249
|
+
* @param options - The query parameter key name configuration
|
|
3250
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3251
|
+
*/
|
|
3252
|
+
private _appendSort;
|
|
3253
|
+
}
|
|
3254
|
+
|
|
3255
|
+
/**
|
|
3256
|
+
* Response strategy for the NestJS (nestjs-paginate) driver
|
|
3257
|
+
*
|
|
3258
|
+
* Parses nested NestJS pagination responses:
|
|
3259
|
+
* ```json
|
|
3260
|
+
* {
|
|
3261
|
+
* "data": [...],
|
|
3262
|
+
* "meta": {
|
|
3263
|
+
* "currentPage": 1,
|
|
3264
|
+
* "totalItems": 100,
|
|
3265
|
+
* "itemsPerPage": 10,
|
|
3266
|
+
* "totalPages": 10
|
|
3267
|
+
* },
|
|
3268
|
+
* "links": {
|
|
3269
|
+
* "first": "url",
|
|
3270
|
+
* "previous": "url",
|
|
3271
|
+
* "next": "url",
|
|
3272
|
+
* "last": "url",
|
|
3273
|
+
* "current": "url"
|
|
3274
|
+
* }
|
|
3275
|
+
* }
|
|
3276
|
+
* ```
|
|
3277
|
+
*
|
|
3278
|
+
* Default key paths are configured in `NestjsResponseOptions`. The
|
|
3279
|
+
* traversal algorithm (dot-notation resolution + computed `from`/`to`) is
|
|
3280
|
+
* inherited from `AbstractDotPathResponseStrategy`; this class exists so
|
|
3281
|
+
* `DriverEnum.NESTJS` resolves to a distinct identity at the DI layer
|
|
3282
|
+
* even though the parsing logic is shared with JSON:API.
|
|
3283
|
+
*
|
|
3284
|
+
* @see https://github.com/ppetzold/nestjs-paginate
|
|
3285
|
+
*/
|
|
3286
|
+
declare class NestjsResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
3287
|
+
}
|
|
3288
|
+
|
|
3289
|
+
/**
|
|
3290
|
+
* Request strategy for the @nestjsx/crud driver
|
|
3291
|
+
*
|
|
3292
|
+
* Generates URIs in [@nestjsx/crud's pipe-delimited query format](https://github.com/nestjsx/crud/wiki/Requests):
|
|
3293
|
+
* - Filters: `filter=field||$eq||value` (repeatable; multi-value
|
|
3294
|
+
* collapses to `filter=field||$in||v1,v2`)
|
|
3295
|
+
* - Operator filters: `filter=field||$op||value` (translated from
|
|
3296
|
+
* `FilterOperatorEnum` — `CONTAINS`→`$cont`, `ILIKE`→`$contL`,
|
|
3297
|
+
* `SW`→`$starts`, `BTW`→`$between`, `NOT`→`$ne`/`$notin`,
|
|
3298
|
+
* `NULL`→`$isnull`/`$notnull` with no value segment)
|
|
3299
|
+
* - Joins: `join=relation` (repeatable, from `addIncludes`)
|
|
3300
|
+
* - Field selection (flat): `fields=col1,col2` (from `addSelect`)
|
|
3301
|
+
* - Sorts: `sort=field,ASC` (repeatable, uppercase direction)
|
|
3302
|
+
* - Pagination (page-based): `page=N&limit=N`
|
|
3303
|
+
*
|
|
3304
|
+
* The JSON-shaped `s={...}` search parameter is intentionally out of
|
|
3305
|
+
* scope: it is not a plain search term, so `setSearch` throws
|
|
3306
|
+
* `UnsupportedSearchError` on this driver. PostgREST-native full-text
|
|
3307
|
+
* search operators (`FTS`, `PHFTS`, `PLFTS`, `WFTS`) throw
|
|
3308
|
+
* `UnsupportedFilterOperatorError`.
|
|
3309
|
+
*
|
|
3310
|
+
* @see https://github.com/nestjsx/crud/wiki/Requests
|
|
3311
|
+
*/
|
|
3312
|
+
declare class NestjsxCrudRequestStrategy extends AbstractRequestStrategy {
|
|
3313
|
+
/**
|
|
3314
|
+
* Filters, operator filters, joins (`includes`), flat field selection
|
|
3315
|
+
* (`select`), sorts — no per-model fields, no global search (the `s`
|
|
3316
|
+
* parameter is JSON-shaped, not a plain term)
|
|
3317
|
+
*/
|
|
3318
|
+
readonly capabilities: IStrategyCapabilities;
|
|
3319
|
+
/**
|
|
3320
|
+
* @nestjsx/crud-native names of the four hardcoded query keys
|
|
3321
|
+
*
|
|
3322
|
+
* The wire format is fixed (the server's `CrudRequestInterceptor`
|
|
3323
|
+
* reads `fields`, `filter`, `join`, and `sort`); these keys are
|
|
3324
|
+
* intentionally not configurable through `QueryBuilderOptions` and
|
|
3325
|
+
* live as private statics so they are visible in one place.
|
|
3326
|
+
*/
|
|
3327
|
+
private static readonly _fieldsKey;
|
|
3328
|
+
private static readonly _filterKey;
|
|
3329
|
+
private static readonly _joinKey;
|
|
3330
|
+
private static readonly _sortKey;
|
|
3331
|
+
/**
|
|
3332
|
+
* Pipe delimiter separating field, operator, and value segments
|
|
3333
|
+
*/
|
|
3334
|
+
private static readonly _separator;
|
|
3335
|
+
/**
|
|
3336
|
+
* Emit @nestjsx/crud-format query-string segments in canonical order:
|
|
3337
|
+
* fields → filters → operator filters → join → sort → limit → page
|
|
3338
|
+
*
|
|
3339
|
+
* @param state - The current query builder state
|
|
3340
|
+
* @param options - The query parameter key name configuration (used
|
|
3341
|
+
* for `page` / `limit`, whose defaults match the wire format; the
|
|
3342
|
+
* `fields` / `filter` / `join` / `sort` keys are fixed by the server)
|
|
3343
|
+
* @returns Ordered query-string fragments
|
|
3344
|
+
*/
|
|
3345
|
+
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
3346
|
+
/**
|
|
3347
|
+
* Append `fields=col1,col2` from the flat select array
|
|
3348
|
+
*
|
|
3349
|
+
* @param state - The current query builder state
|
|
3350
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3351
|
+
*/
|
|
3352
|
+
private _appendFields;
|
|
3353
|
+
/**
|
|
3354
|
+
* Append simple filters as repeatable `filter=field||$eq||value` params
|
|
3355
|
+
*
|
|
3356
|
+
* Single-value filters fold to `$eq`; multi-value filters fold to
|
|
3357
|
+
* `$in` with comma-joined values.
|
|
3358
|
+
*
|
|
3359
|
+
* @param state - The current query builder state
|
|
3360
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3361
|
+
*/
|
|
3362
|
+
private _appendFilters;
|
|
3363
|
+
/**
|
|
3364
|
+
* Append `join=relation` params from the includes array
|
|
3365
|
+
*
|
|
3366
|
+
* Per-relation field projection (`join=relation||f1,f2`) is not
|
|
3367
|
+
* expressible through the current state shape and is out of scope.
|
|
3368
|
+
*
|
|
3369
|
+
* @param state - The current query builder state
|
|
3370
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3371
|
+
*/
|
|
3372
|
+
private _appendJoin;
|
|
3373
|
+
/**
|
|
3374
|
+
* Append the limit parameter
|
|
3375
|
+
*
|
|
3376
|
+
* @param state - The current query builder state
|
|
3377
|
+
* @param options - The query parameter key name configuration
|
|
3378
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3379
|
+
*/
|
|
3380
|
+
private _appendLimit;
|
|
3381
|
+
/**
|
|
3382
|
+
* Append operator filters as repeatable `filter=field||$op||value` params
|
|
3383
|
+
*
|
|
3384
|
+
* @param state - The current query builder state
|
|
3385
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3386
|
+
*/
|
|
3387
|
+
private _appendOperatorFilters;
|
|
3388
|
+
/**
|
|
3389
|
+
* Append the page parameter
|
|
3390
|
+
*
|
|
3391
|
+
* @param state - The current query builder state
|
|
3392
|
+
* @param options - The query parameter key name configuration
|
|
3393
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3394
|
+
*/
|
|
3395
|
+
private _appendPage;
|
|
3396
|
+
/**
|
|
3397
|
+
* Append `sort=field,ASC` params, one per sort rule
|
|
3398
|
+
*
|
|
3399
|
+
* @param state - The current query builder state
|
|
3400
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3401
|
+
*/
|
|
3402
|
+
private _appendSort;
|
|
3403
|
+
/**
|
|
3404
|
+
* Translate a `FilterOperatorEnum` operator filter into @nestjsx/crud's
|
|
3405
|
+
* `$operator||value` condition segment
|
|
3406
|
+
*
|
|
3407
|
+
* The mapping is library-canonical → @nestjsx/crud-native:
|
|
3408
|
+
* - `EQ`/`GT`/`GTE`/`LT`/`LTE`/`IN` → identity (same operator name)
|
|
3409
|
+
* - `CONTAINS` → `$cont`; `ILIKE` → `$contL` (case-insensitive contains)
|
|
3410
|
+
* - `SW` → `$starts`
|
|
3411
|
+
* - `BTW` → `$between` with `min,max` (arity-checked)
|
|
3412
|
+
* - `NOT` → `$ne` (single value) / `$notin` (multi-value)
|
|
3413
|
+
* - `NULL` → `$isnull` (when value is `true`) / `$notnull` (when value
|
|
3414
|
+
* is `false`); both emit **no value segment**; arity- and type-checked
|
|
3415
|
+
*
|
|
3416
|
+
* PostgREST's full-text-search operators (`FTS`, `PHFTS`, `PLFTS`,
|
|
3417
|
+
* `WFTS`) have no @nestjsx/crud equivalent and throw
|
|
3418
|
+
* `UnsupportedFilterOperatorError`.
|
|
1939
3419
|
*
|
|
1940
|
-
* @param
|
|
1941
|
-
* @
|
|
1942
|
-
* @
|
|
3420
|
+
* @param filter - The operator filter to translate
|
|
3421
|
+
* @returns The `$operator||value` (or bare `$operator`) condition segment
|
|
3422
|
+
* @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
|
|
3423
|
+
* exactly two values, or `NULL` does not receive exactly one boolean
|
|
3424
|
+
* @throws {UnsupportedFilterOperatorError} If the operator is a
|
|
3425
|
+
* PostgREST-only FTS variant
|
|
1943
3426
|
*/
|
|
1944
|
-
|
|
3427
|
+
private _formatOperatorCondition;
|
|
1945
3428
|
}
|
|
1946
3429
|
|
|
1947
3430
|
/**
|
|
1948
|
-
* Response strategy for the
|
|
3431
|
+
* Response strategy for the @nestjsx/crud driver
|
|
1949
3432
|
*
|
|
1950
|
-
* Parses
|
|
3433
|
+
* Parses @nestjsx/crud's `getMany` envelope:
|
|
1951
3434
|
* ```json
|
|
1952
3435
|
* {
|
|
1953
|
-
* "data": [
|
|
1954
|
-
* "
|
|
1955
|
-
* "total":
|
|
1956
|
-
* "
|
|
1957
|
-
* "
|
|
1958
|
-
* "to": 15,
|
|
1959
|
-
* "next_page_url": "...",
|
|
1960
|
-
* "prev_page_url": "...",
|
|
1961
|
-
* "first_page_url": "...",
|
|
1962
|
-
* "last_page": 7,
|
|
1963
|
-
* "last_page_url": "..."
|
|
3436
|
+
* "data": [{ "id": 1, "name": "John" }],
|
|
3437
|
+
* "count": 10,
|
|
3438
|
+
* "total": 48,
|
|
3439
|
+
* "page": 2,
|
|
3440
|
+
* "pageCount": 5
|
|
1964
3441
|
* }
|
|
1965
3442
|
* ```
|
|
1966
3443
|
*
|
|
1967
|
-
*
|
|
1968
|
-
*
|
|
1969
|
-
* `
|
|
1970
|
-
*
|
|
3444
|
+
* Default key paths are configured in `NestjsxCrudResponseOptions`. The
|
|
3445
|
+
* envelope carries no `from`/`to` indices and no navigation links, so
|
|
3446
|
+
* `from`/`to` are computed from `page` × `count` by the inherited
|
|
3447
|
+
* traversal algorithm and the URL slots resolve to `undefined` unless
|
|
3448
|
+
* the consumer overrides their paths via `IPaginationConfig`.
|
|
3449
|
+
*
|
|
3450
|
+
* Note that `count` is the number of entities **on the current page**,
|
|
3451
|
+
* not the requested page size — on the last page of a result set the
|
|
3452
|
+
* derived `from`/`to` can underestimate. Consumers needing exact
|
|
3453
|
+
* indices should compute them from the requested limit instead.
|
|
3454
|
+
*
|
|
3455
|
+
* The dot-notation traversal is inherited from
|
|
3456
|
+
* `AbstractDotPathResponseStrategy`; this class exists so
|
|
3457
|
+
* `DriverEnum.NESTJSX_CRUD` resolves to a distinct identity at the DI
|
|
3458
|
+
* layer even though the parsing logic is shared with JSON:API, NestJS,
|
|
3459
|
+
* and Strapi.
|
|
3460
|
+
*
|
|
3461
|
+
* @see https://github.com/nestjsx/crud/wiki/Requests
|
|
1971
3462
|
*/
|
|
1972
|
-
declare class
|
|
3463
|
+
declare class NestjsxCrudResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
1973
3464
|
}
|
|
1974
3465
|
|
|
1975
3466
|
/**
|
|
1976
|
-
* Request strategy for the
|
|
1977
|
-
*
|
|
1978
|
-
* Generates URIs in the NestJS paginate format:
|
|
1979
|
-
* - Simple filters: `filter.field=value`
|
|
1980
|
-
* - Operator filters: `filter.field=$operator:value`
|
|
1981
|
-
* - Sorts: `sortBy=field1:DESC,field2:ASC`
|
|
1982
|
-
* - Select: `select=col1,col2`
|
|
1983
|
-
* - Search: `search=term`
|
|
1984
|
-
* - Pagination: `limit=N&page=N`
|
|
3467
|
+
* Request strategy for the OData v4 driver
|
|
1985
3468
|
*
|
|
1986
|
-
*
|
|
3469
|
+
* Generates URIs using [OData's system query options](https://www.odata.org/getting-started/basic-tutorial/#queryData):
|
|
3470
|
+
* - Filters: a single `$filter=` parameter holding ` and `-joined terms in
|
|
3471
|
+
* OData's expression language (`Price gt 20 and Category eq 'Electronics'`)
|
|
3472
|
+
* - Operator filters: translated from `FilterOperatorEnum` — see the
|
|
3473
|
+
* mapping on `_formatOperatorTerms`
|
|
3474
|
+
* - Sorts: `$orderby=field asc,other desc` (CSV with explicit direction)
|
|
3475
|
+
* - Select: `$select=col1,col2`
|
|
3476
|
+
* - Expand: `$expand=rel,other($select=col1,col2)` — plain relations come
|
|
3477
|
+
* from `addIncludes`, column-projected ones from `addEmbedded`
|
|
3478
|
+
* - Search: `$search=term` (OData v4 free-text search)
|
|
3479
|
+
* - Pagination: `$top=N&$skip=M` (skip derived from state.page) plus a
|
|
3480
|
+
* constant `$count=true` so responses carry the `@odata.count` total
|
|
3481
|
+
* the response strategy needs
|
|
3482
|
+
*
|
|
3483
|
+
* The `$`-prefixed parameter names are fixed by the OData specification
|
|
3484
|
+
* and intentionally not configurable through `QueryBuilderOptions`; they
|
|
3485
|
+
* live as private statics so they are visible in one place. String
|
|
3486
|
+
* literals are single-quoted with embedded quotes doubled (`'O''Brien'`)
|
|
3487
|
+
* per the OData ABNF; numbers and booleans are emitted bare.
|
|
3488
|
+
*
|
|
3489
|
+
* PostgREST-native full-text search operators (`FTS`, `PHFTS`, `PLFTS`,
|
|
3490
|
+
* `WFTS`) throw `UnsupportedFilterOperatorError` — use `$search` or the
|
|
3491
|
+
* `CONTAINS` / `ILIKE` operator filters instead.
|
|
3492
|
+
*
|
|
3493
|
+
* @see https://www.odata.org/
|
|
3494
|
+
* @see https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html
|
|
1987
3495
|
*/
|
|
1988
|
-
declare class
|
|
3496
|
+
declare class OdataRequestStrategy extends AbstractRequestStrategy {
|
|
1989
3497
|
/**
|
|
1990
|
-
* Filters, operator filters, sorts, flat select,
|
|
1991
|
-
* per-model fields
|
|
3498
|
+
* Filters, operator filters, sorts, flat select, includes and embedded
|
|
3499
|
+
* (both folding into `$expand`), global search — no per-model fields
|
|
3500
|
+
* (OData has no JSON:API-style `fields[type]` projection)
|
|
1992
3501
|
*/
|
|
1993
3502
|
readonly capabilities: IStrategyCapabilities;
|
|
1994
3503
|
/**
|
|
1995
|
-
*
|
|
3504
|
+
* OData-native names of the system query options
|
|
1996
3505
|
*
|
|
1997
|
-
*
|
|
1998
|
-
*
|
|
1999
|
-
*
|
|
2000
|
-
* @param limit - The limit value to validate
|
|
2001
|
-
* @throws {InvalidLimitError} If the value is not an integer, or is 0, or is a negative number other than -1
|
|
3506
|
+
* The `$` prefix is mandated by the OData URL conventions; these keys
|
|
3507
|
+
* are intentionally not configurable through `QueryBuilderOptions` and
|
|
3508
|
+
* live as private statics so they are visible in one place.
|
|
2002
3509
|
*/
|
|
2003
|
-
|
|
3510
|
+
private static readonly _countKey;
|
|
3511
|
+
private static readonly _expandKey;
|
|
3512
|
+
private static readonly _filterKey;
|
|
3513
|
+
private static readonly _orderbyKey;
|
|
3514
|
+
private static readonly _searchKey;
|
|
3515
|
+
private static readonly _selectKey;
|
|
3516
|
+
private static readonly _skipKey;
|
|
3517
|
+
private static readonly _topKey;
|
|
2004
3518
|
/**
|
|
2005
|
-
* Emit
|
|
2006
|
-
*
|
|
3519
|
+
* Emit OData-format query-string segments in canonical order:
|
|
3520
|
+
* $filter → $orderby → $select → $expand → $search → $count → $top → $skip
|
|
2007
3521
|
*
|
|
2008
3522
|
* @param state - The current query builder state
|
|
2009
|
-
* @param
|
|
3523
|
+
* @param _options - The query parameter key name configuration (unused —
|
|
3524
|
+
* every OData system query option name is fixed by the specification)
|
|
2010
3525
|
* @returns Ordered query-string fragments
|
|
2011
3526
|
*/
|
|
2012
|
-
protected parts(state: IQueryBuilderState,
|
|
3527
|
+
protected parts(state: IQueryBuilderState, _options: QueryBuilderOptions): string[];
|
|
2013
3528
|
/**
|
|
2014
|
-
* Append
|
|
3529
|
+
* Append the constant `$count=true` parameter
|
|
3530
|
+
*
|
|
3531
|
+
* Always emitted: the OData response strategy reads the total from
|
|
3532
|
+
* `@odata.count`, which servers only include when the request asks
|
|
3533
|
+
* for it.
|
|
2015
3534
|
*
|
|
2016
|
-
* @param state - The current query builder state
|
|
2017
|
-
* @param options - The query parameter key name configuration
|
|
2018
3535
|
* @param out - The accumulator the caller joins into the URI
|
|
2019
3536
|
*/
|
|
2020
|
-
private
|
|
3537
|
+
private _appendCount;
|
|
2021
3538
|
/**
|
|
2022
|
-
* Append the
|
|
3539
|
+
* Append the `$expand=` parameter combining includes and embedded
|
|
3540
|
+
* relations
|
|
3541
|
+
*
|
|
3542
|
+
* Plain relations from `addIncludes` emit bare (`rel`); embedded
|
|
3543
|
+
* relations from `addEmbedded` emit with an inline projection
|
|
3544
|
+
* (`rel($select=col1,col2)`) or bare when no columns were given. A
|
|
3545
|
+
* relation present in both folds into the embedded fragment, which
|
|
3546
|
+
* carries the column information.
|
|
2023
3547
|
*
|
|
2024
3548
|
* @param state - The current query builder state
|
|
2025
|
-
* @param options - The query parameter key name configuration
|
|
2026
3549
|
* @param out - The accumulator the caller joins into the URI
|
|
2027
3550
|
*/
|
|
2028
|
-
private
|
|
3551
|
+
private _appendExpand;
|
|
2029
3552
|
/**
|
|
2030
|
-
* Append
|
|
3553
|
+
* Append the single `$filter=` parameter combining simple and operator
|
|
3554
|
+
* filters
|
|
2031
3555
|
*
|
|
2032
|
-
*
|
|
3556
|
+
* Each term is one OData boolean expression; terms join with ` and `.
|
|
3557
|
+
* Simple single-value filters fold to `eq`; simple multi-value filters
|
|
3558
|
+
* fold to the `in` list operator (`field in ('v1','v2')`).
|
|
2033
3559
|
*
|
|
2034
3560
|
* @param state - The current query builder state
|
|
2035
|
-
* @param options - The query parameter key name configuration
|
|
2036
3561
|
* @param out - The accumulator the caller joins into the URI
|
|
2037
3562
|
*/
|
|
2038
|
-
private
|
|
3563
|
+
private _appendFilter;
|
|
2039
3564
|
/**
|
|
2040
|
-
* Append the
|
|
3565
|
+
* Append the `$orderby=field asc,other desc` CSV parameter
|
|
2041
3566
|
*
|
|
2042
3567
|
* @param state - The current query builder state
|
|
2043
|
-
* @param options - The query parameter key name configuration
|
|
2044
3568
|
* @param out - The accumulator the caller joins into the URI
|
|
2045
3569
|
*/
|
|
2046
|
-
private
|
|
3570
|
+
private _appendOrderby;
|
|
2047
3571
|
/**
|
|
2048
|
-
* Append the search
|
|
3572
|
+
* Append the `$search=` free-text search parameter
|
|
2049
3573
|
*
|
|
2050
3574
|
* @param state - The current query builder state
|
|
2051
|
-
* @param options - The query parameter key name configuration
|
|
2052
3575
|
* @param out - The accumulator the caller joins into the URI
|
|
2053
3576
|
*/
|
|
2054
3577
|
private _appendSearch;
|
|
2055
3578
|
/**
|
|
2056
|
-
* Append the select
|
|
3579
|
+
* Append the `$select=col1,col2` projection parameter
|
|
2057
3580
|
*
|
|
2058
3581
|
* @param state - The current query builder state
|
|
2059
|
-
* @param options - The query parameter key name configuration
|
|
2060
3582
|
* @param out - The accumulator the caller joins into the URI
|
|
2061
3583
|
*/
|
|
2062
3584
|
private _appendSelect;
|
|
2063
3585
|
/**
|
|
2064
|
-
* Append
|
|
3586
|
+
* Append the `$skip=` parameter, derived from state.page
|
|
3587
|
+
*
|
|
3588
|
+
* OData uses offset-based pagination: the skip is computed as
|
|
3589
|
+
* `(page - 1) * limit`. Omitted when the skip would be 0 (i.e. page 1)
|
|
3590
|
+
* since OData defaults to no skip and dropping it keeps the URI shorter.
|
|
3591
|
+
*
|
|
3592
|
+
* @param state - The current query builder state
|
|
3593
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3594
|
+
*/
|
|
3595
|
+
private _appendSkip;
|
|
3596
|
+
/**
|
|
3597
|
+
* Append the `$top=` page-size parameter
|
|
3598
|
+
*
|
|
3599
|
+
* @param state - The current query builder state
|
|
3600
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3601
|
+
*/
|
|
3602
|
+
private _appendTop;
|
|
3603
|
+
/**
|
|
3604
|
+
* Format a filter value as an OData primitive literal
|
|
3605
|
+
*
|
|
3606
|
+
* Strings are single-quoted with embedded single quotes doubled
|
|
3607
|
+
* (`'O''Brien'`) per the OData ABNF; numbers and booleans are emitted
|
|
3608
|
+
* bare.
|
|
3609
|
+
*
|
|
3610
|
+
* @param value - The raw filter value
|
|
3611
|
+
* @returns The OData-formatted literal
|
|
3612
|
+
*/
|
|
3613
|
+
private _formatLiteral;
|
|
3614
|
+
/**
|
|
3615
|
+
* Translate a `FilterOperatorEnum` operator filter into one or more
|
|
3616
|
+
* OData boolean expressions
|
|
3617
|
+
*
|
|
3618
|
+
* The mapping is library-canonical → OData-native:
|
|
3619
|
+
* - `EQ` → `eq`; `GT`/`GTE`/`LT`/`LTE` → `gt` / `ge` / `lt` / `le`
|
|
3620
|
+
* - `CONTAINS` → `contains(field,'val')`
|
|
3621
|
+
* - `ILIKE` → `contains(tolower(field),tolower('val'))` (case-insensitive
|
|
3622
|
+
* contains)
|
|
3623
|
+
* - `SW` → `startswith(field,'val')`
|
|
3624
|
+
* - `IN` → `field in ('v1','v2')` (OData v4.01 list operator)
|
|
3625
|
+
* - `BTW` → **two** AND-ed terms (`field ge min` and `field le max`,
|
|
3626
|
+
* arity-checked)
|
|
3627
|
+
* - `NOT` → `ne` — one term per value, AND-ed (`field ne v1 and field ne v2`)
|
|
3628
|
+
* - `NULL` → `field eq null` (when value is `true`) / `field ne null`
|
|
3629
|
+
* (when value is `false`); arity- and type-checked
|
|
3630
|
+
*
|
|
3631
|
+
* PostgREST's full-text-search operators (`FTS`, `PHFTS`, `PLFTS`,
|
|
3632
|
+
* `WFTS`) have no OData equivalent and throw
|
|
3633
|
+
* `UnsupportedFilterOperatorError`.
|
|
3634
|
+
*
|
|
3635
|
+
* @param filter - The operator filter to translate
|
|
3636
|
+
* @returns One or more OData boolean expressions ready to ` and `-join
|
|
3637
|
+
* @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
|
|
3638
|
+
* exactly two values, or `NULL` does not receive exactly one boolean
|
|
3639
|
+
* @throws {UnsupportedFilterOperatorError} If the operator is a
|
|
3640
|
+
* PostgREST-only FTS variant
|
|
3641
|
+
*/
|
|
3642
|
+
private _formatOperatorTerms;
|
|
3643
|
+
}
|
|
3644
|
+
|
|
3645
|
+
/**
|
|
3646
|
+
* Response strategy for the OData v4 driver
|
|
3647
|
+
*
|
|
3648
|
+
* Parses OData collection responses:
|
|
3649
|
+
*
|
|
3650
|
+
* ```json
|
|
3651
|
+
* {
|
|
3652
|
+
* "@odata.context": "https://api.example.com/$metadata#Products",
|
|
3653
|
+
* "@odata.count": 100,
|
|
3654
|
+
* "@odata.nextLink": "https://api.example.com/Products?$count=true&$top=10&$skip=30",
|
|
3655
|
+
* "value": [...]
|
|
3656
|
+
* }
|
|
3657
|
+
* ```
|
|
3658
|
+
*
|
|
3659
|
+
* OData emits no current-page or page-size field in the body, so this
|
|
3660
|
+
* strategy **derives** them by inspecting the `@odata.nextLink` URL:
|
|
3661
|
+
*
|
|
3662
|
+
* - `perPage` comes from the link's `$top` param, falling back to the
|
|
3663
|
+
* item count of the current (necessarily full) page when the link
|
|
3664
|
+
* carries no `$top`.
|
|
3665
|
+
* - `currentPage` is `$skip ÷ perPage` — the next page starts where the
|
|
3666
|
+
* current one ends. Without a usable link (`$skiptoken`-based
|
|
3667
|
+
* server-driven paging, or the last page) the strategy falls back to
|
|
3668
|
+
* page **1**, which is only guaranteed correct for single-page results.
|
|
3669
|
+
* - `lastPage` is `ceil(total ÷ perPage)`; on a link-less response it
|
|
3670
|
+
* resolves to 1 when the page provably holds the whole result set.
|
|
3671
|
+
*
|
|
3672
|
+
* The total requires `$count=true` on the request — the request strategy
|
|
3673
|
+
* always emits it. Envelope keys contain **literal dots** (`@odata.count`),
|
|
3674
|
+
* so key paths from `OdataResponseOptions` are read with flat bracket
|
|
3675
|
+
* access, never dot-path traversal.
|
|
3676
|
+
*
|
|
3677
|
+
* @see https://docs.oasis-open.org/odata/odata-json-format/v4.01/odata-json-format-v4.01.html
|
|
3678
|
+
*/
|
|
3679
|
+
declare class OdataResponseStrategy implements IResponseStrategy {
|
|
3680
|
+
/**
|
|
3681
|
+
* Parse an OData collection response into a PaginatedCollection
|
|
3682
|
+
*
|
|
3683
|
+
* @param response - The raw API response body
|
|
3684
|
+
* @param options - The response key name configuration
|
|
3685
|
+
* @returns A typed PaginatedCollection instance
|
|
3686
|
+
*/
|
|
3687
|
+
paginate<T extends IPaginatedObject>(response: Record<string, any>, options: ResponseOptions): PaginatedCollection<T>;
|
|
3688
|
+
/**
|
|
3689
|
+
* Derive the current page number from the `@odata.nextLink` URL
|
|
3690
|
+
*
|
|
3691
|
+
* The next page starts where the current one ends, so
|
|
3692
|
+
* `currentPage = $skip ÷ perPage` (e.g. `$skip=30` with `$top=10` →
|
|
3693
|
+
* page 3). Falls back to **1** when the link is absent (last or only
|
|
3694
|
+
* page), carries no `$skip` (`$skiptoken`-based paging), or the page
|
|
3695
|
+
* size is unknown.
|
|
3696
|
+
*
|
|
3697
|
+
* @param nextPageUrl - The `@odata.nextLink` from the response, or null
|
|
3698
|
+
* @param perPage - The derived page size (may be undefined)
|
|
3699
|
+
* @returns The current page number
|
|
3700
|
+
*/
|
|
3701
|
+
private _deriveCurrentPage;
|
|
3702
|
+
/**
|
|
3703
|
+
* Derive `from` as the 1-indexed offset of the first item on this page
|
|
3704
|
+
*
|
|
3705
|
+
* Computed from `currentPage` × `perPage` when the page size is known;
|
|
3706
|
+
* on a link-less single page it is 1 whenever items are present.
|
|
3707
|
+
*
|
|
3708
|
+
* @param nextPageUrl - The `@odata.nextLink` from the response, or null
|
|
3709
|
+
* @param data - The items on the current page
|
|
3710
|
+
* @param currentPage - The current page number
|
|
3711
|
+
* @param perPage - The page size (may be undefined)
|
|
3712
|
+
* @returns The 1-indexed `from` index, or undefined when inputs insufficient
|
|
3713
|
+
*/
|
|
3714
|
+
private _deriveFrom;
|
|
3715
|
+
/**
|
|
3716
|
+
* Derive the last page number
|
|
3717
|
+
*
|
|
3718
|
+
* `ceil(total ÷ perPage)` when both are known; a link-less response
|
|
3719
|
+
* that provably holds the entire non-empty result set resolves to 1.
|
|
3720
|
+
*
|
|
3721
|
+
* @param nextPageUrl - The `@odata.nextLink` from the response, or null
|
|
3722
|
+
* @param data - The items on the current page
|
|
3723
|
+
* @param total - The total item count
|
|
3724
|
+
* @param perPage - The page size
|
|
3725
|
+
* @returns The last page number, or undefined when inputs insufficient
|
|
3726
|
+
*/
|
|
3727
|
+
private _deriveLastPage;
|
|
3728
|
+
/**
|
|
3729
|
+
* Derive `perPage` from the `@odata.nextLink` URL
|
|
3730
|
+
*
|
|
3731
|
+
* Reads the link's `$top` param. When the link exists but carries no
|
|
3732
|
+
* `$top` (server-driven page size), the current page is necessarily
|
|
3733
|
+
* full, so its item count equals the page size. Without a link the
|
|
3734
|
+
* page may be partial and the size is not introspectable.
|
|
3735
|
+
*
|
|
3736
|
+
* @param nextPageUrl - The `@odata.nextLink` from the response, or null
|
|
3737
|
+
* @param data - The items on the current page
|
|
3738
|
+
* @returns The page size, or undefined
|
|
3739
|
+
*/
|
|
3740
|
+
private _derivePerPage;
|
|
3741
|
+
/**
|
|
3742
|
+
* Derive `to` as the 1-indexed offset of the last item on this page
|
|
3743
|
+
*
|
|
3744
|
+
* Clamped to `total` so the last page does not report past the end;
|
|
3745
|
+
* on a link-less single page it is the item count.
|
|
3746
|
+
*
|
|
3747
|
+
* @param nextPageUrl - The `@odata.nextLink` from the response, or null
|
|
3748
|
+
* @param data - The items on the current page
|
|
3749
|
+
* @param currentPage - The current page number
|
|
3750
|
+
* @param perPage - The page size (may be undefined)
|
|
3751
|
+
* @param total - The total item count (may be undefined)
|
|
3752
|
+
* @returns The 1-indexed `to` index, or undefined when inputs insufficient
|
|
3753
|
+
*/
|
|
3754
|
+
private _deriveTo;
|
|
3755
|
+
/**
|
|
3756
|
+
* Extract an integer query parameter from an OData pagination URL
|
|
3757
|
+
*
|
|
3758
|
+
* @param url - The URL to parse
|
|
3759
|
+
* @param name - The query-parameter name to look up (e.g. `$skip`)
|
|
3760
|
+
* @returns The integer value, or undefined
|
|
3761
|
+
*/
|
|
3762
|
+
private _extractNumberParam;
|
|
3763
|
+
/**
|
|
3764
|
+
* Extract a single query parameter from a URL via the WHATWG URL parser
|
|
3765
|
+
*
|
|
3766
|
+
* OData permits **relative** `@odata.nextLink` values, so parsing
|
|
3767
|
+
* retries against a placeholder base before giving up. Returns
|
|
3768
|
+
* undefined when the URL is unparseable or the parameter is absent.
|
|
3769
|
+
*
|
|
3770
|
+
* @param url - The URL to parse
|
|
3771
|
+
* @param name - The query-parameter name to look up
|
|
3772
|
+
* @returns The raw string value of the parameter, or undefined
|
|
3773
|
+
*/
|
|
3774
|
+
private _extractQueryParam;
|
|
3775
|
+
}
|
|
3776
|
+
|
|
3777
|
+
/**
|
|
3778
|
+
* Request strategy for the Payload CMS driver
|
|
3779
|
+
*
|
|
3780
|
+
* Generates URIs in [Payload's REST query format](https://payloadcms.com/docs/queries/overview):
|
|
3781
|
+
* - Filters: `where[field][equals]=value` (multi-value collapses to
|
|
3782
|
+
* `where[field][in]=v1,v2` CSV)
|
|
3783
|
+
* - Operator filters: `where[field][op]=value` (translated from
|
|
3784
|
+
* `FilterOperatorEnum` — `BTW`→`greater_than_equal`+`less_than_equal`
|
|
3785
|
+
* pair, `NOT`→`not_equals`/`not_in`, `NULL`→`exists` with inverted
|
|
3786
|
+
* boolean)
|
|
3787
|
+
* - Sorts: `sort=-createdAt,title` (CSV, `-` prefix = DESC)
|
|
3788
|
+
* - Field selection (flat): `select[col1]=true&select[col2]=true`
|
|
3789
|
+
* - Pagination (page-based): `page=N&limit=M`
|
|
3790
|
+
*
|
|
3791
|
+
* The `where` / `sort` / `select` / `page` / `limit` keys are fixed by
|
|
3792
|
+
* Payload's REST endpoints and intentionally not configurable through
|
|
3793
|
+
* `QueryBuilderOptions`; they live as private statics so they are
|
|
3794
|
+
* visible in one place.
|
|
3795
|
+
*
|
|
3796
|
+
* Relationship population is controlled by Payload's numeric `depth`
|
|
3797
|
+
* param, not a named-relation list — `addIncludes` therefore throws
|
|
3798
|
+
* `UnsupportedIncludesError` (pass `depth` through your HTTP layer if
|
|
3799
|
+
* needed). There is no per-model field selection and no global search
|
|
3800
|
+
* param. `SW` (no starts-with operator) and the PostgREST-native
|
|
3801
|
+
* full-text operators (`FTS`, `PHFTS`, `PLFTS`, `WFTS`) throw
|
|
3802
|
+
* `UnsupportedFilterOperatorError`.
|
|
3803
|
+
*
|
|
3804
|
+
* @see https://payloadcms.com/docs/queries/overview
|
|
3805
|
+
*/
|
|
3806
|
+
declare class PayloadRequestStrategy extends AbstractRequestStrategy {
|
|
3807
|
+
/**
|
|
3808
|
+
* Filters, operator filters, sorts, flat field selection (`select`)
|
|
3809
|
+
* — no per-model fields, no includes (numeric `depth` instead), no
|
|
3810
|
+
* global search, no embedded resources
|
|
3811
|
+
*/
|
|
3812
|
+
readonly capabilities: IStrategyCapabilities;
|
|
3813
|
+
/**
|
|
3814
|
+
* Payload-native names of the five hardcoded query keys
|
|
3815
|
+
*
|
|
3816
|
+
* Fixed by the REST endpoints and intentionally not configurable
|
|
3817
|
+
* through `QueryBuilderOptions`.
|
|
3818
|
+
*/
|
|
3819
|
+
private static readonly _limitKey;
|
|
3820
|
+
private static readonly _pageKey;
|
|
3821
|
+
private static readonly _selectKey;
|
|
3822
|
+
private static readonly _sortKey;
|
|
3823
|
+
private static readonly _whereKey;
|
|
3824
|
+
/**
|
|
3825
|
+
* Emit Payload-format query-string segments in canonical order:
|
|
3826
|
+
* where (merged) → sort → select → page → limit
|
|
3827
|
+
*
|
|
3828
|
+
* Simple filters and operator filters share a single `where` wrapper
|
|
3829
|
+
* so qs emits one ordered bracket structure rather than two duplicate
|
|
3830
|
+
* top-level `where[...]` blocks.
|
|
3831
|
+
*
|
|
3832
|
+
* @param state - The current query builder state
|
|
3833
|
+
* @param _options - The query parameter key name configuration (unused;
|
|
3834
|
+
* Payload's wire keys are fixed by the server)
|
|
3835
|
+
* @returns Ordered query-string fragments
|
|
3836
|
+
*/
|
|
3837
|
+
protected parts(state: IQueryBuilderState, _options: QueryBuilderOptions): string[];
|
|
3838
|
+
/**
|
|
3839
|
+
* Append the `page=` / `limit=` pagination pair
|
|
3840
|
+
*
|
|
3841
|
+
* @param state - The current query builder state
|
|
3842
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3843
|
+
*/
|
|
3844
|
+
private _appendPagination;
|
|
3845
|
+
/**
|
|
3846
|
+
* Append `select[col]=true` flags from the flat select array
|
|
3847
|
+
*
|
|
3848
|
+
* Payload's select API is an object of `true` flags rather than a
|
|
3849
|
+
* CSV; nested selection (`select[group.field]=true`) passes through
|
|
3850
|
+
* when given as a dotted column name.
|
|
3851
|
+
*
|
|
3852
|
+
* @param state - The current query builder state
|
|
3853
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3854
|
+
*/
|
|
3855
|
+
private _appendSelect;
|
|
3856
|
+
/**
|
|
3857
|
+
* Append the `sort=-createdAt,title` CSV parameter
|
|
2065
3858
|
*
|
|
2066
3859
|
* @param state - The current query builder state
|
|
2067
|
-
* @param options - The query parameter key name configuration
|
|
2068
3860
|
* @param out - The accumulator the caller joins into the URI
|
|
2069
3861
|
*/
|
|
2070
|
-
private _appendSort;
|
|
3862
|
+
private _appendSort;
|
|
3863
|
+
/**
|
|
3864
|
+
* Append the unified `where[...]` wrapper combining simple filters
|
|
3865
|
+
* and operator filters
|
|
3866
|
+
*
|
|
3867
|
+
* Both kinds emit into the same nested object under `where` so qs
|
|
3868
|
+
* produces a single bracketed block per request. Simple single-value
|
|
3869
|
+
* filters fold to `equals`; simple multi-value filters fold to the
|
|
3870
|
+
* `in` CSV. Operator filters then merge into the same per-field map,
|
|
3871
|
+
* potentially co-existing with a simple filter on the same field.
|
|
3872
|
+
*
|
|
3873
|
+
* @param state - The current query builder state
|
|
3874
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3875
|
+
*/
|
|
3876
|
+
private _appendWhere;
|
|
3877
|
+
/**
|
|
3878
|
+
* Translate a `FilterOperatorEnum` operator filter into Payload's
|
|
3879
|
+
* `operator → value` payload shape
|
|
3880
|
+
*
|
|
3881
|
+
* The mapping is library-canonical → Payload-native:
|
|
3882
|
+
* - `EQ` → `equals`
|
|
3883
|
+
* - `GT`/`GTE`/`LT`/`LTE` → `greater_than` / `greater_than_equal` /
|
|
3884
|
+
* `less_than` / `less_than_equal`
|
|
3885
|
+
* - `CONTAINS` → `contains` (case-insensitive substring)
|
|
3886
|
+
* - `ILIKE` → `like` (case-insensitive, word-based)
|
|
3887
|
+
* - `IN` → `in` (CSV)
|
|
3888
|
+
* - `BTW` → `greater_than_equal` + `less_than_equal` pair in one
|
|
3889
|
+
* payload (arity-checked)
|
|
3890
|
+
* - `NOT` → `not_equals` (single value) / `not_in` (multi-value, CSV)
|
|
3891
|
+
* - `NULL` → `exists` with **inverted** boolean (`true` →
|
|
3892
|
+
* `exists=false` ⇔ IS NULL); arity- and type-checked
|
|
3893
|
+
*
|
|
3894
|
+
* `SW` (Payload has no starts-with operator) and PostgREST's
|
|
3895
|
+
* full-text-search operators (`FTS`, `PHFTS`, `PLFTS`, `WFTS`) throw
|
|
3896
|
+
* `UnsupportedFilterOperatorError`.
|
|
3897
|
+
*
|
|
3898
|
+
* @param filter - The operator filter to translate
|
|
3899
|
+
* @returns An `{ operator: value }` payload ready to merge under
|
|
3900
|
+
* `where[field]`
|
|
3901
|
+
* @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
|
|
3902
|
+
* exactly two values, or `NULL` does not receive exactly one boolean
|
|
3903
|
+
* @throws {UnsupportedFilterOperatorError} If the operator has no
|
|
3904
|
+
* Payload equivalent
|
|
3905
|
+
*/
|
|
3906
|
+
private _formatOperatorPayload;
|
|
2071
3907
|
}
|
|
2072
3908
|
|
|
2073
3909
|
/**
|
|
2074
|
-
* Response strategy for the
|
|
3910
|
+
* Response strategy for the Payload CMS driver
|
|
2075
3911
|
*
|
|
2076
|
-
* Parses
|
|
3912
|
+
* Parses Payload's paginated collection responses — the
|
|
3913
|
+
* `mongoose-paginate-v2` envelope, shared by many Express/Mongoose
|
|
3914
|
+
* backends:
|
|
2077
3915
|
* ```json
|
|
2078
3916
|
* {
|
|
2079
|
-
* "
|
|
2080
|
-
* "
|
|
2081
|
-
*
|
|
2082
|
-
*
|
|
2083
|
-
*
|
|
2084
|
-
*
|
|
2085
|
-
*
|
|
2086
|
-
* "
|
|
2087
|
-
*
|
|
2088
|
-
*
|
|
2089
|
-
* "next": "url",
|
|
2090
|
-
* "last": "url",
|
|
2091
|
-
* "current": "url"
|
|
2092
|
-
* }
|
|
3917
|
+
* "docs": [{ "id": "abc123", "title": "Hello" }],
|
|
3918
|
+
* "totalDocs": 48,
|
|
3919
|
+
* "limit": 10,
|
|
3920
|
+
* "totalPages": 5,
|
|
3921
|
+
* "page": 2,
|
|
3922
|
+
* "pagingCounter": 11,
|
|
3923
|
+
* "hasPrevPage": true,
|
|
3924
|
+
* "hasNextPage": true,
|
|
3925
|
+
* "prevPage": 1,
|
|
3926
|
+
* "nextPage": 3
|
|
2093
3927
|
* }
|
|
2094
3928
|
* ```
|
|
2095
3929
|
*
|
|
2096
|
-
* Default key paths are configured in `
|
|
2097
|
-
*
|
|
2098
|
-
*
|
|
2099
|
-
* `
|
|
2100
|
-
*
|
|
3930
|
+
* Default key paths are configured in `PayloadResponseOptions`. The
|
|
3931
|
+
* envelope's `pagingCounter` is the 1-indexed offset of the first doc
|
|
3932
|
+
* on the page, so it maps straight onto `from`; `to` is computed from
|
|
3933
|
+
* `page` × `limit` (clamped to the total). `prevPage` / `nextPage` are
|
|
3934
|
+
* **page numbers**, not URLs, so the navigation-URL slots on
|
|
3935
|
+
* `PaginatedCollection` stay `undefined` unless the consumer overrides
|
|
3936
|
+
* their paths via `IPaginationConfig`. The traversal algorithm is
|
|
3937
|
+
* inherited from `AbstractDotPathResponseStrategy`; this class exists
|
|
3938
|
+
* so `DriverEnum.PAYLOAD` resolves to a distinct identity at the DI
|
|
3939
|
+
* layer even though the parsing logic is shared with JSON:API, NestJS,
|
|
3940
|
+
* Strapi, and PocketBase.
|
|
2101
3941
|
*
|
|
2102
|
-
* @see https://
|
|
3942
|
+
* @see https://payloadcms.com/docs/rest-api/overview
|
|
2103
3943
|
*/
|
|
2104
|
-
declare class
|
|
3944
|
+
declare class PayloadResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
2105
3945
|
}
|
|
2106
3946
|
|
|
2107
3947
|
/**
|
|
2108
|
-
* Request strategy for the
|
|
2109
|
-
*
|
|
2110
|
-
* Generates URIs in [
|
|
2111
|
-
* - Filters: `filter=
|
|
2112
|
-
*
|
|
2113
|
-
*
|
|
2114
|
-
*
|
|
2115
|
-
*
|
|
2116
|
-
*
|
|
2117
|
-
* -
|
|
2118
|
-
* - Field selection (flat): `fields=
|
|
2119
|
-
* -
|
|
2120
|
-
* - Pagination (page-based): `page=N&
|
|
2121
|
-
*
|
|
2122
|
-
* The
|
|
2123
|
-
*
|
|
2124
|
-
* `
|
|
2125
|
-
*
|
|
3948
|
+
* Request strategy for the PocketBase driver
|
|
3949
|
+
*
|
|
3950
|
+
* Generates URIs in [PocketBase's records-list format](https://pocketbase.io/docs/api-records/):
|
|
3951
|
+
* - Filters: a single `filter=(...)` expression-language parameter —
|
|
3952
|
+
* simple single-value filters fold to `field='value'`, multi-value
|
|
3953
|
+
* filters fold to an OR group (`(field='v1' || field='v2')`), and all
|
|
3954
|
+
* clauses join with ` && `
|
|
3955
|
+
* - Operator filters: expression terms (`field>=10`, `field~'val'`) —
|
|
3956
|
+
* see the mapping on `_formatOperatorClause`
|
|
3957
|
+
* - Sorts: `sort=-created,title` (CSV, `-` prefix = DESC)
|
|
3958
|
+
* - Field selection (flat): `fields=id,title` (CSV)
|
|
3959
|
+
* - Relation expansion: `expand=author,comments` (CSV)
|
|
3960
|
+
* - Pagination (page-based): `page=N&perPage=M`
|
|
3961
|
+
*
|
|
3962
|
+
* The `page` / `perPage` / `sort` / `filter` / `expand` / `fields` keys
|
|
3963
|
+
* are fixed by the PocketBase records API and intentionally not
|
|
3964
|
+
* configurable through `QueryBuilderOptions`; they live as private
|
|
3965
|
+
* statics so they are visible in one place.
|
|
3966
|
+
*
|
|
3967
|
+
* String literals are single-quoted with embedded quotes
|
|
3968
|
+
* backslash-escaped (`name='O\'Brien'`); numbers and booleans emit
|
|
3969
|
+
* bare. PocketBase has no global search param (use `~` terms instead)
|
|
3970
|
+
* and no per-model field selection — the corresponding fluent methods
|
|
3971
|
+
* throw the matching `Unsupported*Error`. The PostgREST-native
|
|
3972
|
+
* full-text operators (`FTS`, `PHFTS`, `PLFTS`, `WFTS`) throw
|
|
2126
3973
|
* `UnsupportedFilterOperatorError`.
|
|
2127
3974
|
*
|
|
2128
|
-
* @see https://
|
|
3975
|
+
* @see https://pocketbase.io/docs/api-records/
|
|
2129
3976
|
*/
|
|
2130
|
-
declare class
|
|
3977
|
+
declare class PocketbaseRequestStrategy extends AbstractRequestStrategy {
|
|
2131
3978
|
/**
|
|
2132
|
-
* Filters, operator filters,
|
|
2133
|
-
* (`select`)
|
|
2134
|
-
*
|
|
3979
|
+
* Filters, operator filters, sorts, expand (`includes`), flat field
|
|
3980
|
+
* selection (`select`) — no per-model fields, no global search, no
|
|
3981
|
+
* embedded resources
|
|
2135
3982
|
*/
|
|
2136
3983
|
readonly capabilities: IStrategyCapabilities;
|
|
2137
3984
|
/**
|
|
2138
|
-
*
|
|
3985
|
+
* PocketBase-native names of the six hardcoded query keys
|
|
2139
3986
|
*
|
|
2140
|
-
* The
|
|
2141
|
-
*
|
|
2142
|
-
*
|
|
2143
|
-
* live as private statics so they are visible in one place.
|
|
3987
|
+
* The records API reads exactly these names; they are intentionally
|
|
3988
|
+
* not configurable through `QueryBuilderOptions` and live as private
|
|
3989
|
+
* statics so they are visible in one place.
|
|
2144
3990
|
*/
|
|
3991
|
+
private static readonly _expandKey;
|
|
2145
3992
|
private static readonly _fieldsKey;
|
|
2146
3993
|
private static readonly _filterKey;
|
|
2147
|
-
private static readonly
|
|
3994
|
+
private static readonly _pageKey;
|
|
3995
|
+
private static readonly _perPageKey;
|
|
2148
3996
|
private static readonly _sortKey;
|
|
2149
3997
|
/**
|
|
2150
|
-
*
|
|
2151
|
-
|
|
2152
|
-
private static readonly _separator;
|
|
2153
|
-
/**
|
|
2154
|
-
* Emit @nestjsx/crud-format query-string segments in canonical order:
|
|
2155
|
-
* fields → filters → operator filters → join → sort → limit → page
|
|
3998
|
+
* Emit PocketBase-format query-string segments in canonical order:
|
|
3999
|
+
* expand → fields → filter (merged) → sort → page → perPage
|
|
2156
4000
|
*
|
|
2157
|
-
*
|
|
2158
|
-
*
|
|
2159
|
-
*
|
|
2160
|
-
* `fields` / `filter` / `join` / `sort` keys are fixed by the server)
|
|
2161
|
-
* @returns Ordered query-string fragments
|
|
2162
|
-
*/
|
|
2163
|
-
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
2164
|
-
/**
|
|
2165
|
-
* Append `fields=col1,col2` from the flat select array
|
|
4001
|
+
* Simple filters and operator filters share the single `filter=(...)`
|
|
4002
|
+
* parameter so the server receives one combined expression rather
|
|
4003
|
+
* than two conflicting `filter` params.
|
|
2166
4004
|
*
|
|
2167
4005
|
* @param state - The current query builder state
|
|
2168
|
-
* @param
|
|
4006
|
+
* @param _options - The query parameter key name configuration (unused;
|
|
4007
|
+
* PocketBase's wire keys are fixed by the server)
|
|
4008
|
+
* @returns Ordered query-string fragments
|
|
2169
4009
|
*/
|
|
2170
|
-
|
|
4010
|
+
protected parts(state: IQueryBuilderState, _options: QueryBuilderOptions): string[];
|
|
2171
4011
|
/**
|
|
2172
|
-
* Append
|
|
4012
|
+
* Append the `expand=` CSV from the includes array
|
|
2173
4013
|
*
|
|
2174
|
-
*
|
|
2175
|
-
*
|
|
4014
|
+
* Nested expansion (`author.address`) passes through verbatim when
|
|
4015
|
+
* given as a dotted include name.
|
|
2176
4016
|
*
|
|
2177
4017
|
* @param state - The current query builder state
|
|
2178
4018
|
* @param out - The accumulator the caller joins into the URI
|
|
2179
4019
|
*/
|
|
2180
|
-
private
|
|
4020
|
+
private _appendExpand;
|
|
2181
4021
|
/**
|
|
2182
|
-
* Append `
|
|
2183
|
-
*
|
|
2184
|
-
* Per-relation field projection (`join=relation||f1,f2`) is not
|
|
2185
|
-
* expressible through the current state shape and is out of scope.
|
|
4022
|
+
* Append the `fields=` CSV from the flat select array
|
|
2186
4023
|
*
|
|
2187
4024
|
* @param state - The current query builder state
|
|
2188
4025
|
* @param out - The accumulator the caller joins into the URI
|
|
2189
4026
|
*/
|
|
2190
|
-
private
|
|
4027
|
+
private _appendFields;
|
|
2191
4028
|
/**
|
|
2192
|
-
* Append the
|
|
4029
|
+
* Append the single `filter=(...)` expression combining simple
|
|
4030
|
+
* filters and operator filters
|
|
2193
4031
|
*
|
|
2194
|
-
*
|
|
2195
|
-
*
|
|
2196
|
-
*
|
|
2197
|
-
*/
|
|
2198
|
-
private _appendLimit;
|
|
2199
|
-
/**
|
|
2200
|
-
* Append operator filters as repeatable `filter=field||$op||value` params
|
|
4032
|
+
* Clauses join with ` && `; multi-value clauses keep their own
|
|
4033
|
+
* parentheses so OR groups stay correctly scoped inside the AND
|
|
4034
|
+
* chain.
|
|
2201
4035
|
*
|
|
2202
4036
|
* @param state - The current query builder state
|
|
2203
4037
|
* @param out - The accumulator the caller joins into the URI
|
|
2204
4038
|
*/
|
|
2205
|
-
private
|
|
4039
|
+
private _appendFilter;
|
|
2206
4040
|
/**
|
|
2207
|
-
* Append the page
|
|
4041
|
+
* Append the `page=` / `perPage=` pagination pair
|
|
2208
4042
|
*
|
|
2209
4043
|
* @param state - The current query builder state
|
|
2210
|
-
* @param options - The query parameter key name configuration
|
|
2211
4044
|
* @param out - The accumulator the caller joins into the URI
|
|
2212
4045
|
*/
|
|
2213
|
-
private
|
|
4046
|
+
private _appendPagination;
|
|
2214
4047
|
/**
|
|
2215
|
-
* Append `sort
|
|
4048
|
+
* Append the `sort=-created,title` CSV parameter
|
|
2216
4049
|
*
|
|
2217
4050
|
* @param state - The current query builder state
|
|
2218
4051
|
* @param out - The accumulator the caller joins into the URI
|
|
2219
4052
|
*/
|
|
2220
4053
|
private _appendSort;
|
|
2221
4054
|
/**
|
|
2222
|
-
* Translate a `FilterOperatorEnum` operator filter into
|
|
2223
|
-
*
|
|
2224
|
-
*
|
|
2225
|
-
* The mapping is library-canonical →
|
|
2226
|
-
* - `EQ
|
|
2227
|
-
* - `CONTAINS` →
|
|
2228
|
-
* -
|
|
2229
|
-
* - `
|
|
2230
|
-
*
|
|
2231
|
-
* - `
|
|
2232
|
-
*
|
|
4055
|
+
* Translate a `FilterOperatorEnum` operator filter into one
|
|
4056
|
+
* PocketBase expression clause
|
|
4057
|
+
*
|
|
4058
|
+
* The mapping is library-canonical → PocketBase-native:
|
|
4059
|
+
* - `EQ` → `field='v'`; `GT`/`GTE`/`LT`/`LTE` → `>` / `>=` / `<` / `<=`
|
|
4060
|
+
* - `CONTAINS`/`ILIKE` → `field~'v'` (PocketBase's `~` is a
|
|
4061
|
+
* case-insensitive LIKE that auto-wraps the operand in `%...%`)
|
|
4062
|
+
* - `SW` → `field~'v%'` (explicit trailing wildcard disables the
|
|
4063
|
+
* auto-wrap)
|
|
4064
|
+
* - `IN` → OR group `(field='v1' || field='v2')`
|
|
4065
|
+
* - `BTW` → AND group `(field>=min && field<=max)` (arity-checked)
|
|
4066
|
+
* - `NOT` → `field!='v'` (single) / AND group of `!=` terms (multi)
|
|
4067
|
+
* - `NULL` → `field=null` (when value is `true`) / `field!=null`
|
|
4068
|
+
* (when value is `false`); arity- and type-checked
|
|
2233
4069
|
*
|
|
2234
4070
|
* PostgREST's full-text-search operators (`FTS`, `PHFTS`, `PLFTS`,
|
|
2235
|
-
* `WFTS`) have no
|
|
4071
|
+
* `WFTS`) have no PocketBase equivalent and throw
|
|
2236
4072
|
* `UnsupportedFilterOperatorError`.
|
|
2237
4073
|
*
|
|
2238
4074
|
* @param filter - The operator filter to translate
|
|
2239
|
-
* @returns
|
|
4075
|
+
* @returns One expression clause ready to join into `filter=(...)`
|
|
2240
4076
|
* @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
|
|
2241
4077
|
* exactly two values, or `NULL` does not receive exactly one boolean
|
|
2242
4078
|
* @throws {UnsupportedFilterOperatorError} If the operator is a
|
|
2243
4079
|
* PostgREST-only FTS variant
|
|
2244
4080
|
*/
|
|
2245
|
-
private
|
|
4081
|
+
private _formatOperatorClause;
|
|
4082
|
+
/**
|
|
4083
|
+
* Backslash-escape single quotes inside a string literal
|
|
4084
|
+
*
|
|
4085
|
+
* @param value - The raw string value
|
|
4086
|
+
* @returns The escaped string, ready to wrap in single quotes
|
|
4087
|
+
*/
|
|
4088
|
+
private _escape;
|
|
4089
|
+
/**
|
|
4090
|
+
* Format a filter value as a PocketBase expression literal
|
|
4091
|
+
*
|
|
4092
|
+
* Strings are single-quoted (embedded quotes backslash-escaped);
|
|
4093
|
+
* numbers and booleans emit bare, matching the expression language's
|
|
4094
|
+
* literal rules.
|
|
4095
|
+
*
|
|
4096
|
+
* @param value - The raw filter value
|
|
4097
|
+
* @returns The formatted literal
|
|
4098
|
+
*/
|
|
4099
|
+
private _formatValue;
|
|
2246
4100
|
}
|
|
2247
4101
|
|
|
2248
4102
|
/**
|
|
2249
|
-
* Response strategy for the
|
|
4103
|
+
* Response strategy for the PocketBase driver
|
|
2250
4104
|
*
|
|
2251
|
-
* Parses
|
|
4105
|
+
* Parses PocketBase records-list responses:
|
|
2252
4106
|
* ```json
|
|
2253
4107
|
* {
|
|
2254
|
-
* "
|
|
2255
|
-
* "
|
|
2256
|
-
* "
|
|
2257
|
-
* "
|
|
2258
|
-
* "
|
|
4108
|
+
* "page": 1,
|
|
4109
|
+
* "perPage": 30,
|
|
4110
|
+
* "totalItems": 48,
|
|
4111
|
+
* "totalPages": 2,
|
|
4112
|
+
* "items": [{ "id": "abc123", "title": "Hello" }]
|
|
2259
4113
|
* }
|
|
2260
4114
|
* ```
|
|
2261
4115
|
*
|
|
2262
|
-
* Default key paths are configured in `
|
|
2263
|
-
*
|
|
2264
|
-
*
|
|
2265
|
-
*
|
|
2266
|
-
*
|
|
2267
|
-
*
|
|
2268
|
-
*
|
|
2269
|
-
*
|
|
2270
|
-
* derived `from`/`to` can underestimate. Consumers needing exact
|
|
2271
|
-
* indices should compute them from the requested limit instead.
|
|
2272
|
-
*
|
|
2273
|
-
* The dot-notation traversal is inherited from
|
|
2274
|
-
* `AbstractDotPathResponseStrategy`; this class exists so
|
|
2275
|
-
* `DriverEnum.NESTJSX_CRUD` resolves to a distinct identity at the DI
|
|
4116
|
+
* Default key paths are configured in `PocketbaseResponseOptions` —
|
|
4117
|
+
* all flat keys, resolved by the inherited dot-path traversal (a flat
|
|
4118
|
+
* key is just a one-segment path). PocketBase does not include
|
|
4119
|
+
* navigation links in the envelope, so `firstPageUrl`, `prevPageUrl`,
|
|
4120
|
+
* `nextPageUrl`, and `lastPageUrl` resolve to `undefined` unless the
|
|
4121
|
+
* consumer overrides their paths via `IPaginationConfig`; `from`/`to`
|
|
4122
|
+
* are computed from `page` × `perPage`. This class exists so
|
|
4123
|
+
* `DriverEnum.POCKETBASE` resolves to a distinct identity at the DI
|
|
2276
4124
|
* layer even though the parsing logic is shared with JSON:API, NestJS,
|
|
2277
4125
|
* and Strapi.
|
|
2278
4126
|
*
|
|
2279
|
-
*
|
|
4127
|
+
* When the request was sent with `skipTotal=1` (not emitted by this
|
|
4128
|
+
* driver), PocketBase reports `totalItems`/`totalPages` as `-1`;
|
|
4129
|
+
* override the paths or treat the values accordingly if you opt into
|
|
4130
|
+
* that server-side optimisation.
|
|
4131
|
+
*
|
|
4132
|
+
* @see https://pocketbase.io/docs/api-records/
|
|
2280
4133
|
*/
|
|
2281
|
-
declare class
|
|
4134
|
+
declare class PocketbaseResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
2282
4135
|
}
|
|
2283
4136
|
|
|
2284
4137
|
/**
|
|
@@ -2423,10 +4276,17 @@ declare class PostgrestRequestStrategy extends AbstractRequestStrategy {
|
|
|
2423
4276
|
*/
|
|
2424
4277
|
private _appendOrder;
|
|
2425
4278
|
/**
|
|
2426
|
-
* Append the select parameter as `select=col1,col2`
|
|
4279
|
+
* Append the select parameter as `select=col1,col2,rel(col1,col2)`
|
|
2427
4280
|
*
|
|
2428
|
-
* PostgREST uses a `select` query param for column pruning
|
|
2429
|
-
* NestJS semantics
|
|
4281
|
+
* PostgREST uses a single `select` query param for both column pruning
|
|
4282
|
+
* (matching NestJS semantics) and embedded-resource fetching — the
|
|
4283
|
+
* embedded fragments from `addEmbedded` are spliced into the same
|
|
4284
|
+
* param value, never emitted as a second `select`.
|
|
4285
|
+
*
|
|
4286
|
+
* Fragment shape per relation: `rel(col1,col2)` with explicit columns,
|
|
4287
|
+
* `rel(*)` without. When embedded relations are present but no flat
|
|
4288
|
+
* columns were selected, the flat part defaults to `*` so the base
|
|
4289
|
+
* row's columns are not silently dropped from the projection.
|
|
2430
4290
|
*
|
|
2431
4291
|
* @param state - The current query builder state
|
|
2432
4292
|
* @param options - The query parameter key name configuration
|
|
@@ -3054,5 +4914,241 @@ declare class StrapiRequestStrategy extends AbstractRequestStrategy {
|
|
|
3054
4914
|
declare class StrapiResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
3055
4915
|
}
|
|
3056
4916
|
|
|
3057
|
-
|
|
3058
|
-
|
|
4917
|
+
/**
|
|
4918
|
+
* Request strategy for the WordPress REST API driver
|
|
4919
|
+
*
|
|
4920
|
+
* Generates URIs in the [WordPress REST API collection format](https://developer.wordpress.org/rest-api/using-the-rest-api/pagination/):
|
|
4921
|
+
* - Filters: `field=value` (collection parameters like `status`,
|
|
4922
|
+
* `author`, `categories`); multi-value folds to a CSV (`field=v1,v2`,
|
|
4923
|
+
* the list convention WordPress uses for ID params)
|
|
4924
|
+
* - Sorts: `orderby=field&order=asc|desc` — WordPress core supports a
|
|
4925
|
+
* **single** orderby, so only the first sort rule is emitted
|
|
4926
|
+
* - Field selection (flat): `_fields=id,title` (CSV)
|
|
4927
|
+
* - Relation embedding: `_embed=author,wp:term` (CSV)
|
|
4928
|
+
* - Search: `search=term`
|
|
4929
|
+
* - Pagination (page-based): `page=N&per_page=M`
|
|
4930
|
+
*
|
|
4931
|
+
* The `page` / `per_page` / `orderby` / `order` / `search` and the
|
|
4932
|
+
* underscore-prefixed global params (`_fields`, `_embed`) are fixed by
|
|
4933
|
+
* the server and intentionally not configurable through
|
|
4934
|
+
* `QueryBuilderOptions`; they live as private statics so they are
|
|
4935
|
+
* visible in one place.
|
|
4936
|
+
*
|
|
4937
|
+
* WordPress caps `per_page` at **100** server-side (a 400
|
|
4938
|
+
* `rest_invalid_param` response beyond that); the cap is endpoint
|
|
4939
|
+
* policy rather than a syntax rule, so `validateLimit` keeps the
|
|
4940
|
+
* default positive-integer check and the server stays authoritative.
|
|
4941
|
+
* There is no generic comparison-operator syntax (only
|
|
4942
|
+
* parameter-specific helpers like `before`/`after` for dates, which
|
|
4943
|
+
* pass through `addFilter`), so `addFilterOperator` throws
|
|
4944
|
+
* `UnsupportedFilterOperatorError` via the capability gate.
|
|
4945
|
+
*
|
|
4946
|
+
* @see https://developer.wordpress.org/rest-api/reference/posts/#list-posts
|
|
4947
|
+
*/
|
|
4948
|
+
declare class WordpressRequestStrategy extends AbstractRequestStrategy {
|
|
4949
|
+
/**
|
|
4950
|
+
* Filters, sorts, global search, flat field selection (`select`),
|
|
4951
|
+
* embedding (`includes`) — no operator filters, no per-model fields,
|
|
4952
|
+
* no embedded-column projection
|
|
4953
|
+
*/
|
|
4954
|
+
readonly capabilities: IStrategyCapabilities;
|
|
4955
|
+
/**
|
|
4956
|
+
* WordPress-native names of the seven hardcoded query keys
|
|
4957
|
+
*
|
|
4958
|
+
* The underscore prefix marks the REST API's global params apart
|
|
4959
|
+
* from collection filters; all keys are fixed by the server and
|
|
4960
|
+
* intentionally not configurable through `QueryBuilderOptions`.
|
|
4961
|
+
*/
|
|
4962
|
+
private static readonly _embedKey;
|
|
4963
|
+
private static readonly _fieldsKey;
|
|
4964
|
+
private static readonly _orderbyKey;
|
|
4965
|
+
private static readonly _orderKey;
|
|
4966
|
+
private static readonly _pageKey;
|
|
4967
|
+
private static readonly _perPageKey;
|
|
4968
|
+
private static readonly _searchKey;
|
|
4969
|
+
/**
|
|
4970
|
+
* Emit WordPress-format query-string segments in canonical order:
|
|
4971
|
+
* filters → orderby/order → _fields → _embed → search → page → per_page
|
|
4972
|
+
*
|
|
4973
|
+
* @param state - The current query builder state
|
|
4974
|
+
* @param _options - The query parameter key name configuration (unused;
|
|
4975
|
+
* WordPress' wire keys are fixed by the server)
|
|
4976
|
+
* @returns Ordered query-string fragments
|
|
4977
|
+
*/
|
|
4978
|
+
protected parts(state: IQueryBuilderState, _options: QueryBuilderOptions): string[];
|
|
4979
|
+
/**
|
|
4980
|
+
* Append the `_embed=` CSV from the includes array
|
|
4981
|
+
*
|
|
4982
|
+
* A bare `_embed` (no value) embeds everything; this driver always
|
|
4983
|
+
* emits the named form so the response stays lean.
|
|
4984
|
+
*
|
|
4985
|
+
* @param state - The current query builder state
|
|
4986
|
+
* @param out - The accumulator the caller joins into the URI
|
|
4987
|
+
*/
|
|
4988
|
+
private _appendEmbed;
|
|
4989
|
+
/**
|
|
4990
|
+
* Append the `_fields=` CSV from the flat select array
|
|
4991
|
+
*
|
|
4992
|
+
* @param state - The current query builder state
|
|
4993
|
+
* @param out - The accumulator the caller joins into the URI
|
|
4994
|
+
*/
|
|
4995
|
+
private _appendFields;
|
|
4996
|
+
/**
|
|
4997
|
+
* Append simple filter parameters
|
|
4998
|
+
*
|
|
4999
|
+
* A single value emits the bare form (`status=publish`); multiple
|
|
5000
|
+
* values fold to the CSV list convention (`categories=2,3`).
|
|
5001
|
+
*
|
|
5002
|
+
* @param state - The current query builder state
|
|
5003
|
+
* @param out - The accumulator the caller joins into the URI
|
|
5004
|
+
*/
|
|
5005
|
+
private _appendFilters;
|
|
5006
|
+
/**
|
|
5007
|
+
* Append the `page=` / `per_page=` pagination pair
|
|
5008
|
+
*
|
|
5009
|
+
* @param state - The current query builder state
|
|
5010
|
+
* @param out - The accumulator the caller joins into the URI
|
|
5011
|
+
*/
|
|
5012
|
+
private _appendPagination;
|
|
5013
|
+
/**
|
|
5014
|
+
* Append the `search=` parameter
|
|
5015
|
+
*
|
|
5016
|
+
* @param state - The current query builder state
|
|
5017
|
+
* @param out - The accumulator the caller joins into the URI
|
|
5018
|
+
*/
|
|
5019
|
+
private _appendSearch;
|
|
5020
|
+
/**
|
|
5021
|
+
* Append the `orderby=` / `order=` pair from the first sort rule
|
|
5022
|
+
*
|
|
5023
|
+
* WordPress core accepts a single `orderby` value — additional sort
|
|
5024
|
+
* rules in state are ignored by design (the server would reject a
|
|
5025
|
+
* CSV here).
|
|
5026
|
+
*
|
|
5027
|
+
* @param state - The current query builder state
|
|
5028
|
+
* @param out - The accumulator the caller joins into the URI
|
|
5029
|
+
*/
|
|
5030
|
+
private _appendSort;
|
|
5031
|
+
}
|
|
5032
|
+
|
|
5033
|
+
/**
|
|
5034
|
+
* Response strategy for the WordPress REST API driver
|
|
5035
|
+
*
|
|
5036
|
+
* WordPress returns a bare array body for collection endpoints.
|
|
5037
|
+
* Pagination metadata travels in HTTP response headers:
|
|
5038
|
+
*
|
|
5039
|
+
* - `X-WP-Total` — total number of records in the collection
|
|
5040
|
+
* - `X-WP-TotalPages` — total number of pages at the requested
|
|
5041
|
+
* `per_page`
|
|
5042
|
+
* - `Link` — RFC 5988 navigation links (`rel="next"` / `rel="prev"`)
|
|
5043
|
+
*
|
|
5044
|
+
* The strategy surfaces the `Link` URLs as `nextPageUrl` /
|
|
5045
|
+
* `prevPageUrl` and derives position from them:
|
|
5046
|
+
*
|
|
5047
|
+
* - `currentPage` is the `prev` link's `page` param + 1 (no `prev` →
|
|
5048
|
+
* page **1**), falling back to the `next` link's `page` param − 1.
|
|
5049
|
+
* - `perPage` is the item count of the current page whenever a `next`
|
|
5050
|
+
* link exists (a page with a successor is necessarily full); on the
|
|
5051
|
+
* last page of a multi-page set it is not introspectable and stays
|
|
5052
|
+
* `undefined`.
|
|
5053
|
+
* - `from`/`to` derive from `currentPage` × `perPage` on full pages,
|
|
5054
|
+
* or count back from the total on the last page
|
|
5055
|
+
* (`from = total - data.length + 1`, `to = total`).
|
|
5056
|
+
*
|
|
5057
|
+
* This strategy expects the consumer to pass the array body as
|
|
5058
|
+
* `response` (or a plain object with `response[options.data]` pointing
|
|
5059
|
+
* at the array) and the response headers via the optional `headers`
|
|
5060
|
+
* bag — the same call-site shape as the PostgREST driver. Omitted
|
|
5061
|
+
* headers are tolerated and yield a collection with `undefined`
|
|
5062
|
+
* bounds.
|
|
5063
|
+
*
|
|
5064
|
+
* @see https://developer.wordpress.org/rest-api/using-the-rest-api/pagination/
|
|
5065
|
+
*/
|
|
5066
|
+
declare class WordpressResponseStrategy implements IResponseStrategy {
|
|
5067
|
+
private static readonly _linkHeader;
|
|
5068
|
+
private static readonly _linkRegex;
|
|
5069
|
+
private static readonly _pageParamRegex;
|
|
5070
|
+
private static readonly _totalHeader;
|
|
5071
|
+
private static readonly _totalPagesHeader;
|
|
5072
|
+
/**
|
|
5073
|
+
* Parse a WordPress REST response into a typed PaginatedCollection
|
|
5074
|
+
*
|
|
5075
|
+
* @param response - The raw response. Either the array body directly, or
|
|
5076
|
+
* an object with the array at `response[options.data]`.
|
|
5077
|
+
* @param options - The response key configuration (only `options.data` is
|
|
5078
|
+
* consulted; all pagination metadata comes from headers).
|
|
5079
|
+
* @param headers - Optional HTTP response headers. `X-WP-Total` /
|
|
5080
|
+
* `X-WP-TotalPages` drive the totals and the `Link` header drives
|
|
5081
|
+
* navigation and page derivation; omission is tolerated.
|
|
5082
|
+
* @returns A typed PaginatedCollection instance
|
|
5083
|
+
*/
|
|
5084
|
+
paginate<T extends IPaginatedObject>(response: Record<string, unknown>, options: ResponseOptions, headers?: HeaderBag): PaginatedCollection<T>;
|
|
5085
|
+
/**
|
|
5086
|
+
* Derive the current page from the Link relations
|
|
5087
|
+
*
|
|
5088
|
+
* The `prev` URL's `page` param + 1 is authoritative; without a
|
|
5089
|
+
* `prev` the page is 1 unless a `next` URL contradicts it (its page
|
|
5090
|
+
* param − 1). A missing/unparseable Link header yields page 1.
|
|
5091
|
+
*
|
|
5092
|
+
* @param next - The `rel="next"` URL, if present
|
|
5093
|
+
* @param prev - The `rel="prev"` URL, if present
|
|
5094
|
+
* @returns The 1-indexed current page
|
|
5095
|
+
*/
|
|
5096
|
+
private _deriveCurrentPage;
|
|
5097
|
+
/**
|
|
5098
|
+
* Derive `from` as the 1-indexed offset of the first item on this page
|
|
5099
|
+
*
|
|
5100
|
+
* Computed from `currentPage` × `perPage` on full pages; on the last
|
|
5101
|
+
* page (no `next` link) it counts back from the total
|
|
5102
|
+
* (`total - items + 1`), which also covers single-page responses.
|
|
5103
|
+
*
|
|
5104
|
+
* @param data - The items on the current page
|
|
5105
|
+
* @param currentPage - The current page number
|
|
5106
|
+
* @param next - The `rel="next"` URL, if present
|
|
5107
|
+
* @param perPage - The page size (may be undefined)
|
|
5108
|
+
* @param total - The total item count (may be undefined)
|
|
5109
|
+
* @returns The 1-indexed `from` index, or undefined when inputs insufficient
|
|
5110
|
+
*/
|
|
5111
|
+
private _deriveFrom;
|
|
5112
|
+
/**
|
|
5113
|
+
* Derive `to` as the 1-indexed offset of the last item on this page
|
|
5114
|
+
*
|
|
5115
|
+
* Clamped to `total` so the last page does not report past the end;
|
|
5116
|
+
* on the last page (no `next` link) it is simply the total.
|
|
5117
|
+
*
|
|
5118
|
+
* @param data - The items on the current page
|
|
5119
|
+
* @param currentPage - The current page number
|
|
5120
|
+
* @param next - The `rel="next"` URL, if present
|
|
5121
|
+
* @param perPage - The page size (may be undefined)
|
|
5122
|
+
* @param total - The total item count (may be undefined)
|
|
5123
|
+
* @returns The 1-indexed `to` index, or undefined when inputs insufficient
|
|
5124
|
+
*/
|
|
5125
|
+
private _deriveTo;
|
|
5126
|
+
/**
|
|
5127
|
+
* Extract the `page` query param from a navigation URL
|
|
5128
|
+
*
|
|
5129
|
+
* @param url - The URL to inspect (possibly undefined)
|
|
5130
|
+
* @returns The parsed page number, or undefined
|
|
5131
|
+
*/
|
|
5132
|
+
private _pageParam;
|
|
5133
|
+
/**
|
|
5134
|
+
* Parse a non-negative integer count header value
|
|
5135
|
+
*
|
|
5136
|
+
* @param value - Raw header value (possibly null/undefined)
|
|
5137
|
+
* @returns The parsed count, or undefined when absent or unparseable
|
|
5138
|
+
*/
|
|
5139
|
+
private _parseCount;
|
|
5140
|
+
/**
|
|
5141
|
+
* Extract the `rel="next"` / `rel="prev"` URLs from an RFC 5988
|
|
5142
|
+
* `Link` header value
|
|
5143
|
+
*
|
|
5144
|
+
* Tolerates any ordering, extra relations (`rel="collection"` etc.
|
|
5145
|
+
* are ignored), and a missing header.
|
|
5146
|
+
*
|
|
5147
|
+
* @param value - Raw header value (possibly null/undefined)
|
|
5148
|
+
* @returns The navigation URLs found, keyed by relation
|
|
5149
|
+
*/
|
|
5150
|
+
private _parseLinkHeader;
|
|
5151
|
+
}
|
|
5152
|
+
|
|
5153
|
+
export { ApiPlatformRequestStrategy, ApiPlatformResponseOptions, ApiPlatformResponseStrategy, DirectusRequestStrategy, DirectusResponseOptions, DirectusResponseStrategy, DrfRequestStrategy, DrfResponseOptions, DrfResponseStrategy, DriverEnum, FeathersRequestStrategy, FeathersResponseOptions, FeathersResponseStrategy, FilterOperatorEnum, InvalidFilterOperatorValueError, InvalidLimitError, InvalidPageNumberError, InvalidResourceNameError, JsonApiRequestStrategy, JsonApiResponseOptions, JsonApiResponseStrategy, JsonServerRequestStrategy, JsonServerResponseOptions, JsonServerResponseStrategy, KeyNotFoundError, LaravelRequestStrategy, LaravelResponseStrategy, NG_QUBEE_DRIVER, NG_QUBEE_REQUEST_OPTIONS, NG_QUBEE_REQUEST_STRATEGY, NG_QUBEE_RESPONSE_OPTIONS, NG_QUBEE_RESPONSE_STRATEGY, NestjsRequestStrategy, NestjsResponseOptions, NestjsResponseStrategy, NestjsxCrudRequestStrategy, NestjsxCrudResponseOptions, NestjsxCrudResponseStrategy, NgQubeeModule, NgQubeeService, OdataRequestStrategy, OdataResponseOptions, OdataResponseStrategy, PaginatedCollection, PaginationModeEnum, PaginationNotSyncedError, PaginationService, PayloadRequestStrategy, PayloadResponseOptions, PayloadResponseStrategy, PocketbaseRequestStrategy, PocketbaseResponseOptions, PocketbaseResponseStrategy, PostgrestRequestStrategy, PostgrestResponseStrategy, QueryBuilderOptions, ResponseOptions, SieveRequestStrategy, SieveResponseOptions, SieveResponseStrategy, SortEnum, SpatieRequestStrategy, SpatieResponseStrategy, SpringRequestStrategy, SpringResponseOptions, SpringResponseStrategy, StrapiRequestStrategy, StrapiResponseOptions, StrapiResponseStrategy, UnselectableModelError, UnsupportedEmbeddedError, UnsupportedFieldSelectionError, UnsupportedFilterError, UnsupportedFilterOperatorError, UnsupportedIncludesError, UnsupportedSearchError, UnsupportedSelectError, UnsupportedSortError, WordpressRequestStrategy, WordpressResponseStrategy, buildNgQubeeProviders, provideNgQubee, provideNgQubeeInstance, readHeader };
|
|
5154
|
+
export type { Embedded, HeaderBag, IConfig, IFields, IFilters, INestState, IOperatorFilter, IPage, IPaginatedObject, IPaginationConfig, IQueryBuilderConfig, IQueryBuilderState, IRequestStrategy, IResponseStrategy, ISort };
|