ng-qubee 3.5.0 → 3.6.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.
@@ -50,8 +50,11 @@ declare enum DriverEnum {
50
50
  JSON_API = "json-api",
51
51
  LARAVEL = "laravel",
52
52
  NESTJS = "nestjs",
53
+ NESTJSX_CRUD = "nestjsx-crud",
53
54
  POSTGREST = "postgrest",
55
+ SIEVE = "sieve",
54
56
  SPATIE = "spatie",
57
+ SPRING = "spring",
55
58
  STRAPI = "strapi"
56
59
  }
57
60
 
@@ -1445,6 +1448,274 @@ declare abstract class AbstractRequestStrategy implements IRequestStrategy {
1445
1448
  protected join(base: string, segments: string[]): string;
1446
1449
  }
1447
1450
 
1451
+ /**
1452
+ * Request strategy for the Django REST Framework (DRF) driver
1453
+ *
1454
+ * Generates URIs in DRF's flat query-parameter format, augmented by
1455
+ * django-filter's double-underscore lookup convention:
1456
+ *
1457
+ * - Simple filters: `field=value` (multi-value collapses to `field__in=v1,v2`)
1458
+ * - Operator filters: `field__lookup=value` (translated from
1459
+ * `FilterOperatorEnum` — `GTE`→`__gte`, `ILIKE`→`__icontains`,
1460
+ * `BTW`→`__range`, `NULL`→`__isnull`, etc.)
1461
+ * - Ordering: `ordering=-field1,field2` (`-` prefix = DESC)
1462
+ * - Search: `search=term` (DRF's SearchFilter)
1463
+ * - Pagination: `page=N&page_size=M` (PageNumberPagination)
1464
+ *
1465
+ * `ordering` and `page_size` are DRF-idiomatic param names and are
1466
+ * intentionally not configurable via `QueryBuilderOptions` — same
1467
+ * precedent as PostgREST's `order` and `offset`. PostgREST's full-text
1468
+ * search operators (`FTS`, `PHFTS`, `PLFTS`, `WFTS`) and the generic
1469
+ * `NOT` have no django-filter equivalent and throw
1470
+ * `UnsupportedFilterOperatorError`.
1471
+ *
1472
+ * @see https://www.django-rest-framework.org/api-guide/filtering/
1473
+ * @see https://django-filter.readthedocs.io/
1474
+ */
1475
+ declare class DrfRequestStrategy extends AbstractRequestStrategy {
1476
+ /**
1477
+ * Simple filters, operator filters (django-filter lookups), sorts, and
1478
+ * global search — no per-model fields, no relation includes, no flat
1479
+ * select (django-restql adds it but is not core DRF)
1480
+ */
1481
+ readonly capabilities: IStrategyCapabilities;
1482
+ /**
1483
+ * DRF-native names of the three hardcoded query keys
1484
+ *
1485
+ * `ordering` and `page_size` are DRF/django-filter conventions and are
1486
+ * intentionally not configurable through `QueryBuilderOptions`. `page`
1487
+ * matches the default `QueryBuilderOptions.page`, and `search` matches
1488
+ * the default `QueryBuilderOptions.search`, so those flow through the
1489
+ * shared options object.
1490
+ */
1491
+ private static readonly _orderingKey;
1492
+ private static readonly _pageSizeKey;
1493
+ /**
1494
+ * Emit DRF-format query-string segments in canonical order:
1495
+ * filters → operator filters → ordering → search → pagination
1496
+ *
1497
+ * @param state - The current query builder state
1498
+ * @param options - The query parameter key name configuration
1499
+ * @returns Ordered query-string fragments
1500
+ */
1501
+ protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
1502
+ /**
1503
+ * Append simple filter parameters
1504
+ *
1505
+ * Single-value filters emit `field=value` (django-filter's default
1506
+ * exact match). Multi-value filters collapse to django-filter's
1507
+ * `field__in=v1,v2,v3` form, which is the idiomatic way to express
1508
+ * "value in list" in DRF.
1509
+ *
1510
+ * @param state - The current query builder state
1511
+ * @param out - The accumulator the caller joins into the URI
1512
+ */
1513
+ private _appendFilters;
1514
+ /**
1515
+ * Append operator-filter parameters as `field__lookup=value`
1516
+ *
1517
+ * Maps each `FilterOperatorEnum` value to a django-filter lookup
1518
+ * suffix. `BTW` expands to `field__range=min,max`; `NULL` emits
1519
+ * `field__isnull=true|false`; the generic `NOT` and PostgREST-only
1520
+ * FTS operators are unsupported.
1521
+ *
1522
+ * @param state - The current query builder state
1523
+ * @param out - The accumulator the caller joins into the URI
1524
+ * @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
1525
+ * exactly two values, or `NULL` does not receive exactly one boolean
1526
+ * @throws {UnsupportedFilterOperatorError} If the operator has no
1527
+ * django-filter equivalent
1528
+ */
1529
+ private _appendOperatorFilters;
1530
+ /**
1531
+ * Append `ordering=-field1,field2` (django's `-` prefix = DESC)
1532
+ *
1533
+ * @param state - The current query builder state
1534
+ * @param out - The accumulator the caller joins into the URI
1535
+ */
1536
+ private _appendOrdering;
1537
+ /**
1538
+ * Append `page=N&page_size=M`
1539
+ *
1540
+ * `page` follows `options.page` (default `page`, matching DRF); the
1541
+ * size key is hardcoded to DRF's idiomatic `page_size`.
1542
+ *
1543
+ * @param state - The current query builder state
1544
+ * @param options - The query parameter key name configuration
1545
+ * @param out - The accumulator the caller joins into the URI
1546
+ */
1547
+ private _appendPagination;
1548
+ /**
1549
+ * Append `search=term` when a search term is set
1550
+ *
1551
+ * @param state - The current query builder state
1552
+ * @param options - The query parameter key name configuration
1553
+ * @param out - The accumulator the caller joins into the URI
1554
+ */
1555
+ private _appendSearch;
1556
+ /**
1557
+ * Translate a `FilterOperatorEnum` operator filter into a
1558
+ * `[suffix, serializedValue]` pair
1559
+ *
1560
+ * The suffix is appended to the field name with a `__` separator on the
1561
+ * wire side (`field__gte=18`). The empty string means "no suffix" —
1562
+ * django-filter's implicit `exact` lookup.
1563
+ *
1564
+ * Mapping:
1565
+ * - `EQ` → `''` (no suffix; default exact match)
1566
+ * - `GT`/`GTE`/`LT`/`LTE`/`CONTAINS` → identity (lowercased name)
1567
+ * - `ILIKE` → `icontains` (closest case-insensitive analog)
1568
+ * - `IN` → `in` with comma-joined values
1569
+ * - `SW` → `startswith`
1570
+ * - `BTW` → `range` with comma-joined `[min, max]` (arity-checked)
1571
+ * - `NULL` → `isnull` with boolean value (arity- and type-checked)
1572
+ * - `NOT` → `UnsupportedFilterOperatorError` (no generic negation in
1573
+ * django-filter; use `__exclude` on the queryset instead)
1574
+ * - `FTS`/`PLFTS`/`PHFTS`/`WFTS` → `UnsupportedFilterOperatorError`
1575
+ *
1576
+ * @param filter - The operator filter to translate
1577
+ * @returns A `[lookupSuffix, serializedValue]` tuple
1578
+ * @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
1579
+ * exactly two values, or `NULL` does not receive exactly one boolean
1580
+ * @throws {UnsupportedFilterOperatorError} If the operator has no
1581
+ * django-filter equivalent
1582
+ */
1583
+ private _formatOperatorPayload;
1584
+ }
1585
+
1586
+ /**
1587
+ * Response strategy for the Django REST Framework (DRF) driver
1588
+ *
1589
+ * Parses DRF `PageNumberPagination` responses:
1590
+ *
1591
+ * ```json
1592
+ * {
1593
+ * "count": 100,
1594
+ * "next": "http://api.example.com/items/?page=3",
1595
+ * "previous": "http://api.example.com/items/?page=1",
1596
+ * "results": [...]
1597
+ * }
1598
+ * ```
1599
+ *
1600
+ * DRF emits no `current_page` field in the body, so this strategy
1601
+ * **derives** the current page (and the page size) by inspecting the
1602
+ * `next` / `previous` URLs:
1603
+ *
1604
+ * - `previous === null` → current page is **1**.
1605
+ * - `previous` set but has no `?page=N` param → DRF omits `page=1` from
1606
+ * URLs when the previous page is the first, so we infer **2**.
1607
+ * - `previous` has `?page=N` → current page is **N + 1**.
1608
+ *
1609
+ * Similarly, `perPage` is parsed from any `?page_size=N` query param on
1610
+ * `next` or `previous`, and `lastPage` is computed as
1611
+ * `ceil(count / perPage)`. When `perPage` cannot be discovered (e.g. on a
1612
+ * single-page response that emits both URLs as `null`), `perPage` and
1613
+ * `lastPage` are left undefined.
1614
+ *
1615
+ * Key paths are resolved through `DrfResponseOptions`, which defaults
1616
+ * `data → 'results'`, `total → 'count'`, `nextPageUrl → 'next'`,
1617
+ * `prevPageUrl → 'previous'`. The current-page / per-page / last-page
1618
+ * paths default to empty strings — the strategy ignores `options` for
1619
+ * those slots and uses URL inspection instead.
1620
+ *
1621
+ * @see https://www.django-rest-framework.org/api-guide/pagination/#pagenumberpagination
1622
+ */
1623
+ declare class DrfResponseStrategy implements IResponseStrategy {
1624
+ /**
1625
+ * Parse a DRF pagination response into a PaginatedCollection
1626
+ *
1627
+ * @param response - The raw API response body
1628
+ * @param options - The response key name configuration
1629
+ * @returns A typed PaginatedCollection instance
1630
+ */
1631
+ paginate<T extends IPaginatedObject>(response: Record<string, any>, options: ResponseOptions): PaginatedCollection<T>;
1632
+ /**
1633
+ * Derive the current page number from the `previous` URL
1634
+ *
1635
+ * - `null` → page 1
1636
+ * - URL without `?page=N` → page 2 (DRF omits `page=1` from URLs)
1637
+ * - URL with `?page=N` → N + 1
1638
+ *
1639
+ * @param prevPageUrl - The `previous` link from the DRF response, or null
1640
+ * @returns The current page number
1641
+ */
1642
+ private _deriveCurrentPage;
1643
+ /**
1644
+ * Derive `from` as the 1-indexed offset of the first item on this page
1645
+ *
1646
+ * @param currentPage - The current page number
1647
+ * @param perPage - The page size (may be undefined)
1648
+ * @returns The 1-indexed `from` index, or undefined when perPage is unknown
1649
+ */
1650
+ private _deriveFrom;
1651
+ /**
1652
+ * Derive the last page number as `ceil(total / perPage)`
1653
+ *
1654
+ * Both inputs must be defined; an empty result set (`total === 0`)
1655
+ * yields `lastPage = 0` which the caller treats as "no useful info"
1656
+ * and skips the sync to `NestService.lastPage`.
1657
+ *
1658
+ * @param total - The total item count
1659
+ * @param perPage - The page size
1660
+ * @returns The last page number, or undefined when either input is missing
1661
+ */
1662
+ private _deriveLastPage;
1663
+ /**
1664
+ * Derive `perPage` by parsing `?page_size=N` from any available URL
1665
+ *
1666
+ * Tries `next` first (page 1 always has a `next` URL with `page_size`
1667
+ * if any non-default size was requested), then falls back to
1668
+ * `previous`. Returns undefined when neither URL contains the param —
1669
+ * the consumer is then on a single-page result with the server's
1670
+ * default page size, which is not introspectable from the body alone.
1671
+ *
1672
+ * @param nextPageUrl - The `next` link from the response, or null
1673
+ * @param prevPageUrl - The `previous` link from the response, or null
1674
+ * @returns The page size, or undefined
1675
+ */
1676
+ private _derivePerPage;
1677
+ /**
1678
+ * Derive `to` as the 1-indexed offset of the last item on this page
1679
+ *
1680
+ * Clamped to `total` so the last page does not report past the end.
1681
+ *
1682
+ * @param currentPage - The current page number
1683
+ * @param perPage - The page size (may be undefined)
1684
+ * @param total - The total item count (may be undefined)
1685
+ * @returns The 1-indexed `to` index, or undefined when inputs insufficient
1686
+ */
1687
+ private _deriveTo;
1688
+ /**
1689
+ * Extract the `page` query parameter from a DRF pagination URL
1690
+ *
1691
+ * Returns the integer value of `?page=N`, or undefined when the URL is
1692
+ * malformed or has no `page` param (which, by DRF convention, means
1693
+ * page 1 — the caller infers the semantics).
1694
+ *
1695
+ * @param url - The URL to parse
1696
+ * @returns The integer page value, or undefined
1697
+ */
1698
+ private _extractPageParam;
1699
+ /**
1700
+ * Extract the `page_size` query parameter from a DRF pagination URL
1701
+ *
1702
+ * @param url - The URL to parse (or null)
1703
+ * @returns The integer page-size value, or undefined
1704
+ */
1705
+ private _extractPageSizeParam;
1706
+ /**
1707
+ * Extract a single query parameter from a URL via the WHATWG URL parser
1708
+ *
1709
+ * Returns undefined when the URL is unparseable (relative URL without a
1710
+ * base, or malformed) or when the parameter is absent.
1711
+ *
1712
+ * @param url - The URL to parse
1713
+ * @param name - The query-parameter name to look up
1714
+ * @returns The raw string value of the parameter, or undefined
1715
+ */
1716
+ private _extractQueryParam;
1717
+ }
1718
+
1448
1719
  /**
1449
1720
  * Request strategy for the JSON:API driver
1450
1721
  *
@@ -1833,6 +2104,183 @@ declare class NestjsRequestStrategy extends AbstractRequestStrategy {
1833
2104
  declare class NestjsResponseStrategy extends AbstractDotPathResponseStrategy {
1834
2105
  }
1835
2106
 
2107
+ /**
2108
+ * Request strategy for the @nestjsx/crud driver
2109
+ *
2110
+ * Generates URIs in [@nestjsx/crud's pipe-delimited query format](https://github.com/nestjsx/crud/wiki/Requests):
2111
+ * - Filters: `filter=field||$eq||value` (repeatable; multi-value
2112
+ * collapses to `filter=field||$in||v1,v2`)
2113
+ * - Operator filters: `filter=field||$op||value` (translated from
2114
+ * `FilterOperatorEnum` — `CONTAINS`→`$cont`, `ILIKE`→`$contL`,
2115
+ * `SW`→`$starts`, `BTW`→`$between`, `NOT`→`$ne`/`$notin`,
2116
+ * `NULL`→`$isnull`/`$notnull` with no value segment)
2117
+ * - Joins: `join=relation` (repeatable, from `addIncludes`)
2118
+ * - Field selection (flat): `fields=col1,col2` (from `addSelect`)
2119
+ * - Sorts: `sort=field,ASC` (repeatable, uppercase direction)
2120
+ * - Pagination (page-based): `page=N&limit=N`
2121
+ *
2122
+ * The JSON-shaped `s={...}` search parameter is intentionally out of
2123
+ * scope: it is not a plain search term, so `setSearch` throws
2124
+ * `UnsupportedSearchError` on this driver. PostgREST-native full-text
2125
+ * search operators (`FTS`, `PHFTS`, `PLFTS`, `WFTS`) throw
2126
+ * `UnsupportedFilterOperatorError`.
2127
+ *
2128
+ * @see https://github.com/nestjsx/crud/wiki/Requests
2129
+ */
2130
+ declare class NestjsxCrudRequestStrategy extends AbstractRequestStrategy {
2131
+ /**
2132
+ * Filters, operator filters, joins (`includes`), flat field selection
2133
+ * (`select`), sorts — no per-model fields, no global search (the `s`
2134
+ * parameter is JSON-shaped, not a plain term)
2135
+ */
2136
+ readonly capabilities: IStrategyCapabilities;
2137
+ /**
2138
+ * @nestjsx/crud-native names of the four hardcoded query keys
2139
+ *
2140
+ * The wire format is fixed (the server's `CrudRequestInterceptor`
2141
+ * reads `fields`, `filter`, `join`, and `sort`); these keys are
2142
+ * intentionally not configurable through `QueryBuilderOptions` and
2143
+ * live as private statics so they are visible in one place.
2144
+ */
2145
+ private static readonly _fieldsKey;
2146
+ private static readonly _filterKey;
2147
+ private static readonly _joinKey;
2148
+ private static readonly _sortKey;
2149
+ /**
2150
+ * Pipe delimiter separating field, operator, and value segments
2151
+ */
2152
+ private static readonly _separator;
2153
+ /**
2154
+ * Emit @nestjsx/crud-format query-string segments in canonical order:
2155
+ * fields → filters → operator filters → join → sort → limit → page
2156
+ *
2157
+ * @param state - The current query builder state
2158
+ * @param options - The query parameter key name configuration (used
2159
+ * for `page` / `limit`, whose defaults match the wire format; the
2160
+ * `fields` / `filter` / `join` / `sort` keys are fixed by the server)
2161
+ * @returns Ordered query-string fragments
2162
+ */
2163
+ protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
2164
+ /**
2165
+ * Append `fields=col1,col2` from the flat select array
2166
+ *
2167
+ * @param state - The current query builder state
2168
+ * @param out - The accumulator the caller joins into the URI
2169
+ */
2170
+ private _appendFields;
2171
+ /**
2172
+ * Append simple filters as repeatable `filter=field||$eq||value` params
2173
+ *
2174
+ * Single-value filters fold to `$eq`; multi-value filters fold to
2175
+ * `$in` with comma-joined values.
2176
+ *
2177
+ * @param state - The current query builder state
2178
+ * @param out - The accumulator the caller joins into the URI
2179
+ */
2180
+ private _appendFilters;
2181
+ /**
2182
+ * Append `join=relation` params from the includes array
2183
+ *
2184
+ * Per-relation field projection (`join=relation||f1,f2`) is not
2185
+ * expressible through the current state shape and is out of scope.
2186
+ *
2187
+ * @param state - The current query builder state
2188
+ * @param out - The accumulator the caller joins into the URI
2189
+ */
2190
+ private _appendJoin;
2191
+ /**
2192
+ * Append the limit parameter
2193
+ *
2194
+ * @param state - The current query builder state
2195
+ * @param options - The query parameter key name configuration
2196
+ * @param out - The accumulator the caller joins into the URI
2197
+ */
2198
+ private _appendLimit;
2199
+ /**
2200
+ * Append operator filters as repeatable `filter=field||$op||value` params
2201
+ *
2202
+ * @param state - The current query builder state
2203
+ * @param out - The accumulator the caller joins into the URI
2204
+ */
2205
+ private _appendOperatorFilters;
2206
+ /**
2207
+ * Append the page parameter
2208
+ *
2209
+ * @param state - The current query builder state
2210
+ * @param options - The query parameter key name configuration
2211
+ * @param out - The accumulator the caller joins into the URI
2212
+ */
2213
+ private _appendPage;
2214
+ /**
2215
+ * Append `sort=field,ASC` params, one per sort rule
2216
+ *
2217
+ * @param state - The current query builder state
2218
+ * @param out - The accumulator the caller joins into the URI
2219
+ */
2220
+ private _appendSort;
2221
+ /**
2222
+ * Translate a `FilterOperatorEnum` operator filter into @nestjsx/crud's
2223
+ * `$operator||value` condition segment
2224
+ *
2225
+ * The mapping is library-canonical → @nestjsx/crud-native:
2226
+ * - `EQ`/`GT`/`GTE`/`LT`/`LTE`/`IN` → identity (same operator name)
2227
+ * - `CONTAINS` → `$cont`; `ILIKE` → `$contL` (case-insensitive contains)
2228
+ * - `SW` → `$starts`
2229
+ * - `BTW` → `$between` with `min,max` (arity-checked)
2230
+ * - `NOT` → `$ne` (single value) / `$notin` (multi-value)
2231
+ * - `NULL` → `$isnull` (when value is `true`) / `$notnull` (when value
2232
+ * is `false`); both emit **no value segment**; arity- and type-checked
2233
+ *
2234
+ * PostgREST's full-text-search operators (`FTS`, `PHFTS`, `PLFTS`,
2235
+ * `WFTS`) have no @nestjsx/crud equivalent and throw
2236
+ * `UnsupportedFilterOperatorError`.
2237
+ *
2238
+ * @param filter - The operator filter to translate
2239
+ * @returns The `$operator||value` (or bare `$operator`) condition segment
2240
+ * @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
2241
+ * exactly two values, or `NULL` does not receive exactly one boolean
2242
+ * @throws {UnsupportedFilterOperatorError} If the operator is a
2243
+ * PostgREST-only FTS variant
2244
+ */
2245
+ private _formatOperatorCondition;
2246
+ }
2247
+
2248
+ /**
2249
+ * Response strategy for the @nestjsx/crud driver
2250
+ *
2251
+ * Parses @nestjsx/crud's `getMany` envelope:
2252
+ * ```json
2253
+ * {
2254
+ * "data": [{ "id": 1, "name": "John" }],
2255
+ * "count": 10,
2256
+ * "total": 48,
2257
+ * "page": 2,
2258
+ * "pageCount": 5
2259
+ * }
2260
+ * ```
2261
+ *
2262
+ * Default key paths are configured in `NestjsxCrudResponseOptions`. The
2263
+ * envelope carries no `from`/`to` indices and no navigation links, so
2264
+ * `from`/`to` are computed from `page` × `count` by the inherited
2265
+ * traversal algorithm and the URL slots resolve to `undefined` unless
2266
+ * the consumer overrides their paths via `IPaginationConfig`.
2267
+ *
2268
+ * Note that `count` is the number of entities **on the current page**,
2269
+ * not the requested page size — on the last page of a result set the
2270
+ * derived `from`/`to` can underestimate. Consumers needing exact
2271
+ * indices should compute them from the requested limit instead.
2272
+ *
2273
+ * The dot-notation traversal is inherited from
2274
+ * `AbstractDotPathResponseStrategy`; this class exists so
2275
+ * `DriverEnum.NESTJSX_CRUD` resolves to a distinct identity at the DI
2276
+ * layer even though the parsing logic is shared with JSON:API, NestJS,
2277
+ * and Strapi.
2278
+ *
2279
+ * @see https://github.com/nestjsx/crud/wiki/Requests
2280
+ */
2281
+ declare class NestjsxCrudResponseStrategy extends AbstractDotPathResponseStrategy {
2282
+ }
2283
+
1836
2284
  /**
1837
2285
  * Request strategy for the PostgREST driver
1838
2286
  *
@@ -2032,6 +2480,154 @@ declare class PostgrestResponseStrategy implements IResponseStrategy {
2032
2480
  private _parseContentRange;
2033
2481
  }
2034
2482
 
2483
+ /**
2484
+ * Request strategy for the Sieve (.NET) driver
2485
+ *
2486
+ * Generates URIs in [Sieve's compact expression format](https://github.com/Biarity/Sieve):
2487
+ * - Filters: a single `filters=` parameter holding comma-joined (AND)
2488
+ * `Field{op}Value` terms; multi-value terms use the pipe (OR) on the
2489
+ * value side (`status==active|pending`)
2490
+ * - Operator filters: translated from `FilterOperatorEnum` — see the
2491
+ * mapping on `_formatOperatorTerms`
2492
+ * - Sorts: `sorts=field,-other` (CSV, `-` prefix = DESC)
2493
+ * - Pagination: `page=N&pageSize=N`
2494
+ *
2495
+ * Sieve has no per-model field selection, no relation includes, no flat
2496
+ * column selection, and no global search parameter — the corresponding
2497
+ * fluent methods throw the matching `Unsupported*Error`. PostgREST-native
2498
+ * full-text search operators (`FTS`, `PHFTS`, `PLFTS`, `WFTS`) throw
2499
+ * `UnsupportedFilterOperatorError`.
2500
+ *
2501
+ * @see https://github.com/Biarity/Sieve
2502
+ */
2503
+ declare class SieveRequestStrategy extends AbstractRequestStrategy {
2504
+ /**
2505
+ * Filters, operator filters, sorts — no per-model fields, no includes,
2506
+ * no flat select, no global search (use `CONTAINS` / `ILIKE` operator
2507
+ * filters for partial matches)
2508
+ */
2509
+ readonly capabilities: IStrategyCapabilities;
2510
+ /**
2511
+ * Sieve-native names of the three hardcoded query keys
2512
+ *
2513
+ * Sieve's model binder reads `filters`, `sorts`, and `pageSize` (the
2514
+ * plural forms differ from the library-wide `filter` / `sort` /
2515
+ * `limit` defaults); these keys are intentionally not configurable
2516
+ * through `QueryBuilderOptions` and live as private statics so they
2517
+ * are visible in one place.
2518
+ */
2519
+ private static readonly _filtersKey;
2520
+ private static readonly _pageSizeKey;
2521
+ private static readonly _sortsKey;
2522
+ /**
2523
+ * Emit Sieve-format query-string segments in canonical order:
2524
+ * filters → sorts → page → pageSize
2525
+ *
2526
+ * @param state - The current query builder state
2527
+ * @param options - The query parameter key name configuration (used
2528
+ * for `page`, whose default matches the wire format; the `filters` /
2529
+ * `sorts` / `pageSize` keys are fixed by the server)
2530
+ * @returns Ordered query-string fragments
2531
+ */
2532
+ protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
2533
+ /**
2534
+ * Append the single `filters=` parameter combining simple and operator
2535
+ * filters
2536
+ *
2537
+ * Each term is one `Field{op}Value` expression; terms join with the
2538
+ * comma (Sieve's AND). Simple single-value filters fold to `==`;
2539
+ * simple multi-value filters fold to a value-level pipe OR
2540
+ * (`field==v1|v2`).
2541
+ *
2542
+ * @param state - The current query builder state
2543
+ * @param out - The accumulator the caller joins into the URI
2544
+ */
2545
+ private _appendFilters;
2546
+ /**
2547
+ * Append the page parameter
2548
+ *
2549
+ * @param state - The current query builder state
2550
+ * @param options - The query parameter key name configuration
2551
+ * @param out - The accumulator the caller joins into the URI
2552
+ */
2553
+ private _appendPage;
2554
+ /**
2555
+ * Append the pageSize parameter
2556
+ *
2557
+ * @param state - The current query builder state
2558
+ * @param out - The accumulator the caller joins into the URI
2559
+ */
2560
+ private _appendPageSize;
2561
+ /**
2562
+ * Append the `sorts=field,-other` CSV parameter
2563
+ *
2564
+ * @param state - The current query builder state
2565
+ * @param out - The accumulator the caller joins into the URI
2566
+ */
2567
+ private _appendSorts;
2568
+ /**
2569
+ * Translate a `FilterOperatorEnum` operator filter into one or more
2570
+ * Sieve `Field{op}Value` terms
2571
+ *
2572
+ * The mapping is library-canonical → Sieve-native:
2573
+ * - `EQ` → `==`; `GT`/`GTE`/`LT`/`LTE` → `>` / `>=` / `<` / `<=`
2574
+ * - `CONTAINS` → `@=`; `ILIKE` → `@=*` (case-insensitive contains)
2575
+ * - `SW` → `_=` (starts with)
2576
+ * - `IN` → `==` with a value-level pipe OR (`field==v1|v2`)
2577
+ * - `BTW` → **two** AND-ed terms (`field>=min` and `field<=max`,
2578
+ * arity-checked)
2579
+ * - `NOT` → `!=` — one term per value, AND-ed (`field!=v1,field!=v2`)
2580
+ * - `NULL` → `==null` (when value is `true`) / `!=null` (when value is
2581
+ * `false`); arity- and type-checked
2582
+ *
2583
+ * PostgREST's full-text-search operators (`FTS`, `PHFTS`, `PLFTS`,
2584
+ * `WFTS`) have no Sieve equivalent and throw
2585
+ * `UnsupportedFilterOperatorError`.
2586
+ *
2587
+ * @param filter - The operator filter to translate
2588
+ * @returns One or more `Field{op}Value` terms ready to AND-join
2589
+ * @throws {InvalidFilterOperatorValueError} If `BTW` does not receive
2590
+ * exactly two values, or `NULL` does not receive exactly one boolean
2591
+ * @throws {UnsupportedFilterOperatorError} If the operator is a
2592
+ * PostgREST-only FTS variant
2593
+ */
2594
+ private _formatOperatorTerms;
2595
+ }
2596
+
2597
+ /**
2598
+ * Response strategy for the Sieve (.NET) driver
2599
+ *
2600
+ * Sieve itself does not define a response envelope — it returns an
2601
+ * `IQueryable` that the ASP.NET developer wraps in a paging DTO of their
2602
+ * choosing. This strategy therefore ships a **sensible default mapping**
2603
+ * for the common hand-rolled `PagedResult<T>` shape:
2604
+ * ```json
2605
+ * {
2606
+ * "data": [{ "id": 1, "title": "Hello" }],
2607
+ * "page": 2,
2608
+ * "pageSize": 10,
2609
+ * "total": 48,
2610
+ * "totalPages": 5
2611
+ * }
2612
+ * ```
2613
+ *
2614
+ * Every key path is configurable through `IConfig.response` (dot
2615
+ * notation supported), so any wrapper shape — `{ items, meta: {...} }`,
2616
+ * `{ results, pagination: {...} }` — can be mapped without subclassing.
2617
+ * Defaults are encoded in `SieveResponseOptions`. `from`/`to` are
2618
+ * computed from `page` × `pageSize` by the inherited traversal
2619
+ * algorithm, and the navigation-URL slots resolve to `undefined` unless
2620
+ * paths are provided.
2621
+ *
2622
+ * The dot-notation traversal is inherited from
2623
+ * `AbstractDotPathResponseStrategy`; this class exists so
2624
+ * `DriverEnum.SIEVE` resolves to a distinct identity at the DI layer.
2625
+ *
2626
+ * @see https://github.com/Biarity/Sieve
2627
+ */
2628
+ declare class SieveResponseStrategy extends AbstractDotPathResponseStrategy {
2629
+ }
2630
+
2035
2631
  /**
2036
2632
  * Request strategy for the Spatie Query Builder driver
2037
2633
  *
@@ -2141,6 +2737,155 @@ declare class SpatieRequestStrategy extends AbstractRequestStrategy {
2141
2737
  declare class SpatieResponseStrategy extends AbstractFlatResponseStrategy {
2142
2738
  }
2143
2739
 
2740
+ /**
2741
+ * Request strategy for the Spring Data REST driver
2742
+ *
2743
+ * Generates URIs in [Spring Data REST's pagination format](https://docs.spring.io/spring-data/rest/reference/paging-and-sorting.html):
2744
+ * - Sorts: `sort=field,asc&sort=other,desc` (repeatable param, one per rule)
2745
+ * - Pagination: `page=N&size=N` — **`page` is 0-indexed on the wire**;
2746
+ * the library state stays 1-indexed and the strategy subtracts 1 at
2747
+ * emission time
2748
+ *
2749
+ * Spring Data REST defines no standard query parameter convention for
2750
+ * filtering, field selection, includes, or global search — those are
2751
+ * implemented server-side via custom query methods or Specifications.
2752
+ * The corresponding fluent methods (`addFilter`, `addFilterOperator`,
2753
+ * `addSelect`, `addFields`, `addIncludes`, `setSearch`) throw the
2754
+ * matching `Unsupported*Error` on this driver.
2755
+ *
2756
+ * @see https://docs.spring.io/spring-data/rest/reference/paging-and-sorting.html
2757
+ */
2758
+ declare class SpringRequestStrategy extends AbstractRequestStrategy {
2759
+ /**
2760
+ * Sorts only — Spring Data REST has no standard wire convention for
2761
+ * filters, operator filters, per-model fields, flat select, includes,
2762
+ * or global search
2763
+ */
2764
+ readonly capabilities: IStrategyCapabilities;
2765
+ /**
2766
+ * Spring-native name of the hardcoded page-size query key
2767
+ *
2768
+ * The wire format is fixed (Spring's `PageableHandlerMethodArgumentResolver`
2769
+ * reads `size` by default); the key is intentionally not configurable
2770
+ * through `QueryBuilderOptions` and lives as a private static so it is
2771
+ * visible in one place.
2772
+ */
2773
+ private static readonly _sizeKey;
2774
+ /**
2775
+ * Emit Spring-format query-string segments in canonical order:
2776
+ * sort → page → size
2777
+ *
2778
+ * @param state - The current query builder state
2779
+ * @param options - The query parameter key name configuration (used
2780
+ * for `page` and `sort`, whose defaults match the wire format; the
2781
+ * `size` key is fixed by the server)
2782
+ * @returns Ordered query-string fragments
2783
+ */
2784
+ protected parts(state: IQueryBuilderState, options: QueryBuilderOptions): string[];
2785
+ /**
2786
+ * Append the 0-indexed page parameter
2787
+ *
2788
+ * The library state is 1-indexed (page 1 is the first page); Spring's
2789
+ * `page` request parameter is 0-indexed, so the strategy subtracts 1
2790
+ * at emission time.
2791
+ *
2792
+ * @param state - The current query builder state
2793
+ * @param options - The query parameter key name configuration
2794
+ * @param out - The accumulator the caller joins into the URI
2795
+ */
2796
+ private _appendPage;
2797
+ /**
2798
+ * Append the size parameter
2799
+ *
2800
+ * @param state - The current query builder state
2801
+ * @param out - The accumulator the caller joins into the URI
2802
+ */
2803
+ private _appendSize;
2804
+ /**
2805
+ * Append `sort=field,asc` params, one per sort rule (repeatable)
2806
+ *
2807
+ * Spring parses each `sort` occurrence independently — multiple rules
2808
+ * are expressed by repeating the parameter, not by comma-joining the
2809
+ * fields.
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 Spring Data REST driver
2820
+ *
2821
+ * Parses Spring Data REST's HAL envelope:
2822
+ * ```json
2823
+ * {
2824
+ * "_embedded": { "users": [{ "id": 1, "name": "John" }] },
2825
+ * "_links": {
2826
+ * "first": { "href": "..." },
2827
+ * "prev": { "href": "..." },
2828
+ * "next": { "href": "..." },
2829
+ * "last": { "href": "..." }
2830
+ * },
2831
+ * "page": { "size": 20, "totalElements": 100, "totalPages": 5, "number": 1 }
2832
+ * }
2833
+ * ```
2834
+ *
2835
+ * Two HAL quirks are absorbed here on top of the inherited dot-path
2836
+ * traversal:
2837
+ *
2838
+ * - **`page.number` is 0-indexed** — the strategy adds 1 so the library
2839
+ * state stays 1-indexed (mirroring `SpringRequestStrategy`, which
2840
+ * subtracts 1 on the way out).
2841
+ * - **The collection key under `_embedded` is the resource rel name**
2842
+ * (e.g. `_embedded.users`), which cannot be known statically. The
2843
+ * default `data` path is plain `_embedded`; when it resolves to an
2844
+ * object rather than an array, the strategy picks the first array
2845
+ * value inside it. Consumers with multiple embedded rels can pin the
2846
+ * exact path via `IConfig.response` (e.g. `data: '_embedded.users'`).
2847
+ *
2848
+ * Default key paths are configured in `SpringResponseOptions`.
2849
+ *
2850
+ * @see https://docs.spring.io/spring-data/rest/reference/paging-and-sorting.html
2851
+ */
2852
+ declare class SpringResponseStrategy extends AbstractDotPathResponseStrategy {
2853
+ /**
2854
+ * Parse a Spring Data REST HAL response into a PaginatedCollection
2855
+ *
2856
+ * @param response - The raw API response body
2857
+ * @param options - The response key name configuration
2858
+ * @returns A typed PaginatedCollection instance
2859
+ */
2860
+ paginate<T extends IPaginatedObject>(response: Record<string, any>, options: ResponseOptions): PaginatedCollection<T>;
2861
+ /**
2862
+ * Resolve the 1-indexed current page from the 0-indexed `page.number`
2863
+ *
2864
+ * Falls back to page 1 when the path is missing entirely (defensive —
2865
+ * Spring always emits the `page` block on paged endpoints).
2866
+ *
2867
+ * @param response - The raw response object
2868
+ * @param options - The response key name configuration
2869
+ * @returns The 1-indexed current page number
2870
+ */
2871
+ private _resolveCurrentPage;
2872
+ /**
2873
+ * Resolve the data array from the HAL `_embedded` wrapper
2874
+ *
2875
+ * When the configured path resolves directly to an array (a consumer
2876
+ * pinned `data: '_embedded.users'`), it is used as-is. When it
2877
+ * resolves to an object (the default `_embedded` path), the first
2878
+ * array value inside it is used — Spring emits exactly one collection
2879
+ * rel per listing endpoint. An empty array is returned when nothing
2880
+ * matches (e.g. Spring omits `_embedded` on empty result sets).
2881
+ *
2882
+ * @param response - The raw response object
2883
+ * @param options - The response key name configuration
2884
+ * @returns The resolved data array (possibly empty)
2885
+ */
2886
+ private _resolveData;
2887
+ }
2888
+
2144
2889
  /**
2145
2890
  * Request strategy for the Strapi driver
2146
2891
  *
@@ -2309,5 +3054,5 @@ declare class StrapiRequestStrategy extends AbstractRequestStrategy {
2309
3054
  declare class StrapiResponseStrategy extends AbstractDotPathResponseStrategy {
2310
3055
  }
2311
3056
 
2312
- export { DriverEnum, FilterOperatorEnum, InvalidFilterOperatorValueError, InvalidLimitError, InvalidPageNumberError, InvalidResourceNameError, JsonApiRequestStrategy, JsonApiResponseStrategy, KeyNotFoundError, LaravelRequestStrategy, LaravelResponseStrategy, NG_QUBEE_DRIVER, NG_QUBEE_REQUEST_OPTIONS, NG_QUBEE_REQUEST_STRATEGY, NG_QUBEE_RESPONSE_OPTIONS, NG_QUBEE_RESPONSE_STRATEGY, NestjsRequestStrategy, NestjsResponseStrategy, NgQubeeModule, NgQubeeService, PaginatedCollection, PaginationModeEnum, PaginationNotSyncedError, PaginationService, PostgrestRequestStrategy, PostgrestResponseStrategy, SortEnum, SpatieRequestStrategy, SpatieResponseStrategy, StrapiRequestStrategy, StrapiResponseStrategy, UnselectableModelError, UnsupportedFieldSelectionError, UnsupportedFilterError, UnsupportedFilterOperatorError, UnsupportedIncludesError, UnsupportedSearchError, UnsupportedSelectError, UnsupportedSortError, buildNgQubeeProviders, provideNgQubee, provideNgQubeeInstance, readHeader };
3057
+ export { DrfRequestStrategy, DrfResponseStrategy, DriverEnum, FilterOperatorEnum, InvalidFilterOperatorValueError, InvalidLimitError, InvalidPageNumberError, InvalidResourceNameError, JsonApiRequestStrategy, JsonApiResponseStrategy, KeyNotFoundError, LaravelRequestStrategy, LaravelResponseStrategy, NG_QUBEE_DRIVER, NG_QUBEE_REQUEST_OPTIONS, NG_QUBEE_REQUEST_STRATEGY, NG_QUBEE_RESPONSE_OPTIONS, NG_QUBEE_RESPONSE_STRATEGY, NestjsRequestStrategy, NestjsResponseStrategy, NestjsxCrudRequestStrategy, NestjsxCrudResponseStrategy, NgQubeeModule, NgQubeeService, PaginatedCollection, PaginationModeEnum, PaginationNotSyncedError, PaginationService, PostgrestRequestStrategy, PostgrestResponseStrategy, SieveRequestStrategy, SieveResponseStrategy, SortEnum, SpatieRequestStrategy, SpatieResponseStrategy, SpringRequestStrategy, SpringResponseStrategy, StrapiRequestStrategy, StrapiResponseStrategy, UnselectableModelError, UnsupportedFieldSelectionError, UnsupportedFilterError, UnsupportedFilterOperatorError, UnsupportedIncludesError, UnsupportedSearchError, UnsupportedSelectError, UnsupportedSortError, buildNgQubeeProviders, provideNgQubee, provideNgQubeeInstance, readHeader };
2313
3058
  export type { HeaderBag, IConfig, IFields, IFilters, INestState, IOperatorFilter, IPage, IPaginatedObject, IPaginationConfig, IQueryBuilderConfig, IQueryBuilderState, IRequestStrategy, IResponseStrategy, ISort };