@adonis-agora/filter 0.0.0-beta-20261110131309

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 (168) hide show
  1. package/CHANGELOG.md +417 -0
  2. package/LICENSE +21 -0
  3. package/README.md +75 -0
  4. package/dist/commands/main.d.ts +19 -0
  5. package/dist/commands/main.d.ts.map +1 -0
  6. package/dist/commands/main.js +19 -0
  7. package/dist/commands/main.js.map +1 -0
  8. package/dist/commands/make_filter.d.ts +18 -0
  9. package/dist/commands/make_filter.d.ts.map +1 -0
  10. package/dist/commands/make_filter.js +32 -0
  11. package/dist/commands/make_filter.js.map +1 -0
  12. package/dist/commands/make_filter_client.d.ts +35 -0
  13. package/dist/commands/make_filter_client.d.ts.map +1 -0
  14. package/dist/commands/make_filter_client.js +85 -0
  15. package/dist/commands/make_filter_client.js.map +1 -0
  16. package/dist/configure.d.ts +15 -0
  17. package/dist/configure.d.ts.map +1 -0
  18. package/dist/configure.js +20 -0
  19. package/dist/configure.js.map +1 -0
  20. package/dist/providers/filter_provider.d.ts +28 -0
  21. package/dist/providers/filter_provider.d.ts.map +1 -0
  22. package/dist/providers/filter_provider.js +33 -0
  23. package/dist/providers/filter_provider.js.map +1 -0
  24. package/dist/src/aggregate.d.ts +70 -0
  25. package/dist/src/aggregate.d.ts.map +1 -0
  26. package/dist/src/aggregate.js +195 -0
  27. package/dist/src/aggregate.js.map +1 -0
  28. package/dist/src/aggregate_path.d.ts +25 -0
  29. package/dist/src/aggregate_path.d.ts.map +1 -0
  30. package/dist/src/aggregate_path.js +35 -0
  31. package/dist/src/aggregate_path.js.map +1 -0
  32. package/dist/src/apply_from_request.d.ts +85 -0
  33. package/dist/src/apply_from_request.d.ts.map +1 -0
  34. package/dist/src/apply_from_request.js +164 -0
  35. package/dist/src/apply_from_request.js.map +1 -0
  36. package/dist/src/base_filter.d.ts +49 -0
  37. package/dist/src/base_filter.d.ts.map +1 -0
  38. package/dist/src/base_filter.js +33 -0
  39. package/dist/src/base_filter.js.map +1 -0
  40. package/dist/src/base_model_filter.d.ts +90 -0
  41. package/dist/src/base_model_filter.d.ts.map +1 -0
  42. package/dist/src/base_model_filter.js +85 -0
  43. package/dist/src/base_model_filter.js.map +1 -0
  44. package/dist/src/coerce_value.d.ts +26 -0
  45. package/dist/src/coerce_value.d.ts.map +1 -0
  46. package/dist/src/coerce_value.js +82 -0
  47. package/dist/src/coerce_value.js.map +1 -0
  48. package/dist/src/cursor.d.ts +92 -0
  49. package/dist/src/cursor.d.ts.map +1 -0
  50. package/dist/src/cursor.js +107 -0
  51. package/dist/src/cursor.js.map +1 -0
  52. package/dist/src/custom_filter.d.ts +36 -0
  53. package/dist/src/custom_filter.d.ts.map +1 -0
  54. package/dist/src/custom_filter.js +127 -0
  55. package/dist/src/custom_filter.js.map +1 -0
  56. package/dist/src/decorator_metadata.d.ts +41 -0
  57. package/dist/src/decorator_metadata.d.ts.map +1 -0
  58. package/dist/src/decorator_metadata.js +83 -0
  59. package/dist/src/decorator_metadata.js.map +1 -0
  60. package/dist/src/decorators.d.ts +73 -0
  61. package/dist/src/decorators.d.ts.map +1 -0
  62. package/dist/src/decorators.js +118 -0
  63. package/dist/src/decorators.js.map +1 -0
  64. package/dist/src/escape-like.d.ts +10 -0
  65. package/dist/src/escape-like.d.ts.map +1 -0
  66. package/dist/src/escape-like.js +15 -0
  67. package/dist/src/escape-like.js.map +1 -0
  68. package/dist/src/field_aliases.d.ts +30 -0
  69. package/dist/src/field_aliases.d.ts.map +1 -0
  70. package/dist/src/field_aliases.js +65 -0
  71. package/dist/src/field_aliases.js.map +1 -0
  72. package/dist/src/filter_class.d.ts +46 -0
  73. package/dist/src/filter_class.d.ts.map +1 -0
  74. package/dist/src/filter_class.js +244 -0
  75. package/dist/src/filter_class.js.map +1 -0
  76. package/dist/src/filter_spec.d.ts +231 -0
  77. package/dist/src/filter_spec.d.ts.map +1 -0
  78. package/dist/src/filter_spec.js +182 -0
  79. package/dist/src/filter_spec.js.map +1 -0
  80. package/dist/src/filterable_mixin.d.ts +49 -0
  81. package/dist/src/filterable_mixin.d.ts.map +1 -0
  82. package/dist/src/filterable_mixin.js +47 -0
  83. package/dist/src/filterable_mixin.js.map +1 -0
  84. package/dist/src/generate_client.d.ts +107 -0
  85. package/dist/src/generate_client.d.ts.map +1 -0
  86. package/dist/src/generate_client.js +164 -0
  87. package/dist/src/generate_client.js.map +1 -0
  88. package/dist/src/group_by_count.d.ts +67 -0
  89. package/dist/src/group_by_count.d.ts.map +1 -0
  90. package/dist/src/group_by_count.js +71 -0
  91. package/dist/src/group_by_count.js.map +1 -0
  92. package/dist/src/in_memory.d.ts +279 -0
  93. package/dist/src/in_memory.d.ts.map +1 -0
  94. package/dist/src/in_memory.js +810 -0
  95. package/dist/src/in_memory.js.map +1 -0
  96. package/dist/src/index.d.ts +51 -0
  97. package/dist/src/index.d.ts.map +1 -0
  98. package/dist/src/index.js +33 -0
  99. package/dist/src/index.js.map +1 -0
  100. package/dist/src/lucid_adapter.d.ts +311 -0
  101. package/dist/src/lucid_adapter.d.ts.map +1 -0
  102. package/dist/src/lucid_adapter.js +469 -0
  103. package/dist/src/lucid_adapter.js.map +1 -0
  104. package/dist/src/lucid_macros.d.ts +87 -0
  105. package/dist/src/lucid_macros.d.ts.map +1 -0
  106. package/dist/src/lucid_macros.js +67 -0
  107. package/dist/src/lucid_macros.js.map +1 -0
  108. package/dist/src/normalizer.d.ts +21 -0
  109. package/dist/src/normalizer.d.ts.map +1 -0
  110. package/dist/src/normalizer.js +61 -0
  111. package/dist/src/normalizer.js.map +1 -0
  112. package/dist/src/operators.d.ts +37 -0
  113. package/dist/src/operators.d.ts.map +1 -0
  114. package/dist/src/operators.js +43 -0
  115. package/dist/src/operators.js.map +1 -0
  116. package/dist/src/paginate.d.ts +12 -0
  117. package/dist/src/paginate.d.ts.map +1 -0
  118. package/dist/src/paginate.js +88 -0
  119. package/dist/src/paginate.js.map +1 -0
  120. package/dist/src/pagination_stash.d.ts +4 -0
  121. package/dist/src/pagination_stash.d.ts.map +1 -0
  122. package/dist/src/pagination_stash.js +19 -0
  123. package/dist/src/pagination_stash.js.map +1 -0
  124. package/dist/src/parse_request.d.ts +50 -0
  125. package/dist/src/parse_request.d.ts.map +1 -0
  126. package/dist/src/parse_request.js +220 -0
  127. package/dist/src/parse_request.js.map +1 -0
  128. package/dist/src/runner.d.ts +65 -0
  129. package/dist/src/runner.d.ts.map +1 -0
  130. package/dist/src/runner.js +371 -0
  131. package/dist/src/runner.js.map +1 -0
  132. package/dist/src/source_resolver.d.ts +18 -0
  133. package/dist/src/source_resolver.d.ts.map +1 -0
  134. package/dist/src/source_resolver.js +64 -0
  135. package/dist/src/source_resolver.js.map +1 -0
  136. package/dist/src/spatie_parser.d.ts +39 -0
  137. package/dist/src/spatie_parser.d.ts.map +1 -0
  138. package/dist/src/spatie_parser.js +134 -0
  139. package/dist/src/spatie_parser.js.map +1 -0
  140. package/dist/src/testing.d.ts +73 -0
  141. package/dist/src/testing.d.ts.map +1 -0
  142. package/dist/src/testing.js +136 -0
  143. package/dist/src/testing.js.map +1 -0
  144. package/dist/src/types.d.ts +226 -0
  145. package/dist/src/types.d.ts.map +1 -0
  146. package/dist/src/types.js +2 -0
  147. package/dist/src/types.js.map +1 -0
  148. package/dist/src/validate-column-filter.d.ts +30 -0
  149. package/dist/src/validate-column-filter.d.ts.map +1 -0
  150. package/dist/src/validate-column-filter.js +148 -0
  151. package/dist/src/validate-column-filter.js.map +1 -0
  152. package/dist/src/value-shape.d.ts +18 -0
  153. package/dist/src/value-shape.d.ts.map +1 -0
  154. package/dist/src/value-shape.js +36 -0
  155. package/dist/src/value-shape.js.map +1 -0
  156. package/dist/stubs/main.d.ts +3 -0
  157. package/dist/stubs/main.d.ts.map +1 -0
  158. package/dist/stubs/main.js +4 -0
  159. package/dist/stubs/main.js.map +1 -0
  160. package/dist/stubs/make/filter/main.stub +45 -0
  161. package/package.json +102 -0
  162. package/skills/filter-basics/SKILL.md +285 -0
  163. package/skills/filter-codegen/SKILL.md +246 -0
  164. package/skills/filter-definitions/SKILL.md +340 -0
  165. package/skills/filter-querying/SKILL.md +319 -0
  166. package/skills/filter-safety/SKILL.md +304 -0
  167. package/stubs/main.ts +4 -0
  168. package/stubs/make/filter/main.stub +45 -0
@@ -0,0 +1,469 @@
1
+ import { escapeLike } from './escape-like.js';
2
+ import { normalizeOperator } from './validate-column-filter.js';
3
+ /** pgvector distance operator for each {@link VectorDistanceMetric}. */
4
+ const VECTOR_OPERATORS = {
5
+ cosine: '<=>',
6
+ l2: '<->',
7
+ innerProduct: '<#>',
8
+ };
9
+ /** A safe SQL identifier: an unquoted column, optionally `table.column` qualified. */
10
+ const SAFE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*$/;
11
+ /** Quote a (possibly dotted) identifier for Postgres, one segment at a time. */
12
+ function quoteColumn(column) {
13
+ return column
14
+ .split('.')
15
+ .map((seg) => `"${seg}"`)
16
+ .join('.');
17
+ }
18
+ /**
19
+ * Serialize a numeric embedding to a pgvector literal (`[1,2,3]`). Returns `null`
20
+ * for an empty vector (a no-op signal). Throws on a non-finite component so a bad
21
+ * embedding fails loudly rather than emitting `NaN`/`Infinity` into SQL.
22
+ */
23
+ function serializeVector(vector) {
24
+ if (vector.length === 0)
25
+ return null;
26
+ for (const n of vector) {
27
+ if (typeof n !== 'number' || !Number.isFinite(n)) {
28
+ throw new TypeError('Vector search embedding must contain only finite numbers.');
29
+ }
30
+ }
31
+ return `[${vector.join(',')}]`;
32
+ }
33
+ /**
34
+ * Apply an **embedding similarity** ordering (pgvector) to a Lucid query builder.
35
+ *
36
+ * This is *not* full-text search — it ranks rows by distance between a stored
37
+ * embedding column and a query *embedding vector*. For matching a text query
38
+ * string, use {@link applyFullTextSearch} instead.
39
+ *
40
+ * pgvector expresses similarity through raw distance operators (`<=>`, `<->`,
41
+ * `<#>`) that no structured query-builder method covers, so this drives the
42
+ * adapter's raw seam ({@link QueryBuilderLike.whereRaw}/`orderByRaw`) with the
43
+ * query embedding passed as a positional binding — the column name is the only
44
+ * interpolated fragment, and it is validated against a strict identifier charset
45
+ * so it can never carry injection. The distance expression is
46
+ * `<column> <op> ?::vector`, cast to `vector` so a text binding compares against
47
+ * the column.
48
+ *
49
+ * A no-op when the embedding is empty. When `order` is not `false`, rows are
50
+ * ordered nearest-first (ascending distance); `threshold` adds a max-distance
51
+ * filter; `topK` truncates to the K nearest.
52
+ */
53
+ export function applyVectorSimilarity(qb, opts) {
54
+ const literal = serializeVector(opts.vector);
55
+ if (literal === null)
56
+ return;
57
+ if (!SAFE_IDENTIFIER.test(opts.column)) {
58
+ throw new TypeError(`Invalid vector column name: ${JSON.stringify(opts.column)}`);
59
+ }
60
+ const operator = VECTOR_OPERATORS[opts.metric ?? 'cosine'];
61
+ const distance = `${quoteColumn(opts.column)} ${operator} ?::vector`;
62
+ if (opts.threshold !== undefined) {
63
+ qb.whereRaw(`${distance} < ?`, [literal, opts.threshold]);
64
+ }
65
+ if (opts.order !== false) {
66
+ qb.orderByRaw(`${distance} asc`, [literal]);
67
+ }
68
+ if (opts.topK !== undefined) {
69
+ qb.limit(opts.topK);
70
+ }
71
+ }
72
+ /**
73
+ * Apply a Postgres **tsvector full-text search** to a Lucid query builder — the
74
+ * parity port of the NestJS reference's `applyVectorSearch` (tsvector), NOT the
75
+ * embedding similarity {@link applyVectorSimilarity}.
76
+ *
77
+ * Injection-safety: the user `query` string ALWAYS travels as a positional
78
+ * binding (`websearch_to_tsquery('<lang>', ?)`); it is never interpolated.
79
+ * `websearch_to_tsquery` (not the raw `to_tsquery`) parses arbitrary user input
80
+ * — multi-word text, `"quoted phrases"`, `-exclude`, `or` — without throwing a
81
+ * syntax error. The only spliced fragments are the column name(s) and the
82
+ * language config, each validated against the strict identifier charset
83
+ * ({@link SAFE_IDENTIFIER}) before use, so neither can carry injection.
84
+ *
85
+ * The match predicate is `<document> @@ websearch_to_tsquery('<lang>', ?)` where
86
+ * `<document>` is either the tsvector column directly, or
87
+ * `to_tsvector('<lang>', coalesce(col1,'') || ' ' || coalesce(col2,''))` for
88
+ * text columns. When `rank` is set, rows are additionally ordered by descending
89
+ * `ts_rank(<document>, websearch_to_tsquery('<lang>', ?))`. A no-op for a blank
90
+ * query.
91
+ */
92
+ export function applyFullTextSearch(qb, opts) {
93
+ const query = opts.query.trim();
94
+ if (query.length === 0)
95
+ return;
96
+ const columns = Array.isArray(opts.column) ? opts.column : [opts.column];
97
+ if (columns.length === 0)
98
+ return;
99
+ for (const col of columns) {
100
+ if (!SAFE_IDENTIFIER.test(col)) {
101
+ throw new TypeError(`Invalid full-text search column name: ${JSON.stringify(col)}`);
102
+ }
103
+ }
104
+ const language = opts.language ?? 'english';
105
+ if (!SAFE_IDENTIFIER.test(language)) {
106
+ throw new TypeError(`Invalid full-text search language: ${JSON.stringify(language)}`);
107
+ }
108
+ // The user query is a positional binding; only the validated language splices in.
109
+ const tsquery = `websearch_to_tsquery('${language}', ?)`;
110
+ // A precomputed tsvector column is matched directly; text columns are tokenized
111
+ // at query time via to_tsvector, coalescing NULLs so a null column can't null
112
+ // the whole document.
113
+ const kind = opts.columnKind ?? (columns.length > 1 ? 'text' : 'tsvector');
114
+ const document = kind === 'text'
115
+ ? `to_tsvector('${language}', ${columns
116
+ .map((c) => `coalesce(${quoteColumn(c)}, '')`)
117
+ .join(" || ' ' || ")})`
118
+ : quoteColumn(columns[0]);
119
+ qb.whereRaw(`${document} @@ ${tsquery}`, [query]);
120
+ if (opts.rank) {
121
+ qb.orderByRaw(`ts_rank(${document}, ${tsquery}) desc`, [query]);
122
+ }
123
+ }
124
+ /** Wrap a value as a LIKE pattern with escaped metacharacters. */
125
+ function like(value, kind) {
126
+ const v = escapeLike(String(value));
127
+ if (kind === 'startsWith')
128
+ return `${v}%`;
129
+ if (kind === 'endsWith')
130
+ return `%${v}`;
131
+ return `%${v}%`;
132
+ }
133
+ /**
134
+ * Apply a single (leaf) column filter to the builder.
135
+ *
136
+ * A dotted `field` is a **relation path** (`posts.title`, `posts.comments.body`):
137
+ * every segment but the last is a relation hop, translated into a nested Lucid
138
+ * `whereHas` subquery, and the final segment is the bare column the operator
139
+ * lands on inside the innermost relation query — so `posts.title = x` becomes
140
+ * `whereHas('posts', (q) => q.where('title', x))`. Depth is already bounded by
141
+ * the spec's `maxDepth` allow-list before a filter reaches the adapter, so this
142
+ * only translates paths that were explicitly whitelisted. A non-dotted `field`
143
+ * is a plain base column and takes the operator switch directly.
144
+ */
145
+ function applyLeaf(qb, field, operator, value) {
146
+ const dot = field.indexOf('.');
147
+ if (dot !== -1) {
148
+ const relation = field.slice(0, dot);
149
+ const rest = field.slice(dot + 1);
150
+ qb.whereHas(relation, (sub) => applyLeaf(sub, rest, operator, value));
151
+ return;
152
+ }
153
+ switch (operator) {
154
+ case 'equals':
155
+ qb.where(field, value);
156
+ break;
157
+ case 'notEquals':
158
+ qb.whereNot(field, value);
159
+ break;
160
+ case 'contains':
161
+ case 'iContains':
162
+ qb.whereILike(field, like(value, 'contains'));
163
+ break;
164
+ case 'startsWith':
165
+ qb.whereILike(field, like(value, 'startsWith'));
166
+ break;
167
+ case 'endsWith':
168
+ qb.whereILike(field, like(value, 'endsWith'));
169
+ break;
170
+ case 'notContains':
171
+ qb.where((sub) => sub
172
+ .whereNotNull(field)
173
+ .whereNot((inner) => inner.whereILike(field, like(value, 'contains'))));
174
+ break;
175
+ case 'gt':
176
+ qb.where(field, '>', value);
177
+ break;
178
+ case 'gte':
179
+ qb.where(field, '>=', value);
180
+ break;
181
+ case 'lt':
182
+ qb.where(field, '<', value);
183
+ break;
184
+ case 'lte':
185
+ qb.where(field, '<=', value);
186
+ break;
187
+ case 'between':
188
+ qb.whereBetween(field, value);
189
+ break;
190
+ case 'notBetween':
191
+ qb.whereNotBetween(field, value);
192
+ break;
193
+ case 'in':
194
+ case 'isAnyOf':
195
+ qb.whereIn(field, value);
196
+ break;
197
+ case 'notIn':
198
+ qb.whereNotIn(field, value);
199
+ break;
200
+ case 'isNull':
201
+ case 'notExists':
202
+ qb.whereNull(field);
203
+ break;
204
+ case 'isNotNull':
205
+ case 'exists':
206
+ qb.whereNotNull(field);
207
+ break;
208
+ case 'isEmpty':
209
+ qb.where(field, '');
210
+ break;
211
+ case 'isNotEmpty':
212
+ qb.whereNot(field, '');
213
+ break;
214
+ }
215
+ }
216
+ /**
217
+ * Apply one {@link ColumnFilter} (possibly an AND/OR group) to a builder. A leaf
218
+ * is a single condition; `AND`/`OR` recurse into a grouped sub-builder so the
219
+ * boolean structure maps to Lucid's nested `where`/`orWhere` closures.
220
+ */
221
+ function applyOne(qb, filter) {
222
+ const op = normalizeOperator(filter.operator);
223
+ const hasField = typeof filter.field === 'string' && filter.field.length > 0;
224
+ qb.where((group) => {
225
+ if (hasField) {
226
+ applyLeaf(group, filter.field, op, filter.value);
227
+ }
228
+ if (filter.AND) {
229
+ for (const sub of filter.AND) {
230
+ group.where((g) => applyOne(g, sub));
231
+ }
232
+ }
233
+ if (filter.OR) {
234
+ for (const sub of filter.OR) {
235
+ group.orWhere((g) => applyOne(g, sub));
236
+ }
237
+ }
238
+ });
239
+ }
240
+ /** Apply an array of column filters (combined with AND) to a Lucid query builder. */
241
+ export function applyColumnFilters(qb, filters) {
242
+ for (const filter of filters) {
243
+ applyOne(qb, filter);
244
+ }
245
+ }
246
+ /** Apply sort directives to a Lucid query builder, in order. */
247
+ export function applySort(qb, sorts) {
248
+ for (const sort of sorts) {
249
+ qb.orderBy(sort.field, sort.direction);
250
+ }
251
+ }
252
+ /**
253
+ * Apply a DISTINCT projection over `columns` to a Lucid query builder — the
254
+ * executable half of the client's `.distinct(...)` (which until now the server
255
+ * silently ignored). A no-op for an empty list. The columns are the
256
+ * already-validated, alias-resolved field names (the runner resolves aliases and
257
+ * enforces the allow-list before calling this), so nothing client-controlled is
258
+ * interpolated: Lucid quotes each identifier itself.
259
+ */
260
+ export function applyDistinct(qb, columns) {
261
+ if (columns.length === 0)
262
+ return;
263
+ qb.distinct(...columns);
264
+ }
265
+ /**
266
+ * Terminal group-by-count aggregation over one column:
267
+ * `SELECT <col> AS value, COUNT(*) AS count … GROUP BY <col>`, most groups first —
268
+ * what populates a filter dropdown. `column` must already be validated (allow-listed): it is
269
+ * interpolated as an identifier, while every client VALUE rides a positional binding.
270
+ *
271
+ * Fixed ordering (count desc, value asc) is load-bearing, not cosmetic: the answer is pageable,
272
+ * and paging an unordered listing repeats and skips rows.
273
+ *
274
+ * Requires a builder carrying the optional aggregation seam (`select`/`count`/`groupBy`/`offset`);
275
+ * throws a plain `Error` naming the missing method otherwise, so a minimal custom implementation
276
+ * fails loudly instead of silently returning entity rows.
277
+ */
278
+ export function applyGroupByCount(qb, column, opts = {}) {
279
+ if (!qb.select || !qb.count || !qb.groupBy || !qb.offset) {
280
+ throw new Error('groupByCount needs a builder with select/count/groupBy/offset — the active one does not implement the aggregation seam.');
281
+ }
282
+ qb.select(`${column} AS value`);
283
+ qb.count('* AS count');
284
+ const needle = opts.search?.trim();
285
+ if (needle) {
286
+ qb.whereRaw(`LOWER(??) LIKE ?`, [column, `%${escapeLike(needle.toLowerCase())}%`]);
287
+ }
288
+ qb.groupBy(column);
289
+ qb.orderBy('count', 'desc');
290
+ qb.orderBy(column, 'asc');
291
+ if (opts.limit !== undefined)
292
+ qb.limit(Math.max(0, opts.limit));
293
+ if (opts.offset !== undefined)
294
+ qb.offset(Math.max(0, opts.offset));
295
+ }
296
+ /**
297
+ * Resolve a {@link ComputedSource} to its final SQL expression string. The
298
+ * string form is verbatim; the function form is invoked with the root table
299
+ * {@link ComputedContext} so it can splice the outer alias into a correlated
300
+ * subquery. Either way the result is dev-authored — never client text.
301
+ */
302
+ export function resolveComputedExpression(source, alias) {
303
+ return typeof source === 'function' ? source({ alias }) : source;
304
+ }
305
+ /**
306
+ * Apply a filter on a dev-declared **computed field** to a Lucid query builder.
307
+ *
308
+ * The already-resolved `expression` is inlined as the raw left-hand side (it is
309
+ * dev-authored — a verbatim string or a function's output — never client text);
310
+ * the client's filter VALUE always rides through as a positional `?` binding,
311
+ * exactly the injection-safety contract real-column filters have. The whole
312
+ * expression is parenthesized so a compound source
313
+ * (`first || ' ' || last`, `(SELECT …)`) composes under the operator without a
314
+ * precedence surprise.
315
+ */
316
+ export function applyComputedField(qb, expression, filter) {
317
+ const op = normalizeOperator(filter.operator);
318
+ const value = filter.value;
319
+ const lhs = `(${expression})`;
320
+ switch (op) {
321
+ case 'equals':
322
+ qb.whereRaw(`${lhs} = ?`, [value]);
323
+ break;
324
+ case 'notEquals':
325
+ qb.whereRaw(`${lhs} <> ?`, [value]);
326
+ break;
327
+ case 'gt':
328
+ qb.whereRaw(`${lhs} > ?`, [value]);
329
+ break;
330
+ case 'gte':
331
+ qb.whereRaw(`${lhs} >= ?`, [value]);
332
+ break;
333
+ case 'lt':
334
+ qb.whereRaw(`${lhs} < ?`, [value]);
335
+ break;
336
+ case 'lte':
337
+ qb.whereRaw(`${lhs} <= ?`, [value]);
338
+ break;
339
+ case 'in':
340
+ case 'isAnyOf': {
341
+ const values = Array.isArray(value) ? value : [];
342
+ // An empty IN list matches nothing — emit an always-false predicate rather
343
+ // than invalid `IN ()` SQL.
344
+ if (values.length === 0)
345
+ qb.whereRaw('1 = 0');
346
+ else
347
+ qb.whereRaw(`${lhs} in (${values.map(() => '?').join(', ')})`, values);
348
+ break;
349
+ }
350
+ case 'notIn': {
351
+ const values = Array.isArray(value) ? value : [];
352
+ if (values.length === 0)
353
+ qb.whereRaw('1 = 1');
354
+ else
355
+ qb.whereRaw(`${lhs} not in (${values.map(() => '?').join(', ')})`, values);
356
+ break;
357
+ }
358
+ case 'between': {
359
+ const [low, high] = value;
360
+ qb.whereRaw(`${lhs} between ? and ?`, [low, high]);
361
+ break;
362
+ }
363
+ case 'notBetween': {
364
+ const [low, high] = value;
365
+ qb.whereRaw(`${lhs} not between ? and ?`, [low, high]);
366
+ break;
367
+ }
368
+ case 'contains':
369
+ case 'iContains':
370
+ qb.whereRaw(`${lhs} ilike ?`, [like(value, 'contains')]);
371
+ break;
372
+ case 'notContains':
373
+ qb.whereRaw(`(${lhs} not ilike ? or ${lhs} is null)`, [like(value, 'contains')]);
374
+ break;
375
+ case 'startsWith':
376
+ qb.whereRaw(`${lhs} ilike ?`, [like(value, 'startsWith')]);
377
+ break;
378
+ case 'endsWith':
379
+ qb.whereRaw(`${lhs} ilike ?`, [like(value, 'endsWith')]);
380
+ break;
381
+ case 'isNull':
382
+ case 'notExists':
383
+ qb.whereRaw(`${lhs} is null`);
384
+ break;
385
+ case 'isNotNull':
386
+ case 'exists':
387
+ qb.whereRaw(`${lhs} is not null`);
388
+ break;
389
+ case 'isEmpty':
390
+ qb.whereRaw(`${lhs} = ?`, ['']);
391
+ break;
392
+ case 'isNotEmpty':
393
+ qb.whereRaw(`${lhs} <> ?`, ['']);
394
+ break;
395
+ }
396
+ }
397
+ /**
398
+ * Append an ORDER BY on a dev-declared **computed field** to a Lucid query
399
+ * builder via `orderByRaw`. Uses append semantics (like `orderBy`) so a computed
400
+ * sort composes with real-column sorts in request order. The expression is
401
+ * dev-authored and parenthesized; the direction is a validated literal.
402
+ */
403
+ export function applyComputedSort(qb, expression, direction) {
404
+ qb.orderByRaw(`(${expression}) ${direction === 'desc' ? 'desc' : 'asc'}`);
405
+ }
406
+ /**
407
+ * Apply a keyset (cursor) seek predicate to a Lucid query builder for row-value
408
+ * comparison across the keyset columns.
409
+ *
410
+ * Given a keyset (the active sort columns plus a primary-key tiebreaker, each
411
+ * with a direction) and a boundary row's values, this constrains the query to
412
+ * rows strictly *after* the boundary in keyset order. The row-value comparison
413
+ * is expanded into the portable "OR of AND tiers" form that works across all
414
+ * SQL dialects:
415
+ *
416
+ * ```text
417
+ * (c0 OP0 v0)
418
+ * OR (c0 = v0 AND c1 OP1 v1)
419
+ * OR (c0 = v0 AND c1 = v1 AND c2 OP2 v2) ...
420
+ * ```
421
+ *
422
+ * where `OPi` is `>` for an `asc` column and `<` for a `desc` column. The whole
423
+ * predicate is wrapped in one AND-group so it composes with any existing
424
+ * `where` conditions. A no-op when the keyset is empty or `values` does not line
425
+ * up positionally with it.
426
+ *
427
+ * With more than one column, the group is preceded by the bound every tier
428
+ * already implies, `c0 >= v0` (`<=` for `desc`): Postgres cannot derive an index
429
+ * range from the OR form alone and would scan from the start of the index. The
430
+ * bound is skipped when `v0` is null, where the OR form matches no `c0 > NULL`
431
+ * tier and a `>= NULL` bound would wrongly match nothing.
432
+ */
433
+ export function applyKeyset(qb, keyset, values) {
434
+ if (keyset.length === 0 || values.length !== keyset.length)
435
+ return;
436
+ const lead = keyset[0];
437
+ if (keyset.length > 1 && values[0] !== null && values[0] !== undefined) {
438
+ qb.where(lead.field, lead.direction === 'asc' ? '>=' : '<=', values[0]);
439
+ }
440
+ qb.where((outer) => {
441
+ for (let tier = 0; tier < keyset.length; tier++) {
442
+ const buildTier = (inner) => {
443
+ // Equality on every column before this tier.
444
+ for (let i = 0; i < tier; i++) {
445
+ inner.where(keyset[i].field, values[i]);
446
+ }
447
+ const cmp = keyset[tier].direction === 'asc' ? '>' : '<';
448
+ inner.where(keyset[tier].field, cmp, values[tier]);
449
+ };
450
+ // First tier seeds the group with AND; the rest OR onto it.
451
+ if (tier === 0)
452
+ outer.where(buildTier);
453
+ else
454
+ outer.orWhere(buildTier);
455
+ }
456
+ });
457
+ }
458
+ /** Apply a free-text ILIKE search across `columns` (OR-combined) to a Lucid query builder. */
459
+ export function applySearch(qb, term, columns) {
460
+ if (columns.length === 0 || term.length === 0)
461
+ return;
462
+ const pattern = like(term, 'contains');
463
+ qb.where((group) => {
464
+ for (const column of columns) {
465
+ group.orWhereILike(column, pattern);
466
+ }
467
+ });
468
+ }
469
+ //# sourceMappingURL=lucid_adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lucid_adapter.js","sourceRoot":"","sources":["../../src/lucid_adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ import { type ApplyFromRequestOptions, type FilterRequestContext } from './apply_from_request.js';
2
+ import { type FilterClass } from './filter_class.js';
3
+ import type { FilterSpec } from './filter_spec.js';
4
+ import type { ResolvedPagination } from './runner.js';
5
+ /**
6
+ * The static slice of a Lucid query-builder class we register onto: Adonis'
7
+ * `Macroable.macro(name, fn)` adds `fn` to the builder prototype so every query
8
+ * instance gains the method. Declared structurally so this module never
9
+ * hard-imports `@adonisjs/lucid` at runtime (the provider passes the real
10
+ * `ModelQueryBuilder` in) — matching how the rest of the package stays
11
+ * framework-free.
12
+ */
13
+ export interface MacroableQueryBuilder {
14
+ macro(name: string, fn: (this: unknown, ...args: never[]) => unknown): void;
15
+ }
16
+ /**
17
+ * Register the chainable filter macros onto a Lucid query-builder class (the
18
+ * method-call form of {@link applyFilterFromRequest}). Call this from a provider's
19
+ * `boot()` with `ModelQueryBuilder` (from `@adonisjs/lucid/orm`); the
20
+ * `@adonis-agora/filter` provider does exactly that.
21
+ *
22
+ * Two macros are added:
23
+ *
24
+ * - `query.applyFilterFromRequest(spec, ctx, options?)` — applies the spec's
25
+ * server scope + allow-listed filter/sort/search and returns the query so it
26
+ * chains (`User.query().applyFilterFromRequest(spec, ctx).orderBy(...)`). The
27
+ * resolved pagination is dropped; use `filterPaginate` (or the free function)
28
+ * when you need it.
29
+ * - `query.filterPaginate(spec, ctx, options?)` — applies the same and then
30
+ * `paginate(page, size)` with the resolved pagination, returning Lucid's
31
+ * paginator (`await User.query().filterPaginate(spec, ctx)`).
32
+ *
33
+ * Idempotent enough to call once at boot; calling twice re-defines the macros to
34
+ * the same implementations.
35
+ */
36
+ export declare function registerFilterMacros(ModelQueryBuilder: MacroableQueryBuilder): void;
37
+ declare module '@adonisjs/lucid/types/model' {
38
+ interface ModelQueryBuilderContract<Model extends LucidModel, Result = InstanceType<Model>> {
39
+ /**
40
+ * Apply a {@link FilterSpec} from the request context (server scope +
41
+ * allow-listed filter/sort/search) and return the query for chaining — the
42
+ * method form of the free `applyFilterFromRequest`. Pagination is resolved
43
+ * but not returned here; use {@link filterPaginate} when you need it.
44
+ *
45
+ * `ctx` is optional: when omitted, the active `HttpContext` is read from
46
+ * AsyncLocalStorage (`HttpContext.getOrFail()`). Pass it explicitly outside a
47
+ * request scope (e.g. a job/command), where there is no ambient context.
48
+ */
49
+ applyFilterFromRequest(spec: FilterSpec, ctx?: FilterRequestContext, options?: ApplyFromRequestOptions): this;
50
+ /**
51
+ * The same for a filter **class**: resolved through the IoC container (so `@inject()` works),
52
+ * `setup()` first, then every request key the class owns a method for.
53
+ *
54
+ * Resolution is async, so this returns a promise — of the resolved `{ page, size }`, not of
55
+ * the builder (a Lucid builder is thenable, so awaiting a promise of one would run the query).
56
+ * The builder is the one you called it on, still yours to compose on:
57
+ *
58
+ * ```ts
59
+ * const query = User.query().whereNull('deletedAt')
60
+ * const { page, size } = await query.applyFilterFromRequest(UserFilter)
61
+ * return query.preload('team').paginate(page, size)
62
+ * ```
63
+ */
64
+ applyFilterFromRequest(filter: FilterClass, ctx?: FilterRequestContext, options?: ApplyFromRequestOptions): Promise<ResolvedPagination>;
65
+ /**
66
+ * Apply a {@link FilterSpec} from the request context and paginate with the
67
+ * resolved `{ page, size }`, returning Lucid's paginator — filter + paginate
68
+ * in one terminal call. `ctx` is optional (see {@link applyFilterFromRequest}).
69
+ */
70
+ filterPaginate(spec: FilterSpec, ctx?: FilterRequestContext, options?: ApplyFromRequestOptions): ReturnType<this['paginate']>;
71
+ /** The filter-class form of {@link filterPaginate} — async, for the same reason. */
72
+ filterPaginate(filter: FilterClass, ctx?: FilterRequestContext, options?: ApplyFromRequestOptions): Promise<Awaited<ReturnType<this['paginate']>>>;
73
+ /**
74
+ * Page a query that has **already** been filtered (by the model's `filter()` or by the
75
+ * `applyFilterFromRequest` macro) with the `{ page, size }` that call resolved — so a
76
+ * controller can keep composing on the builder and still page it the way the request asked.
77
+ *
78
+ * ```ts
79
+ * const query = await User.filter(ctx)
80
+ * query.whereNotNull('confirmedAt')
81
+ * return query.filterPaginate()
82
+ * ```
83
+ */
84
+ filterPaginate(): ReturnType<this['paginate']>;
85
+ }
86
+ }
87
+ //# sourceMappingURL=lucid_macros.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lucid_macros.d.ts","sourceRoot":"","sources":["../../src/lucid_macros.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,uBAAuB,EAE5B,KAAK,oBAAoB,EAC1B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,KAAK,WAAW,EAAiB,MAAM,mBAAmB,CAAC;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAYtD;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,GAAG,IAAI,CAAC;CAC7E;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAAC,iBAAiB,EAAE,qBAAqB,GAAG,IAAI,CA+CnF;AAED,OAAO,QAAQ,6BAA6B,CAAC;IAC3C,UAAU,yBAAyB,CAAC,KAAK,SAAS,UAAU,EAAE,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC;QACxF;;;;;;;;;WASG;QACH,sBAAsB,CACpB,IAAI,EAAE,UAAU,EAChB,GAAG,CAAC,EAAE,oBAAoB,EAC1B,OAAO,CAAC,EAAE,uBAAuB,GAChC,IAAI,CAAC;QACR;;;;;;;;;;;;;WAaG;QACH,sBAAsB,CACpB,MAAM,EAAE,WAAW,EACnB,GAAG,CAAC,EAAE,oBAAoB,EAC1B,OAAO,CAAC,EAAE,uBAAuB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CAAC;QAC/B;;;;WAIG;QACH,cAAc,CACZ,IAAI,EAAE,UAAU,EAChB,GAAG,CAAC,EAAE,oBAAoB,EAC1B,OAAO,CAAC,EAAE,uBAAuB,GAChC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAChC,oFAAoF;QACpF,cAAc,CACZ,MAAM,EAAE,WAAW,EACnB,GAAG,CAAC,EAAE,oBAAoB,EAC1B,OAAO,CAAC,EAAE,uBAAuB,GAChC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD;;;;;;;;;;WAUG;QACH,cAAc,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;KAChD;CACF"}
@@ -0,0 +1,67 @@
1
+ import { HttpContext } from '@adonisjs/core/http';
2
+ import { applyFilterFromRequest, } from './apply_from_request.js';
3
+ import { isFilterClass } from './filter_class.js';
4
+ import { paginate } from './paginate.js';
5
+ import { readPagination, stashPagination } from './pagination_stash.js';
6
+ /**
7
+ * O ctx da request para o macro: explícito, ou o `HttpContext` ativo lido do AsyncLocalStorage do
8
+ * Adonis quando omitido. `getOrFail()` lança quando não há request em escopo (ex.: chamada dentro de
9
+ * um job/command) — nesse caso passe o ctx explicitamente. Fica no macro (camada Adonis); o
10
+ * `applyFilterFromRequest` livre continua framework-agnostic, exigindo o ctx.
11
+ */
12
+ function resolveCtx(ctx) {
13
+ return ctx ?? HttpContext.getOrFail();
14
+ }
15
+ /**
16
+ * Register the chainable filter macros onto a Lucid query-builder class (the
17
+ * method-call form of {@link applyFilterFromRequest}). Call this from a provider's
18
+ * `boot()` with `ModelQueryBuilder` (from `@adonisjs/lucid/orm`); the
19
+ * `@adonis-agora/filter` provider does exactly that.
20
+ *
21
+ * Two macros are added:
22
+ *
23
+ * - `query.applyFilterFromRequest(spec, ctx, options?)` — applies the spec's
24
+ * server scope + allow-listed filter/sort/search and returns the query so it
25
+ * chains (`User.query().applyFilterFromRequest(spec, ctx).orderBy(...)`). The
26
+ * resolved pagination is dropped; use `filterPaginate` (or the free function)
27
+ * when you need it.
28
+ * - `query.filterPaginate(spec, ctx, options?)` — applies the same and then
29
+ * `paginate(page, size)` with the resolved pagination, returning Lucid's
30
+ * paginator (`await User.query().filterPaginate(spec, ctx)`).
31
+ *
32
+ * Idempotent enough to call once at boot; calling twice re-defines the macros to
33
+ * the same implementations.
34
+ */
35
+ export function registerFilterMacros(ModelQueryBuilder) {
36
+ ModelQueryBuilder.macro('applyFilterFromRequest', function (filter, ctx, options) {
37
+ // A class is resolved through the container, so this leg is async — and it resolves to the
38
+ // pagination rather than to the builder: a Lucid query builder is thenable, so a promise that
39
+ // resolved to one would execute the query instead of handing it back. You already hold the
40
+ // builder; `await query.applyFilterFromRequest(UserFilter)` gives you its `{ page, size }`.
41
+ if (isFilterClass(filter)) {
42
+ return applyFilterFromRequest(this, filter, resolveCtx(ctx), options).then((pagination) => {
43
+ stashPagination(this, pagination);
44
+ return pagination;
45
+ });
46
+ }
47
+ stashPagination(this, applyFilterFromRequest(this, filter, resolveCtx(ctx), options));
48
+ return this;
49
+ });
50
+ ModelQueryBuilder.macro('filterPaginate', function (filter, ctx, options) {
51
+ // No filter argument: this query has already been through one (the model's `filter()`, or the
52
+ // `applyFilterFromRequest` macro), so page it with the pagination that call resolved.
53
+ if (filter === undefined) {
54
+ const stashed = readPagination(this);
55
+ if (!stashed) {
56
+ throw new Error('filterPaginate() was called with no filter on a query that has not been filtered. Pass the filter — filterPaginate(UserFilter) — or apply one first.');
57
+ }
58
+ return paginate(this, stashed.page, stashed.size);
59
+ }
60
+ if (isFilterClass(filter)) {
61
+ return applyFilterFromRequest(this, filter, resolveCtx(ctx), options).then(({ page, size }) => paginate(this, page, size));
62
+ }
63
+ const { page, size } = applyFilterFromRequest(this, filter, resolveCtx(ctx), options);
64
+ return paginate(this, page, size);
65
+ });
66
+ }
67
+ //# sourceMappingURL=lucid_macros.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lucid_macros.js","sourceRoot":"","sources":["../../src/lucid_macros.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAEL,sBAAsB,GAEvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAoB,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGpE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxE;;;;;GAKG;AACH,SAAS,UAAU,CAAC,GAAqC;IACvD,OAAO,GAAG,IAAI,WAAW,CAAC,SAAS,EAAE,CAAC;AACxC,CAAC;AAcD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,oBAAoB,CAAC,iBAAwC;IAC3E,iBAAiB,CAAC,KAAK,CAAC,wBAAwB,EAAE,UAEhD,MAAgC,EAChC,GAA0B,EAC1B,OAAiC;QAEjC,2FAA2F;QAC3F,8FAA8F;QAC9F,2FAA2F;QAC3F,4FAA4F;QAC5F,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,OAAO,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE;gBACxF,eAAe,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;gBAClC,OAAO,UAAU,CAAC;YACpB,CAAC,CAAC,CAAC;QACL,CAAC;QACD,eAAe,CAAC,IAAI,EAAE,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QACtF,OAAO,IAAI,CAAC;IACd,CAAiD,CAAC,CAAC;IAEnD,iBAAiB,CAAC,KAAK,CAAC,gBAAgB,EAAE,UAExC,MAAiC,EACjC,GAA0B,EAC1B,OAAiC;QAEjC,8FAA8F;QAC9F,sFAAsF;QACtF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;YACrC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CACb,sJAAsJ,CACvJ,CAAC;YACJ,CAAC;YACD,OAAO,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACpD,CAAC;QAED,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,OAAO,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CACxE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAsB,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CACnE,CAAC;QACJ,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;QACtF,OAAO,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACpC,CAAiD,CAAC,CAAC;AACrD,CAAC"}