@rapiq/sql 2.0.0-beta.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 +59 -0
- package/dist/index.d.mts +580 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +876 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +66 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021-2026 Peter Placzek
|
|
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,59 @@
|
|
|
1
|
+
# @rapiq/sql
|
|
2
|
+
|
|
3
|
+
Part of [rapiq](https://github.com/tada5hi/rapiq) — typed REST queries: build, transport, validate, execute.
|
|
4
|
+
|
|
5
|
+
Turns query AST nodes into **parameterized SQL fragments**. Database-agnostic: per-database behavior is injected as a small dialect option object (presets for `pg`, `mysql`, `sqlite`, `mssql`, `oracle`), and values are always bound as parameters — never interpolated. It is also the foundation the [TypeORM adapter](https://www.npmjs.com/package/@rapiq/typeorm) builds on.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @rapiq/core @rapiq/sql
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
A root `Adapter` bundles one sub-adapter per parameter; `execute(query)` walks a whole `Query` into it and returns the accumulated clause fragments:
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { Adapter, pg } from '@rapiq/sql';
|
|
19
|
+
|
|
20
|
+
const adapter = new Adapter({ ...pg, rootAlias: 'user' });
|
|
21
|
+
|
|
22
|
+
const fragments = adapter.execute(query);
|
|
23
|
+
// {
|
|
24
|
+
// columns: ['"user"."id"', '"user"."name"', '"realm"."name"'],
|
|
25
|
+
// where: '("user"."age" >= $1 and ...)',
|
|
26
|
+
// params: [18, ...],
|
|
27
|
+
// orderBy: ['"user"."age" DESC'],
|
|
28
|
+
// limit: 25,
|
|
29
|
+
// offset: 50,
|
|
30
|
+
// relations: ['realm'],
|
|
31
|
+
// }
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Construct the `Adapter` **per request** — it accumulates per-call state, so the shareable, long-lived part is the options object, not the adapter instance.
|
|
35
|
+
|
|
36
|
+
Per-parameter adapter/visitor pairs work standalone — e.g. rendering just the filters:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { FiltersAdapter, FiltersVisitor, RelationsAdapter, pg } from '@rapiq/sql';
|
|
40
|
+
|
|
41
|
+
const filters = new FiltersAdapter(new RelationsAdapter(), pg);
|
|
42
|
+
query.filters.accept(new FiltersVisitor(filters));
|
|
43
|
+
|
|
44
|
+
const [sql, params] = filters.getQueryAndParameters();
|
|
45
|
+
// sql: ("name" ~* $1 and "age" >= $2)
|
|
46
|
+
// params: ['jo', 18]
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The package deliberately stops at fragments: composing the final `SELECT` — in particular `FROM`/`JOIN` conditions — is the caller's job, or a backend adapter's (that's exactly what [@rapiq/typeorm](https://www.npmjs.com/package/@rapiq/typeorm) does).
|
|
50
|
+
|
|
51
|
+
Notable semantics: `null` filter values render as `IS NULL` / `IS NOT NULL` predicates, empty `IN` lists render as `1 = 0` (never invalid SQL), string-matching operators match literally on every dialect, and `resolveDialect(name)` maps driver/connection type names (`postgres`, `mariadb`, `better-sqlite3`, …) to the matching preset. On dialects without a regexp operator (SQL Server, stock SQLite), `contains`/`startsWith`/`endsWith` fall back to escaped `LIKE`; only the `regex` operator throws a typed `AdapterError`.
|
|
52
|
+
|
|
53
|
+
## Documentation
|
|
54
|
+
|
|
55
|
+
Full guide (dialects, null semantics, fragment API): [rapiq.tada5hi.net/packages/sql](https://rapiq.tada5hi.net/packages/sql)
|
|
56
|
+
|
|
57
|
+
## License
|
|
58
|
+
|
|
59
|
+
Published under the [MIT License](https://github.com/tada5hi/rapiq/blob/master/LICENSE).
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
import { Field, FieldOperator, Fields, Filter, FilterFieldOperator, Filters, IField, IFieldVisitor, IFields, IFieldsVisitor, IFilterVisitor, IFiltersVisitor, IPaginationVisitor, IQuery, IQueryVisitor, IRelationVisitor, IRelationsVisitor, ISortVisitor, ISortsVisitor, Pagination, Query, Relation, Relations, Sort, SortDirection, Sorts } from "@rapiq/core";
|
|
2
|
+
//#region src/helpers/relation-alias.d.ts
|
|
3
|
+
type RelationAliasFn = (path: string) => string;
|
|
4
|
+
/**
|
|
5
|
+
* Default join-alias derivation: every path segment is length-prefixed
|
|
6
|
+
* (e.g. `role.realm` -> `r4_role_5_realm`). Unlike replacing dots with
|
|
7
|
+
* underscores, this is injective even when relation names contain `_`.
|
|
8
|
+
* Aliases that would exceed the database identifier limit are bounded:
|
|
9
|
+
* a readable prefix plus a hash of the full path — otherwise engines
|
|
10
|
+
* such as PostgreSQL would truncate them (silently collapsing long,
|
|
11
|
+
* distinct paths onto one alias).
|
|
12
|
+
*/
|
|
13
|
+
declare function buildRelationAlias(path: string): string;
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/helpers/field.d.ts
|
|
16
|
+
type Field$1 = {
|
|
17
|
+
prefix?: string;
|
|
18
|
+
relation?: string;
|
|
19
|
+
name: string;
|
|
20
|
+
};
|
|
21
|
+
declare function parseField(input: string, rootAlias?: string, relationAlias?: RelationAliasFn): Field$1;
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/helpers/like.d.ts
|
|
24
|
+
/**
|
|
25
|
+
* Escape LIKE pattern wildcards (incl. the MSSQL bracket range)
|
|
26
|
+
* so user input matches literally under `ESCAPE '\'`.
|
|
27
|
+
*/
|
|
28
|
+
declare function escapeLikePattern(input: string): string;
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/helpers/name-split.d.ts
|
|
31
|
+
declare function splitFirst(input: string): [string, string | undefined];
|
|
32
|
+
declare function splitLast(input: string): [string, string | undefined];
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/helpers/param-placeholder-indexer.d.ts
|
|
35
|
+
declare class ParamPlaceholderIndexer {
|
|
36
|
+
protected index: number;
|
|
37
|
+
constructor(index?: number);
|
|
38
|
+
next(): number;
|
|
39
|
+
reset(): void;
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/types.d.ts
|
|
43
|
+
type RootAliasFn<TARGET extends Record<string, any> = Record<string, any>> = (target?: TARGET) => string;
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/helpers/root-alias.d.ts
|
|
46
|
+
declare function toRootAliasFn<TARGET extends Record<string, any> = Record<string, any>>(input: string | RootAliasFn<TARGET>): RootAliasFn<TARGET>;
|
|
47
|
+
declare function isRootAliasFn(input: string | RootAliasFn): input is RootAliasFn;
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region src/visitor/types.d.ts
|
|
50
|
+
type VisitorOptions = {
|
|
51
|
+
/**
|
|
52
|
+
* Field keys whose equality comparisons (eq/ne/in/nin) stay
|
|
53
|
+
* case-sensitive instead of the case-insensitive default —
|
|
54
|
+
* e.g. identifier or token columns. Typically forwarded from
|
|
55
|
+
* a schema's `filters.caseSensitive` list.
|
|
56
|
+
*/
|
|
57
|
+
caseSensitive?: string[];
|
|
58
|
+
[key: string]: any;
|
|
59
|
+
};
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/adapter/filters/types.d.ts
|
|
62
|
+
interface IFiltersAdapter extends ISubAdapter {
|
|
63
|
+
conditions: string[];
|
|
64
|
+
params: unknown[];
|
|
65
|
+
where(field: string, operator: string, value?: unknown): this;
|
|
66
|
+
whereRaw(sql: string, ...values: unknown[]): this;
|
|
67
|
+
buildField(input: string): string;
|
|
68
|
+
buildParamPlaceholder(): string;
|
|
69
|
+
buildParamsPlaceholders(input: unknown[]): string[];
|
|
70
|
+
getFieldPrefix(): string;
|
|
71
|
+
setFieldPrefix(prefix: string): void;
|
|
72
|
+
regexp(field: string, placeholder: string, ignoreCase: boolean): string;
|
|
73
|
+
isRegexpSupported(): boolean;
|
|
74
|
+
caseFold(input: string): string;
|
|
75
|
+
isCaseFoldable(field: string): boolean;
|
|
76
|
+
merge<T extends IFiltersAdapter>(query: T, operator?: 'and' | 'or', isInverted?: boolean): this;
|
|
77
|
+
child(): this;
|
|
78
|
+
getQueryAndParameters(): [string, unknown[]];
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region src/adapter/filters/base.d.ts
|
|
82
|
+
declare abstract class FiltersBaseAdapter<RelationsAdapter extends IRelationsAdapter = IRelationsAdapter> implements IFiltersAdapter {
|
|
83
|
+
/**
|
|
84
|
+
* where conditions
|
|
85
|
+
*
|
|
86
|
+
* e.g. ['"foo.bar" = "1"' ]
|
|
87
|
+
*/
|
|
88
|
+
conditions: string[];
|
|
89
|
+
params: unknown[];
|
|
90
|
+
protected relations: RelationsAdapter;
|
|
91
|
+
protected paramPlaceholderIndexer: ParamPlaceholderIndexer;
|
|
92
|
+
protected fieldPrefix: string;
|
|
93
|
+
protected constructor(relations: RelationsAdapter);
|
|
94
|
+
clear(): void;
|
|
95
|
+
protected abstract rootAlias(): string | undefined;
|
|
96
|
+
protected abstract paramPlaceholder(index: number): string;
|
|
97
|
+
protected abstract escapeField(field: string): string;
|
|
98
|
+
abstract regexp(field: string, placeholder: string, ignoreCase: boolean): string;
|
|
99
|
+
abstract execute(): void;
|
|
100
|
+
abstract child(): this;
|
|
101
|
+
/**
|
|
102
|
+
* Whether the dialect can build regular-expression conditions.
|
|
103
|
+
* Anchored operators fall back to LIKE otherwise.
|
|
104
|
+
*/
|
|
105
|
+
isRegexpSupported(): boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Fold an expression for a case-insensitive equality comparison
|
|
108
|
+
* (eq/ne/in/nin on strings). Dialects whose plain `=` already
|
|
109
|
+
* compares case-insensitively return the input unchanged.
|
|
110
|
+
*/
|
|
111
|
+
caseFold(input: string): string;
|
|
112
|
+
/**
|
|
113
|
+
* Whether equality comparisons on this field may case-fold at all.
|
|
114
|
+
* Backends with column metadata override this to exempt non-string
|
|
115
|
+
* columns — folding them is wasted work at best and a type error at
|
|
116
|
+
* worst (e.g. `lower(integer)` on postgres).
|
|
117
|
+
*/
|
|
118
|
+
isCaseFoldable(_field: string): boolean;
|
|
119
|
+
where(field: string, operator: string, value?: unknown): this;
|
|
120
|
+
whereRaw(sql: string, ...values: unknown[]): this;
|
|
121
|
+
buildParamPlaceholder(): string;
|
|
122
|
+
buildParamsPlaceholders(input: unknown[]): string[];
|
|
123
|
+
buildField(input: string): string;
|
|
124
|
+
merge<T extends IFiltersAdapter>(query: T, operator?: 'and' | 'or', isInverted?: boolean): this;
|
|
125
|
+
protected setChildAttributes<T extends FiltersBaseAdapter>(child: T): T;
|
|
126
|
+
setLastPlaceholderIndexer(input: ParamPlaceholderIndexer): void;
|
|
127
|
+
getFieldPrefix(): string;
|
|
128
|
+
setFieldPrefix(prefix: string): void;
|
|
129
|
+
getQuery(): string;
|
|
130
|
+
getQueryAndParameters(): [string, unknown[]];
|
|
131
|
+
}
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/dialect/types.d.ts
|
|
134
|
+
type DialectOptions = {
|
|
135
|
+
/**
|
|
136
|
+
* Build a regular-expression condition.
|
|
137
|
+
* Omit when the dialect has no regexp support — anchored operators
|
|
138
|
+
* (startsWith, endsWith, contains) fall back to LIKE and the
|
|
139
|
+
* regex operator raises a typed AdapterError.
|
|
140
|
+
*/
|
|
141
|
+
regexp?: (field: string, placeholder: string, ignoreCase: boolean) => string;
|
|
142
|
+
/**
|
|
143
|
+
* Fold an expression (field or parameter placeholder) for a
|
|
144
|
+
* case-insensitive equality comparison (eq/ne/in/nin on strings).
|
|
145
|
+
* Omit for the default `lower(...)` wrapping — dialects whose plain
|
|
146
|
+
* `=` already compares case-insensitively under their default
|
|
147
|
+
* collation (mysql, mssql) return the input unchanged instead.
|
|
148
|
+
*/
|
|
149
|
+
caseFold?: (input: string) => string;
|
|
150
|
+
escapeField: (input: string) => string;
|
|
151
|
+
paramPlaceholder: (index: number) => string;
|
|
152
|
+
};
|
|
153
|
+
//#endregion
|
|
154
|
+
//#region src/dialect/mssql.d.ts
|
|
155
|
+
declare const mssql: DialectOptions;
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region src/dialect/mysql.d.ts
|
|
158
|
+
declare const mysql: DialectOptions;
|
|
159
|
+
//#endregion
|
|
160
|
+
//#region src/dialect/oracle.d.ts
|
|
161
|
+
declare const oracle: DialectOptions;
|
|
162
|
+
//#endregion
|
|
163
|
+
//#region src/dialect/pg.d.ts
|
|
164
|
+
declare const pg: DialectOptions;
|
|
165
|
+
//#endregion
|
|
166
|
+
//#region src/dialect/resolve.d.ts
|
|
167
|
+
/**
|
|
168
|
+
* Resolve a driver/connection type name (e.g. TypeORM's
|
|
169
|
+
* `connection.options.type` or a knex client name) to the
|
|
170
|
+
* matching {@link DialectOptions} preset.
|
|
171
|
+
*/
|
|
172
|
+
declare function resolveDialect(name: string): DialectOptions | undefined;
|
|
173
|
+
//#endregion
|
|
174
|
+
//#region src/dialect/sqlite.d.ts
|
|
175
|
+
declare const sqlite: DialectOptions;
|
|
176
|
+
//#endregion
|
|
177
|
+
//#region src/adapter/filters/module.d.ts
|
|
178
|
+
type FiltersContainerOptions = {
|
|
179
|
+
rootAlias?: string;
|
|
180
|
+
} & DialectOptions;
|
|
181
|
+
declare class FiltersAdapter extends FiltersBaseAdapter {
|
|
182
|
+
protected options: FiltersContainerOptions;
|
|
183
|
+
constructor(relations: RelationsAdapter, options: FiltersContainerOptions);
|
|
184
|
+
rootAlias(): string | undefined;
|
|
185
|
+
paramPlaceholder(index: number): string;
|
|
186
|
+
escapeField(field: string): string;
|
|
187
|
+
isRegexpSupported(): boolean;
|
|
188
|
+
regexp(field: string, placeholder: string, ignoreCase: boolean): string;
|
|
189
|
+
caseFold(input: string): string;
|
|
190
|
+
child(): this;
|
|
191
|
+
execute(): void;
|
|
192
|
+
}
|
|
193
|
+
//#endregion
|
|
194
|
+
//#region src/adapter/pagination/types.d.ts
|
|
195
|
+
interface IPaginationAdapter extends ISubAdapter {
|
|
196
|
+
setLimit(limit?: number): void;
|
|
197
|
+
setOffset(offset?: number): void;
|
|
198
|
+
}
|
|
199
|
+
//#endregion
|
|
200
|
+
//#region src/adapter/pagination/base.d.ts
|
|
201
|
+
declare abstract class PaginationBaseAdapter implements IPaginationAdapter {
|
|
202
|
+
limit: number | undefined;
|
|
203
|
+
offset: number | undefined;
|
|
204
|
+
clear(): void;
|
|
205
|
+
setLimit(limit?: number): void;
|
|
206
|
+
setOffset(offset?: number): void;
|
|
207
|
+
abstract execute(): void;
|
|
208
|
+
}
|
|
209
|
+
//#endregion
|
|
210
|
+
//#region src/adapter/pagination/module.d.ts
|
|
211
|
+
declare class PaginationAdapter extends PaginationBaseAdapter {
|
|
212
|
+
execute(): void;
|
|
213
|
+
}
|
|
214
|
+
//#endregion
|
|
215
|
+
//#region src/adapter/sort/types.d.ts
|
|
216
|
+
interface ISortAdapter extends ISubAdapter {
|
|
217
|
+
add(input: string, value: `${SortDirection}`): void;
|
|
218
|
+
}
|
|
219
|
+
//#endregion
|
|
220
|
+
//#region src/adapter/sort/base.d.ts
|
|
221
|
+
declare abstract class SortBaseAdapter implements ISortAdapter {
|
|
222
|
+
protected relations: RelationsBaseAdapter;
|
|
223
|
+
protected value: Record<string, `${SortDirection}`>;
|
|
224
|
+
protected constructor(relations: RelationsBaseAdapter);
|
|
225
|
+
clear(): void;
|
|
226
|
+
protected abstract rootAlias(): string | undefined;
|
|
227
|
+
protected abstract escapeField(field: string): string;
|
|
228
|
+
abstract execute(): void;
|
|
229
|
+
add(input: string, value: `${SortDirection}`): void;
|
|
230
|
+
/**
|
|
231
|
+
* Escaped ORDER BY entries, e.g. ['"user"."age" DESC'].
|
|
232
|
+
*/
|
|
233
|
+
getOrderBy(): string[];
|
|
234
|
+
protected normalizeField(input: string): string;
|
|
235
|
+
}
|
|
236
|
+
//#endregion
|
|
237
|
+
//#region src/adapter/sort/module.d.ts
|
|
238
|
+
type SortContainerOptions = {
|
|
239
|
+
rootAlias?: string;
|
|
240
|
+
escapeField?: (input: string) => string;
|
|
241
|
+
};
|
|
242
|
+
declare class SortAdapter extends SortBaseAdapter {
|
|
243
|
+
protected options: SortContainerOptions;
|
|
244
|
+
constructor(relations: RelationsAdapter, options: SortContainerOptions);
|
|
245
|
+
escapeField(field: string): string;
|
|
246
|
+
rootAlias(): string | undefined;
|
|
247
|
+
execute(): void;
|
|
248
|
+
}
|
|
249
|
+
//#endregion
|
|
250
|
+
//#region src/adapter/types.d.ts
|
|
251
|
+
/**
|
|
252
|
+
* Options for a single {@link IRootAdapter.execute} call.
|
|
253
|
+
*/
|
|
254
|
+
type ExecuteOptions = {
|
|
255
|
+
/**
|
|
256
|
+
* Reset the accumulated state before walking the query.
|
|
257
|
+
*
|
|
258
|
+
* `true` (default) makes execute() self-contained and re-runnable;
|
|
259
|
+
* pass `false` to accumulate across multiple execute() calls.
|
|
260
|
+
*/
|
|
261
|
+
clear?: boolean;
|
|
262
|
+
/**
|
|
263
|
+
* Options forwarded to the {@link QueryVisitor} (and its sub-visitors)
|
|
264
|
+
* that walks the query.
|
|
265
|
+
*/
|
|
266
|
+
visitor?: VisitorOptions;
|
|
267
|
+
};
|
|
268
|
+
/**
|
|
269
|
+
* Shared contract for the per-parameter sub-adapters that accumulate
|
|
270
|
+
* clause state while a query is walked, then flush it on {@link execute}.
|
|
271
|
+
*/
|
|
272
|
+
interface ISubAdapter {
|
|
273
|
+
execute(): void;
|
|
274
|
+
clear(): void;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Root adapter contract: walks a rapiq {@link IQuery} into the sub-adapters
|
|
278
|
+
* and emits the backend result — SQL fragments, or the echo of a mutated
|
|
279
|
+
* backend query object.
|
|
280
|
+
*/
|
|
281
|
+
interface IRootAdapter<OUTPUT = unknown> {
|
|
282
|
+
relations: IRelationsAdapter;
|
|
283
|
+
fields: IFieldsAdapter;
|
|
284
|
+
filters: IFiltersAdapter;
|
|
285
|
+
pagination: IPaginationAdapter;
|
|
286
|
+
sort: ISortAdapter;
|
|
287
|
+
/**
|
|
288
|
+
* Walk `query` into the sub-adapters and emit the backend result.
|
|
289
|
+
*
|
|
290
|
+
* @param query the parsed rapiq query (AST) to consume.
|
|
291
|
+
* @param options per-call options ({@link ExecuteOptions}).
|
|
292
|
+
*/
|
|
293
|
+
execute(query: IQuery, options?: ExecuteOptions): OUTPUT;
|
|
294
|
+
clear(): void;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Clause fragments accumulated from a Query walk.
|
|
298
|
+
* Statement assembly (FROM/JOIN conditions) is owned by the caller,
|
|
299
|
+
* which knows the table layout — rapiq only knows relation names.
|
|
300
|
+
*/
|
|
301
|
+
type SqlFragments = {
|
|
302
|
+
/**
|
|
303
|
+
* Escaped selection columns, e.g. ['"user"."id"', '"realm"."name"'].
|
|
304
|
+
*/
|
|
305
|
+
columns: string[];
|
|
306
|
+
/**
|
|
307
|
+
* Joined WHERE condition ('' when no filters apply).
|
|
308
|
+
*/
|
|
309
|
+
where: string;
|
|
310
|
+
/**
|
|
311
|
+
* Bound parameters for `where`.
|
|
312
|
+
*/
|
|
313
|
+
params: unknown[];
|
|
314
|
+
/**
|
|
315
|
+
* Escaped ORDER BY entries, e.g. ['"user"."age" DESC'].
|
|
316
|
+
*/
|
|
317
|
+
orderBy: string[];
|
|
318
|
+
limit: number | undefined;
|
|
319
|
+
offset: number | undefined;
|
|
320
|
+
/**
|
|
321
|
+
* Canonical relation paths to join (parents included),
|
|
322
|
+
* e.g. ['items', 'items.realm'].
|
|
323
|
+
*/
|
|
324
|
+
relations: string[];
|
|
325
|
+
};
|
|
326
|
+
//#endregion
|
|
327
|
+
//#region src/adapter/relations/types.d.ts
|
|
328
|
+
interface IRelationsAdapter extends ISubAdapter {
|
|
329
|
+
add(input: string): void;
|
|
330
|
+
buildAlias(path: string): string;
|
|
331
|
+
}
|
|
332
|
+
type JoinRelationFn = (relation: string, alias?: string) => boolean;
|
|
333
|
+
type RelationsAdapterBaseOptions = {
|
|
334
|
+
/**
|
|
335
|
+
* Join and select relations.
|
|
336
|
+
*/
|
|
337
|
+
joinAndSelect?: boolean;
|
|
338
|
+
/**
|
|
339
|
+
* Derive the join alias for a relation path
|
|
340
|
+
* (e.g. `role.realm` -> `r4_role_5_realm`).
|
|
341
|
+
* Field references in filters/sort/fields resolve against the
|
|
342
|
+
* same derivation, so it must be injected once, on the relations
|
|
343
|
+
* adapter shared by all sub-adapters.
|
|
344
|
+
*/
|
|
345
|
+
relationAlias?: RelationAliasFn;
|
|
346
|
+
};
|
|
347
|
+
type RelationsAdapterOptions = RelationsAdapterBaseOptions & {
|
|
348
|
+
join?: JoinRelationFn;
|
|
349
|
+
};
|
|
350
|
+
//#endregion
|
|
351
|
+
//#region src/adapter/relations/base.d.ts
|
|
352
|
+
declare abstract class RelationsBaseAdapter implements IRelationsAdapter {
|
|
353
|
+
/**
|
|
354
|
+
* joins
|
|
355
|
+
*
|
|
356
|
+
* [alias].project.user.name
|
|
357
|
+
*
|
|
358
|
+
* JOIN xxx.yyy as yyy
|
|
359
|
+
*
|
|
360
|
+
* { path: "xxx.zzz", name: "zzz" }[]
|
|
361
|
+
* @protected
|
|
362
|
+
*/
|
|
363
|
+
protected value: {
|
|
364
|
+
path: string;
|
|
365
|
+
name: string;
|
|
366
|
+
executed?: boolean;
|
|
367
|
+
}[];
|
|
368
|
+
protected relationAlias: RelationAliasFn;
|
|
369
|
+
protected constructor(options?: RelationsAdapterBaseOptions);
|
|
370
|
+
/**
|
|
371
|
+
* Join alias for a relation path (e.g. `role.realm` ->
|
|
372
|
+
* `r4_role_5_realm`).
|
|
373
|
+
* The single derivation point shared by join application and the
|
|
374
|
+
* field references built by the fields/filters/sort adapters.
|
|
375
|
+
*/
|
|
376
|
+
buildAlias(path: string): string;
|
|
377
|
+
clear(): void;
|
|
378
|
+
abstract execute(): void;
|
|
379
|
+
add(relation: string): boolean;
|
|
380
|
+
has(name: string): boolean;
|
|
381
|
+
/**
|
|
382
|
+
* Canonical relation paths (parents included), e.g. ['items', 'items.realm'].
|
|
383
|
+
*/
|
|
384
|
+
getPaths(): string[];
|
|
385
|
+
}
|
|
386
|
+
//#endregion
|
|
387
|
+
//#region src/adapter/relations/module.d.ts
|
|
388
|
+
declare class RelationsAdapter extends RelationsBaseAdapter {
|
|
389
|
+
protected options: RelationsAdapterOptions;
|
|
390
|
+
constructor(options?: RelationsAdapterOptions);
|
|
391
|
+
execute(): void;
|
|
392
|
+
}
|
|
393
|
+
//#endregion
|
|
394
|
+
//#region src/adapter/fields/types.d.ts
|
|
395
|
+
interface IFieldsAdapter extends ISubAdapter {
|
|
396
|
+
add(input: string, operator?: `${FieldOperator}`): void;
|
|
397
|
+
}
|
|
398
|
+
//#endregion
|
|
399
|
+
//#region src/adapter/fields/base.d.ts
|
|
400
|
+
declare abstract class FieldsBaseAdapter implements IFieldsAdapter {
|
|
401
|
+
protected relations: RelationsBaseAdapter;
|
|
402
|
+
/**
|
|
403
|
+
* selection fields.
|
|
404
|
+
*
|
|
405
|
+
* e.g. ['name', 'project.id']
|
|
406
|
+
*/
|
|
407
|
+
protected value: {
|
|
408
|
+
name: string;
|
|
409
|
+
operator?: `${FieldOperator}`;
|
|
410
|
+
}[];
|
|
411
|
+
protected constructor(relations: RelationsBaseAdapter);
|
|
412
|
+
clear(): void;
|
|
413
|
+
protected abstract rootAlias(): string | undefined;
|
|
414
|
+
protected abstract escapeField(field: string): string;
|
|
415
|
+
abstract execute(): void;
|
|
416
|
+
add(input: string, operator?: `${FieldOperator}`): void;
|
|
417
|
+
/**
|
|
418
|
+
* Escaped selection columns (excluded fields are dropped).
|
|
419
|
+
*/
|
|
420
|
+
getColumns(): string[];
|
|
421
|
+
buildField(input: string): string;
|
|
422
|
+
}
|
|
423
|
+
//#endregion
|
|
424
|
+
//#region src/adapter/fields/module.d.ts
|
|
425
|
+
type FieldsContainerOptions = {
|
|
426
|
+
rootAlias?: string;
|
|
427
|
+
escapeField?: (input: string) => string;
|
|
428
|
+
};
|
|
429
|
+
declare class FieldsAdapter extends FieldsBaseAdapter {
|
|
430
|
+
protected options: FieldsContainerOptions;
|
|
431
|
+
constructor(relations: RelationsAdapter, options: FieldsContainerOptions);
|
|
432
|
+
escapeField(field: string): string;
|
|
433
|
+
rootAlias(): string | undefined;
|
|
434
|
+
execute(): void;
|
|
435
|
+
}
|
|
436
|
+
//#endregion
|
|
437
|
+
//#region src/adapter/module.d.ts
|
|
438
|
+
type AdapterOptions = DialectOptions & {
|
|
439
|
+
rootAlias?: string;
|
|
440
|
+
/**
|
|
441
|
+
* Derive the join alias for a relation path
|
|
442
|
+
* (default: length-prefixed segments, e.g. `role.realm` ->
|
|
443
|
+
* `r4_role_5_realm`).
|
|
444
|
+
*/
|
|
445
|
+
relationAlias?: RelationAliasFn;
|
|
446
|
+
};
|
|
447
|
+
declare class Adapter implements IRootAdapter<SqlFragments> {
|
|
448
|
+
readonly relations: RelationsAdapter;
|
|
449
|
+
readonly fields: FieldsAdapter;
|
|
450
|
+
readonly filters: FiltersAdapter;
|
|
451
|
+
readonly pagination: PaginationAdapter;
|
|
452
|
+
readonly sort: SortAdapter;
|
|
453
|
+
constructor(options: AdapterOptions);
|
|
454
|
+
clear(): void;
|
|
455
|
+
/**
|
|
456
|
+
* Walk `query` into the sub-adapters and collect the accumulated
|
|
457
|
+
* clause fragments. Plain SQL has no backend target — it returns the
|
|
458
|
+
* fragments for the caller to assemble.
|
|
459
|
+
*/
|
|
460
|
+
execute(query: IQuery, options?: ExecuteOptions): SqlFragments;
|
|
461
|
+
}
|
|
462
|
+
//#endregion
|
|
463
|
+
//#region src/visitor/fields.d.ts
|
|
464
|
+
type FieldsInterpreterOptions = VisitorOptions;
|
|
465
|
+
declare class FieldsVisitor implements IFieldsVisitor<IFieldsAdapter>, IFieldVisitor<IFieldsAdapter> {
|
|
466
|
+
protected adapter: IFieldsAdapter;
|
|
467
|
+
protected options: FieldsInterpreterOptions;
|
|
468
|
+
constructor(adapter: IFieldsAdapter, options?: FieldsInterpreterOptions);
|
|
469
|
+
visitField(expr: IField): IFieldsAdapter;
|
|
470
|
+
visitFields(expr: IFields): IFieldsAdapter;
|
|
471
|
+
}
|
|
472
|
+
//#endregion
|
|
473
|
+
//#region src/visitor/filters.d.ts
|
|
474
|
+
declare class FiltersVisitor implements IFiltersVisitor<IFiltersAdapter>, IFilterVisitor<IFiltersAdapter> {
|
|
475
|
+
protected adapter: IFiltersAdapter;
|
|
476
|
+
protected options: VisitorOptions;
|
|
477
|
+
protected caseSensitiveFields: Set<string>;
|
|
478
|
+
constructor(adapter: IFiltersAdapter, options?: VisitorOptions);
|
|
479
|
+
visitFilterEqual(expr: Filter<FilterFieldOperator.EQUAL>): IFiltersAdapter;
|
|
480
|
+
visitFilterNotEqual(expr: Filter<FilterFieldOperator.NOT_EQUAL>): IFiltersAdapter;
|
|
481
|
+
visitFilterLessThan(expr: Filter<FilterFieldOperator.LESS_THAN>): IFiltersAdapter;
|
|
482
|
+
visitFilterLessThanEqual(expr: Filter<FilterFieldOperator.LESS_THAN_EQUAL>): IFiltersAdapter;
|
|
483
|
+
visitFilterGreaterThan(expr: Filter<FilterFieldOperator.GREATER_THAN>): IFiltersAdapter;
|
|
484
|
+
visitFilterGreaterThanEqual(expr: Filter<FilterFieldOperator.GREATER_THAN_EQUAL>): IFiltersAdapter;
|
|
485
|
+
visitFilterExists(expr: Filter<FilterFieldOperator.EXISTS, boolean>): IFiltersAdapter;
|
|
486
|
+
visitFilterIn(expr: Filter<FilterFieldOperator.IN, unknown[]>): IFiltersAdapter;
|
|
487
|
+
visitFilterNotIn(expr: Filter<FilterFieldOperator.NOT_IN, unknown[]>): IFiltersAdapter;
|
|
488
|
+
visitFilterMod(expr: Filter<FilterFieldOperator.MOD, [number, number]>): IFiltersAdapter;
|
|
489
|
+
visitFilterSize(): IFiltersAdapter;
|
|
490
|
+
visitFilterElemMatch(expr: Filter<FilterFieldOperator.ELEM_MATCH, Filter | Filters>): IFiltersAdapter;
|
|
491
|
+
visitFilterStartsWith(expr: Filter<FilterFieldOperator.STARTS_WITH, unknown>): IFiltersAdapter;
|
|
492
|
+
visitFilterNotStartsWith(expr: Filter<FilterFieldOperator.NOT_STARTS_WITH, unknown>): IFiltersAdapter;
|
|
493
|
+
visitFilterEndsWith(expr: Filter<FilterFieldOperator.ENDS_WITH, unknown>): IFiltersAdapter;
|
|
494
|
+
visitFilterNotEndsWith(expr: Filter<FilterFieldOperator.NOT_ENDS_WITH, unknown>): IFiltersAdapter;
|
|
495
|
+
visitFilterContains(expr: Filter<FilterFieldOperator.CONTAINS, unknown>): IFiltersAdapter;
|
|
496
|
+
visitFilterNotContains(expr: Filter<FilterFieldOperator.NOT_CONTAINS, unknown>): IFiltersAdapter;
|
|
497
|
+
visitFilterRegex(expr: Filter<FilterFieldOperator.REGEX, RegExp | string>): IFiltersAdapter;
|
|
498
|
+
visitFilters(expr: Filters): IFiltersAdapter;
|
|
499
|
+
visitFilter(expr: Filter): IFiltersAdapter;
|
|
500
|
+
/**
|
|
501
|
+
* Render an IN/NOT IN condition.
|
|
502
|
+
* A null element also matches the absence of a value (IS NULL);
|
|
503
|
+
* an empty list matches no row (every row when negated).
|
|
504
|
+
*/
|
|
505
|
+
protected whereIn(fieldName: string, input: unknown[], negated: boolean): IFiltersAdapter;
|
|
506
|
+
/**
|
|
507
|
+
* Render a startsWith/endsWith/contains condition (or its negation)
|
|
508
|
+
* as a regexp condition, falling back to LIKE on regexp-less dialects.
|
|
509
|
+
*/
|
|
510
|
+
protected whereAnchored(field: string, value: unknown, flag: number): IFiltersAdapter;
|
|
511
|
+
protected whereLike(field: string, pattern: string, negated?: boolean): IFiltersAdapter;
|
|
512
|
+
/**
|
|
513
|
+
* Render a negated condition null-inclusively. Negated operators are
|
|
514
|
+
* exact complements of their positive twins (complement law), but the
|
|
515
|
+
* bare SQL negation follows three-valued logic and drops NULL rows.
|
|
516
|
+
*/
|
|
517
|
+
protected whereComplement(field: string, sql: string, ...values: unknown[]): IFiltersAdapter;
|
|
518
|
+
/**
|
|
519
|
+
* Equality-family comparisons (eq/ne/in/nin) match string values
|
|
520
|
+
* case-insensitively unless the field is opted out via the
|
|
521
|
+
* `caseSensitive` visitor option or the adapter exempts it
|
|
522
|
+
* (non-string columns never fold).
|
|
523
|
+
*/
|
|
524
|
+
protected isCaseInsensitive(field: string, value: unknown): boolean;
|
|
525
|
+
protected isCaseFoldableField(field: string): boolean;
|
|
526
|
+
}
|
|
527
|
+
//#endregion
|
|
528
|
+
//#region src/visitor/pagination.d.ts
|
|
529
|
+
type PaginationVisitorOptions = VisitorOptions;
|
|
530
|
+
declare class PaginationVisitor implements IPaginationVisitor<IPaginationAdapter> {
|
|
531
|
+
protected adapter: IPaginationAdapter;
|
|
532
|
+
protected options: PaginationVisitorOptions;
|
|
533
|
+
constructor(adapter: IPaginationAdapter, options?: PaginationVisitorOptions);
|
|
534
|
+
visitPagination(expr: Pagination): IPaginationAdapter;
|
|
535
|
+
}
|
|
536
|
+
//#endregion
|
|
537
|
+
//#region src/visitor/relations.d.ts
|
|
538
|
+
type RelationInterpreterOptions = VisitorOptions;
|
|
539
|
+
declare class RelationsVisitor implements IRelationsVisitor<IRelationsAdapter>, IRelationVisitor<IRelationsAdapter> {
|
|
540
|
+
protected adapter: IRelationsAdapter;
|
|
541
|
+
protected options: RelationInterpreterOptions;
|
|
542
|
+
constructor(adapter: IRelationsAdapter, options?: RelationInterpreterOptions);
|
|
543
|
+
visitRelation(expr: Relation): IRelationsAdapter;
|
|
544
|
+
visitRelations(expr: Relations): IRelationsAdapter;
|
|
545
|
+
}
|
|
546
|
+
//#endregion
|
|
547
|
+
//#region src/visitor/sort.d.ts
|
|
548
|
+
type SortInterpreterOptions = VisitorOptions;
|
|
549
|
+
declare class SortsVisitor implements ISortsVisitor<ISortAdapter>, ISortVisitor<ISortAdapter> {
|
|
550
|
+
protected adapter: ISortAdapter;
|
|
551
|
+
protected options: SortInterpreterOptions;
|
|
552
|
+
constructor(adapter: ISortAdapter, options?: SortInterpreterOptions);
|
|
553
|
+
visitSort(expr: Sort): ISortAdapter;
|
|
554
|
+
visitSorts(expr: Sorts): ISortAdapter;
|
|
555
|
+
}
|
|
556
|
+
//#endregion
|
|
557
|
+
//#region src/visitor/module.d.ts
|
|
558
|
+
declare class QueryVisitor implements IQueryVisitor<IRootAdapter>, IFieldsVisitor<IFieldsAdapter>, IFieldVisitor<IFieldsAdapter>, IFiltersVisitor<IFiltersAdapter>, IFilterVisitor<IFiltersAdapter>, IPaginationVisitor<IPaginationAdapter>, IRelationsVisitor<IRelationsAdapter>, IRelationVisitor<IRelationsAdapter>, ISortsVisitor<ISortAdapter>, ISortVisitor<ISortAdapter> {
|
|
559
|
+
protected container: IRootAdapter;
|
|
560
|
+
protected options: VisitorOptions;
|
|
561
|
+
readonly fields: FieldsVisitor;
|
|
562
|
+
readonly filters: FiltersVisitor;
|
|
563
|
+
readonly pagination: PaginationVisitor;
|
|
564
|
+
readonly relations: RelationsVisitor;
|
|
565
|
+
readonly sorts: SortsVisitor;
|
|
566
|
+
constructor(adapter: IRootAdapter, options?: VisitorOptions);
|
|
567
|
+
visitQuery(input: Query): IRootAdapter;
|
|
568
|
+
visitFields(expr: Fields): IFieldsAdapter;
|
|
569
|
+
visitField(expr: Field): IFieldsAdapter;
|
|
570
|
+
visitFilters(expr: Filters): IFiltersAdapter;
|
|
571
|
+
visitFilter(expr: Filter): IFiltersAdapter;
|
|
572
|
+
visitPagination(expr: Pagination): IPaginationAdapter;
|
|
573
|
+
visitRelations(input: Relations): IRelationsAdapter;
|
|
574
|
+
visitRelation(expr: Relation): IRelationsAdapter;
|
|
575
|
+
visitSorts(expr: Sorts): ISortAdapter;
|
|
576
|
+
visitSort(expr: Sort): ISortAdapter;
|
|
577
|
+
}
|
|
578
|
+
//#endregion
|
|
579
|
+
export { Adapter, AdapterOptions, DialectOptions, ExecuteOptions, FieldsAdapter, FieldsBaseAdapter, FieldsContainerOptions, FieldsInterpreterOptions, FieldsVisitor, FiltersAdapter, FiltersBaseAdapter, FiltersContainerOptions, FiltersVisitor, IFieldsAdapter, IFiltersAdapter, IPaginationAdapter, IRelationsAdapter, IRootAdapter, ISortAdapter, ISubAdapter, JoinRelationFn, PaginationAdapter, PaginationBaseAdapter, PaginationVisitor, PaginationVisitorOptions, ParamPlaceholderIndexer, QueryVisitor, RelationAliasFn, RelationInterpreterOptions, RelationsAdapter, RelationsAdapterBaseOptions, RelationsAdapterOptions, RelationsBaseAdapter, RelationsVisitor, SortAdapter, SortBaseAdapter, SortContainerOptions, SortInterpreterOptions, SortsVisitor, SqlFragments, VisitorOptions, buildRelationAlias, escapeLikePattern, isRootAliasFn, mssql, mysql, oracle, parseField, pg, resolveDialect, splitFirst, splitLast, sqlite, toRootAliasFn };
|
|
580
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/helpers/relation-alias.ts","../src/helpers/field.ts","../src/helpers/like.ts","../src/helpers/name-split.ts","../src/helpers/param-placeholder-indexer.ts","../src/types.ts","../src/helpers/root-alias.ts","../src/visitor/types.ts","../src/adapter/filters/types.ts","../src/adapter/filters/base.ts","../src/dialect/types.ts","../src/dialect/mssql.ts","../src/dialect/mysql.ts","../src/dialect/oracle.ts","../src/dialect/pg.ts","../src/dialect/resolve.ts","../src/dialect/sqlite.ts","../src/adapter/filters/module.ts","../src/adapter/pagination/types.ts","../src/adapter/pagination/base.ts","../src/adapter/pagination/module.ts","../src/adapter/sort/types.ts","../src/adapter/sort/base.ts","../src/adapter/sort/module.ts","../src/adapter/types.ts","../src/adapter/relations/types.ts","../src/adapter/relations/base.ts","../src/adapter/relations/module.ts","../src/adapter/fields/types.ts","../src/adapter/fields/base.ts","../src/adapter/fields/module.ts","../src/adapter/module.ts","../src/visitor/fields.ts","../src/visitor/filters.ts","../src/visitor/pagination.ts","../src/visitor/relations.ts","../src/visitor/sort.ts","../src/visitor/module.ts"],"mappings":"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"}
|