@dudousxd/nestjs-filter 1.7.0 → 1.8.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.
Files changed (35) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/adapter/adapter.d.ts +119 -3
  3. package/dist/adapter/adapter.d.ts.map +1 -1
  4. package/dist/decorator/allowed.d.ts +30 -0
  5. package/dist/decorator/allowed.d.ts.map +1 -0
  6. package/dist/decorator/allowed.js +32 -0
  7. package/dist/decorator/allowed.js.map +1 -0
  8. package/dist/decorator/filter-for.decorator.d.ts.map +1 -1
  9. package/dist/decorator/filter-for.decorator.js +5 -0
  10. package/dist/decorator/filter-for.decorator.js.map +1 -1
  11. package/dist/decorator/filterable.decorator.d.ts.map +1 -1
  12. package/dist/decorator/filterable.decorator.js +3 -0
  13. package/dist/decorator/filterable.decorator.js.map +1 -1
  14. package/dist/decorator/relations.decorator.d.ts.map +1 -1
  15. package/dist/decorator/relations.decorator.js +25 -9
  16. package/dist/decorator/relations.decorator.js.map +1 -1
  17. package/dist/index.d.ts +7 -2
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/input/spatie-parser.d.ts +40 -0
  22. package/dist/input/spatie-parser.d.ts.map +1 -0
  23. package/dist/input/spatie-parser.js +159 -0
  24. package/dist/input/spatie-parser.js.map +1 -0
  25. package/dist/pagination/cursor.d.ts +37 -0
  26. package/dist/pagination/cursor.d.ts.map +1 -0
  27. package/dist/pagination/cursor.js +69 -0
  28. package/dist/pagination/cursor.js.map +1 -0
  29. package/dist/runner.d.ts +78 -3
  30. package/dist/runner.d.ts.map +1 -1
  31. package/dist/runner.js +402 -49
  32. package/dist/runner.js.map +1 -1
  33. package/dist/types.d.ts +113 -3
  34. package/dist/types.d.ts.map +1 -1
  35. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @dudousxd/nestjs-filter
2
2
 
3
+ ## 1.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#27](https://github.com/DavideCarvalho/nestjs-filter/pull/27) [`ab90005`](https://github.com/DavideCarvalho/nestjs-filter/commit/ab90005b46894bc560eee5047e9a0dca1e6495e2) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - Ecosystem improvements across the filter core and both ORM adapters.
8
+
9
+ - **Full-text vector search fix**: switched Postgres full-text matching to `websearch_to_tsquery` for correct, user-friendly query parsing, with optional `ts_rank`-based relevance ordering.
10
+ - **`throwOnInvalid` policy**: opt-in strict mode that rejects unknown fields/operators/invalid input instead of silently dropping them.
11
+ - **`defaultSort`**: configure a fallback sort applied when no explicit sort is requested.
12
+ - **Deterministic query param names**: stable, predictable parameter naming in generated queries for easier debugging and caching.
13
+ - **Cursor / keyset pagination**: stable, non-overlapping cursor-based pagination for both the TypeORM and MikroORM adapters.
14
+ - **Per-field operator allowlist**: restrict which operators are permitted on a per-field basis.
15
+ - **Computed / virtual field filtering**: filter on computed/virtual fields that are not plain columns.
16
+ - **Opt-in spatie / JSON:API query syntax**: support for `filter[field][op]` bracket syntax and sparse fieldsets, enabled opt-in.
17
+ - **Cross-adapter contract suite + testcontainers**: a shared contract test suite run against both adapters, backed by Postgres and MySQL testcontainers for real-DB integration coverage.
18
+
19
+ ## 1.7.1
20
+
21
+ ### Patch Changes
22
+
23
+ - [`cedbf3c`](https://github.com/DavideCarvalho/nestjs-filter/commit/cedbf3c201c349e692f29e3a9148da96c4bda0ea) - perf: cache immutable ORM metadata and decorator maps — `WeakMap`-cache `getEntityFields`/`getEntityRelations`/`resolveFieldPath` in the MikroORM and TypeORM adapters (previously recomputed 3–6× per request), memoize `getFilterForMap`, and build a reverse index for `resolveRelation`.
24
+
3
25
  ## 1.7.0
4
26
 
5
27
  ### Minor Changes
@@ -27,6 +27,17 @@ export interface EntityRelationInfo {
27
27
  /** Relation cardinality type. */
28
28
  type: 'one-to-one' | 'many-to-one' | 'one-to-many' | 'many-to-many';
29
29
  }
30
+ /**
31
+ * Behavior flags for full-text vector search ({@link FilterAdapter.applyVectorSearch}).
32
+ */
33
+ export interface VectorSearchOptions {
34
+ /**
35
+ * When true, add relevance ordering for matched rows (e.g. Postgres
36
+ * `ORDER BY ts_rank(...) DESC`). Off by default because it changes the
37
+ * query's default ordering.
38
+ */
39
+ rank?: boolean;
40
+ }
30
41
  export interface FilterAdapter {
31
42
  createQueryBuilder<E>(entity: Type<E>): unknown;
32
43
  /**
@@ -51,8 +62,11 @@ export interface FilterAdapter {
51
62
  *
52
63
  * @param qb - The query builder instance.
53
64
  * @param filters - Array of ColumnFilter conditions to apply.
65
+ * @param entity - The entity being queried. When provided, lets the adapter
66
+ * resolve column types (e.g. so `isEmpty`/`isNotEmpty` only compare against
67
+ * `''` on string columns — a DATE/number `col = ''` errors on MySQL).
54
68
  */
55
- applyColumnFilters?(qb: unknown, filters: ColumnFilter[]): void;
69
+ applyColumnFilters?(qb: unknown, filters: ColumnFilter[], entity?: Type<unknown>): void;
56
70
  /**
57
71
  * Applies an auto-field value to the query builder.
58
72
  *
@@ -188,13 +202,21 @@ export interface FilterAdapter {
188
202
  /**
189
203
  * Applies a full-text vector search using a tsvector column.
190
204
  *
205
+ * Implementations must parse arbitrary user input safely (e.g. Postgres
206
+ * `websearch_to_tsquery`, not the raw `to_tsquery`, which throws a syntax
207
+ * error on ordinary multi-word input like `"foo bar"`).
208
+ *
209
+ * When `opts.rank` is true, the adapter may add relevance ordering
210
+ * (e.g. `ts_rank`) for the matched rows.
211
+ *
191
212
  * Optional — adapters that don't support vector search should not implement this.
192
213
  *
193
214
  * @param qb - The query builder instance.
194
- * @param term - The search term.
215
+ * @param term - The search term (arbitrary user text).
195
216
  * @param vectorColumn - The tsvector column name.
217
+ * @param opts - Optional behavior flags (e.g. `{ rank: true }`).
196
218
  */
197
- applyVectorSearch?(qb: unknown, term: string, vectorColumn: string): void;
219
+ applyVectorSearch?(qb: unknown, term: string, vectorColumn: string, opts?: VectorSearchOptions): void;
198
220
  /**
199
221
  * Restricts the query to DISTINCT values of the given field(s).
200
222
  *
@@ -211,6 +233,21 @@ export interface FilterAdapter {
211
233
  * @param entity - The root entity class.
212
234
  */
213
235
  applyDistinct?(qb: unknown, fields: string[], entity: Type<unknown>): void;
236
+ /**
237
+ * Restricts the query's projection to the given field(s) — JSON:API "sparse
238
+ * fieldsets". Unlike {@link applyDistinct}, this adds **no** `DISTINCT`
239
+ * modifier; it only narrows the SELECT list (the primary key should remain
240
+ * selected so rows stay addressable). Active WHERE / search / sort /
241
+ * pagination are unaffected.
242
+ *
243
+ * Optional — adapters that don't support projection narrowing should not
244
+ * implement this.
245
+ *
246
+ * @param qb - The query builder instance.
247
+ * @param fields - Field/column names to select.
248
+ * @param entity - The root entity class.
249
+ */
250
+ applySelect?(qb: unknown, fields: string[], entity: Type<unknown>): void;
214
251
  /**
215
252
  * Applies sort ordering to the query builder.
216
253
  *
@@ -218,6 +255,33 @@ export interface FilterAdapter {
218
255
  * @param sorts - Array of SortItem directives (field + direction).
219
256
  */
220
257
  applySort?(qb: unknown, sorts: SortItem[]): void;
258
+ /**
259
+ * Applies a WHERE condition on a **computed/virtual field** — a developer-
260
+ * provided SQL expression declared via `@Filterable.computed`. Behaves like
261
+ * {@link applyAutoField} (scalar → equals, array → IN, operator object →
262
+ * those operators) but evaluates the raw `expression` instead of a column
263
+ * reference. The expression is dev-provided (never client input); values are
264
+ * always parameterized.
265
+ *
266
+ * Optional — adapters that don't support computed fields should not
267
+ * implement this.
268
+ *
269
+ * @param qb - The query builder instance.
270
+ * @param expression - The raw SQL expression for the computed field.
271
+ * @param value - The filter value (scalar, array, or operator object).
272
+ */
273
+ applyComputedField?(qb: unknown, expression: string, value: unknown): void;
274
+ /**
275
+ * Applies an ORDER BY on a computed/virtual field's SQL expression.
276
+ *
277
+ * Optional — adapters that don't support computed fields should not
278
+ * implement this.
279
+ *
280
+ * @param qb - The query builder instance.
281
+ * @param expression - The raw SQL expression for the computed field.
282
+ * @param direction - Sort direction.
283
+ */
284
+ applyComputedSort?(qb: unknown, expression: string, direction: 'asc' | 'desc'): void;
221
285
  /**
222
286
  * Applies offset-based pagination to the query builder.
223
287
  *
@@ -239,6 +303,58 @@ export interface FilterAdapter {
239
303
  rows: unknown[];
240
304
  total: number;
241
305
  }>;
306
+ /**
307
+ * Executes the query builder and returns the matching rows (no count). Used
308
+ * by `FilterRunner.findPage` for cursor/keyset pagination, where a total
309
+ * count is intentionally not computed.
310
+ *
311
+ * Optional — required only if you call `findPage`.
312
+ *
313
+ * @param qb - The query builder instance.
314
+ * @returns The fetched rows.
315
+ */
316
+ getResult?(qb: unknown): Promise<unknown[]>;
317
+ /**
318
+ * Returns the primary-key property name of the entity, used as the stable
319
+ * tiebreaker for keyset/cursor pagination. Returns `null` when no single
320
+ * primary key can be determined.
321
+ *
322
+ * Optional — required only for `findPage` cursor pagination.
323
+ *
324
+ * @param entity - The entity class.
325
+ */
326
+ getPrimaryKey?(entity: Type<unknown>): string | null;
327
+ /**
328
+ * Applies a keyset (cursor) WHERE predicate to the query builder for
329
+ * row-value comparison across the keyset columns.
330
+ *
331
+ * Given a keyset (the active sort columns plus a primary-key tiebreaker, each
332
+ * with a direction) and the boundary row's column values, the adapter adds a
333
+ * predicate equivalent to a lexicographic tuple comparison that selects rows
334
+ * strictly *after* the boundary in keyset order. Columns sorted `asc` use
335
+ * `>` and `desc` use `<` at each tier; ties on a column fall through to the
336
+ * next. Implementations must parameterize all values.
337
+ *
338
+ * Optional — required only for `findPage` cursor pagination.
339
+ *
340
+ * @param qb - The query builder instance.
341
+ * @param keyset - The keyset columns with directions (sort cols + pk).
342
+ * @param values - The boundary row's values, positionally aligned to keyset.
343
+ */
344
+ applyKeysetPagination?(qb: unknown, keyset: SortItem[], values: unknown[]): void;
345
+ /**
346
+ * Applies an ORDER BY for the keyset columns and a row LIMIT — the ordering
347
+ * and slice for a cursor page. Separate from {@link applySort} so `findPage`
348
+ * controls the keyset ordering (including direction reversal for backward
349
+ * paging) independently of the request `sort`.
350
+ *
351
+ * Optional — required only for `findPage` cursor pagination.
352
+ *
353
+ * @param qb - The query builder instance.
354
+ * @param keyset - The keyset columns with directions.
355
+ * @param limit - Max rows to fetch.
356
+ */
357
+ applyKeysetOrderAndLimit?(qb: unknown, keyset: SortItem[], limit: number): void;
242
358
  /**
243
359
  * Loads the given relations onto already-fetched rows in a **separate query**
244
360
  * (not a join), so that pagination of the parent is unaffected. Used by
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { FilterOperator } from '../operators/types.js';
2
+ import type { AllowedFieldEntry } from '../types.js';
3
+ /**
4
+ * A normalized view of a `@Filterable` `allowed` list:
5
+ *
6
+ * - `fields` — the set of allowed field-name keys (regardless of operator
7
+ * restrictions), suitable as the allowlist for sort/distinct/auto-field
8
+ * membership checks.
9
+ * - `operatorsByField` — for entries that restricted operators, the set of
10
+ * permitted operators per field. Fields declared as a plain string (allow
11
+ * all operators) are **absent** from this map.
12
+ */
13
+ export interface NormalizedAllowed {
14
+ fields: string[];
15
+ operatorsByField: Map<string, Set<FilterOperator>>;
16
+ }
17
+ /**
18
+ * Normalizes a `@Filterable` `allowed` list (which mixes plain field-name
19
+ * strings with `{ field, operators }` objects) into a {@link NormalizedAllowed}.
20
+ *
21
+ * Returns `undefined` when no allowlist was declared.
22
+ */
23
+ export declare function normalizeAllowed(allowed: readonly AllowedFieldEntry[] | undefined): NormalizedAllowed | undefined;
24
+ /**
25
+ * Returns the allowed field-name keys from a `@Filterable` `allowed` list,
26
+ * discarding any per-field operator restrictions. Used wherever the prior
27
+ * code expected a plain `string[]` allowlist (sort, distinct, auto-fields).
28
+ */
29
+ export declare function allowedFieldNames(allowed: readonly AllowedFieldEntry[] | undefined): string[] | undefined;
30
+ //# sourceMappingURL=allowed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allowed.d.ts","sourceRoot":"","sources":["../../src/decorator/allowed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;CACpD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,iBAAiB,EAAE,GAAG,SAAS,GAChD,iBAAiB,GAAG,SAAS,CAa/B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,SAAS,iBAAiB,EAAE,GAAG,SAAS,GAChD,MAAM,EAAE,GAAG,SAAS,CAGtB"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Normalizes a `@Filterable` `allowed` list (which mixes plain field-name
3
+ * strings with `{ field, operators }` objects) into a {@link NormalizedAllowed}.
4
+ *
5
+ * Returns `undefined` when no allowlist was declared.
6
+ */
7
+ export function normalizeAllowed(allowed) {
8
+ if (!allowed)
9
+ return undefined;
10
+ const fields = [];
11
+ const operatorsByField = new Map();
12
+ for (const entry of allowed) {
13
+ if (typeof entry === 'string') {
14
+ fields.push(entry);
15
+ continue;
16
+ }
17
+ fields.push(entry.field);
18
+ operatorsByField.set(entry.field, new Set(entry.operators));
19
+ }
20
+ return { fields, operatorsByField };
21
+ }
22
+ /**
23
+ * Returns the allowed field-name keys from a `@Filterable` `allowed` list,
24
+ * discarding any per-field operator restrictions. Used wherever the prior
25
+ * code expected a plain `string[]` allowlist (sort, distinct, auto-fields).
26
+ */
27
+ export function allowedFieldNames(allowed) {
28
+ if (!allowed)
29
+ return undefined;
30
+ return allowed.map((entry) => (typeof entry === 'string' ? entry : entry.field));
31
+ }
32
+ //# sourceMappingURL=allowed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allowed.js","sourceRoot":"","sources":["../../src/decorator/allowed.ts"],"names":[],"mappings":"AAkBA;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAiD;IAEjD,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAA+B,CAAC;IAChE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,SAAS;QACX,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACzB,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;AACtC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAiD;IAEjD,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;AACnF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"filter-for.decorator.d.ts","sourceRoot":"","sources":["../../src/decorator/filter-for.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAG1B;;;;;;;;;;GAUG;AACH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;AAE/F,gCAAgC;AAChC,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC5B;AAED,wBAAgB,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,eAAe,CAmBrF;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAenE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAejF"}
1
+ {"version":3,"file":"filter-for.decorator.d.ts","sourceRoot":"","sources":["../../src/decorator/filter-for.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAG1B;;;;;;;;;;GAUG;AACH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;AAE/F,gCAAgC;AAChC,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC5B;AAED,wBAAgB,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,eAAe,CAmBrF;AAID,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAoBnE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAejF"}
@@ -19,7 +19,11 @@ export function FilterFor(inputKey, opts) {
19
19
  }
20
20
  };
21
21
  }
22
+ const filterForMapCache = new WeakMap();
22
23
  export function getFilterForMap(target) {
24
+ const cached = filterForMapCache.get(target);
25
+ if (cached)
26
+ return cached;
23
27
  const result = new Map();
24
28
  let current = target;
25
29
  while (current && current !== Function.prototype && current !== Object) {
@@ -32,6 +36,7 @@ export function getFilterForMap(target) {
32
36
  }
33
37
  current = Object.getPrototypeOf(current);
34
38
  }
39
+ filterForMapCache.set(target, result);
35
40
  return result;
36
41
  }
37
42
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"filter-for.decorator.js","sourceRoot":"","sources":["../../src/decorator/filter-for.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAwB7E,MAAM,UAAU,SAAS,CAAC,QAAiB,EAAE,IAAuB;IAClE,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE;QAC7B,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,QAAQ,IAAI,UAAU,CAAC;QACnC,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC;QAChC,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,mBAAmB,EAAE,IAAI,CAAC;YACjE,IAAI,GAAG,EAAkB,CAAwB,CAAC;QACpD,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QAC9B,OAAO,CAAC,cAAc,CAAC,mBAAmB,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QAE5D,4EAA4E;QAC5E,uEAAuE;QACvE,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM,YAAY,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,wBAAwB,EAAE,IAAI,CAAC;gBAC1E,IAAI,GAAG,EAA4B,CAAkC,CAAC;YACxE,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC5B,OAAO,CAAC,cAAc,CAAC,wBAAwB,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC;QACvE,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,IAAI,OAAO,GAAkB,MAAM,CAAC;IACpC,OAAO,OAAO,IAAI,OAAO,KAAK,QAAQ,CAAC,SAAS,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvE,MAAM,GAAG,GAAG,OAAO,CAAC,cAAc,CAAC,mBAAmB,EAAE,OAAO,CAElD,CAAC;QACd,IAAI,GAAG,EAAE,CAAC;YACR,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;gBAChC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;oBAAE,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;QACD,OAAO,GAAG,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,MAAM,MAAM,GAAG,IAAI,GAAG,EAA4B,CAAC;IACnD,IAAI,OAAO,GAAkB,MAAM,CAAC;IACpC,OAAO,OAAO,IAAI,OAAO,KAAK,QAAQ,CAAC,SAAS,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvE,MAAM,GAAG,GAAG,OAAO,CAAC,cAAc,CAAC,wBAAwB,EAAE,OAAO,CAEvD,CAAC;QACd,IAAI,GAAG,EAAE,CAAC;YACR,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;gBAC9B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;oBAAE,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;QACD,OAAO,GAAG,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"filter-for.decorator.js","sourceRoot":"","sources":["../../src/decorator/filter-for.decorator.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"filterable.decorator.d.ts","sourceRoot":"","sources":["../../src/decorator/filterable.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErE,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CAgBrE;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEhF"}
1
+ {"version":3,"file":"filterable.decorator.d.ts","sourceRoot":"","sources":["../../src/decorator/filterable.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErE,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CAmBrE;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEhF"}
@@ -14,6 +14,9 @@ export function Filterable(options) {
14
14
  ...(options.allowed !== undefined && { allowed: options.allowed }),
15
15
  ...(options.blocked !== undefined && { blocked: options.blocked }),
16
16
  autoFields: options.autoFields ?? true,
17
+ ...(options.throwOnInvalid !== undefined && { throwOnInvalid: options.throwOnInvalid }),
18
+ ...(options.defaultSort !== undefined && { defaultSort: options.defaultSort }),
19
+ ...(options.computed !== undefined && { computed: options.computed }),
17
20
  };
18
21
  Reflect.defineMetadata(FILTERABLE_METADATA, meta, target);
19
22
  };
@@ -1 +1 @@
1
- {"version":3,"file":"filterable.decorator.js","sourceRoot":"","sources":["../../src/decorator/filterable.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAGnD,MAAM,UAAU,UAAU,CAAC,OAA0B;IACnD,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,IAAI,4BAA4B,CAAC,MAAM,CAAC,IAAI,IAAI,iBAAiB,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,kBAAkB,MAAM,CAAC,IAAI,6CAA6C,CAAC,CAAC;QAC9F,CAAC;QACD,MAAM,IAAI,GAAmB;YAC3B,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;YAClE,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;YAClE,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,IAAI;SACvC,CAAC;QACF,OAAO,CAAC,cAAc,CAAC,mBAAmB,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC5D,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,OAAO,OAAO,CAAC,WAAW,CAAC,mBAAmB,EAAE,MAAM,CAA+B,CAAC;AACxF,CAAC"}
1
+ {"version":3,"file":"filterable.decorator.js","sourceRoot":"","sources":["../../src/decorator/filterable.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAGnD,MAAM,UAAU,UAAU,CAAC,OAA0B;IACnD,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,IAAI,4BAA4B,CAAC,MAAM,CAAC,IAAI,IAAI,iBAAiB,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,kBAAkB,MAAM,CAAC,IAAI,6CAA6C,CAAC,CAAC;QAC9F,CAAC;QACD,MAAM,IAAI,GAAmB;YAC3B,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;YAClE,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;YAClE,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,IAAI;YACtC,GAAG,CAAC,OAAO,CAAC,cAAc,KAAK,SAAS,IAAI,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC;YACvF,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;YAC9E,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;SACtE,CAAC;QACF,OAAO,CAAC,cAAc,CAAC,mBAAmB,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC5D,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,OAAO,OAAO,CAAC,WAAW,CAAC,mBAAmB,EAAE,MAAM,CAA+B,CAAC;AACxF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"relations.decorator.d.ts","sourceRoot":"","sources":["../../src/decorator/relations.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAG3C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACtB,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAE1D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,YAAY,GAAG,cAAc,CAI3D;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAExE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,SAAS,CAStC"}
1
+ {"version":3,"file":"relations.decorator.d.ts","sourceRoot":"","sources":["../../src/decorator/relations.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAG3C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACtB,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAE1D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,YAAY,GAAG,cAAc,CAI3D;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAExE;AA4BD;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,SAAS,CAEtC"}
@@ -23,18 +23,34 @@ export function getRelationsMap(target) {
23
23
  return Reflect.getMetadata(FILTER_RELATIONS_METADATA, target);
24
24
  }
25
25
  /**
26
- * Resolves which relation (if any) owns a given input key.
27
- * Returns [relationName, RelationConfig] or undefined.
26
+ * Per-class reverse index: input key [relationName, RelationConfig].
27
+ * The relations map is fixed at decoration time, so the flattened lookup is
28
+ * computed once on first access and cached.
28
29
  */
29
- export function resolveRelation(target, inputKey) {
30
+ const reverseIndexCache = new WeakMap();
31
+ function getReverseIndex(target) {
32
+ const cached = reverseIndexCache.get(target);
33
+ if (cached)
34
+ return cached;
35
+ const index = new Map();
30
36
  const map = getRelationsMap(target);
31
- if (!map)
32
- return undefined;
33
- for (const [relationName, config] of Object.entries(map)) {
34
- if (config.keys.includes(inputKey)) {
35
- return [relationName, config];
37
+ if (map) {
38
+ for (const [relationName, config] of Object.entries(map)) {
39
+ for (const inputKey of config.keys) {
40
+ // Preserve current scan semantics: first relation declaring the key wins.
41
+ if (!index.has(inputKey))
42
+ index.set(inputKey, [relationName, config]);
43
+ }
36
44
  }
37
45
  }
38
- return undefined;
46
+ reverseIndexCache.set(target, index);
47
+ return index;
48
+ }
49
+ /**
50
+ * Resolves which relation (if any) owns a given input key.
51
+ * Returns [relationName, RelationConfig] or undefined.
52
+ */
53
+ export function resolveRelation(target, inputKey) {
54
+ return getReverseIndex(target).get(inputKey);
39
55
  }
40
56
  //# sourceMappingURL=relations.decorator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"relations.decorator.js","sourceRoot":"","sources":["../../src/decorator/relations.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AASzD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,SAAS,CAAC,GAAiB;IACzC,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,OAAO,CAAC,cAAc,CAAC,yBAAyB,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IACjE,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,OAAO,CAAC,WAAW,CAAC,yBAAyB,EAAE,MAAM,CAA6B,CAAC;AAC5F,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAc,EACd,QAAgB;IAEhB,MAAM,GAAG,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,KAAK,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACzD,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACnC,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
1
+ {"version":3,"file":"relations.decorator.js","sourceRoot":"","sources":["../../src/decorator/relations.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AASzD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,SAAS,CAAC,GAAiB;IACzC,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,OAAO,CAAC,cAAc,CAAC,yBAAyB,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IACjE,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,OAAO,CAAC,WAAW,CAAC,yBAAyB,EAAE,MAAM,CAA6B,CAAC;AAC5F,CAAC;AAED;;;;GAIG;AACH,MAAM,iBAAiB,GAAG,IAAI,OAAO,EAAiD,CAAC;AAEvF,SAAS,eAAe,CAAC,MAAc;IACrC,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAoC,CAAC;IAC1D,MAAM,GAAG,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,GAAG,EAAE,CAAC;QACR,KAAK,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACzD,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;gBACnC,0EAA0E;gBAC1E,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;oBAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;IACH,CAAC;IAED,iBAAiB,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAc,EACd,QAAgB;IAEhB,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC/C,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  export declare const VERSION = "0.0.0";
2
2
  export { BaseFilter } from './base-filter.js';
3
- export type { FilterAdapter, EntityFieldInfo, EntityRelationInfo } from './adapter/adapter.js';
3
+ export type { FilterAdapter, EntityFieldInfo, EntityRelationInfo, VectorSearchOptions, } from './adapter/adapter.js';
4
4
  export { Filterable, getFilterableMetadata } from './decorator/filterable.decorator.js';
5
+ export { normalizeAllowed, allowedFieldNames } from './decorator/allowed.js';
6
+ export type { NormalizedAllowed } from './decorator/allowed.js';
5
7
  export { FilterFor, getFilterForMap, getFilterForOptsMap, } from './decorator/filter-for.decorator.js';
6
8
  export type { FilterFieldTypeHint, FilterForOptions, } from './decorator/filter-for.decorator.js';
7
9
  export { ApplyFilter, getApplyFilterMetadata } from './decorator/apply-filter.decorator.js';
@@ -15,10 +17,13 @@ export { FilterRunner } from './runner.js';
15
17
  export { FilterModule } from './module.js';
16
18
  export { FilterException, FilterNotRegisteredException, FilterMissingEntityException, FilterStateUnavailableException, UnknownFilterKeyException, FilterValidationException, FilterMissingAdapterException, FilterMethodException, } from './errors/exceptions.js';
17
19
  export { FILTER_MODULE_OPTIONS, FILTER_ADAPTER, FILTERABLE_METADATA, FILTER_FOR_METADATA, FILTER_FOR_OPTS_METADATA, FILTER_RELATIONS_METADATA, APPLY_FILTER_METADATA, APPLY_FILTER_REQ_KEY, TENANT_SCOPED_METADATA, CONTEXT_ACCESSOR, } from './tokens.js';
18
- export type { ApplyFilterOptions, CursorPagination, EntityDescription, FieldMeta, FilterableOptions, FilterContext, FilterInput, FilterInputStrict, FilterInputLoose, FilterMetadata, FilterModuleOptions, FilterModuleOptionsFactory, FilterModuleAsyncOptions, InputNormalizer, InputSource, OffsetPagination, OnUnknownKey, RelationMeta, SortItem, StructuredInput, ValidationMode, } from './types.js';
20
+ export type { AllowedFieldEntry, ApplyFilterOptions, CursorPage, CursorPagination, EntityDescription, FieldMeta, FilterableOptions, FilterContext, FilterInput, FilterInputStrict, FilterInputLoose, FilterMetadata, FilterModuleOptions, FilterModuleOptionsFactory, FilterModuleAsyncOptions, InputFormat, InputNormalizer, InputSource, OffsetPagination, OnUnknownKey, RelationMeta, SortItem, StructuredInput, ValidationMode, } from './types.js';
19
21
  export { resolveInputFromRequest } from './input/source-resolver.js';
20
22
  export { normalizeInput } from './input/normalizer.js';
23
+ export { parseSpatieInput } from './input/spatie-parser.js';
21
24
  export { escapeLike } from './utils/escape-like.js';
25
+ export { encodeCursor, decodeCursor, buildKeyset, extractCursorValues, } from './pagination/cursor.js';
26
+ export type { CursorValues } from './pagination/cursor.js';
22
27
  export type { ColumnFilter, FilterOperator, FilterOperatorAlias, FilterOperatorInput, } from './operators/types.js';
23
28
  export { FILTER_OPERATORS, OPERATOR_ALIASES } from './operators/types.js';
24
29
  export { ColumnFilterDto } from './operators/column-filter.dto.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,UAAU,CAAC;AAE/B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/F,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AACxF,OAAO,EACL,SAAS,EACT,eAAe,EACf,mBAAmB,GACpB,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EACV,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC5F,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACjG,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AACvF,OAAO,EACL,YAAY,EACZ,oBAAoB,GACrB,MAAM,wCAAwC,CAAC;AAChD,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACpF,OAAO,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,eAAe,EACf,4BAA4B,EAC5B,4BAA4B,EAC5B,+BAA+B,EAC/B,yBAAyB,EACzB,yBAAyB,EACzB,6BAA6B,EAC7B,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,qBAAqB,EACrB,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,SAAS,EACT,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,0BAA0B,EAC1B,wBAAwB,EACxB,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,QAAQ,EACR,eAAe,EACf,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,YAAY,EACV,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,wBAAwB,EACxB,gBAAgB,GACjB,MAAM,uCAAuC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export const VERSION = '0.0.0';
2
2
  export { BaseFilter } from './base-filter.js';
3
3
  export { Filterable, getFilterableMetadata } from './decorator/filterable.decorator.js';
4
+ export { normalizeAllowed, allowedFieldNames } from './decorator/allowed.js';
4
5
  export { FilterFor, getFilterForMap, getFilterForOptsMap, } from './decorator/filter-for.decorator.js';
5
6
  export { ApplyFilter, getApplyFilterMetadata } from './decorator/apply-filter.decorator.js';
6
7
  export { Relations, getRelationsMap, resolveRelation } from './decorator/relations.decorator.js';
@@ -13,7 +14,9 @@ export { FilterException, FilterNotRegisteredException, FilterMissingEntityExcep
13
14
  export { FILTER_MODULE_OPTIONS, FILTER_ADAPTER, FILTERABLE_METADATA, FILTER_FOR_METADATA, FILTER_FOR_OPTS_METADATA, FILTER_RELATIONS_METADATA, APPLY_FILTER_METADATA, APPLY_FILTER_REQ_KEY, TENANT_SCOPED_METADATA, CONTEXT_ACCESSOR, } from './tokens.js';
14
15
  export { resolveInputFromRequest } from './input/source-resolver.js';
15
16
  export { normalizeInput } from './input/normalizer.js';
17
+ export { parseSpatieInput } from './input/spatie-parser.js';
16
18
  export { escapeLike } from './utils/escape-like.js';
19
+ export { encodeCursor, decodeCursor, buildKeyset, extractCursorValues, } from './pagination/cursor.js';
17
20
  export { FILTER_OPERATORS, OPERATOR_ALIASES } from './operators/types.js';
18
21
  export { ColumnFilterDto } from './operators/column-filter.dto.js';
19
22
  export { validateColumnFilter, validateColumnFilters, normalizeOperator, InvalidColumnFilterError, MAX_FILTER_DEPTH, } from './operators/validate-column-filter.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AACxF,OAAO,EACL,SAAS,EACT,eAAe,EACf,mBAAmB,GACpB,MAAM,qCAAqC,CAAC;AAK7C,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC5F,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAEjG,OAAO,EACL,YAAY,EACZ,oBAAoB,GACrB,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,eAAe,EACf,4BAA4B,EAC5B,4BAA4B,EAC5B,+BAA+B,EAC/B,yBAAyB,EACzB,yBAAyB,EACzB,6BAA6B,EAC7B,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,qBAAqB,EACrB,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAwBrB,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAOpD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,wBAAwB,EACxB,gBAAgB,GACjB,MAAM,uCAAuC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAO9C,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AACxF,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE7E,OAAO,EACL,SAAS,EACT,eAAe,EACf,mBAAmB,GACpB,MAAM,qCAAqC,CAAC;AAK7C,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC5F,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAEjG,OAAO,EACL,YAAY,EACZ,oBAAoB,GACrB,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,eAAe,EACf,4BAA4B,EAC5B,4BAA4B,EAC5B,+BAA+B,EAC/B,yBAAyB,EACzB,yBAAyB,EACzB,6BAA6B,EAC7B,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,qBAAqB,EACrB,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AA2BrB,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAQhC,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,wBAAwB,EACxB,gBAAgB,GACjB,MAAM,uCAAuC,CAAC"}
@@ -0,0 +1,40 @@
1
+ import type { StructuredInput } from '../types.js';
2
+ /**
3
+ * Parses a spatie-laravel-query-builder / JSON:API-style query input into the
4
+ * library's internal {@link StructuredInput} model.
5
+ *
6
+ * This is an **opt-in** input format (enabled via the `inputFormat: 'spatie'`
7
+ * module option). The default `'native'` format is unchanged. The parser is a
8
+ * pure reshape — it does **not** enforce safety itself; its output flows through
9
+ * the same runner pipeline as native input, so the allowlist, per-field operator
10
+ * allowlist, and `throwOnInvalid` policy still apply.
11
+ *
12
+ * The input is the object produced after a query string has been decoded by
13
+ * Express + `qs` (bracket notation expanded into nested objects):
14
+ *
15
+ * | Query string | Decoded input | Mapped to |
16
+ * | ------------------------------------ | ----------------------------------------------- | ------------------------------------------ |
17
+ * | `filter[name]=Al` | `{ filter: { name: 'Al' } }` | `{ filter: { name: 'Al' } }` (equals) |
18
+ * | `filter[id]=1,2,3` | `{ filter: { id: '1,2,3' } }` | `{ filter: { id: ['1','2','3'] } }` (in) |
19
+ * | `filter[name][contains]=Al` | `{ filter: { name: { contains: 'Al' } } }` | operator object → existing operator path |
20
+ * | `sort=-createdAt,name` | `{ sort: '-createdAt,name' }` | `{ sort: '-createdAt,name' }` |
21
+ * | `include=posts,comments` | `{ include: 'posts,comments' }` | `{ include: 'posts,comments' }` |
22
+ * | `fields[users]=id,name` | `{ fields: { users: 'id,name' } }` | `{ select: ['id','name'] }` (sparse) |
23
+ * | `page[number]=2&page[size]=10` | `{ page: { number: '2', size: '10' } }` | `{ paginate: { page: 2, size: 10 } }` |
24
+ * | `page[after]=cur&page[size]=10` | `{ page: { after: 'cur', size: '10' } }` | `{ paginate: { after, first } }` (cursor) |
25
+ *
26
+ * Design notes:
27
+ * - **Filter values**: a bare scalar is interpreted by the adapter as `equals`;
28
+ * a comma-separated scalar (spatie's convention for multi-value filters) is
29
+ * split into an array (interpreted as `in`); an object whose keys are operators
30
+ * passes straight through to the existing operator-object mechanism.
31
+ * - **Sparse fieldsets** (`fields[resource]`): JSON:API keys these by resource
32
+ * type, but the runner applies a single SELECT to the primary entity, so the
33
+ * per-resource lists are flattened (deduped, order-preserving) into one
34
+ * `select` list and validated against the entity / allowlist downstream.
35
+ * - **Pagination**: JSON:API page-based (`page[number]`/`page[size]`) maps to
36
+ * offset pagination; cursor-style (`page[after]`/`page[before]`) maps to the
37
+ * library's keyset pagination input.
38
+ */
39
+ export declare function parseSpatieInput(input: unknown): StructuredInput;
40
+ //# sourceMappingURL=spatie-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spatie-parser.d.ts","sourceRoot":"","sources":["../../src/input/spatie-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAmChE"}