@adonis-agora/filter-client 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +21 -0
- package/dist/field-types.d.ts +68 -0
- package/dist/field-types.d.ts.map +1 -0
- package/dist/field-types.js +2 -0
- package/dist/field-types.js.map +1 -0
- package/dist/filter-query-builder.d.ts +301 -0
- package/dist/filter-query-builder.d.ts.map +1 -0
- package/dist/filter-query-builder.js +538 -0
- package/dist/filter-query-builder.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/tanstack.d.ts +58 -0
- package/dist/tanstack.d.ts.map +1 -0
- package/dist/tanstack.js +58 -0
- package/dist/tanstack.js.map +1 -0
- package/dist/to-query-string.d.ts +17 -0
- package/dist/to-query-string.d.ts.map +1 -0
- package/dist/to-query-string.js +72 -0
- package/dist/to-query-string.js.map +1 -0
- package/dist/typed-filter-query-builder.d.ts +78 -0
- package/dist/typed-filter-query-builder.d.ts.map +1 -0
- package/dist/typed-filter-query-builder.js +25 -0
- package/dist/typed-filter-query-builder.js.map +1 -0
- package/dist/typed-filter-query.d.ts +20 -0
- package/dist/typed-filter-query.d.ts.map +1 -0
- package/dist/typed-filter-query.js +2 -0
- package/dist/typed-filter-query.js.map +1 -0
- package/dist/types.d.ts +20 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +28 -0
- package/dist/types.js.map +1 -0
- package/dist/validate-operator-value.d.ts +35 -0
- package/dist/validate-operator-value.d.ts.map +1 -0
- package/dist/validate-operator-value.js +91 -0
- package/dist/validate-operator-value.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
import { columnFiltersToQueryString, flatObjectToQueryString } from './to-query-string.js';
|
|
2
|
+
import { validateAddOperator, validateOperatorValue } from './validate-operator-value.js';
|
|
3
|
+
/**
|
|
4
|
+
* Client-side query builder for @agora/filter.
|
|
5
|
+
* Zero dependencies. Runs in browser + Node.
|
|
6
|
+
*/
|
|
7
|
+
export class FilterQueryBuilder {
|
|
8
|
+
conditions = [];
|
|
9
|
+
groups = [];
|
|
10
|
+
extra = {};
|
|
11
|
+
includes = [];
|
|
12
|
+
searchTerm;
|
|
13
|
+
sorts = [];
|
|
14
|
+
distinctFields = [];
|
|
15
|
+
pagination;
|
|
16
|
+
// ─── Reactivity (framework-agnostic store contract) ──────────────────────
|
|
17
|
+
// The builder doubles as an observable store so framework adapters
|
|
18
|
+
// (React's useSyncExternalStore, Vue refs, Svelte stores) can react to
|
|
19
|
+
// mutations. `version` increments on every mutation; `snapshot` caches the
|
|
20
|
+
// last `build()` so `getSnapshot()` returns a stable reference until the
|
|
21
|
+
// next mutation — required by useSyncExternalStore to avoid render loops.
|
|
22
|
+
version = 0;
|
|
23
|
+
snapshot = null;
|
|
24
|
+
listeners = new Set();
|
|
25
|
+
where(field, operatorOrValue, maybeValue) {
|
|
26
|
+
// Remove any existing filter(s) for this field
|
|
27
|
+
this.conditions = this.conditions.filter((c) => c.field !== field);
|
|
28
|
+
if (maybeValue !== undefined) {
|
|
29
|
+
// Three-arg form: where(field, operator, value)
|
|
30
|
+
const op = operatorOrValue;
|
|
31
|
+
validateOperatorValue(op, maybeValue);
|
|
32
|
+
this.conditions.push({
|
|
33
|
+
field,
|
|
34
|
+
operator: op,
|
|
35
|
+
value: maybeValue,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
else if (Array.isArray(operatorOrValue)) {
|
|
39
|
+
// Array value → auto in
|
|
40
|
+
this.conditions.push({
|
|
41
|
+
field,
|
|
42
|
+
operator: 'in',
|
|
43
|
+
value: operatorOrValue,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
else if (typeof operatorOrValue === 'string' &&
|
|
47
|
+
['isNull', 'isNotNull', 'isEmpty', 'isNotEmpty', 'exists', 'notExists'].includes(operatorOrValue)) {
|
|
48
|
+
// Two-arg form with unary operator: where(field, 'isNull')
|
|
49
|
+
validateOperatorValue(operatorOrValue, undefined);
|
|
50
|
+
this.conditions.push({
|
|
51
|
+
field,
|
|
52
|
+
operator: operatorOrValue,
|
|
53
|
+
value: undefined,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
// Simple value → equals
|
|
58
|
+
this.conditions.push({
|
|
59
|
+
field,
|
|
60
|
+
operator: 'equals',
|
|
61
|
+
value: operatorOrValue,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
this.notify();
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
67
|
+
add(field, operator, value) {
|
|
68
|
+
validateAddOperator(operator);
|
|
69
|
+
validateOperatorValue(operator, value);
|
|
70
|
+
this.conditions.push({ field, operator, value });
|
|
71
|
+
this.notify();
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Removes ALL filters for a given field (both from `where()` and `add()`).
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* filterQuery()
|
|
79
|
+
* .equals('status', 'COMPLETED')
|
|
80
|
+
* .contains('name', 'fleet')
|
|
81
|
+
* .remove('status')
|
|
82
|
+
* .build();
|
|
83
|
+
* // → { where: [{ field: 'name', operator: 'contains', value: 'fleet' }] }
|
|
84
|
+
*/
|
|
85
|
+
remove(field) {
|
|
86
|
+
this.conditions = this.conditions.filter((c) => c.field !== field);
|
|
87
|
+
this.notify();
|
|
88
|
+
return this;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Removes all filters and extra keys, resetting the builder to its initial state.
|
|
92
|
+
*/
|
|
93
|
+
clear() {
|
|
94
|
+
this.conditions = [];
|
|
95
|
+
this.groups.length = 0;
|
|
96
|
+
this.extra = {};
|
|
97
|
+
this.includes = [];
|
|
98
|
+
this.searchTerm = undefined;
|
|
99
|
+
this.sorts = [];
|
|
100
|
+
this.distinctFields = [];
|
|
101
|
+
this.pagination = undefined;
|
|
102
|
+
this.notify();
|
|
103
|
+
return this;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Adds an OR group. Conditions inside the callback are OR-ed together.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* filterQuery()
|
|
110
|
+
* .where('status', 'active')
|
|
111
|
+
* .or(q => q
|
|
112
|
+
* .where('name', 'contains', 'sync')
|
|
113
|
+
* .where('email', 'contains', 'sync')
|
|
114
|
+
* )
|
|
115
|
+
*/
|
|
116
|
+
or(fn) {
|
|
117
|
+
const sub = new FilterQueryBuilder();
|
|
118
|
+
fn(sub);
|
|
119
|
+
this.groups.push({ type: 'OR', conditions: sub.conditions });
|
|
120
|
+
this.notify();
|
|
121
|
+
return this;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Adds an AND group. Conditions inside the callback are AND-ed together.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* filterQuery()
|
|
128
|
+
* .and(q => q
|
|
129
|
+
* .where('age', 'gte', 18)
|
|
130
|
+
* .where('age', 'lte', 65)
|
|
131
|
+
* )
|
|
132
|
+
*/
|
|
133
|
+
and(fn) {
|
|
134
|
+
const sub = new FilterQueryBuilder();
|
|
135
|
+
fn(sub);
|
|
136
|
+
this.groups.push({ type: 'AND', conditions: sub.conditions });
|
|
137
|
+
this.notify();
|
|
138
|
+
return this;
|
|
139
|
+
}
|
|
140
|
+
// ─── Convenience methods ─────────────────────────────────────────────────
|
|
141
|
+
equals(field, value) {
|
|
142
|
+
return this.where(field, 'equals', value);
|
|
143
|
+
}
|
|
144
|
+
notEquals(field, value) {
|
|
145
|
+
return this.where(field, 'notEquals', value);
|
|
146
|
+
}
|
|
147
|
+
contains(field, value) {
|
|
148
|
+
return this.where(field, 'contains', value);
|
|
149
|
+
}
|
|
150
|
+
in(field, values) {
|
|
151
|
+
return this.where(field, 'in', values);
|
|
152
|
+
}
|
|
153
|
+
notIn(field, values) {
|
|
154
|
+
return this.where(field, 'notIn', values);
|
|
155
|
+
}
|
|
156
|
+
between(field, low, high) {
|
|
157
|
+
return this.where(field, 'between', [low, high]);
|
|
158
|
+
}
|
|
159
|
+
gt(field, value) {
|
|
160
|
+
return this.where(field, 'gt', value);
|
|
161
|
+
}
|
|
162
|
+
gte(field, value) {
|
|
163
|
+
return this.where(field, 'gte', value);
|
|
164
|
+
}
|
|
165
|
+
lt(field, value) {
|
|
166
|
+
return this.where(field, 'lt', value);
|
|
167
|
+
}
|
|
168
|
+
lte(field, value) {
|
|
169
|
+
return this.where(field, 'lte', value);
|
|
170
|
+
}
|
|
171
|
+
isNull(field) {
|
|
172
|
+
return this.where(field, 'isNull');
|
|
173
|
+
}
|
|
174
|
+
isNotNull(field) {
|
|
175
|
+
return this.where(field, 'isNotNull');
|
|
176
|
+
}
|
|
177
|
+
isEmpty(field) {
|
|
178
|
+
return this.where(field, 'isEmpty');
|
|
179
|
+
}
|
|
180
|
+
isNotEmpty(field) {
|
|
181
|
+
return this.where(field, 'isNotEmpty');
|
|
182
|
+
}
|
|
183
|
+
startsWith(field, value) {
|
|
184
|
+
return this.where(field, 'startsWith', value);
|
|
185
|
+
}
|
|
186
|
+
endsWith(field, value) {
|
|
187
|
+
return this.where(field, 'endsWith', value);
|
|
188
|
+
}
|
|
189
|
+
// ─── Range helpers (use add — accumulate) ───────────────────────────────
|
|
190
|
+
/**
|
|
191
|
+
* Adds a `gte` filter using `add()` (accumulating).
|
|
192
|
+
* Useful for range queries where you also need an `lte` on the same field.
|
|
193
|
+
*/
|
|
194
|
+
addGte(field, value) {
|
|
195
|
+
return this.add(field, 'gte', value);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Adds a `lte` filter using `add()` (accumulating).
|
|
199
|
+
* Useful for range queries where you also need a `gte` on the same field.
|
|
200
|
+
*/
|
|
201
|
+
addLte(field, value) {
|
|
202
|
+
return this.add(field, 'lte', value);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Adds a `gt` filter using `add()` (accumulating).
|
|
206
|
+
*/
|
|
207
|
+
addGt(field, value) {
|
|
208
|
+
return this.add(field, 'gt', value);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Adds a `lt` filter using `add()` (accumulating).
|
|
212
|
+
*/
|
|
213
|
+
addLt(field, value) {
|
|
214
|
+
return this.add(field, 'lt', value);
|
|
215
|
+
}
|
|
216
|
+
// ─── Extra keys ─────────────────────────────────────────────────────────
|
|
217
|
+
/**
|
|
218
|
+
* Adds an extra key/value pair to the query result (e.g. page, size).
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* filterQuery()
|
|
222
|
+
* .where('status', 'active')
|
|
223
|
+
* .set('page', 1)
|
|
224
|
+
* .set('size', 25)
|
|
225
|
+
* .build();
|
|
226
|
+
* // → { where: [...], page: 1, size: 25 }
|
|
227
|
+
*/
|
|
228
|
+
set(key, value) {
|
|
229
|
+
this.extra[key] = value;
|
|
230
|
+
this.notify();
|
|
231
|
+
return this;
|
|
232
|
+
}
|
|
233
|
+
// ─── Include & Search ────────────────────────────────────────────────────
|
|
234
|
+
/**
|
|
235
|
+
* Adds relation paths to eagerly load.
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* filterQuery().include('role', 'posts').build()
|
|
239
|
+
* // → { filter: { where: [] }, include: ['role', 'posts'] }
|
|
240
|
+
*/
|
|
241
|
+
include(...relations) {
|
|
242
|
+
for (const rel of relations) {
|
|
243
|
+
if (typeof rel !== 'string')
|
|
244
|
+
continue;
|
|
245
|
+
if (!this.includes.includes(rel)) {
|
|
246
|
+
this.includes.push(rel);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
this.notify();
|
|
250
|
+
return this;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Sets the global search term.
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* filterQuery().search('fleet').build()
|
|
257
|
+
* // → { filter: { where: [] }, search: 'fleet' }
|
|
258
|
+
*/
|
|
259
|
+
search(term) {
|
|
260
|
+
if (typeof term !== 'string')
|
|
261
|
+
return this;
|
|
262
|
+
this.searchTerm = term;
|
|
263
|
+
this.notify();
|
|
264
|
+
return this;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Selects DISTINCT values of the given field(s) — the active where/search/
|
|
268
|
+
* sort/pagination still apply. Useful for populating a filter dropdown with
|
|
269
|
+
* the distinct values of a column. Repeated fields are deduplicated.
|
|
270
|
+
*
|
|
271
|
+
* @example
|
|
272
|
+
* filterQuery().where('baseId', 'b1').distinct('afsc').page(0, 20).build()
|
|
273
|
+
* // → { filter: { where: [...] }, distinct: ['afsc'], paginate: { page: 0, size: 20 } }
|
|
274
|
+
*/
|
|
275
|
+
distinct(...fields) {
|
|
276
|
+
for (const field of fields) {
|
|
277
|
+
if (typeof field !== 'string')
|
|
278
|
+
continue;
|
|
279
|
+
if (!this.distinctFields.includes(field)) {
|
|
280
|
+
this.distinctFields.push(field);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
this.notify();
|
|
284
|
+
return this;
|
|
285
|
+
}
|
|
286
|
+
// ─── Sort & Pagination ──────────────────────────────────────────────────
|
|
287
|
+
/**
|
|
288
|
+
* Adds or replaces a sort directive for the given field.
|
|
289
|
+
* If a sort for the same field already exists, it is replaced.
|
|
290
|
+
*
|
|
291
|
+
* @example
|
|
292
|
+
* filterQuery().sort('createdAt', 'desc').sort('name').build()
|
|
293
|
+
* // → { ..., sort: [{ field: 'createdAt', direction: 'desc' }, { field: 'name', direction: 'asc' }] }
|
|
294
|
+
*/
|
|
295
|
+
sort(field, direction = 'asc') {
|
|
296
|
+
this.sorts = this.sorts.filter((s) => s.field !== field);
|
|
297
|
+
this.sorts.push({ field, direction });
|
|
298
|
+
this.notify();
|
|
299
|
+
return this;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Shorthand for `sort(field, 'desc')`.
|
|
303
|
+
*/
|
|
304
|
+
sortDesc(field) {
|
|
305
|
+
return this.sort(field, 'desc');
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Shorthand for `sort(field, 'asc')`.
|
|
309
|
+
*/
|
|
310
|
+
sortAsc(field) {
|
|
311
|
+
return this.sort(field, 'asc');
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Sets offset-based pagination.
|
|
315
|
+
*
|
|
316
|
+
* @param page - Zero-based page number.
|
|
317
|
+
* @param size - Number of records per page (default 25).
|
|
318
|
+
*
|
|
319
|
+
* @example
|
|
320
|
+
* filterQuery().page(0, 25).build()
|
|
321
|
+
* // → { ..., paginate: { page: 0, size: 25 } }
|
|
322
|
+
*/
|
|
323
|
+
page(page, size = 25) {
|
|
324
|
+
this.pagination = { page, size };
|
|
325
|
+
this.notify();
|
|
326
|
+
return this;
|
|
327
|
+
}
|
|
328
|
+
// ─── Reactivity ───────────────────────────────────────────────────────────
|
|
329
|
+
/**
|
|
330
|
+
* Bumps the version, invalidates the cached snapshot, and notifies every
|
|
331
|
+
* subscriber. Called internally by every mutating method. Convenience
|
|
332
|
+
* methods (`equals`, `sortAsc`, `addGte`, …) delegate to a primitive
|
|
333
|
+
* mutator, so they notify transitively — never call `notify()` from them.
|
|
334
|
+
*/
|
|
335
|
+
notify() {
|
|
336
|
+
this.version++;
|
|
337
|
+
this.snapshot = null;
|
|
338
|
+
for (const listener of this.listeners) {
|
|
339
|
+
listener();
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Subscribes to mutations. Returns an unsubscribe function.
|
|
344
|
+
*
|
|
345
|
+
* Bound so it can be passed directly to `useSyncExternalStore` /
|
|
346
|
+
* Svelte's store contract without wrapping in an arrow.
|
|
347
|
+
*
|
|
348
|
+
* @example
|
|
349
|
+
* const unsubscribe = qb.subscribe(() => rerender());
|
|
350
|
+
*/
|
|
351
|
+
subscribe = (listener) => {
|
|
352
|
+
this.listeners.add(listener);
|
|
353
|
+
return () => {
|
|
354
|
+
this.listeners.delete(listener);
|
|
355
|
+
};
|
|
356
|
+
};
|
|
357
|
+
/**
|
|
358
|
+
* Returns the current built result, cached until the next mutation.
|
|
359
|
+
*
|
|
360
|
+
* The reference is stable across calls while the builder is unchanged, which
|
|
361
|
+
* is what `useSyncExternalStore` requires to avoid infinite render loops.
|
|
362
|
+
*
|
|
363
|
+
* Bound for the same reason as `subscribe`.
|
|
364
|
+
*/
|
|
365
|
+
getSnapshot = () => {
|
|
366
|
+
if (this.snapshot === null) {
|
|
367
|
+
this.snapshot = this.build();
|
|
368
|
+
}
|
|
369
|
+
return this.snapshot;
|
|
370
|
+
};
|
|
371
|
+
/**
|
|
372
|
+
* Monotonic mutation counter. Useful as a cheap dependency/key for adapters
|
|
373
|
+
* that prefer an integer over reference comparison.
|
|
374
|
+
*/
|
|
375
|
+
getVersion() {
|
|
376
|
+
return this.version;
|
|
377
|
+
}
|
|
378
|
+
// ─── Build ──────────────────────────────────────────────────────────────
|
|
379
|
+
/**
|
|
380
|
+
* Builds the query as a `FilterQueryResult` object.
|
|
381
|
+
*
|
|
382
|
+
* Returns the structured format: `{ filter: { where: [...] }, include: [...], search: '...' }`
|
|
383
|
+
*/
|
|
384
|
+
build() {
|
|
385
|
+
const filters = [];
|
|
386
|
+
for (const cond of this.conditions) {
|
|
387
|
+
filters.push({
|
|
388
|
+
field: cond.field,
|
|
389
|
+
operator: cond.operator,
|
|
390
|
+
value: cond.value,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
for (const group of this.groups) {
|
|
394
|
+
const groupFilters = group.conditions.map((c) => ({
|
|
395
|
+
field: c.field,
|
|
396
|
+
operator: c.operator,
|
|
397
|
+
value: c.value,
|
|
398
|
+
}));
|
|
399
|
+
if (group.type === 'OR') {
|
|
400
|
+
filters.push({
|
|
401
|
+
field: '',
|
|
402
|
+
operator: 'equals',
|
|
403
|
+
value: undefined,
|
|
404
|
+
OR: groupFilters,
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
filters.push({
|
|
409
|
+
field: '',
|
|
410
|
+
operator: 'equals',
|
|
411
|
+
value: undefined,
|
|
412
|
+
AND: groupFilters,
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
const result = {
|
|
417
|
+
...this.extra,
|
|
418
|
+
filter: { where: filters },
|
|
419
|
+
};
|
|
420
|
+
if (this.includes.length > 0) {
|
|
421
|
+
result.include = [...this.includes];
|
|
422
|
+
}
|
|
423
|
+
if (this.searchTerm !== undefined) {
|
|
424
|
+
result.search = this.searchTerm;
|
|
425
|
+
}
|
|
426
|
+
if (this.sorts.length > 0) {
|
|
427
|
+
result.sort = [...this.sorts];
|
|
428
|
+
}
|
|
429
|
+
if (this.distinctFields.length > 0) {
|
|
430
|
+
result.distinct = [...this.distinctFields];
|
|
431
|
+
}
|
|
432
|
+
if (this.pagination !== undefined) {
|
|
433
|
+
result.paginate = { ...this.pagination };
|
|
434
|
+
}
|
|
435
|
+
return result;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Serializes to a query string suitable for GET requests.
|
|
439
|
+
*
|
|
440
|
+
* Uses the structured format:
|
|
441
|
+
* - Simple conditions → `filter[field]=value&filter[field][op]=value`
|
|
442
|
+
* - OR/AND groups → `filter[where][i][field]=...`
|
|
443
|
+
* - Includes → `include=role,posts`
|
|
444
|
+
* - Search → `search=term`
|
|
445
|
+
*/
|
|
446
|
+
toQueryString() {
|
|
447
|
+
const parts = [];
|
|
448
|
+
// Build filter portion
|
|
449
|
+
let filterQs;
|
|
450
|
+
if (this.groups.length === 0) {
|
|
451
|
+
const flat = this.toFlatObject();
|
|
452
|
+
filterQs = flatObjectToQueryString(Object.fromEntries(Object.entries(flat).map(([k, v]) => [`filter[${k}]`, v])));
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
455
|
+
filterQs = columnFiltersToQueryString(this.build().filter.where);
|
|
456
|
+
}
|
|
457
|
+
if (filterQs)
|
|
458
|
+
parts.push(filterQs);
|
|
459
|
+
// Build include
|
|
460
|
+
if (this.includes.length > 0) {
|
|
461
|
+
parts.push(`include=${encodeURIComponent(this.includes.join(','))}`);
|
|
462
|
+
}
|
|
463
|
+
// Build search
|
|
464
|
+
if (this.searchTerm !== undefined) {
|
|
465
|
+
parts.push(`search=${encodeURIComponent(this.searchTerm)}`);
|
|
466
|
+
}
|
|
467
|
+
// Build sort
|
|
468
|
+
if (this.sorts.length > 0) {
|
|
469
|
+
const sortStr = this.sorts
|
|
470
|
+
.map((s) => (s.direction === 'desc' ? `-${s.field}` : s.field))
|
|
471
|
+
.join(',');
|
|
472
|
+
parts.push(`sort=${encodeURIComponent(sortStr)}`);
|
|
473
|
+
}
|
|
474
|
+
// Build distinct
|
|
475
|
+
if (this.distinctFields.length > 0) {
|
|
476
|
+
parts.push(`distinct=${encodeURIComponent(this.distinctFields.join(','))}`);
|
|
477
|
+
}
|
|
478
|
+
// Build pagination
|
|
479
|
+
if (this.pagination !== undefined) {
|
|
480
|
+
parts.push(`page=${encodeURIComponent(String(this.pagination.page))}`);
|
|
481
|
+
parts.push(`size=${encodeURIComponent(String(this.pagination.size))}`);
|
|
482
|
+
}
|
|
483
|
+
// Build extra keys
|
|
484
|
+
const extraQs = flatObjectToQueryString(this.extra);
|
|
485
|
+
if (extraQs)
|
|
486
|
+
parts.push(extraQs);
|
|
487
|
+
return parts.join('&');
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Converts to a flat object suitable for auto-fields.
|
|
491
|
+
*
|
|
492
|
+
* Simple equals → `{ field: value }`
|
|
493
|
+
* Array (in) → `{ field: [values] }`
|
|
494
|
+
* Other operators → `{ field: { operator: value } }`
|
|
495
|
+
* Multiple operators on same field → merged into one object.
|
|
496
|
+
*
|
|
497
|
+
* Note: OR/AND groups are NOT representable as flat objects.
|
|
498
|
+
* Use `build()` for complex queries.
|
|
499
|
+
*/
|
|
500
|
+
toFlatObject() {
|
|
501
|
+
const result = {};
|
|
502
|
+
for (const cond of this.conditions) {
|
|
503
|
+
if (cond.operator === 'equals') {
|
|
504
|
+
result[cond.field] = cond.value;
|
|
505
|
+
}
|
|
506
|
+
else if (cond.operator === 'in') {
|
|
507
|
+
result[cond.field] = cond.value;
|
|
508
|
+
}
|
|
509
|
+
else {
|
|
510
|
+
// Operator → bracket notation object
|
|
511
|
+
const existing = result[cond.field];
|
|
512
|
+
if (existing != null && typeof existing === 'object' && !Array.isArray(existing)) {
|
|
513
|
+
// Merge operators on same field
|
|
514
|
+
existing[cond.operator] = cond.value;
|
|
515
|
+
}
|
|
516
|
+
else {
|
|
517
|
+
result[cond.field] = { [cond.operator]: cond.value };
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
return result;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* Creates a new FilterQueryBuilder instance.
|
|
526
|
+
*
|
|
527
|
+
* @example
|
|
528
|
+
* import { filterQuery } from '@adonis-agora/filter-client';
|
|
529
|
+
*
|
|
530
|
+
* const q = filterQuery()
|
|
531
|
+
* .where('name', 'contains', 'fleet')
|
|
532
|
+
* .where('status', ['COMPLETED', 'FAILED'])
|
|
533
|
+
* .build();
|
|
534
|
+
*/
|
|
535
|
+
export function filterQuery() {
|
|
536
|
+
return new FilterQueryBuilder();
|
|
537
|
+
}
|
|
538
|
+
//# sourceMappingURL=filter-query-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter-query-builder.js","sourceRoot":"","sources":["../src/filter-query-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAE3F,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAqD1F;;;GAGG;AACH,MAAM,OAAO,kBAAkB;IACrB,UAAU,GAAgB,EAAE,CAAC;IACpB,MAAM,GAAY,EAAE,CAAC;IAC9B,KAAK,GAA4B,EAAE,CAAC;IACpC,QAAQ,GAAa,EAAE,CAAC;IACxB,UAAU,CAAqB;IAC/B,KAAK,GAAe,EAAE,CAAC;IACvB,cAAc,GAAa,EAAE,CAAC;IAC9B,UAAU,CAA+B;IAEjD,4EAA4E;IAC5E,mEAAmE;IACnE,uEAAuE;IACvE,2EAA2E;IAC3E,yEAAyE;IACzE,0EAA0E;IAClE,OAAO,GAAG,CAAC,CAAC;IACZ,QAAQ,GAA6B,IAAI,CAAC;IACjC,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;IA+CnD,KAAK,CAAC,KAAa,EAAE,eAAwB,EAAE,UAAoB;QACjE,+CAA+C;QAC/C,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;QAEnE,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,gDAAgD;YAChD,MAAM,EAAE,GAAG,eAAiC,CAAC;YAC7C,qBAAqB,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBACnB,KAAK;gBACL,QAAQ,EAAE,EAAE;gBACZ,KAAK,EAAE,UAAU;aAClB,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;YAC1C,wBAAwB;YACxB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBACnB,KAAK;gBACL,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,eAAe;aACvB,CAAC,CAAC;QACL,CAAC;aAAM,IACL,OAAO,eAAe,KAAK,QAAQ;YACnC,CAAC,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC,QAAQ,CAC9E,eAAe,CAChB,EACD,CAAC;YACD,2DAA2D;YAC3D,qBAAqB,CAAC,eAAiC,EAAE,SAAS,CAAC,CAAC;YACpE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBACnB,KAAK;gBACL,QAAQ,EAAE,eAAiC;gBAC3C,KAAK,EAAE,SAAS;aACjB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,wBAAwB;YACxB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBACnB,KAAK;gBACL,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,eAAe;aACvB,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAoBD,GAAG,CAAC,KAAa,EAAE,QAAwB,EAAE,KAAe;QAC1D,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAC9B,qBAAqB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QACjD,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;;OAUG;IACH,MAAM,CAAC,KAAa;QAClB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;QACnE,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;;OAUG;IACH,EAAE,CAAC,EAAmC;QACpC,MAAM,GAAG,GAAG,IAAI,kBAAkB,EAAE,CAAC;QACrC,EAAE,CAAC,GAAG,CAAC,CAAC;QACR,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;OASG;IACH,GAAG,CAAC,EAAmC;QACrC,MAAM,GAAG,GAAG,IAAI,kBAAkB,EAAE,CAAC;QACrC,EAAE,CAAC,GAAG,CAAC,CAAC;QACR,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,4EAA4E;IAE5E,MAAM,CAAC,KAAa,EAAE,KAAc;QAClC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED,SAAS,CAAC,KAAa,EAAE,KAAc;QACrC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;IAED,QAAQ,CAAC,KAAa,EAAE,KAAa;QACnC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC;IAED,EAAE,CAAC,KAAa,EAAE,MAAiB;QACjC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,KAAa,EAAE,MAAiB;QACpC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,CAAC,KAAa,EAAE,GAAY,EAAE,IAAa;QAChD,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,EAAE,CAAC,KAAa,EAAE,KAAc;QAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,GAAG,CAAC,KAAa,EAAE,KAAc;QAC/B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACzC,CAAC;IAED,EAAE,CAAC,KAAa,EAAE,KAAc;QAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,GAAG,CAAC,KAAa,EAAE,KAAc;QAC/B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,CAAC,KAAa;QAClB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED,SAAS,CAAC,KAAa;QACrB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,CAAC,KAAa;QACnB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACtC,CAAC;IAED,UAAU,CAAC,KAAa;QACtB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IACzC,CAAC;IAED,UAAU,CAAC,KAAa,EAAE,KAAa;QACrC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;IAChD,CAAC;IAED,QAAQ,CAAC,KAAa,EAAE,KAAa;QACnC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC;IAED,2EAA2E;IAE3E;;;OAGG;IACH,MAAM,CAAC,KAAa,EAAE,KAAc;QAClC,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACvC,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,KAAa,EAAE,KAAc;QAClC,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAa,EAAE,KAAc;QACjC,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IACtC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAa,EAAE,KAAc;QACjC,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IACtC,CAAC;IAED,2EAA2E;IAE3E;;;;;;;;;;OAUG;IACH,GAAG,CAAC,GAAW,EAAE,KAAc;QAC7B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,4EAA4E;IAE5E;;;;;;OAMG;IACH,OAAO,CAAC,GAAG,SAAmB;QAC5B,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;YAC5B,IAAI,OAAO,GAAG,KAAK,QAAQ;gBAAE,SAAS;YACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QACD,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,IAAY;QACjB,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC1C,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;OAQG;IACH,QAAQ,CAAC,GAAG,MAAgB;QAC1B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,SAAS;YACxC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;QACD,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,2EAA2E;IAE3E;;;;;;;OAOG;IACH,IAAI,CAAC,KAAa,EAAE,YAA4B,KAAK;QACnD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;QACzD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,KAAa;QACpB,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,KAAa;QACnB,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;IAED;;;;;;;;;OASG;IACH,IAAI,CAAC,IAAY,EAAE,IAAI,GAAG,EAAE;QAC1B,IAAI,CAAC,UAAU,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACjC,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6EAA6E;IAE7E;;;;;OAKG;IACK,MAAM;QACZ,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,QAAQ,EAAE,CAAC;QACb,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACH,SAAS,GAAG,CAAC,QAAoB,EAAgB,EAAE;QACjD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC,CAAC;IACJ,CAAC,CAAC;IAEF;;;;;;;OAOG;IACH,WAAW,GAAG,GAAsB,EAAE;QACpC,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC3B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAC/B,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC,CAAC;IAEF;;;OAGG;IACH,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,2EAA2E;IAE3E;;;;OAIG;IACH,KAAK;QACH,MAAM,OAAO,GAAmB,EAAE,CAAC;QAEnC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACnC,OAAO,CAAC,IAAI,CAAC;gBACX,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,KAAK,EAAE,IAAI,CAAC,KAAK;aAClB,CAAC,CAAC;QACL,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,YAAY,GAAmB,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAChE,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,KAAK,EAAE,CAAC,CAAC,KAAK;aACf,CAAC,CAAC,CAAC;YAEJ,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;gBACxB,OAAO,CAAC,IAAI,CAAC;oBACX,KAAK,EAAE,EAAE;oBACT,QAAQ,EAAE,QAAQ;oBAClB,KAAK,EAAE,SAAS;oBAChB,EAAE,EAAE,YAAY;iBACjB,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CAAC;oBACX,KAAK,EAAE,EAAE;oBACT,QAAQ,EAAE,QAAQ;oBAClB,KAAK,EAAE,SAAS;oBAChB,GAAG,EAAE,YAAY;iBAClB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAsB;YAChC,GAAG,IAAI,CAAC,KAAK;YACb,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;SAC3B,CAAC;QACF,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,CAAC,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtC,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAClC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC;QAClC,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QACD,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnC,MAAM,CAAC,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAClC,MAAM,CAAC,QAAQ,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAC3C,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;;;OAQG;IACH,aAAa;QACX,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,uBAAuB;QACvB,IAAI,QAAgB,CAAC;QACrB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;YACjC,QAAQ,GAAG,uBAAuB,CAChC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAC9E,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,QAAQ,GAAG,0BAA0B,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnE,CAAC;QACD,IAAI,QAAQ;YAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEnC,gBAAgB;QAChB,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,WAAW,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;QACvE,CAAC;QAED,eAAe;QACf,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,UAAU,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;QAED,aAAa;QACb,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK;iBACvB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;iBAC9D,IAAI,CAAC,GAAG,CAAC,CAAC;YACb,KAAK,CAAC,IAAI,CAAC,QAAQ,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACpD,CAAC;QAED,iBAAiB;QACjB,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,YAAY,kBAAkB,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;QAC9E,CAAC;QAED,mBAAmB;QACnB,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,QAAQ,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;YACvE,KAAK,CAAC,IAAI,CAAC,QAAQ,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;QACzE,CAAC;QAED,mBAAmB;QACnB,MAAM,OAAO,GAAG,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpD,IAAI,OAAO;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEjC,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED;;;;;;;;;;OAUG;IACH,YAAY;QACV,MAAM,MAAM,GAA4B,EAAE,CAAC;QAE3C,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACnC,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAC/B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;YAClC,CAAC;iBAAM,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;gBAClC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;YAClC,CAAC;iBAAM,CAAC;gBACN,qCAAqC;gBACrC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACpC,IAAI,QAAQ,IAAI,IAAI,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACjF,gCAAgC;oBAC/B,QAAoC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;gBACpE,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;gBACvD,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO,IAAI,kBAAkB,EAAE,CAAC;AAClC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { FilterQueryBuilder, filterQuery } from './filter-query-builder.js';
|
|
2
|
+
export type { FilterQueryResult, SortItem, OffsetPagination } from './filter-query-builder.js';
|
|
3
|
+
export { flatObjectToQueryString, columnFiltersToQueryString } from './to-query-string.js';
|
|
4
|
+
export type { ColumnFilter, FilterOperator } from './types.js';
|
|
5
|
+
export { FILTER_OPERATORS } from './types.js';
|
|
6
|
+
export { validateOperatorValue, validateAddOperator, RANGE_OPERATORS, } from './validate-operator-value.js';
|
|
7
|
+
export type { FieldTypeKind, FilterFieldTypes, ValueAt, Base, OperatorsFor, ValueForOp, StringFieldsOf, OrderableFieldsOf, } from './field-types.js';
|
|
8
|
+
export type { TypedFilterQuery } from './typed-filter-query.js';
|
|
9
|
+
export type { TypedFilterQueryBuilder } from './typed-filter-query-builder.js';
|
|
10
|
+
export { filterQueryTyped } from './typed-filter-query-builder.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC5E,YAAY,EAAE,iBAAiB,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC/F,OAAO,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAC3F,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,GAChB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,UAAU,EACV,cAAc,EACd,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,YAAY,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { FilterQueryBuilder, filterQuery } from './filter-query-builder.js';
|
|
2
|
+
export { flatObjectToQueryString, columnFiltersToQueryString } from './to-query-string.js';
|
|
3
|
+
export { FILTER_OPERATORS } from './types.js';
|
|
4
|
+
export { validateOperatorValue, validateAddOperator, RANGE_OPERATORS, } from './validate-operator-value.js';
|
|
5
|
+
export { filterQueryTyped } from './typed-filter-query-builder.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE5E,OAAO,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAE3F,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,GAChB,MAAM,8BAA8B,CAAC;AAatC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { ColumnFiltersState, PaginationState, SortingState } from '@tanstack/table-core';
|
|
2
|
+
import { FilterQueryBuilder } from './filter-query-builder.js';
|
|
3
|
+
import type { FilterQueryResult } from './filter-query-builder.js';
|
|
4
|
+
import type { FilterOperator } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Resolves the @agora/filter operator for a vanilla TanStack column filter.
|
|
7
|
+
*
|
|
8
|
+
* Vanilla TanStack column filters are `{ id, value }` with **no operator** —
|
|
9
|
+
* the operator lives in the column's `filterFn`. @agora/filter needs one, so
|
|
10
|
+
* this is the seam: supply your own to read `column.meta`, map a symbol
|
|
11
|
+
* vocabulary, etc.
|
|
12
|
+
*/
|
|
13
|
+
export type ResolveOperator = (columnId: string, value: unknown) => FilterOperator;
|
|
14
|
+
export interface TanstackTableStateOptions {
|
|
15
|
+
/** Vanilla TanStack `ColumnFiltersState` — `{ id, value }[]`. */
|
|
16
|
+
columnFilters?: ColumnFiltersState;
|
|
17
|
+
/** Vanilla TanStack `SortingState` — `{ id, desc }[]`. */
|
|
18
|
+
sorting?: SortingState;
|
|
19
|
+
/** Vanilla TanStack `PaginationState` — `{ pageIndex (0-based), pageSize }`. */
|
|
20
|
+
pagination?: PaginationState;
|
|
21
|
+
/**
|
|
22
|
+
* Maps each column filter to an operator. Defaults to: array → `in`,
|
|
23
|
+
* string → `iContains` (mirrors TanStack's `auto` substring filtering),
|
|
24
|
+
* everything else → `equals`.
|
|
25
|
+
*/
|
|
26
|
+
resolveOperator?: ResolveOperator;
|
|
27
|
+
/** Optional allowlist; filters/sorts whose column id isn't here are dropped. */
|
|
28
|
+
fields?: Iterable<string>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Applies vanilla TanStack Table state (column filters, sorting, pagination)
|
|
32
|
+
* onto an existing `FilterQueryBuilder`, then returns the same builder so you
|
|
33
|
+
* can chain `include`/`search`/extra `where` calls before `build()`.
|
|
34
|
+
*
|
|
35
|
+
* Framework-agnostic — works with any TanStack Table adapter (React, Vue,
|
|
36
|
+
* Svelte, Solid). `@tanstack/table-core` is a types-only peer.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* import { filterQuery } from '@adonis-agora/filter-client';
|
|
40
|
+
* import { applyTanstackTableState } from '@adonis-agora/filter-client/tanstack';
|
|
41
|
+
*
|
|
42
|
+
* const body = applyTanstackTableState(filterQuery(), {
|
|
43
|
+
* columnFilters: table.getState().columnFilters,
|
|
44
|
+
* sorting: table.getState().sorting,
|
|
45
|
+
* pagination: table.getState().pagination,
|
|
46
|
+
* resolveOperator: (id) => (id === 'createdAt' ? 'gte' : 'iContains'),
|
|
47
|
+
* })
|
|
48
|
+
* .include('author')
|
|
49
|
+
* .build();
|
|
50
|
+
*/
|
|
51
|
+
export declare function applyTanstackTableState(builder: FilterQueryBuilder, options?: TanstackTableStateOptions): FilterQueryBuilder;
|
|
52
|
+
/**
|
|
53
|
+
* One-shot convenience: builds a `FilterQueryResult` straight from vanilla
|
|
54
|
+
* TanStack Table state. Equivalent to
|
|
55
|
+
* `applyTanstackTableState(filterQuery(), options).build()`.
|
|
56
|
+
*/
|
|
57
|
+
export declare function tanstackTableToFilterQuery(options?: TanstackTableStateOptions): FilterQueryResult;
|
|
58
|
+
//# sourceMappingURL=tanstack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tanstack.d.ts","sourceRoot":"","sources":["../src/tanstack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC9F,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,cAAc,CAAC;AAEnF,MAAM,WAAW,yBAAyB;IACxC,iEAAiE;IACjE,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,0DAA0D;IAC1D,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,gFAAgF;IAChF,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B;;;;OAIG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,gFAAgF;IAChF,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC3B;AAQD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,GAAE,yBAA8B,GACtC,kBAAkB,CA0BpB;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,GAAE,yBAA8B,GACtC,iBAAiB,CAEnB"}
|