ng-qubee 3.5.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 +14 -3
- package/fesm2022/ng-qubee.mjs +4750 -769
- package/fesm2022/ng-qubee.mjs.map +1 -1
- package/package.json +24 -2
- package/types/ng-qubee.d.ts +3126 -285
package/types/ng-qubee.d.ts
CHANGED
|
@@ -40,36 +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
|
-
|
|
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;
|
|
56
69
|
}
|
|
57
70
|
|
|
58
71
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* `QUERY` (default) — the request strategy emits `limit` and `offset` (or
|
|
62
|
-
* equivalent) query parameters on the URL.
|
|
72
|
+
* Resolved query parameter key names with defaults applied
|
|
63
73
|
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* `NgQubeeService.paginationHeaders()`. Currently honoured only by the
|
|
67
|
-
* PostgREST driver, which maps it to `Range-Unit: items` + `Range: 0-9`.
|
|
68
|
-
* 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.
|
|
69
76
|
*/
|
|
70
|
-
declare
|
|
71
|
-
|
|
72
|
-
|
|
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);
|
|
73
89
|
}
|
|
74
90
|
|
|
75
91
|
/**
|
|
@@ -109,32 +125,264 @@ interface IPaginationConfig {
|
|
|
109
125
|
}
|
|
110
126
|
|
|
111
127
|
/**
|
|
112
|
-
*
|
|
128
|
+
* Resolved response field key names with defaults applied
|
|
113
129
|
*
|
|
114
|
-
*
|
|
115
|
-
* 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
|
+
* ```
|
|
116
140
|
*/
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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"
|
|
138
386
|
}
|
|
139
387
|
|
|
140
388
|
/**
|
|
@@ -349,6 +597,19 @@ interface ISort {
|
|
|
349
597
|
order: SortEnum;
|
|
350
598
|
}
|
|
351
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
|
+
|
|
352
613
|
/**
|
|
353
614
|
* Represents the complete query builder state
|
|
354
615
|
*
|
|
@@ -358,6 +619,8 @@ interface ISort {
|
|
|
358
619
|
interface IQueryBuilderState {
|
|
359
620
|
/** The base URL to prepend to generated URIs */
|
|
360
621
|
baseUrl: string;
|
|
622
|
+
/** Embedded-resource selection (PostgREST only) */
|
|
623
|
+
embedded: Embedded;
|
|
361
624
|
/** Per-model field selection (Spatie only) */
|
|
362
625
|
fields: IFields;
|
|
363
626
|
/** Simple key-value filters (Spatie and NestJS) */
|
|
@@ -395,6 +658,8 @@ interface IQueryBuilderState {
|
|
|
395
658
|
* strategy class — `NgQubeeService` does not need to be touched.
|
|
396
659
|
*/
|
|
397
660
|
interface IStrategyCapabilities {
|
|
661
|
+
/** Embedded-resource selection inside `select` (PostgREST `select=col,rel(col1)`) */
|
|
662
|
+
readonly embedded: boolean;
|
|
398
663
|
/** Per-model field selection (e.g. JSON:API `fields[type]=col1,col2`) */
|
|
399
664
|
readonly fields: boolean;
|
|
400
665
|
/** Simple key-value filters (e.g. `filter.status=active`) */
|
|
@@ -411,26 +676,6 @@ interface IStrategyCapabilities {
|
|
|
411
676
|
readonly sort: boolean;
|
|
412
677
|
}
|
|
413
678
|
|
|
414
|
-
/**
|
|
415
|
-
* Resolved query parameter key names with defaults applied
|
|
416
|
-
*
|
|
417
|
-
* Maps logical query concepts to the actual query parameter names
|
|
418
|
-
* used in the generated URI. Unset values fall back to defaults.
|
|
419
|
-
*/
|
|
420
|
-
declare class QueryBuilderOptions {
|
|
421
|
-
readonly appends: string;
|
|
422
|
-
readonly fields: string;
|
|
423
|
-
readonly filters: string;
|
|
424
|
-
readonly includes: string;
|
|
425
|
-
readonly limit: string;
|
|
426
|
-
readonly page: string;
|
|
427
|
-
readonly search: string;
|
|
428
|
-
readonly select: string;
|
|
429
|
-
readonly sort: string;
|
|
430
|
-
readonly sortBy: string;
|
|
431
|
-
constructor(options: IQueryBuilderConfig);
|
|
432
|
-
}
|
|
433
|
-
|
|
434
679
|
/**
|
|
435
680
|
* Strategy interface for building request URIs
|
|
436
681
|
*
|
|
@@ -556,6 +801,21 @@ declare class NestService {
|
|
|
556
801
|
* @private
|
|
557
802
|
*/
|
|
558
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;
|
|
559
819
|
/**
|
|
560
820
|
* Add selectable fields for the given model to the request
|
|
561
821
|
* Automatically prevents duplicate fields for each model
|
|
@@ -621,6 +881,18 @@ declare class NestService {
|
|
|
621
881
|
* service.addSort({ field: 'name', order: SortEnum.ASC });
|
|
622
882
|
*/
|
|
623
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;
|
|
624
896
|
/**
|
|
625
897
|
* Remove fields for the given model
|
|
626
898
|
* Uses deep cloning to prevent mutations to the original state
|
|
@@ -762,10 +1034,33 @@ declare class NgQubeeService {
|
|
|
762
1034
|
*/
|
|
763
1035
|
private _assertCapability;
|
|
764
1036
|
/**
|
|
765
|
-
* Add
|
|
1037
|
+
* Add an embedded resource to the select statement (PostgREST only)
|
|
766
1038
|
*
|
|
767
|
-
*
|
|
768
|
-
*
|
|
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;
|
|
1059
|
+
/**
|
|
1060
|
+
* Add fields to the select statement for the given model (JSON:API and Spatie only)
|
|
1061
|
+
*
|
|
1062
|
+
* @param model - Model that holds the fields
|
|
1063
|
+
* @param fields - Fields to select
|
|
769
1064
|
* @returns {this}
|
|
770
1065
|
* @throws {UnsupportedFieldSelectionError} If the active driver does not support per-model field selection
|
|
771
1066
|
*/
|
|
@@ -827,6 +1122,16 @@ declare class NgQubeeService {
|
|
|
827
1122
|
* @returns The current page number
|
|
828
1123
|
*/
|
|
829
1124
|
currentPage(): number;
|
|
1125
|
+
/**
|
|
1126
|
+
* Remove embedded resources from the current query builder state (PostgREST only)
|
|
1127
|
+
*
|
|
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;
|
|
830
1135
|
/**
|
|
831
1136
|
* Delete selected fields for the given models in the current query builder state (JSON:API and Spatie only)
|
|
832
1137
|
*
|
|
@@ -1073,36 +1378,6 @@ type HeaderBag = {
|
|
|
1073
1378
|
*/
|
|
1074
1379
|
declare function readHeader(bag: HeaderBag | null | undefined, name: string): string | null;
|
|
1075
1380
|
|
|
1076
|
-
/**
|
|
1077
|
-
* Resolved response field key names with defaults applied
|
|
1078
|
-
*
|
|
1079
|
-
* Maps logical pagination concepts to the actual key names
|
|
1080
|
-
* used in the API response. Unset values fall back to Laravel defaults.
|
|
1081
|
-
*
|
|
1082
|
-
* For NestJS responses, use dot-notation paths:
|
|
1083
|
-
* ```typescript
|
|
1084
|
-
* new ResponseOptions({
|
|
1085
|
-
* currentPage: 'meta.currentPage',
|
|
1086
|
-
* total: 'meta.totalItems'
|
|
1087
|
-
* });
|
|
1088
|
-
* ```
|
|
1089
|
-
*/
|
|
1090
|
-
declare class ResponseOptions {
|
|
1091
|
-
readonly currentPage: string;
|
|
1092
|
-
readonly data: string;
|
|
1093
|
-
readonly firstPageUrl: string;
|
|
1094
|
-
readonly from: string;
|
|
1095
|
-
readonly lastPage: string;
|
|
1096
|
-
readonly lastPageUrl: string;
|
|
1097
|
-
readonly nextPageUrl: string;
|
|
1098
|
-
readonly path: string;
|
|
1099
|
-
readonly perPage: string;
|
|
1100
|
-
readonly prevPageUrl: string;
|
|
1101
|
-
readonly to: string;
|
|
1102
|
-
readonly total: string;
|
|
1103
|
-
constructor(options: IPaginationConfig);
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
1381
|
/**
|
|
1107
1382
|
* Strategy interface for parsing paginated API responses
|
|
1108
1383
|
*
|
|
@@ -1247,6 +1522,19 @@ declare class UnselectableModelError extends Error {
|
|
|
1247
1522
|
constructor(model: string);
|
|
1248
1523
|
}
|
|
1249
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
|
+
|
|
1250
1538
|
/**
|
|
1251
1539
|
* Error thrown when per-model field selection is attempted with a driver that does not support it
|
|
1252
1540
|
*
|
|
@@ -1446,78 +1734,131 @@ declare abstract class AbstractRequestStrategy implements IRequestStrategy {
|
|
|
1446
1734
|
}
|
|
1447
1735
|
|
|
1448
1736
|
/**
|
|
1449
|
-
* Request strategy for the
|
|
1737
|
+
* Request strategy for the API Platform (Symfony) driver
|
|
1450
1738
|
*
|
|
1451
|
-
* Generates URIs in
|
|
1452
|
-
* -
|
|
1453
|
-
*
|
|
1454
|
-
* -
|
|
1455
|
-
*
|
|
1456
|
-
*
|
|
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`
|
|
1457
1750
|
*
|
|
1458
|
-
*
|
|
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/
|
|
1459
1765
|
*/
|
|
1460
|
-
declare class
|
|
1766
|
+
declare class ApiPlatformRequestStrategy extends AbstractRequestStrategy {
|
|
1461
1767
|
/**
|
|
1462
|
-
* Filters,
|
|
1463
|
-
*
|
|
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
|
|
1464
1771
|
*/
|
|
1465
1772
|
readonly capabilities: IStrategyCapabilities;
|
|
1466
1773
|
/**
|
|
1467
|
-
*
|
|
1468
|
-
*
|
|
1774
|
+
* API Platform-native names of the two hardcoded query keys
|
|
1775
|
+
*
|
|
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.
|
|
1780
|
+
*/
|
|
1781
|
+
private static readonly _itemsPerPageKey;
|
|
1782
|
+
private static readonly _orderKey;
|
|
1783
|
+
/**
|
|
1784
|
+
* Emit API Platform-format query-string segments in canonical order:
|
|
1785
|
+
* filters → operator filters → order → page → itemsPerPage
|
|
1469
1786
|
*
|
|
1470
1787
|
* @param state - The current query builder state
|
|
1471
|
-
* @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)
|
|
1472
1790
|
* @returns Ordered query-string fragments
|
|
1473
1791
|
*/
|
|
1474
1792
|
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
1475
1793
|
/**
|
|
1476
|
-
* Append
|
|
1794
|
+
* Append simple filter parameters
|
|
1795
|
+
*
|
|
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`).
|
|
1477
1799
|
*
|
|
1478
1800
|
* @param state - The current query builder state
|
|
1479
|
-
* @param options - The query parameter key name configuration
|
|
1480
1801
|
* @param out - The accumulator the caller joins into the URI
|
|
1481
|
-
* @throws Error if the resource is missing from the fields object
|
|
1482
|
-
* @throws UnselectableModelError if a field type is not the resource or in includes
|
|
1483
1802
|
*/
|
|
1484
|
-
private
|
|
1803
|
+
private _appendFilters;
|
|
1485
1804
|
/**
|
|
1486
|
-
* Append
|
|
1805
|
+
* Append the itemsPerPage parameter
|
|
1487
1806
|
*
|
|
1488
1807
|
* @param state - The current query builder state
|
|
1489
|
-
* @param options - The query parameter key name configuration
|
|
1490
1808
|
* @param out - The accumulator the caller joins into the URI
|
|
1491
1809
|
*/
|
|
1492
|
-
private
|
|
1810
|
+
private _appendItemsPerPage;
|
|
1493
1811
|
/**
|
|
1494
|
-
* Append
|
|
1812
|
+
* Append explicit operator filters in the bracket syntax
|
|
1495
1813
|
*
|
|
1496
1814
|
* @param state - The current query builder state
|
|
1497
|
-
* @param options - The query parameter key name configuration
|
|
1498
1815
|
* @param out - The accumulator the caller joins into the URI
|
|
1499
1816
|
*/
|
|
1500
|
-
private
|
|
1817
|
+
private _appendOperatorFilters;
|
|
1501
1818
|
/**
|
|
1502
|
-
* Append
|
|
1503
|
-
*
|
|
1504
|
-
* `qs.stringify` already returns the two segments joined with `&`, so we
|
|
1505
|
-
* push the whole string as one accumulator entry — `_join` will glue
|
|
1506
|
-
* it onto the rest with the same separator.
|
|
1819
|
+
* Append `order[field]=asc` / `order[field]=desc` params, one per rule
|
|
1507
1820
|
*
|
|
1508
1821
|
* @param state - The current query builder state
|
|
1509
|
-
* @param options - The query parameter key name configuration
|
|
1510
1822
|
* @param out - The accumulator the caller joins into the URI
|
|
1511
1823
|
*/
|
|
1512
|
-
private
|
|
1824
|
+
private _appendOrder;
|
|
1513
1825
|
/**
|
|
1514
|
-
* Append
|
|
1826
|
+
* Append the page parameter
|
|
1515
1827
|
*
|
|
1516
1828
|
* @param state - The current query builder state
|
|
1517
1829
|
* @param options - The query parameter key name configuration
|
|
1518
1830
|
* @param out - The accumulator the caller joins into the URI
|
|
1519
1831
|
*/
|
|
1520
|
-
private
|
|
1832
|
+
private _appendPage;
|
|
1833
|
+
/**
|
|
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`.
|
|
1853
|
+
*
|
|
1854
|
+
* @param filter - The operator filter to translate
|
|
1855
|
+
* @returns One or more bracket-syntax query-string segments
|
|
1856
|
+
* @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
|
|
1857
|
+
* exactly two values, or `NULL` does not receive exactly one boolean
|
|
1858
|
+
* @throws {UnsupportedFilterOperatorError} If the operator has no API
|
|
1859
|
+
* Platform equivalent
|
|
1860
|
+
*/
|
|
1861
|
+
private _formatOperatorSegments;
|
|
1521
1862
|
}
|
|
1522
1863
|
|
|
1523
1864
|
/**
|
|
@@ -1586,153 +1927,189 @@ declare abstract class AbstractDotPathResponseStrategy implements IResponseStrat
|
|
|
1586
1927
|
}
|
|
1587
1928
|
|
|
1588
1929
|
/**
|
|
1589
|
-
* Response strategy for the
|
|
1930
|
+
* Response strategy for the API Platform (Symfony) driver
|
|
1931
|
+
*
|
|
1932
|
+
* Parses API Platform's default Hydra/JSON-LD collection envelope:
|
|
1590
1933
|
*
|
|
1591
|
-
* Parses JSON:API pagination responses:
|
|
1592
1934
|
* ```json
|
|
1593
1935
|
* {
|
|
1594
|
-
* "
|
|
1595
|
-
* "
|
|
1596
|
-
*
|
|
1597
|
-
*
|
|
1598
|
-
*
|
|
1599
|
-
* "
|
|
1600
|
-
* "
|
|
1601
|
-
* "
|
|
1602
|
-
*
|
|
1603
|
-
*
|
|
1604
|
-
* "first": "url",
|
|
1605
|
-
* "prev": "url",
|
|
1606
|
-
* "next": "url",
|
|
1607
|
-
* "last": "url"
|
|
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"
|
|
1608
1946
|
* }
|
|
1609
1947
|
* }
|
|
1610
1948
|
* ```
|
|
1611
1949
|
*
|
|
1612
|
-
*
|
|
1613
|
-
*
|
|
1614
|
-
*
|
|
1615
|
-
*
|
|
1616
|
-
*
|
|
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**:
|
|
1617
1955
|
*
|
|
1618
|
-
*
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
*
|
|
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.
|
|
1625
1965
|
*
|
|
1626
|
-
*
|
|
1627
|
-
* -
|
|
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).
|
|
1628
1970
|
*
|
|
1629
|
-
*
|
|
1971
|
+
* @see https://api-platform.com/docs/core/pagination/
|
|
1630
1972
|
*/
|
|
1631
|
-
declare class
|
|
1973
|
+
declare class ApiPlatformResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
1632
1974
|
/**
|
|
1633
|
-
*
|
|
1975
|
+
* Parse a Hydra collection response into a PaginatedCollection
|
|
1976
|
+
*
|
|
1977
|
+
* @param response - The raw API response body
|
|
1978
|
+
* @param options - The response key name configuration (dot-notation paths supported)
|
|
1979
|
+
* @returns A typed PaginatedCollection instance
|
|
1634
1980
|
*/
|
|
1635
|
-
|
|
1981
|
+
paginate<T extends IPaginatedObject>(response: Record<string, any>, options: ResponseOptions): PaginatedCollection<T>;
|
|
1636
1982
|
/**
|
|
1637
|
-
*
|
|
1983
|
+
* Derive the current page number from the `hydra:view` `@id` URL
|
|
1638
1984
|
*
|
|
1639
|
-
*
|
|
1640
|
-
*
|
|
1641
|
-
*
|
|
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.
|
|
1988
|
+
*
|
|
1989
|
+
* @param viewUrl - The `hydra:view.@id` URL, or null
|
|
1990
|
+
* @returns The current page number
|
|
1642
1991
|
*/
|
|
1643
|
-
|
|
1644
|
-
}
|
|
1645
|
-
|
|
1646
|
-
/**
|
|
1647
|
-
* Base class for response strategies whose pagination metadata is a flat
|
|
1648
|
-
* key-value envelope on the response body
|
|
1649
|
-
*
|
|
1650
|
-
* Laravel's stock pagination and Spatie's `QueryBuilder` both emit the
|
|
1651
|
-
* same flat shape — `{ data, current_page, total, per_page, from, to,
|
|
1652
|
-
* next_page_url, prev_page_url, first_page_url, last_page, last_page_url
|
|
1653
|
-
* }` — and both response strategies were duplicating the byte-identical
|
|
1654
|
-
* `new PaginatedCollection(response[options.X], ...)` body before this
|
|
1655
|
-
* base existed. Concrete classes now extend and provide only the
|
|
1656
|
-
* docstring describing their driver's specific shape (see
|
|
1657
|
-
* `LaravelResponseStrategy`, `SpatieResponseStrategy`).
|
|
1658
|
-
*
|
|
1659
|
-
* Drivers whose pagination metadata is a nested envelope (JSON:API,
|
|
1660
|
-
* NestJS, Strapi) extend `AbstractDotPathResponseStrategy` instead.
|
|
1661
|
-
* Drivers whose metadata comes from HTTP headers (PostgREST) or is
|
|
1662
|
-
* derived from response URLs (DRF) implement `IResponseStrategy`
|
|
1663
|
-
* directly.
|
|
1664
|
-
*/
|
|
1665
|
-
declare abstract class AbstractFlatResponseStrategy implements IResponseStrategy {
|
|
1992
|
+
private _deriveCurrentPage;
|
|
1666
1993
|
/**
|
|
1667
|
-
*
|
|
1994
|
+
* Derive the last page number
|
|
1668
1995
|
*
|
|
1669
|
-
*
|
|
1670
|
-
*
|
|
1671
|
-
*
|
|
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.
|
|
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
|
|
2003
|
+
* @param total - The total item count
|
|
2004
|
+
* @param perPage - The page size
|
|
2005
|
+
* @returns The last page number, or undefined when inputs insufficient
|
|
1672
2006
|
*/
|
|
1673
|
-
|
|
2007
|
+
private _deriveLastPage;
|
|
2008
|
+
/**
|
|
2009
|
+
* Derive `perPage` from the `hydra:view` `@id` URL
|
|
2010
|
+
*
|
|
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.
|
|
2014
|
+
*
|
|
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
|
|
2018
|
+
* @returns The page size, or undefined
|
|
2019
|
+
*/
|
|
2020
|
+
private _derivePerPage;
|
|
2021
|
+
/**
|
|
2022
|
+
* Extract an integer query parameter from a Hydra URL
|
|
2023
|
+
*
|
|
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
|
|
2027
|
+
*/
|
|
2028
|
+
private _extractNumberParam;
|
|
2029
|
+
/**
|
|
2030
|
+
* Extract a single query parameter from a URL via the WHATWG URL parser
|
|
2031
|
+
*
|
|
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.
|
|
2035
|
+
*
|
|
2036
|
+
* @param url - The URL to parse
|
|
2037
|
+
* @param name - The query-parameter name to look up
|
|
2038
|
+
* @returns The raw string value of the parameter, or undefined
|
|
2039
|
+
*/
|
|
2040
|
+
private _extractQueryParam;
|
|
2041
|
+
/**
|
|
2042
|
+
* Derive `from` for a view-less response holding the whole collection
|
|
2043
|
+
*
|
|
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
|
|
2048
|
+
*/
|
|
2049
|
+
private _wholeSetFrom;
|
|
2050
|
+
/**
|
|
2051
|
+
* Derive `to` for a view-less response holding the whole collection
|
|
2052
|
+
*
|
|
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
|
|
2057
|
+
*/
|
|
2058
|
+
private _wholeSetTo;
|
|
1674
2059
|
}
|
|
1675
2060
|
|
|
1676
2061
|
/**
|
|
1677
|
-
*
|
|
2062
|
+
* Request strategy for the Directus driver
|
|
1678
2063
|
*
|
|
1679
|
-
*
|
|
1680
|
-
*
|
|
1681
|
-
*
|
|
1682
|
-
*
|
|
1683
|
-
*
|
|
1684
|
-
*
|
|
1685
|
-
*
|
|
1686
|
-
*
|
|
1687
|
-
*
|
|
1688
|
-
*
|
|
1689
|
-
*
|
|
1690
|
-
*
|
|
1691
|
-
*
|
|
1692
|
-
* "last_page_url": "..."
|
|
1693
|
-
* }
|
|
1694
|
-
* ```
|
|
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`
|
|
1695
2077
|
*
|
|
1696
|
-
* The
|
|
1697
|
-
*
|
|
1698
|
-
* `
|
|
1699
|
-
*
|
|
1700
|
-
|
|
1701
|
-
declare class LaravelResponseStrategy extends AbstractFlatResponseStrategy {
|
|
1702
|
-
}
|
|
1703
|
-
|
|
1704
|
-
/**
|
|
1705
|
-
* Request strategy for the NestJS (nestjs-paginate) driver
|
|
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.
|
|
1706
2083
|
*
|
|
1707
|
-
*
|
|
1708
|
-
*
|
|
1709
|
-
*
|
|
1710
|
-
* - Sorts: `sortBy=field1:DESC,field2:ASC`
|
|
1711
|
-
* - Select: `select=col1,col2`
|
|
1712
|
-
* - Search: `search=term`
|
|
1713
|
-
* - Pagination: `limit=N&page=N`
|
|
2084
|
+
* PostgREST-native full-text search operators (`FTS`, `PHFTS`, `PLFTS`,
|
|
2085
|
+
* `WFTS`) throw `UnsupportedFilterOperatorError` — use `search` or the
|
|
2086
|
+
* `CONTAINS` / `ILIKE` operator filters instead.
|
|
1714
2087
|
*
|
|
1715
|
-
* @see https://
|
|
2088
|
+
* @see https://docs.directus.io/reference/query.html
|
|
2089
|
+
* @see https://docs.directus.io/reference/filter-rules.html
|
|
1716
2090
|
*/
|
|
1717
|
-
declare class
|
|
2091
|
+
declare class DirectusRequestStrategy extends AbstractRequestStrategy {
|
|
1718
2092
|
/**
|
|
1719
|
-
* Filters, operator filters, sorts, flat select,
|
|
1720
|
-
*
|
|
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)
|
|
1721
2097
|
*/
|
|
1722
2098
|
readonly capabilities: IStrategyCapabilities;
|
|
1723
2099
|
/**
|
|
1724
|
-
*
|
|
1725
|
-
*
|
|
1726
|
-
* Accepts any integer `>= 1` as a page size, plus `-1` which nestjs-paginate
|
|
1727
|
-
* interprets as "fetch all items" (server must opt-in via `maxLimit: -1`).
|
|
2100
|
+
* Directus-native name of the metadata query key
|
|
1728
2101
|
*
|
|
1729
|
-
*
|
|
1730
|
-
*
|
|
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.
|
|
1731
2104
|
*/
|
|
1732
|
-
|
|
2105
|
+
private static readonly _metaKey;
|
|
1733
2106
|
/**
|
|
1734
|
-
* Emit
|
|
1735
|
-
*
|
|
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.
|
|
1736
2113
|
*
|
|
1737
2114
|
* @param state - The current query builder state
|
|
1738
2115
|
* @param options - The query parameter key name configuration
|
|
@@ -1740,7 +2117,31 @@ declare class NestjsRequestStrategy extends AbstractRequestStrategy {
|
|
|
1740
2117
|
*/
|
|
1741
2118
|
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
1742
2119
|
/**
|
|
1743
|
-
* 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.
|
|
2130
|
+
*
|
|
2131
|
+
* @param state - The current query builder state
|
|
2132
|
+
* @param options - The query parameter key name configuration
|
|
2133
|
+
* @param out - The accumulator the caller joins into the URI
|
|
2134
|
+
*/
|
|
2135
|
+
private _appendFields;
|
|
2136
|
+
/**
|
|
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.
|
|
1744
2145
|
*
|
|
1745
2146
|
* @param state - The current query builder state
|
|
1746
2147
|
* @param options - The query parameter key name configuration
|
|
@@ -1756,25 +2157,26 @@ declare class NestjsRequestStrategy extends AbstractRequestStrategy {
|
|
|
1756
2157
|
*/
|
|
1757
2158
|
private _appendLimit;
|
|
1758
2159
|
/**
|
|
1759
|
-
* Append
|
|
2160
|
+
* Append the constant `meta=total_count,filter_count` parameter
|
|
1760
2161
|
*
|
|
1761
|
-
*
|
|
2162
|
+
* Always emitted: the Directus response strategy reads the totals from
|
|
2163
|
+
* `meta`, which the server only includes when the request asks for it.
|
|
1762
2164
|
*
|
|
1763
|
-
* @param state - The current query builder state
|
|
1764
|
-
* @param options - The query parameter key name configuration
|
|
1765
2165
|
* @param out - The accumulator the caller joins into the URI
|
|
1766
2166
|
*/
|
|
1767
|
-
private
|
|
2167
|
+
private _appendMeta;
|
|
1768
2168
|
/**
|
|
1769
2169
|
* Append the page parameter
|
|
1770
2170
|
*
|
|
2171
|
+
* Directus pages are 1-indexed, matching the library state directly.
|
|
2172
|
+
*
|
|
1771
2173
|
* @param state - The current query builder state
|
|
1772
2174
|
* @param options - The query parameter key name configuration
|
|
1773
2175
|
* @param out - The accumulator the caller joins into the URI
|
|
1774
2176
|
*/
|
|
1775
2177
|
private _appendPage;
|
|
1776
2178
|
/**
|
|
1777
|
-
* Append the search
|
|
2179
|
+
* Append the `search=` global full-text search parameter
|
|
1778
2180
|
*
|
|
1779
2181
|
* @param state - The current query builder state
|
|
1780
2182
|
* @param options - The query parameter key name configuration
|
|
@@ -1782,55 +2184,1954 @@ declare class NestjsRequestStrategy extends AbstractRequestStrategy {
|
|
|
1782
2184
|
*/
|
|
1783
2185
|
private _appendSearch;
|
|
1784
2186
|
/**
|
|
1785
|
-
* Append the
|
|
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
|
-
private
|
|
2193
|
+
private _appendSort;
|
|
1792
2194
|
/**
|
|
1793
|
-
*
|
|
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;
|
|
2221
|
+
}
|
|
2222
|
+
|
|
2223
|
+
/**
|
|
2224
|
+
* Response strategy for the Directus driver
|
|
2225
|
+
*
|
|
2226
|
+
* Parses Directus collection responses (with `meta=total_count,filter_count`
|
|
2227
|
+
* requested, which the request strategy always does):
|
|
2228
|
+
*
|
|
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
|
|
2257
|
+
*/
|
|
2258
|
+
declare class DirectusResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
2259
|
+
/**
|
|
2260
|
+
* Parse a Directus collection response into a PaginatedCollection
|
|
2261
|
+
*
|
|
2262
|
+
* @param response - The raw API response body
|
|
2263
|
+
* @param options - The response key name configuration (dot-notation paths supported)
|
|
2264
|
+
* @returns A typed PaginatedCollection instance
|
|
2265
|
+
*/
|
|
2266
|
+
paginate<T extends IPaginatedObject>(response: Record<string, any>, options: ResponseOptions): PaginatedCollection<T>;
|
|
2267
|
+
/**
|
|
2268
|
+
* Derive the last page number
|
|
2269
|
+
*
|
|
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.
|
|
2273
|
+
*
|
|
2274
|
+
* @param response - The raw response object
|
|
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
|
|
2280
|
+
*/
|
|
2281
|
+
private _deriveLastPage;
|
|
2282
|
+
/**
|
|
2283
|
+
* Derive `from` for a response that holds the whole filtered set
|
|
2284
|
+
*
|
|
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
|
|
2288
|
+
*/
|
|
2289
|
+
private _singlePageFrom;
|
|
2290
|
+
/**
|
|
2291
|
+
* Derive `to` for a response that holds the whole filtered set
|
|
2292
|
+
*
|
|
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
|
|
2296
|
+
*/
|
|
2297
|
+
private _singlePageTo;
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2300
|
+
/**
|
|
2301
|
+
* Request strategy for the Django REST Framework (DRF) driver
|
|
2302
|
+
*
|
|
2303
|
+
* Generates URIs in DRF's flat query-parameter format, augmented by
|
|
2304
|
+
* django-filter's double-underscore lookup convention:
|
|
2305
|
+
*
|
|
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)
|
|
2313
|
+
*
|
|
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`.
|
|
2320
|
+
*
|
|
2321
|
+
* @see https://www.django-rest-framework.org/api-guide/filtering/
|
|
2322
|
+
* @see https://django-filter.readthedocs.io/
|
|
2323
|
+
*/
|
|
2324
|
+
declare class DrfRequestStrategy extends AbstractRequestStrategy {
|
|
2325
|
+
/**
|
|
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)
|
|
2329
|
+
*/
|
|
2330
|
+
readonly capabilities: IStrategyCapabilities;
|
|
2331
|
+
/**
|
|
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
|
|
2345
|
+
*
|
|
2346
|
+
* @param state - The current query builder state
|
|
2347
|
+
* @param options - The query parameter key name configuration
|
|
2348
|
+
* @returns Ordered query-string fragments
|
|
2349
|
+
*/
|
|
2350
|
+
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
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
|
|
1794
2399
|
*
|
|
1795
2400
|
* @param state - The current query builder state
|
|
1796
2401
|
* @param options - The query parameter key name configuration
|
|
1797
2402
|
* @param out - The accumulator the caller joins into the URI
|
|
1798
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
|
+
*/
|
|
1799
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;
|
|
1800
2693
|
}
|
|
1801
2694
|
|
|
1802
2695
|
/**
|
|
1803
|
-
* Response strategy for the
|
|
2696
|
+
* Response strategy for the FeathersJS driver
|
|
2697
|
+
*
|
|
2698
|
+
* Parses the paginated envelope emitted by Feathers database adapters:
|
|
1804
2699
|
*
|
|
1805
|
-
* Parses nested NestJS pagination responses:
|
|
1806
2700
|
* ```json
|
|
1807
2701
|
* {
|
|
1808
|
-
* "
|
|
1809
|
-
* "
|
|
1810
|
-
*
|
|
1811
|
-
*
|
|
1812
|
-
*
|
|
1813
|
-
*
|
|
1814
|
-
*
|
|
1815
|
-
*
|
|
1816
|
-
*
|
|
1817
|
-
*
|
|
1818
|
-
*
|
|
1819
|
-
*
|
|
1820
|
-
*
|
|
1821
|
-
*
|
|
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,
|
|
3113
|
+
* NestJS, Strapi) extend `AbstractDotPathResponseStrategy` instead.
|
|
3114
|
+
* Drivers whose metadata comes from HTTP headers (PostgREST) or is
|
|
3115
|
+
* derived from response URLs (DRF) implement `IResponseStrategy`
|
|
3116
|
+
* directly.
|
|
3117
|
+
*/
|
|
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 {
|
|
3171
|
+
/**
|
|
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`.
|
|
3419
|
+
*
|
|
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
|
|
3426
|
+
*/
|
|
3427
|
+
private _formatOperatorCondition;
|
|
3428
|
+
}
|
|
3429
|
+
|
|
3430
|
+
/**
|
|
3431
|
+
* Response strategy for the @nestjsx/crud driver
|
|
3432
|
+
*
|
|
3433
|
+
* Parses @nestjsx/crud's `getMany` envelope:
|
|
3434
|
+
* ```json
|
|
3435
|
+
* {
|
|
3436
|
+
* "data": [{ "id": 1, "name": "John" }],
|
|
3437
|
+
* "count": 10,
|
|
3438
|
+
* "total": 48,
|
|
3439
|
+
* "page": 2,
|
|
3440
|
+
* "pageCount": 5
|
|
3441
|
+
* }
|
|
3442
|
+
* ```
|
|
3443
|
+
*
|
|
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
|
|
3462
|
+
*/
|
|
3463
|
+
declare class NestjsxCrudResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
3464
|
+
}
|
|
3465
|
+
|
|
3466
|
+
/**
|
|
3467
|
+
* Request strategy for the OData v4 driver
|
|
3468
|
+
*
|
|
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
|
|
3495
|
+
*/
|
|
3496
|
+
declare class OdataRequestStrategy extends AbstractRequestStrategy {
|
|
3497
|
+
/**
|
|
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)
|
|
3501
|
+
*/
|
|
3502
|
+
readonly capabilities: IStrategyCapabilities;
|
|
3503
|
+
/**
|
|
3504
|
+
* OData-native names of the system query options
|
|
3505
|
+
*
|
|
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.
|
|
3509
|
+
*/
|
|
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;
|
|
3518
|
+
/**
|
|
3519
|
+
* Emit OData-format query-string segments in canonical order:
|
|
3520
|
+
* $filter → $orderby → $select → $expand → $search → $count → $top → $skip
|
|
3521
|
+
*
|
|
3522
|
+
* @param state - The current query builder state
|
|
3523
|
+
* @param _options - The query parameter key name configuration (unused —
|
|
3524
|
+
* every OData system query option name is fixed by the specification)
|
|
3525
|
+
* @returns Ordered query-string fragments
|
|
3526
|
+
*/
|
|
3527
|
+
protected parts(state: IQueryBuilderState, _options: QueryBuilderOptions): string[];
|
|
3528
|
+
/**
|
|
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.
|
|
3534
|
+
*
|
|
3535
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3536
|
+
*/
|
|
3537
|
+
private _appendCount;
|
|
3538
|
+
/**
|
|
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.
|
|
3547
|
+
*
|
|
3548
|
+
* @param state - The current query builder state
|
|
3549
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3550
|
+
*/
|
|
3551
|
+
private _appendExpand;
|
|
3552
|
+
/**
|
|
3553
|
+
* Append the single `$filter=` parameter combining simple and operator
|
|
3554
|
+
* filters
|
|
3555
|
+
*
|
|
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')`).
|
|
3559
|
+
*
|
|
3560
|
+
* @param state - The current query builder state
|
|
3561
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3562
|
+
*/
|
|
3563
|
+
private _appendFilter;
|
|
3564
|
+
/**
|
|
3565
|
+
* Append the `$orderby=field asc,other desc` CSV parameter
|
|
3566
|
+
*
|
|
3567
|
+
* @param state - The current query builder state
|
|
3568
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3569
|
+
*/
|
|
3570
|
+
private _appendOrderby;
|
|
3571
|
+
/**
|
|
3572
|
+
* Append the `$search=` free-text search parameter
|
|
3573
|
+
*
|
|
3574
|
+
* @param state - The current query builder state
|
|
3575
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3576
|
+
*/
|
|
3577
|
+
private _appendSearch;
|
|
3578
|
+
/**
|
|
3579
|
+
* Append the `$select=col1,col2` projection parameter
|
|
3580
|
+
*
|
|
3581
|
+
* @param state - The current query builder state
|
|
3582
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3583
|
+
*/
|
|
3584
|
+
private _appendSelect;
|
|
3585
|
+
/**
|
|
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
|
|
3858
|
+
*
|
|
3859
|
+
* @param state - The current query builder state
|
|
3860
|
+
* @param out - The accumulator the caller joins into the URI
|
|
3861
|
+
*/
|
|
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;
|
|
3907
|
+
}
|
|
3908
|
+
|
|
3909
|
+
/**
|
|
3910
|
+
* Response strategy for the Payload CMS driver
|
|
3911
|
+
*
|
|
3912
|
+
* Parses Payload's paginated collection responses — the
|
|
3913
|
+
* `mongoose-paginate-v2` envelope, shared by many Express/Mongoose
|
|
3914
|
+
* backends:
|
|
3915
|
+
* ```json
|
|
3916
|
+
* {
|
|
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
|
|
3927
|
+
* }
|
|
3928
|
+
* ```
|
|
3929
|
+
*
|
|
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.
|
|
3941
|
+
*
|
|
3942
|
+
* @see https://payloadcms.com/docs/rest-api/overview
|
|
3943
|
+
*/
|
|
3944
|
+
declare class PayloadResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
3945
|
+
}
|
|
3946
|
+
|
|
3947
|
+
/**
|
|
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
|
|
3973
|
+
* `UnsupportedFilterOperatorError`.
|
|
3974
|
+
*
|
|
3975
|
+
* @see https://pocketbase.io/docs/api-records/
|
|
3976
|
+
*/
|
|
3977
|
+
declare class PocketbaseRequestStrategy extends AbstractRequestStrategy {
|
|
3978
|
+
/**
|
|
3979
|
+
* Filters, operator filters, sorts, expand (`includes`), flat field
|
|
3980
|
+
* selection (`select`) — no per-model fields, no global search, no
|
|
3981
|
+
* embedded resources
|
|
3982
|
+
*/
|
|
3983
|
+
readonly capabilities: IStrategyCapabilities;
|
|
3984
|
+
/**
|
|
3985
|
+
* PocketBase-native names of the six hardcoded query keys
|
|
3986
|
+
*
|
|
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.
|
|
3990
|
+
*/
|
|
3991
|
+
private static readonly _expandKey;
|
|
3992
|
+
private static readonly _fieldsKey;
|
|
3993
|
+
private static readonly _filterKey;
|
|
3994
|
+
private static readonly _pageKey;
|
|
3995
|
+
private static readonly _perPageKey;
|
|
3996
|
+
private static readonly _sortKey;
|
|
3997
|
+
/**
|
|
3998
|
+
* Emit PocketBase-format query-string segments in canonical order:
|
|
3999
|
+
* expand → fields → filter (merged) → sort → page → perPage
|
|
4000
|
+
*
|
|
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.
|
|
4004
|
+
*
|
|
4005
|
+
* @param state - The current query builder state
|
|
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
|
|
4009
|
+
*/
|
|
4010
|
+
protected parts(state: IQueryBuilderState, _options: QueryBuilderOptions): string[];
|
|
4011
|
+
/**
|
|
4012
|
+
* Append the `expand=` CSV from the includes array
|
|
4013
|
+
*
|
|
4014
|
+
* Nested expansion (`author.address`) passes through verbatim when
|
|
4015
|
+
* given as a dotted include name.
|
|
4016
|
+
*
|
|
4017
|
+
* @param state - The current query builder state
|
|
4018
|
+
* @param out - The accumulator the caller joins into the URI
|
|
4019
|
+
*/
|
|
4020
|
+
private _appendExpand;
|
|
4021
|
+
/**
|
|
4022
|
+
* Append the `fields=` CSV from the flat select array
|
|
4023
|
+
*
|
|
4024
|
+
* @param state - The current query builder state
|
|
4025
|
+
* @param out - The accumulator the caller joins into the URI
|
|
4026
|
+
*/
|
|
4027
|
+
private _appendFields;
|
|
4028
|
+
/**
|
|
4029
|
+
* Append the single `filter=(...)` expression combining simple
|
|
4030
|
+
* filters and operator filters
|
|
4031
|
+
*
|
|
4032
|
+
* Clauses join with ` && `; multi-value clauses keep their own
|
|
4033
|
+
* parentheses so OR groups stay correctly scoped inside the AND
|
|
4034
|
+
* chain.
|
|
4035
|
+
*
|
|
4036
|
+
* @param state - The current query builder state
|
|
4037
|
+
* @param out - The accumulator the caller joins into the URI
|
|
4038
|
+
*/
|
|
4039
|
+
private _appendFilter;
|
|
4040
|
+
/**
|
|
4041
|
+
* Append the `page=` / `perPage=` pagination pair
|
|
4042
|
+
*
|
|
4043
|
+
* @param state - The current query builder state
|
|
4044
|
+
* @param out - The accumulator the caller joins into the URI
|
|
4045
|
+
*/
|
|
4046
|
+
private _appendPagination;
|
|
4047
|
+
/**
|
|
4048
|
+
* Append the `sort=-created,title` CSV parameter
|
|
4049
|
+
*
|
|
4050
|
+
* @param state - The current query builder state
|
|
4051
|
+
* @param out - The accumulator the caller joins into the URI
|
|
4052
|
+
*/
|
|
4053
|
+
private _appendSort;
|
|
4054
|
+
/**
|
|
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
|
|
4069
|
+
*
|
|
4070
|
+
* PostgREST's full-text-search operators (`FTS`, `PHFTS`, `PLFTS`,
|
|
4071
|
+
* `WFTS`) have no PocketBase equivalent and throw
|
|
4072
|
+
* `UnsupportedFilterOperatorError`.
|
|
4073
|
+
*
|
|
4074
|
+
* @param filter - The operator filter to translate
|
|
4075
|
+
* @returns One expression clause ready to join into `filter=(...)`
|
|
4076
|
+
* @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
|
|
4077
|
+
* exactly two values, or `NULL` does not receive exactly one boolean
|
|
4078
|
+
* @throws {UnsupportedFilterOperatorError} If the operator is a
|
|
4079
|
+
* PostgREST-only FTS variant
|
|
4080
|
+
*/
|
|
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;
|
|
4100
|
+
}
|
|
4101
|
+
|
|
4102
|
+
/**
|
|
4103
|
+
* Response strategy for the PocketBase driver
|
|
4104
|
+
*
|
|
4105
|
+
* Parses PocketBase records-list responses:
|
|
4106
|
+
* ```json
|
|
4107
|
+
* {
|
|
4108
|
+
* "page": 1,
|
|
4109
|
+
* "perPage": 30,
|
|
4110
|
+
* "totalItems": 48,
|
|
4111
|
+
* "totalPages": 2,
|
|
4112
|
+
* "items": [{ "id": "abc123", "title": "Hello" }]
|
|
1822
4113
|
* }
|
|
1823
4114
|
* ```
|
|
1824
4115
|
*
|
|
1825
|
-
* Default key paths are configured in `
|
|
1826
|
-
*
|
|
1827
|
-
*
|
|
1828
|
-
*
|
|
1829
|
-
*
|
|
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
|
|
4124
|
+
* layer even though the parsing logic is shared with JSON:API, NestJS,
|
|
4125
|
+
* and Strapi.
|
|
1830
4126
|
*
|
|
1831
|
-
*
|
|
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/
|
|
1832
4133
|
*/
|
|
1833
|
-
declare class
|
|
4134
|
+
declare class PocketbaseResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
1834
4135
|
}
|
|
1835
4136
|
|
|
1836
4137
|
/**
|
|
@@ -1975,10 +4276,17 @@ declare class PostgrestRequestStrategy extends AbstractRequestStrategy {
|
|
|
1975
4276
|
*/
|
|
1976
4277
|
private _appendOrder;
|
|
1977
4278
|
/**
|
|
1978
|
-
* Append the select parameter as `select=col1,col2`
|
|
4279
|
+
* Append the select parameter as `select=col1,col2,rel(col1,col2)`
|
|
4280
|
+
*
|
|
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`.
|
|
1979
4285
|
*
|
|
1980
|
-
*
|
|
1981
|
-
*
|
|
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.
|
|
1982
4290
|
*
|
|
1983
4291
|
* @param state - The current query builder state
|
|
1984
4292
|
* @param options - The query parameter key name configuration
|
|
@@ -2032,6 +4340,154 @@ declare class PostgrestResponseStrategy implements IResponseStrategy {
|
|
|
2032
4340
|
private _parseContentRange;
|
|
2033
4341
|
}
|
|
2034
4342
|
|
|
4343
|
+
/**
|
|
4344
|
+
* Request strategy for the Sieve (.NET) driver
|
|
4345
|
+
*
|
|
4346
|
+
* Generates URIs in [Sieve's compact expression format](https://github.com/Biarity/Sieve):
|
|
4347
|
+
* - Filters: a single `filters=` parameter holding comma-joined (AND)
|
|
4348
|
+
* `Field{op}Value` terms; multi-value terms use the pipe (OR) on the
|
|
4349
|
+
* value side (`status==active|pending`)
|
|
4350
|
+
* - Operator filters: translated from `FilterOperatorEnum` — see the
|
|
4351
|
+
* mapping on `_formatOperatorTerms`
|
|
4352
|
+
* - Sorts: `sorts=field,-other` (CSV, `-` prefix = DESC)
|
|
4353
|
+
* - Pagination: `page=N&pageSize=N`
|
|
4354
|
+
*
|
|
4355
|
+
* Sieve has no per-model field selection, no relation includes, no flat
|
|
4356
|
+
* column selection, and no global search parameter — the corresponding
|
|
4357
|
+
* fluent methods throw the matching `Unsupported*Error`. PostgREST-native
|
|
4358
|
+
* full-text search operators (`FTS`, `PHFTS`, `PLFTS`, `WFTS`) throw
|
|
4359
|
+
* `UnsupportedFilterOperatorError`.
|
|
4360
|
+
*
|
|
4361
|
+
* @see https://github.com/Biarity/Sieve
|
|
4362
|
+
*/
|
|
4363
|
+
declare class SieveRequestStrategy extends AbstractRequestStrategy {
|
|
4364
|
+
/**
|
|
4365
|
+
* Filters, operator filters, sorts — no per-model fields, no includes,
|
|
4366
|
+
* no flat select, no global search (use `CONTAINS` / `ILIKE` operator
|
|
4367
|
+
* filters for partial matches)
|
|
4368
|
+
*/
|
|
4369
|
+
readonly capabilities: IStrategyCapabilities;
|
|
4370
|
+
/**
|
|
4371
|
+
* Sieve-native names of the three hardcoded query keys
|
|
4372
|
+
*
|
|
4373
|
+
* Sieve's model binder reads `filters`, `sorts`, and `pageSize` (the
|
|
4374
|
+
* plural forms differ from the library-wide `filter` / `sort` /
|
|
4375
|
+
* `limit` defaults); these keys are intentionally not configurable
|
|
4376
|
+
* through `QueryBuilderOptions` and live as private statics so they
|
|
4377
|
+
* are visible in one place.
|
|
4378
|
+
*/
|
|
4379
|
+
private static readonly _filtersKey;
|
|
4380
|
+
private static readonly _pageSizeKey;
|
|
4381
|
+
private static readonly _sortsKey;
|
|
4382
|
+
/**
|
|
4383
|
+
* Emit Sieve-format query-string segments in canonical order:
|
|
4384
|
+
* filters → sorts → page → pageSize
|
|
4385
|
+
*
|
|
4386
|
+
* @param state - The current query builder state
|
|
4387
|
+
* @param options - The query parameter key name configuration (used
|
|
4388
|
+
* for `page`, whose default matches the wire format; the `filters` /
|
|
4389
|
+
* `sorts` / `pageSize` keys are fixed by the server)
|
|
4390
|
+
* @returns Ordered query-string fragments
|
|
4391
|
+
*/
|
|
4392
|
+
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
4393
|
+
/**
|
|
4394
|
+
* Append the single `filters=` parameter combining simple and operator
|
|
4395
|
+
* filters
|
|
4396
|
+
*
|
|
4397
|
+
* Each term is one `Field{op}Value` expression; terms join with the
|
|
4398
|
+
* comma (Sieve's AND). Simple single-value filters fold to `==`;
|
|
4399
|
+
* simple multi-value filters fold to a value-level pipe OR
|
|
4400
|
+
* (`field==v1|v2`).
|
|
4401
|
+
*
|
|
4402
|
+
* @param state - The current query builder state
|
|
4403
|
+
* @param out - The accumulator the caller joins into the URI
|
|
4404
|
+
*/
|
|
4405
|
+
private _appendFilters;
|
|
4406
|
+
/**
|
|
4407
|
+
* Append the page parameter
|
|
4408
|
+
*
|
|
4409
|
+
* @param state - The current query builder state
|
|
4410
|
+
* @param options - The query parameter key name configuration
|
|
4411
|
+
* @param out - The accumulator the caller joins into the URI
|
|
4412
|
+
*/
|
|
4413
|
+
private _appendPage;
|
|
4414
|
+
/**
|
|
4415
|
+
* Append the pageSize parameter
|
|
4416
|
+
*
|
|
4417
|
+
* @param state - The current query builder state
|
|
4418
|
+
* @param out - The accumulator the caller joins into the URI
|
|
4419
|
+
*/
|
|
4420
|
+
private _appendPageSize;
|
|
4421
|
+
/**
|
|
4422
|
+
* Append the `sorts=field,-other` CSV parameter
|
|
4423
|
+
*
|
|
4424
|
+
* @param state - The current query builder state
|
|
4425
|
+
* @param out - The accumulator the caller joins into the URI
|
|
4426
|
+
*/
|
|
4427
|
+
private _appendSorts;
|
|
4428
|
+
/**
|
|
4429
|
+
* Translate a `FilterOperatorEnum` operator filter into one or more
|
|
4430
|
+
* Sieve `Field{op}Value` terms
|
|
4431
|
+
*
|
|
4432
|
+
* The mapping is library-canonical → Sieve-native:
|
|
4433
|
+
* - `EQ` → `==`; `GT`/`GTE`/`LT`/`LTE` → `>` / `>=` / `<` / `<=`
|
|
4434
|
+
* - `CONTAINS` → `@=`; `ILIKE` → `@=*` (case-insensitive contains)
|
|
4435
|
+
* - `SW` → `_=` (starts with)
|
|
4436
|
+
* - `IN` → `==` with a value-level pipe OR (`field==v1|v2`)
|
|
4437
|
+
* - `BTW` → **two** AND-ed terms (`field>=min` and `field<=max`,
|
|
4438
|
+
* arity-checked)
|
|
4439
|
+
* - `NOT` → `!=` — one term per value, AND-ed (`field!=v1,field!=v2`)
|
|
4440
|
+
* - `NULL` → `==null` (when value is `true`) / `!=null` (when value is
|
|
4441
|
+
* `false`); arity- and type-checked
|
|
4442
|
+
*
|
|
4443
|
+
* PostgREST's full-text-search operators (`FTS`, `PHFTS`, `PLFTS`,
|
|
4444
|
+
* `WFTS`) have no Sieve equivalent and throw
|
|
4445
|
+
* `UnsupportedFilterOperatorError`.
|
|
4446
|
+
*
|
|
4447
|
+
* @param filter - The operator filter to translate
|
|
4448
|
+
* @returns One or more `Field{op}Value` terms ready to AND-join
|
|
4449
|
+
* @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
|
|
4450
|
+
* exactly two values, or `NULL` does not receive exactly one boolean
|
|
4451
|
+
* @throws {UnsupportedFilterOperatorError} If the operator is a
|
|
4452
|
+
* PostgREST-only FTS variant
|
|
4453
|
+
*/
|
|
4454
|
+
private _formatOperatorTerms;
|
|
4455
|
+
}
|
|
4456
|
+
|
|
4457
|
+
/**
|
|
4458
|
+
* Response strategy for the Sieve (.NET) driver
|
|
4459
|
+
*
|
|
4460
|
+
* Sieve itself does not define a response envelope — it returns an
|
|
4461
|
+
* `IQueryable` that the ASP.NET developer wraps in a paging DTO of their
|
|
4462
|
+
* choosing. This strategy therefore ships a **sensible default mapping**
|
|
4463
|
+
* for the common hand-rolled `PagedResult<T>` shape:
|
|
4464
|
+
* ```json
|
|
4465
|
+
* {
|
|
4466
|
+
* "data": [{ "id": 1, "title": "Hello" }],
|
|
4467
|
+
* "page": 2,
|
|
4468
|
+
* "pageSize": 10,
|
|
4469
|
+
* "total": 48,
|
|
4470
|
+
* "totalPages": 5
|
|
4471
|
+
* }
|
|
4472
|
+
* ```
|
|
4473
|
+
*
|
|
4474
|
+
* Every key path is configurable through `IConfig.response` (dot
|
|
4475
|
+
* notation supported), so any wrapper shape — `{ items, meta: {...} }`,
|
|
4476
|
+
* `{ results, pagination: {...} }` — can be mapped without subclassing.
|
|
4477
|
+
* Defaults are encoded in `SieveResponseOptions`. `from`/`to` are
|
|
4478
|
+
* computed from `page` × `pageSize` by the inherited traversal
|
|
4479
|
+
* algorithm, and the navigation-URL slots resolve to `undefined` unless
|
|
4480
|
+
* paths are provided.
|
|
4481
|
+
*
|
|
4482
|
+
* The dot-notation traversal is inherited from
|
|
4483
|
+
* `AbstractDotPathResponseStrategy`; this class exists so
|
|
4484
|
+
* `DriverEnum.SIEVE` resolves to a distinct identity at the DI layer.
|
|
4485
|
+
*
|
|
4486
|
+
* @see https://github.com/Biarity/Sieve
|
|
4487
|
+
*/
|
|
4488
|
+
declare class SieveResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
4489
|
+
}
|
|
4490
|
+
|
|
2035
4491
|
/**
|
|
2036
4492
|
* Request strategy for the Spatie Query Builder driver
|
|
2037
4493
|
*
|
|
@@ -2141,6 +4597,155 @@ declare class SpatieRequestStrategy extends AbstractRequestStrategy {
|
|
|
2141
4597
|
declare class SpatieResponseStrategy extends AbstractFlatResponseStrategy {
|
|
2142
4598
|
}
|
|
2143
4599
|
|
|
4600
|
+
/**
|
|
4601
|
+
* Request strategy for the Spring Data REST driver
|
|
4602
|
+
*
|
|
4603
|
+
* Generates URIs in [Spring Data REST's pagination format](https://docs.spring.io/spring-data/rest/reference/paging-and-sorting.html):
|
|
4604
|
+
* - Sorts: `sort=field,asc&sort=other,desc` (repeatable param, one per rule)
|
|
4605
|
+
* - Pagination: `page=N&size=N` — **`page` is 0-indexed on the wire**;
|
|
4606
|
+
* the library state stays 1-indexed and the strategy subtracts 1 at
|
|
4607
|
+
* emission time
|
|
4608
|
+
*
|
|
4609
|
+
* Spring Data REST defines no standard query parameter convention for
|
|
4610
|
+
* filtering, field selection, includes, or global search — those are
|
|
4611
|
+
* implemented server-side via custom query methods or Specifications.
|
|
4612
|
+
* The corresponding fluent methods (`addFilter`, `addFilterOperator`,
|
|
4613
|
+
* `addSelect`, `addFields`, `addIncludes`, `setSearch`) throw the
|
|
4614
|
+
* matching `Unsupported*Error` on this driver.
|
|
4615
|
+
*
|
|
4616
|
+
* @see https://docs.spring.io/spring-data/rest/reference/paging-and-sorting.html
|
|
4617
|
+
*/
|
|
4618
|
+
declare class SpringRequestStrategy extends AbstractRequestStrategy {
|
|
4619
|
+
/**
|
|
4620
|
+
* Sorts only — Spring Data REST has no standard wire convention for
|
|
4621
|
+
* filters, operator filters, per-model fields, flat select, includes,
|
|
4622
|
+
* or global search
|
|
4623
|
+
*/
|
|
4624
|
+
readonly capabilities: IStrategyCapabilities;
|
|
4625
|
+
/**
|
|
4626
|
+
* Spring-native name of the hardcoded page-size query key
|
|
4627
|
+
*
|
|
4628
|
+
* The wire format is fixed (Spring's `PageableHandlerMethodArgumentResolver`
|
|
4629
|
+
* reads `size` by default); the key is intentionally not configurable
|
|
4630
|
+
* through `QueryBuilderOptions` and lives as a private static so it is
|
|
4631
|
+
* visible in one place.
|
|
4632
|
+
*/
|
|
4633
|
+
private static readonly _sizeKey;
|
|
4634
|
+
/**
|
|
4635
|
+
* Emit Spring-format query-string segments in canonical order:
|
|
4636
|
+
* sort → page → size
|
|
4637
|
+
*
|
|
4638
|
+
* @param state - The current query builder state
|
|
4639
|
+
* @param options - The query parameter key name configuration (used
|
|
4640
|
+
* for `page` and `sort`, whose defaults match the wire format; the
|
|
4641
|
+
* `size` key is fixed by the server)
|
|
4642
|
+
* @returns Ordered query-string fragments
|
|
4643
|
+
*/
|
|
4644
|
+
protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
|
|
4645
|
+
/**
|
|
4646
|
+
* Append the 0-indexed page parameter
|
|
4647
|
+
*
|
|
4648
|
+
* The library state is 1-indexed (page 1 is the first page); Spring's
|
|
4649
|
+
* `page` request parameter is 0-indexed, so the strategy subtracts 1
|
|
4650
|
+
* at emission time.
|
|
4651
|
+
*
|
|
4652
|
+
* @param state - The current query builder state
|
|
4653
|
+
* @param options - The query parameter key name configuration
|
|
4654
|
+
* @param out - The accumulator the caller joins into the URI
|
|
4655
|
+
*/
|
|
4656
|
+
private _appendPage;
|
|
4657
|
+
/**
|
|
4658
|
+
* Append the size parameter
|
|
4659
|
+
*
|
|
4660
|
+
* @param state - The current query builder state
|
|
4661
|
+
* @param out - The accumulator the caller joins into the URI
|
|
4662
|
+
*/
|
|
4663
|
+
private _appendSize;
|
|
4664
|
+
/**
|
|
4665
|
+
* Append `sort=field,asc` params, one per sort rule (repeatable)
|
|
4666
|
+
*
|
|
4667
|
+
* Spring parses each `sort` occurrence independently — multiple rules
|
|
4668
|
+
* are expressed by repeating the parameter, not by comma-joining the
|
|
4669
|
+
* fields.
|
|
4670
|
+
*
|
|
4671
|
+
* @param state - The current query builder state
|
|
4672
|
+
* @param options - The query parameter key name configuration
|
|
4673
|
+
* @param out - The accumulator the caller joins into the URI
|
|
4674
|
+
*/
|
|
4675
|
+
private _appendSort;
|
|
4676
|
+
}
|
|
4677
|
+
|
|
4678
|
+
/**
|
|
4679
|
+
* Response strategy for the Spring Data REST driver
|
|
4680
|
+
*
|
|
4681
|
+
* Parses Spring Data REST's HAL envelope:
|
|
4682
|
+
* ```json
|
|
4683
|
+
* {
|
|
4684
|
+
* "_embedded": { "users": [{ "id": 1, "name": "John" }] },
|
|
4685
|
+
* "_links": {
|
|
4686
|
+
* "first": { "href": "..." },
|
|
4687
|
+
* "prev": { "href": "..." },
|
|
4688
|
+
* "next": { "href": "..." },
|
|
4689
|
+
* "last": { "href": "..." }
|
|
4690
|
+
* },
|
|
4691
|
+
* "page": { "size": 20, "totalElements": 100, "totalPages": 5, "number": 1 }
|
|
4692
|
+
* }
|
|
4693
|
+
* ```
|
|
4694
|
+
*
|
|
4695
|
+
* Two HAL quirks are absorbed here on top of the inherited dot-path
|
|
4696
|
+
* traversal:
|
|
4697
|
+
*
|
|
4698
|
+
* - **`page.number` is 0-indexed** — the strategy adds 1 so the library
|
|
4699
|
+
* state stays 1-indexed (mirroring `SpringRequestStrategy`, which
|
|
4700
|
+
* subtracts 1 on the way out).
|
|
4701
|
+
* - **The collection key under `_embedded` is the resource rel name**
|
|
4702
|
+
* (e.g. `_embedded.users`), which cannot be known statically. The
|
|
4703
|
+
* default `data` path is plain `_embedded`; when it resolves to an
|
|
4704
|
+
* object rather than an array, the strategy picks the first array
|
|
4705
|
+
* value inside it. Consumers with multiple embedded rels can pin the
|
|
4706
|
+
* exact path via `IConfig.response` (e.g. `data: '_embedded.users'`).
|
|
4707
|
+
*
|
|
4708
|
+
* Default key paths are configured in `SpringResponseOptions`.
|
|
4709
|
+
*
|
|
4710
|
+
* @see https://docs.spring.io/spring-data/rest/reference/paging-and-sorting.html
|
|
4711
|
+
*/
|
|
4712
|
+
declare class SpringResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
4713
|
+
/**
|
|
4714
|
+
* Parse a Spring Data REST HAL response into a PaginatedCollection
|
|
4715
|
+
*
|
|
4716
|
+
* @param response - The raw API response body
|
|
4717
|
+
* @param options - The response key name configuration
|
|
4718
|
+
* @returns A typed PaginatedCollection instance
|
|
4719
|
+
*/
|
|
4720
|
+
paginate<T extends IPaginatedObject>(response: Record<string, any>, options: ResponseOptions): PaginatedCollection<T>;
|
|
4721
|
+
/**
|
|
4722
|
+
* Resolve the 1-indexed current page from the 0-indexed `page.number`
|
|
4723
|
+
*
|
|
4724
|
+
* Falls back to page 1 when the path is missing entirely (defensive —
|
|
4725
|
+
* Spring always emits the `page` block on paged endpoints).
|
|
4726
|
+
*
|
|
4727
|
+
* @param response - The raw response object
|
|
4728
|
+
* @param options - The response key name configuration
|
|
4729
|
+
* @returns The 1-indexed current page number
|
|
4730
|
+
*/
|
|
4731
|
+
private _resolveCurrentPage;
|
|
4732
|
+
/**
|
|
4733
|
+
* Resolve the data array from the HAL `_embedded` wrapper
|
|
4734
|
+
*
|
|
4735
|
+
* When the configured path resolves directly to an array (a consumer
|
|
4736
|
+
* pinned `data: '_embedded.users'`), it is used as-is. When it
|
|
4737
|
+
* resolves to an object (the default `_embedded` path), the first
|
|
4738
|
+
* array value inside it is used — Spring emits exactly one collection
|
|
4739
|
+
* rel per listing endpoint. An empty array is returned when nothing
|
|
4740
|
+
* matches (e.g. Spring omits `_embedded` on empty result sets).
|
|
4741
|
+
*
|
|
4742
|
+
* @param response - The raw response object
|
|
4743
|
+
* @param options - The response key name configuration
|
|
4744
|
+
* @returns The resolved data array (possibly empty)
|
|
4745
|
+
*/
|
|
4746
|
+
private _resolveData;
|
|
4747
|
+
}
|
|
4748
|
+
|
|
2144
4749
|
/**
|
|
2145
4750
|
* Request strategy for the Strapi driver
|
|
2146
4751
|
*
|
|
@@ -2309,5 +4914,241 @@ declare class StrapiRequestStrategy extends AbstractRequestStrategy {
|
|
|
2309
4914
|
declare class StrapiResponseStrategy extends AbstractDotPathResponseStrategy {
|
|
2310
4915
|
}
|
|
2311
4916
|
|
|
2312
|
-
|
|
2313
|
-
|
|
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 };
|