@adonis-agora/filter 0.9.0 → 0.11.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/CHANGELOG.md +12 -0
- package/README.md +17 -0
- package/dist/src/in_memory.d.ts +268 -0
- package/dist/src/in_memory.d.ts.map +1 -0
- package/dist/src/in_memory.js +759 -0
- package/dist/src/in_memory.js.map +1 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/package.json +29 -20
- package/skills/filter-basics/SKILL.md +34 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @adonis-agora/filter
|
|
2
2
|
|
|
3
|
+
## 0.11.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#105](https://github.com/DavideCarvalho/adonis-agora-filter/pull/105) [`72ff139`](https://github.com/DavideCarvalho/adonis-agora-filter/commit/72ff139e16c9ac05f326d490a997579ac5fb3273) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - Drop Node.js 20 and 22: `engines.node` is now `>=24`. Node 20 reached end-of-life on 2026-04-30, and AdonisJS 7, which these packages require as a peer, needs Node 24 or later (`@adonisjs/core` declares `engines.node >=24.0.0`). The supported lines are the ones Node still maintains that AdonisJS 7 accepts: 24 and 26, both tested in CI.
|
|
8
|
+
|
|
9
|
+
## 0.10.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [#67](https://github.com/DavideCarvalho/adonis-agora-filter/pull/67) [`1dd11c3`](https://github.com/DavideCarvalho/adonis-agora-filter/commit/1dd11c3563cd015d27627808cc3e23830ed4be50) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - In-memory adapter at `@adonis-agora/filter/in-memory`: `defineCollection({ fields, primaryKey, relations })` declares a row source (field types incl. `'string[]'`-style arrays, virtual fields, to-one/to-many relations), and `collection.query(rows)` is a `QueryBuilderLike` the existing runner drives unchanged — `applyFilter`, `applyCursor`, `applyFilterFromRequest`, `applyCursorFromRequest` and `groupByCountFromRequest` all work over a plain array with the same parsing, allow-listing and coercion. Evaluation mirrors the SQL the Lucid adapter emits (ILIKE, three-valued NULL logic, NULLS LAST asc / FIRST desc, EXISTS for to-many paths). `filterInMemory` / `cursorInMemory` do it in one call; `InMemoryQueryError` is thrown for SQL-only features (`computed`, `fullText`, `vectorSimilarity`).
|
|
14
|
+
|
|
3
15
|
## 0.9.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# `@adonis-agora/filter`
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@adonis-agora/filter) [](https://www.npmjs.com/package/@adonis-agora/filter) [](https://github.com/DavideCarvalho/adonis-agora-filter/actions/workflows/ci.yml) [](https://www.npmjs.com/package/@adonis-agora/filter)
|
|
4
|
+
|
|
3
5
|
Server-side query filtering, sorting, and pagination for AdonisJS. Parses the
|
|
4
6
|
Spatie/JSON:API query the `@adonis-agora/filter-client` builder emits, applies it to a
|
|
5
7
|
Lucid query through a field allow-list, and resolves offset or keyset (cursor)
|
|
@@ -50,6 +52,21 @@ AND/OR composition. The `allowed`/`sortable`/`searchable` lists are the security
|
|
|
50
52
|
boundary. The Lucid binding is structural (`QueryBuilderLike`) so any Lucid query
|
|
51
53
|
builder works and the adapter is unit-testable.
|
|
52
54
|
|
|
55
|
+
### In-memory lists
|
|
56
|
+
|
|
57
|
+
`@adonis-agora/filter/in-memory` runs the same input against a plain array — an
|
|
58
|
+
in-memory `QueryBuilderLike` the runner drives exactly like a Lucid query:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { defineCollection, filterInMemory } from '@adonis-agora/filter/in-memory'
|
|
62
|
+
|
|
63
|
+
const users = defineCollection<UserRow>({
|
|
64
|
+
fields: { name: 'string', age: 'number', fullName: { type: 'string', get: (u) => u.first + ' ' + u.last } },
|
|
65
|
+
})
|
|
66
|
+
const page = filterInMemory(users, rows, input, { allowed: ['name', 'age', 'fullName'] })
|
|
67
|
+
// { data, meta: { total, perPage, currentPage, lastPage, firstPage } }
|
|
68
|
+
```
|
|
69
|
+
|
|
53
70
|
See the [repository README](https://github.com/DavideCarvalho/adonis-filter).
|
|
54
71
|
|
|
55
72
|
## License
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { type CursorPage, type CursorParams } from './cursor.js';
|
|
2
|
+
import type { QueryBuilderLike } from './lucid_adapter.js';
|
|
3
|
+
import type { FilterConfig, FilterFieldKind, FilterInput } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* The in-memory adapter: a {@link QueryBuilderLike} that evaluates against a plain JS array.
|
|
6
|
+
*
|
|
7
|
+
* The runner (`applyFilter`, `applyCursor`, `applyFilterFromRequest`, `groupByCountFromRequest`)
|
|
8
|
+
* does exactly what it does for a Lucid query — parse, alias-resolve, validate, allow-list, coerce —
|
|
9
|
+
* and then drives the same builder calls it would hand Lucid. This builder records those calls and
|
|
10
|
+
* evaluates them over rows instead of compiling SQL, so an in-memory listing speaks the same wire
|
|
11
|
+
* format, operators and error shapes as a database one, and a filter spec written for a model
|
|
12
|
+
* works unchanged over rows assembled in memory (several sources merged, a static catalog, a
|
|
13
|
+
* remote API page).
|
|
14
|
+
*
|
|
15
|
+
* The evaluation mirrors what Postgres does with the SQL the Lucid adapter emits — including the
|
|
16
|
+
* places that surprise people: three-valued NULL logic (a NULL value fails `notEquals`/`notIn`/
|
|
17
|
+
* `notBetween`, `NOT IN` a list holding NULL matches nothing), ILIKE for every LIKE-style operator,
|
|
18
|
+
* and NULLS LAST on ascending / NULLS FIRST on descending order.
|
|
19
|
+
*/
|
|
20
|
+
/** A scalar array kind — an in-memory extension; see {@link InMemoryFieldType}. */
|
|
21
|
+
export type InMemoryArrayKind = 'string[]' | 'number[]' | 'boolean[]' | 'date[]';
|
|
22
|
+
/**
|
|
23
|
+
* A declared field type. The scalar kinds are the lib's own {@link FilterFieldKind}; the array
|
|
24
|
+
* kinds declare a list-valued field, on which a scalar operator matches when ANY element matches
|
|
25
|
+
* and a negated operator (`notEquals`, `notIn`, `notBetween`) matches when NO element does.
|
|
26
|
+
*/
|
|
27
|
+
export type InMemoryFieldType = FilterFieldKind | InMemoryArrayKind;
|
|
28
|
+
/** A virtual field: a value computed from the row — the in-memory counterpart of `computed`. */
|
|
29
|
+
export interface InMemoryVirtualField<T> {
|
|
30
|
+
type: InMemoryFieldType;
|
|
31
|
+
get: (row: T) => unknown;
|
|
32
|
+
}
|
|
33
|
+
/** One entry of {@link DefineCollectionOptions.fields}: a stored field's type, or a virtual field. */
|
|
34
|
+
export type InMemoryFieldDeclaration<T> = InMemoryFieldType | InMemoryVirtualField<T>;
|
|
35
|
+
/** Relation cardinality. `*-to-one` reads a row (or null); `*-to-many` reads an array. */
|
|
36
|
+
export type InMemoryRelationKind = 'one-to-one' | 'many-to-one' | 'one-to-many' | 'many-to-many';
|
|
37
|
+
/**
|
|
38
|
+
* A relation a dotted filter path (`posts.title`) can cross. The runner turns such a path into a
|
|
39
|
+
* `whereHas`, evaluated here with EXISTS semantics: the row matches when at least one related row
|
|
40
|
+
* satisfies the nested conditions.
|
|
41
|
+
*/
|
|
42
|
+
export interface InMemoryRelation<T> {
|
|
43
|
+
kind: InMemoryRelationKind;
|
|
44
|
+
/** The related collection — a thunk so two collections can reference each other. */
|
|
45
|
+
target: () => InMemoryCollection<any>;
|
|
46
|
+
/** Read the related row(s) off a row. `null`/`undefined` means no related row. */
|
|
47
|
+
get: (row: T) => unknown;
|
|
48
|
+
}
|
|
49
|
+
/** Options for {@link defineCollection}. */
|
|
50
|
+
export interface DefineCollectionOptions<T> {
|
|
51
|
+
/**
|
|
52
|
+
* The field declarations — what each field is, so filter values are compared as that kind
|
|
53
|
+
* (`'3'` equals `3` on a `number` field, `'true'` equals `true` on a `boolean`, ISO strings
|
|
54
|
+
* compare as instants on a `date`). A field that is not declared is read as an own property and
|
|
55
|
+
* compared by the kind its value has at runtime.
|
|
56
|
+
*/
|
|
57
|
+
fields: Record<string, InMemoryFieldDeclaration<T>>;
|
|
58
|
+
/** The keyset tiebreaker for cursor pagination. Default `'id'`. */
|
|
59
|
+
primaryKey?: string;
|
|
60
|
+
/** Relations dotted filter paths may cross. */
|
|
61
|
+
relations?: Record<string, InMemoryRelation<T>>;
|
|
62
|
+
/**
|
|
63
|
+
* The collection's "table" name. A `distinct`/sort field qualified with it (`users.name`, the
|
|
64
|
+
* form {@link FilterConfig.table} makes projectable) reads the root field `name`.
|
|
65
|
+
*/
|
|
66
|
+
name?: string;
|
|
67
|
+
}
|
|
68
|
+
interface ResolvedField<T> {
|
|
69
|
+
kind: FilterFieldKind;
|
|
70
|
+
array: boolean;
|
|
71
|
+
get: ((row: T) => unknown) | undefined;
|
|
72
|
+
}
|
|
73
|
+
/** A declared, reusable row source. Create one with {@link defineCollection}. */
|
|
74
|
+
export interface InMemoryCollection<T extends object> {
|
|
75
|
+
readonly name: string | undefined;
|
|
76
|
+
readonly primaryKey: string;
|
|
77
|
+
/**
|
|
78
|
+
* The declared fields as the colocated `filterable` map `defineFilter` accepts
|
|
79
|
+
* (`defineFilter({ filterable: users.filterable })`) — array kinds map to their element kind,
|
|
80
|
+
* which is what the runner coerces a filter value to.
|
|
81
|
+
*/
|
|
82
|
+
readonly filterable: Readonly<Record<string, FilterFieldKind>>;
|
|
83
|
+
/** The declared fields as {@link FilterConfig.fieldTypes}, for `applyFilter` callers. */
|
|
84
|
+
readonly fieldTypes: Readonly<Record<string, {
|
|
85
|
+
kind: FilterFieldKind;
|
|
86
|
+
}>>;
|
|
87
|
+
/** Start a query over `rows` — hand the builder to the runner like a Lucid query. */
|
|
88
|
+
query(rows: Iterable<T>): InMemoryQueryBuilder<T>;
|
|
89
|
+
/** @internal */
|
|
90
|
+
readonly $fields: Readonly<Record<string, ResolvedField<T>>>;
|
|
91
|
+
/** @internal */
|
|
92
|
+
readonly $relations: Readonly<Record<string, InMemoryRelation<T>>>;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Thrown when the runner asks the in-memory builder for something only SQL can do: a raw
|
|
96
|
+
* predicate or ordering (policy `computed` fields, `fullText`, `vectorSimilarity`) — declare a
|
|
97
|
+
* virtual field instead — or a relation/field path the collection does not declare.
|
|
98
|
+
*/
|
|
99
|
+
export declare class InMemoryQueryError extends Error {
|
|
100
|
+
constructor(message: string);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Declare a collection: its fields (and their types), virtual fields, primary key and relations.
|
|
104
|
+
*
|
|
105
|
+
* ```ts
|
|
106
|
+
* const posts = defineCollection<Post>({ fields: { id: 'number', title: 'string' } })
|
|
107
|
+
* const users = defineCollection<User>({
|
|
108
|
+
* fields: {
|
|
109
|
+
* id: 'number',
|
|
110
|
+
* name: 'string',
|
|
111
|
+
* age: 'number',
|
|
112
|
+
* tags: 'string[]',
|
|
113
|
+
* fullName: { type: 'string', get: (u) => `${u.first} ${u.last}` },
|
|
114
|
+
* },
|
|
115
|
+
* relations: { posts: { kind: 'one-to-many', target: () => posts, get: (u) => u.posts } },
|
|
116
|
+
* })
|
|
117
|
+
*
|
|
118
|
+
* const qb = users.query(rows)
|
|
119
|
+
* const { page, size } = applyFilter(qb, input, { allowed: ['name', 'posts.title'] })
|
|
120
|
+
* return qb.paginate(page, size)
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
export declare function defineCollection<T extends object>(options: DefineCollectionOptions<T>): InMemoryCollection<T>;
|
|
124
|
+
/** The pagination meta {@link InMemoryQueryBuilder.paginate} returns — Lucid's paginator fields. */
|
|
125
|
+
export interface InMemoryPageMeta {
|
|
126
|
+
total: number;
|
|
127
|
+
perPage: number;
|
|
128
|
+
currentPage: number;
|
|
129
|
+
lastPage: number;
|
|
130
|
+
firstPage: number;
|
|
131
|
+
}
|
|
132
|
+
/** One offset page — the shape of a serialized Lucid paginator (`{ meta, data }`). */
|
|
133
|
+
export interface InMemoryPage<T> {
|
|
134
|
+
data: T[];
|
|
135
|
+
meta: InMemoryPageMeta;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* A {@link QueryBuilderLike} over an array. Created by {@link InMemoryCollection.query}; hand it to
|
|
139
|
+
* any runner entry point exactly as you would a Lucid query, then read the result with
|
|
140
|
+
* {@link all}, {@link paginate}, or by awaiting it (it is thenable, like a Lucid query — which is
|
|
141
|
+
* what lets `groupByCountFromRequest` run over it unchanged).
|
|
142
|
+
*/
|
|
143
|
+
export declare class InMemoryQueryBuilder<T extends object> implements QueryBuilderLike {
|
|
144
|
+
readonly collection: InMemoryCollection<T>;
|
|
145
|
+
private readonly rows;
|
|
146
|
+
private readonly clauses;
|
|
147
|
+
private readonly sorts;
|
|
148
|
+
private readonly selects;
|
|
149
|
+
private readonly groups;
|
|
150
|
+
private readonly groupSearches;
|
|
151
|
+
private distinctFields;
|
|
152
|
+
private countAlias;
|
|
153
|
+
private limitCount;
|
|
154
|
+
private offsetCount;
|
|
155
|
+
constructor(collection: InMemoryCollection<T>, rows?: readonly T[]);
|
|
156
|
+
private field;
|
|
157
|
+
/** Strip a leading `<collection name>.` qualifier. */
|
|
158
|
+
private unqualify;
|
|
159
|
+
/**
|
|
160
|
+
* Read a (possibly dotted) path off a row. A dotted path crosses a to-one relation; crossing a
|
|
161
|
+
* to-many relation is ambiguous outside a `whereHas` (which the runner uses for filters) and is
|
|
162
|
+
* rejected.
|
|
163
|
+
*/
|
|
164
|
+
read(row: T, rawPath: string): unknown;
|
|
165
|
+
/** The declared kind of a path (following to-one relations), or `unknown`. */
|
|
166
|
+
private kindOf;
|
|
167
|
+
/**
|
|
168
|
+
* Build a leaf predicate. `match` tests one non-null element; `negated` flips the element-level
|
|
169
|
+
* result into "no element matches" — with SQL's rule that a NULL value (or an uncastable
|
|
170
|
+
* comparison) satisfies neither a condition nor its negation.
|
|
171
|
+
*/
|
|
172
|
+
private leaf;
|
|
173
|
+
private equalsLeaf;
|
|
174
|
+
private compareLeaf;
|
|
175
|
+
private inLeaf;
|
|
176
|
+
private betweenLeaf;
|
|
177
|
+
private likeLeaf;
|
|
178
|
+
private add;
|
|
179
|
+
private group;
|
|
180
|
+
/**
|
|
181
|
+
* Does `row` satisfy every recorded condition? Clauses chain left to right the way knex joins
|
|
182
|
+
* them — `a AND b OR c` — so AND binds tighter than OR, exactly as the emitted SQL would.
|
|
183
|
+
*/
|
|
184
|
+
matches(row: T): boolean;
|
|
185
|
+
where(callback: (qb: QueryBuilderLike) => void): this;
|
|
186
|
+
where(column: string, value: unknown): this;
|
|
187
|
+
where(column: string, operator: string, value: unknown): this;
|
|
188
|
+
orWhere(callback: (qb: QueryBuilderLike) => void): this;
|
|
189
|
+
whereHas(relation: any, callback: (qb: QueryBuilderLike) => void): this;
|
|
190
|
+
whereNot(column: string, value: unknown): this;
|
|
191
|
+
whereIn(column: string, values: unknown[]): this;
|
|
192
|
+
whereNotIn(column: string, values: unknown[]): this;
|
|
193
|
+
whereNull(column: string): this;
|
|
194
|
+
whereNotNull(column: string): this;
|
|
195
|
+
whereBetween(column: string, range: [unknown, unknown]): this;
|
|
196
|
+
whereNotBetween(column: string, range: [unknown, unknown]): this;
|
|
197
|
+
whereILike(column: string, value: string): this;
|
|
198
|
+
orWhereILike(column: string, value: string): this;
|
|
199
|
+
orderBy(column: string, direction: 'asc' | 'desc'): this;
|
|
200
|
+
/**
|
|
201
|
+
* Only the group-by-count search predicate (`LOWER(??) LIKE ?`) is understood; any other raw
|
|
202
|
+
* SQL — a policy's `computed` fields, `fullText`, `vectorSimilarity` — throws
|
|
203
|
+
* {@link InMemoryQueryError}. Declare a virtual field on the collection instead of `computed`.
|
|
204
|
+
*/
|
|
205
|
+
whereRaw(sql: string, bindings?: readonly unknown[]): this;
|
|
206
|
+
orderByRaw(sql: string, _bindings?: readonly unknown[]): this;
|
|
207
|
+
distinct(...columns: string[]): this;
|
|
208
|
+
limit(count: number): this;
|
|
209
|
+
offset(n: number): this;
|
|
210
|
+
select(...columns: string[]): this;
|
|
211
|
+
count(column: string): this;
|
|
212
|
+
groupBy(...columns: string[]): this;
|
|
213
|
+
private compareRows;
|
|
214
|
+
/** Ascending comparison with NULLs sorting last (so NULLS FIRST once a desc sort negates it). */
|
|
215
|
+
private compareValues;
|
|
216
|
+
/** Filter + sort (+ distinct / projection / aggregation), before limit/offset. */
|
|
217
|
+
private evaluate;
|
|
218
|
+
/**
|
|
219
|
+
* `GROUP BY` over the matched rows. An array-typed grouping field is unnested — each element is
|
|
220
|
+
* its own group — which is what a tag picker wants (Postgres would group whole arrays).
|
|
221
|
+
*/
|
|
222
|
+
private aggregate;
|
|
223
|
+
private window;
|
|
224
|
+
/**
|
|
225
|
+
* Execute: the matching rows in order, honouring `limit`/`offset` (which is what a cursor page
|
|
226
|
+
* sets). Under a `distinct`, a `select` or a `groupBy`, the rows are projection objects — just
|
|
227
|
+
* as a Lucid query returns them.
|
|
228
|
+
*/
|
|
229
|
+
all(): T[];
|
|
230
|
+
/** How many rows (or distinct tuples / groups) match, ignoring `limit`/`offset`. */
|
|
231
|
+
total(): number;
|
|
232
|
+
/**
|
|
233
|
+
* One offset page — the in-memory `query.paginate(page, size)`. Feed it the `{ page, size }`
|
|
234
|
+
* the runner resolved (clamped and defaulted), never raw request values.
|
|
235
|
+
*/
|
|
236
|
+
paginate(page: number, perPage: number): InMemoryPage<T>;
|
|
237
|
+
/**
|
|
238
|
+
* Thenable, like a Lucid query: `await qb` resolves to {@link all}. This is what lets helpers
|
|
239
|
+
* that execute a builder by awaiting it (`groupByCountFromRequest`) run over an array.
|
|
240
|
+
*/
|
|
241
|
+
then<R1 = T[], R2 = never>(onfulfilled?: ((rows: T[]) => R1 | PromiseLike<R1>) | null, onrejected?: ((reason: unknown) => R2 | PromiseLike<R2>) | null): Promise<R1 | R2>;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Filter, search, sort and offset-paginate `rows` in one call: {@link applyFilter} over a fresh
|
|
245
|
+
* builder, then {@link InMemoryQueryBuilder.paginate} with the resolved page. A `distinct` request
|
|
246
|
+
* pages the distinct tuples instead of rows.
|
|
247
|
+
*
|
|
248
|
+
* ```ts
|
|
249
|
+
* const page = filterInMemory(users, rows, parseFilterRequest(ctx.request.qs()), {
|
|
250
|
+
* allowed: ['name', 'age', 'posts.title'],
|
|
251
|
+
* searchable: ['name'],
|
|
252
|
+
* fieldTypes: users.fieldTypes,
|
|
253
|
+
* })
|
|
254
|
+
* // → { data, meta: { total, perPage, currentPage, lastPage, firstPage } }
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
export declare function filterInMemory<T extends object>(collection: InMemoryCollection<T>, rows: Iterable<T>, input: FilterInput, config: FilterConfig): InMemoryPage<T>;
|
|
258
|
+
/**
|
|
259
|
+
* The keyset (cursor) counterpart of {@link filterInMemory}: {@link applyCursor} over a fresh
|
|
260
|
+
* builder (the primary key defaults to the collection's), then `buildCursorPage`. Keyset values
|
|
261
|
+
* are read through the collection, so a virtual field or a to-one relation path works as a cursor
|
|
262
|
+
* sort field.
|
|
263
|
+
*/
|
|
264
|
+
export declare function cursorInMemory<T extends object>(collection: InMemoryCollection<T>, rows: Iterable<T>, input: FilterInput & CursorParams, config: FilterConfig & {
|
|
265
|
+
primaryKey?: string;
|
|
266
|
+
}): CursorPage<T>;
|
|
267
|
+
export {};
|
|
268
|
+
//# sourceMappingURL=in_memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in_memory.d.ts","sourceRoot":"","sources":["../../src/in_memory.ts"],"names":[],"mappings":"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"}
|