@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.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -0
  3. package/dist/field-types.d.ts +68 -0
  4. package/dist/field-types.d.ts.map +1 -0
  5. package/dist/field-types.js +2 -0
  6. package/dist/field-types.js.map +1 -0
  7. package/dist/filter-query-builder.d.ts +301 -0
  8. package/dist/filter-query-builder.d.ts.map +1 -0
  9. package/dist/filter-query-builder.js +538 -0
  10. package/dist/filter-query-builder.js.map +1 -0
  11. package/dist/index.d.ts +11 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +6 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/tanstack.d.ts +58 -0
  16. package/dist/tanstack.d.ts.map +1 -0
  17. package/dist/tanstack.js +58 -0
  18. package/dist/tanstack.js.map +1 -0
  19. package/dist/to-query-string.d.ts +17 -0
  20. package/dist/to-query-string.d.ts.map +1 -0
  21. package/dist/to-query-string.js +72 -0
  22. package/dist/to-query-string.js.map +1 -0
  23. package/dist/typed-filter-query-builder.d.ts +78 -0
  24. package/dist/typed-filter-query-builder.d.ts.map +1 -0
  25. package/dist/typed-filter-query-builder.js +25 -0
  26. package/dist/typed-filter-query-builder.js.map +1 -0
  27. package/dist/typed-filter-query.d.ts +20 -0
  28. package/dist/typed-filter-query.d.ts.map +1 -0
  29. package/dist/typed-filter-query.js +2 -0
  30. package/dist/typed-filter-query.js.map +1 -0
  31. package/dist/types.d.ts +20 -0
  32. package/dist/types.d.ts.map +1 -0
  33. package/dist/types.js +28 -0
  34. package/dist/types.js.map +1 -0
  35. package/dist/validate-operator-value.d.ts +35 -0
  36. package/dist/validate-operator-value.d.ts.map +1 -0
  37. package/dist/validate-operator-value.js +91 -0
  38. package/dist/validate-operator-value.js.map +1 -0
  39. package/package.json +64 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Davi Carvalho
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # `@agora/filter-client`
2
+
3
+ Framework-agnostic client-side query builder for [`@agora/filter`](https://github.com/DavideCarvalho/adonis-filter)
4
+ — fluently build filter/sort/pagination query strings, with optional TanStack
5
+ Table state sync.
6
+
7
+ ```ts
8
+ import { filterQuery } from '@agora/filter-client'
9
+
10
+ const qs = filterQuery()
11
+ .where('status', 'eq', 'active')
12
+ .where('age', 'gte', 18)
13
+ .sort('createdAt', 'desc')
14
+ .page(1, 25)
15
+ .toQueryString()
16
+ // → filter[status]=active&filter[age][gte]=18&sort=-createdAt&page=1&size=25
17
+ ```
18
+
19
+ ## License
20
+
21
+ MIT © Davi Carvalho
@@ -0,0 +1,68 @@
1
+ import type { FilterOperator } from './types.js';
2
+ /**
3
+ * Canonical classification used by codegen + the runtime adapters. Mirrors EntityFieldInfo['type'].
4
+ *
5
+ * NOT to be unified with `FilterFieldTypeHint` (core `@FilterFor` decorator): that hint is a
6
+ * codegen *authoring* surface — it uses `'Date'` to mirror the TS type name and accepts a
7
+ * `readonly string[]` of enum literals, whereas `FieldTypeKind` is this layer's lowercase
8
+ * *classifier output* (`'date'`, plus `'json'`/`'unknown'` buckets the hint has no concept of).
9
+ * Different layers, different purposes; keep them separate.
10
+ */
11
+ export type FieldTypeKind = 'string' | 'number' | 'boolean' | 'date' | 'json' | 'unknown';
12
+ /** Shape of the per-field type map: each field maps to its TS value type. */
13
+ export type FilterFieldTypes<F extends string> = Partial<Record<F, unknown>>;
14
+ /** Look up a field's TS type; default to `unknown` when absent from the map. */
15
+ export type ValueAt<M, K> = K extends keyof M ? M[K] : unknown;
16
+ /** Strip null/undefined so nullable fields still get base-type operators. */
17
+ export type Base<T> = NonNullable<T>;
18
+ export type EqualityOps = 'equals' | 'notEquals';
19
+ export type OrderingOps = 'gt' | 'gte' | 'lt' | 'lte';
20
+ export type StringOps = 'contains' | 'notContains' | 'iContains' | 'startsWith' | 'endsWith';
21
+ export type ArrayOps = 'in' | 'notIn' | 'isAnyOf';
22
+ export type TupleOps = 'between' | 'notBetween';
23
+ export type NullUnaryOps = 'isNull' | 'isNotNull';
24
+ export type EmptyUnaryOps = 'isEmpty' | 'isNotEmpty';
25
+ export type ExistsUnaryOps = 'exists' | 'notExists';
26
+ export type CommonUnary = NullUnaryOps | ExistsUnaryOps;
27
+ export type AllUnaryOps = CommonUnary | EmptyUnaryOps;
28
+ /** Resolve the operators valid for a field's base (non-null) type. */
29
+ export type OperatorsFor<T> = unknown extends T ? FilterOperator : [Base<T>] extends [string] ? EqualityOps | StringOps | ArrayOps | EmptyUnaryOps | CommonUnary : [Base<T>] extends [number] ? EqualityOps | OrderingOps | TupleOps | ArrayOps | CommonUnary : [Base<T>] extends [boolean] ? EqualityOps | ArrayOps | CommonUnary : [Base<T>] extends [Date] ? EqualityOps | OrderingOps | TupleOps | ArrayOps | CommonUnary : FilterOperator;
30
+ /**
31
+ * NOTE on ordering: `string` MUST be checked first so string-literal enums resolve
32
+ * to the string branch (the tuple-wrapped `[Base<T>] extends [...]` guard prevents
33
+ * union distribution). Everything unmatched falls through to the permissive
34
+ * `FilterOperator` fallback (json/object/other).
35
+ */
36
+ /**
37
+ * Resolve the value type for a (field-type, operator) pair.
38
+ *
39
+ * The arms below cover every group in `FilterOperator` (unary/array/tuple/string/
40
+ * equality+ordering = the whole union), so the final fallthrough is unreachable for
41
+ * any `Op extends FilterOperator`. We resolve it to `never` rather than `unknown` to
42
+ * make exhaustiveness explicit: if an operator is added to `FilterOperator` without
43
+ * being placed in a group above, it lands here and its value type collapses to
44
+ * `never`, breaking call sites instead of silently going permissive.
45
+ */
46
+ export type ValueForOp<T, Op> = Op extends AllUnaryOps ? never : Op extends ArrayOps ? Base<T>[] : Op extends TupleOps ? [Base<T>, Base<T>] : Op extends StringOps ? string : Op extends EqualityOps | OrderingOps ? Base<T> : never;
47
+ /** Operators with no value (covers the 2-arg call site). */
48
+ export type UnaryOf<T> = Extract<OperatorsFor<T>, AllUnaryOps>;
49
+ /** Two-arg value shorthand: scalar (auto-equals) or array (auto-in). Mirrors runtime. */
50
+ export type EqValue<T> = Base<T> | Base<T>[];
51
+ /** Field names in M whose type allows string operators. */
52
+ export type StringFieldsOf<M> = {
53
+ [K in keyof M]: StringOps extends OperatorsFor<M[K]> ? K : never;
54
+ }[keyof M];
55
+ /** Field names in M whose type allows ordering operators (number/Date/unknown). */
56
+ export type OrderableFieldsOf<M> = {
57
+ [K in keyof M]: OrderingOps extends OperatorsFor<M[K]> ? K : never;
58
+ }[keyof M];
59
+ /**
60
+ * Field names in M whose type's operator set includes `Op` — the general form of
61
+ * `StringFieldsOf`/`OrderableFieldsOf`, used to gate per-operator convenience methods
62
+ * (e.g. `isEmpty`). For unknown-typed fields `OperatorsFor<unknown>` is the full union,
63
+ * so every field qualifies (single-generic builders stay permissive).
64
+ */
65
+ export type FieldsWithOp<M, Op extends FilterOperator> = {
66
+ [K in keyof M]: Op extends OperatorsFor<M[K]> ? K : never;
67
+ }[keyof M];
68
+ //# sourceMappingURL=field-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-types.d.ts","sourceRoot":"","sources":["../src/field-types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=field-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-types.js","sourceRoot":"","sources":["../src/field-types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,301 @@
1
+ import type { ColumnFilter, FilterOperator } from './types.js';
2
+ /**
3
+ * A single sort directive: field name and direction.
4
+ */
5
+ export interface SortItem {
6
+ field: string;
7
+ direction: 'asc' | 'desc';
8
+ }
9
+ /**
10
+ * Offset-based pagination parameters.
11
+ */
12
+ export interface OffsetPagination {
13
+ page: number;
14
+ size: number;
15
+ }
16
+ /**
17
+ * The result shape returned by `build()`.
18
+ *
19
+ * Uses the structured input format: `{ filter, include, search, sort, paginate }`.
20
+ */
21
+ export interface FilterQueryResult {
22
+ filter: {
23
+ where: ColumnFilter[];
24
+ [key: string]: unknown;
25
+ };
26
+ include?: string[];
27
+ search?: string;
28
+ sort?: SortItem[];
29
+ distinct?: string[];
30
+ paginate?: OffsetPagination;
31
+ [key: string]: unknown;
32
+ }
33
+ /**
34
+ * Client-side query builder for @agora/filter.
35
+ * Zero dependencies. Runs in browser + Node.
36
+ */
37
+ export declare class FilterQueryBuilder {
38
+ private conditions;
39
+ private readonly groups;
40
+ private extra;
41
+ private includes;
42
+ private searchTerm;
43
+ private sorts;
44
+ private distinctFields;
45
+ private pagination;
46
+ private version;
47
+ private snapshot;
48
+ private readonly listeners;
49
+ /**
50
+ * Adds a filter condition, **replacing** any existing filter(s) for the same field.
51
+ * Each field has at most one filter via `where()`. This is the natural mode for
52
+ * React UIs where a dropdown/input replaces the previous selection.
53
+ *
54
+ * Use `add()` when you need multiple filters on the same field (e.g. ranges).
55
+ *
56
+ * @example
57
+ * // Equals
58
+ * where('name', 'foo')
59
+ *
60
+ * // With operator
61
+ * where('age', 'gte', 25)
62
+ *
63
+ * // Array → auto in
64
+ * where('status', ['A', 'B'])
65
+ *
66
+ * // Replaces previous status filter
67
+ * where('status', ['C'])
68
+ */
69
+ where(field: string, operator: 'equals' | 'notEquals' | 'gt' | 'gte' | 'lt' | 'lte', value: string | number | boolean | Date): this;
70
+ where(field: string, operator: 'contains' | 'notContains' | 'iContains' | 'startsWith' | 'endsWith', value: string): this;
71
+ where(field: string, operator: 'in' | 'notIn' | 'isAnyOf', value: unknown[]): this;
72
+ where(field: string, operator: 'between' | 'notBetween', value: [unknown, unknown]): this;
73
+ where(field: string, operator: 'isNull' | 'isNotNull' | 'isEmpty' | 'isNotEmpty' | 'exists' | 'notExists'): this;
74
+ where(field: string, value: unknown): this;
75
+ where(field: string, operator: FilterOperator, value?: unknown): this;
76
+ /**
77
+ * Adds a filter condition, **accumulating** with any existing filters for the
78
+ * same field. Use for range queries where you need multiple operators on one field.
79
+ *
80
+ * Only range operators (`gt`, `gte`, `lt`, `lte`) are allowed. For other
81
+ * operators, use `where()` which replaces the previous filter for the field.
82
+ *
83
+ * @example
84
+ * filterQuery()
85
+ * .add('createdAt', 'gte', '2026-01-01')
86
+ * .add('createdAt', 'lte', '2026-12-31')
87
+ */
88
+ add(field: string, operator: 'gt' | 'gte' | 'lt' | 'lte', value: string | number | boolean | Date): this;
89
+ add(field: string, operator: FilterOperator, value?: unknown): this;
90
+ /**
91
+ * Removes ALL filters for a given field (both from `where()` and `add()`).
92
+ *
93
+ * @example
94
+ * filterQuery()
95
+ * .equals('status', 'COMPLETED')
96
+ * .contains('name', 'fleet')
97
+ * .remove('status')
98
+ * .build();
99
+ * // → { where: [{ field: 'name', operator: 'contains', value: 'fleet' }] }
100
+ */
101
+ remove(field: string): this;
102
+ /**
103
+ * Removes all filters and extra keys, resetting the builder to its initial state.
104
+ */
105
+ clear(): this;
106
+ /**
107
+ * Adds an OR group. Conditions inside the callback are OR-ed together.
108
+ *
109
+ * @example
110
+ * filterQuery()
111
+ * .where('status', 'active')
112
+ * .or(q => q
113
+ * .where('name', 'contains', 'sync')
114
+ * .where('email', 'contains', 'sync')
115
+ * )
116
+ */
117
+ or(fn: (q: FilterQueryBuilder) => void): this;
118
+ /**
119
+ * Adds an AND group. Conditions inside the callback are AND-ed together.
120
+ *
121
+ * @example
122
+ * filterQuery()
123
+ * .and(q => q
124
+ * .where('age', 'gte', 18)
125
+ * .where('age', 'lte', 65)
126
+ * )
127
+ */
128
+ and(fn: (q: FilterQueryBuilder) => void): this;
129
+ equals(field: string, value: unknown): this;
130
+ notEquals(field: string, value: unknown): this;
131
+ contains(field: string, value: string): this;
132
+ in(field: string, values: unknown[]): this;
133
+ notIn(field: string, values: unknown[]): this;
134
+ between(field: string, low: unknown, high: unknown): this;
135
+ gt(field: string, value: unknown): this;
136
+ gte(field: string, value: unknown): this;
137
+ lt(field: string, value: unknown): this;
138
+ lte(field: string, value: unknown): this;
139
+ isNull(field: string): this;
140
+ isNotNull(field: string): this;
141
+ isEmpty(field: string): this;
142
+ isNotEmpty(field: string): this;
143
+ startsWith(field: string, value: string): this;
144
+ endsWith(field: string, value: string): this;
145
+ /**
146
+ * Adds a `gte` filter using `add()` (accumulating).
147
+ * Useful for range queries where you also need an `lte` on the same field.
148
+ */
149
+ addGte(field: string, value: unknown): this;
150
+ /**
151
+ * Adds a `lte` filter using `add()` (accumulating).
152
+ * Useful for range queries where you also need a `gte` on the same field.
153
+ */
154
+ addLte(field: string, value: unknown): this;
155
+ /**
156
+ * Adds a `gt` filter using `add()` (accumulating).
157
+ */
158
+ addGt(field: string, value: unknown): this;
159
+ /**
160
+ * Adds a `lt` filter using `add()` (accumulating).
161
+ */
162
+ addLt(field: string, value: unknown): this;
163
+ /**
164
+ * Adds an extra key/value pair to the query result (e.g. page, size).
165
+ *
166
+ * @example
167
+ * filterQuery()
168
+ * .where('status', 'active')
169
+ * .set('page', 1)
170
+ * .set('size', 25)
171
+ * .build();
172
+ * // → { where: [...], page: 1, size: 25 }
173
+ */
174
+ set(key: string, value: unknown): this;
175
+ /**
176
+ * Adds relation paths to eagerly load.
177
+ *
178
+ * @example
179
+ * filterQuery().include('role', 'posts').build()
180
+ * // → { filter: { where: [] }, include: ['role', 'posts'] }
181
+ */
182
+ include(...relations: string[]): this;
183
+ /**
184
+ * Sets the global search term.
185
+ *
186
+ * @example
187
+ * filterQuery().search('fleet').build()
188
+ * // → { filter: { where: [] }, search: 'fleet' }
189
+ */
190
+ search(term: string): this;
191
+ /**
192
+ * Selects DISTINCT values of the given field(s) — the active where/search/
193
+ * sort/pagination still apply. Useful for populating a filter dropdown with
194
+ * the distinct values of a column. Repeated fields are deduplicated.
195
+ *
196
+ * @example
197
+ * filterQuery().where('baseId', 'b1').distinct('afsc').page(0, 20).build()
198
+ * // → { filter: { where: [...] }, distinct: ['afsc'], paginate: { page: 0, size: 20 } }
199
+ */
200
+ distinct(...fields: string[]): this;
201
+ /**
202
+ * Adds or replaces a sort directive for the given field.
203
+ * If a sort for the same field already exists, it is replaced.
204
+ *
205
+ * @example
206
+ * filterQuery().sort('createdAt', 'desc').sort('name').build()
207
+ * // → { ..., sort: [{ field: 'createdAt', direction: 'desc' }, { field: 'name', direction: 'asc' }] }
208
+ */
209
+ sort(field: string, direction?: 'asc' | 'desc'): this;
210
+ /**
211
+ * Shorthand for `sort(field, 'desc')`.
212
+ */
213
+ sortDesc(field: string): this;
214
+ /**
215
+ * Shorthand for `sort(field, 'asc')`.
216
+ */
217
+ sortAsc(field: string): this;
218
+ /**
219
+ * Sets offset-based pagination.
220
+ *
221
+ * @param page - Zero-based page number.
222
+ * @param size - Number of records per page (default 25).
223
+ *
224
+ * @example
225
+ * filterQuery().page(0, 25).build()
226
+ * // → { ..., paginate: { page: 0, size: 25 } }
227
+ */
228
+ page(page: number, size?: number): this;
229
+ /**
230
+ * Bumps the version, invalidates the cached snapshot, and notifies every
231
+ * subscriber. Called internally by every mutating method. Convenience
232
+ * methods (`equals`, `sortAsc`, `addGte`, …) delegate to a primitive
233
+ * mutator, so they notify transitively — never call `notify()` from them.
234
+ */
235
+ private notify;
236
+ /**
237
+ * Subscribes to mutations. Returns an unsubscribe function.
238
+ *
239
+ * Bound so it can be passed directly to `useSyncExternalStore` /
240
+ * Svelte's store contract without wrapping in an arrow.
241
+ *
242
+ * @example
243
+ * const unsubscribe = qb.subscribe(() => rerender());
244
+ */
245
+ subscribe: (listener: () => void) => (() => void);
246
+ /**
247
+ * Returns the current built result, cached until the next mutation.
248
+ *
249
+ * The reference is stable across calls while the builder is unchanged, which
250
+ * is what `useSyncExternalStore` requires to avoid infinite render loops.
251
+ *
252
+ * Bound for the same reason as `subscribe`.
253
+ */
254
+ getSnapshot: () => FilterQueryResult;
255
+ /**
256
+ * Monotonic mutation counter. Useful as a cheap dependency/key for adapters
257
+ * that prefer an integer over reference comparison.
258
+ */
259
+ getVersion(): number;
260
+ /**
261
+ * Builds the query as a `FilterQueryResult` object.
262
+ *
263
+ * Returns the structured format: `{ filter: { where: [...] }, include: [...], search: '...' }`
264
+ */
265
+ build(): FilterQueryResult;
266
+ /**
267
+ * Serializes to a query string suitable for GET requests.
268
+ *
269
+ * Uses the structured format:
270
+ * - Simple conditions → `filter[field]=value&filter[field][op]=value`
271
+ * - OR/AND groups → `filter[where][i][field]=...`
272
+ * - Includes → `include=role,posts`
273
+ * - Search → `search=term`
274
+ */
275
+ toQueryString(): string;
276
+ /**
277
+ * Converts to a flat object suitable for auto-fields.
278
+ *
279
+ * Simple equals → `{ field: value }`
280
+ * Array (in) → `{ field: [values] }`
281
+ * Other operators → `{ field: { operator: value } }`
282
+ * Multiple operators on same field → merged into one object.
283
+ *
284
+ * Note: OR/AND groups are NOT representable as flat objects.
285
+ * Use `build()` for complex queries.
286
+ */
287
+ toFlatObject(): Record<string, unknown>;
288
+ }
289
+ /**
290
+ * Creates a new FilterQueryBuilder instance.
291
+ *
292
+ * @example
293
+ * import { filterQuery } from '@adonis-agora/filter-client';
294
+ *
295
+ * const q = filterQuery()
296
+ * .where('name', 'contains', 'fleet')
297
+ * .where('status', ['COMPLETED', 'FAILED'])
298
+ * .build();
299
+ */
300
+ export declare function filterQuery(): FilterQueryBuilder;
301
+ //# sourceMappingURL=filter-query-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-query-builder.d.ts","sourceRoot":"","sources":["../src/filter-query-builder.ts"],"names":[],"mappings":"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"}