@rapiq/typeorm 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 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,46 @@
1
+ # @rapiq/typeorm
2
+
3
+ Part of [rapiq](https://github.com/tada5hi/rapiq) — typed REST queries: build, transport, validate, execute.
4
+
5
+ Applies a parsed [`Query`](https://rapiq.tada5hi.net/guide/query-ast) directly to a TypeORM `SelectQueryBuilder` — filters become parameterized `WHERE` conditions, relations become joins, fields/sort/pagination map to `select`/`orderBy`/`take`+`skip`.
6
+
7
+ ## Installation
8
+
9
+ ```sh
10
+ npm install @rapiq/core @rapiq/sql @rapiq/typeorm
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```typescript
16
+ import { TypeormAdapter } from '@rapiq/typeorm';
17
+
18
+ const queryBuilder = dataSource.getRepository(User).createQueryBuilder('user');
19
+
20
+ const adapter = new TypeormAdapter({
21
+ queryBuilder,
22
+ relations: { joinAndSelect: true },
23
+ });
24
+
25
+ const { pagination } = adapter.execute(query);
26
+
27
+ const [entities, total] = await queryBuilder.getManyAndCount();
28
+ ```
29
+
30
+ The `queryBuilder` (the builder to write into) is bound at construction; `adapter.execute(query)` then walks the parsed `Query`, collects the state into its sub-adapters, and applies it to that builder — returning the applied pagination (e.g. for the response `meta` block). State is cleared before each call by default (pass `{ clear: false }` as the second argument to apply several queries onto the same builder).
31
+
32
+ Construct the adapter **per request**, like the `SelectQueryBuilder` you hand it — it holds per-call state. The shareable, long-lived part is your config (`relations`, …), spread into the per-request options with the request's builder as `queryBuilder`.
33
+
34
+ The SQL dialect is resolved from the attached builder's connection type; joins are applied idempotently and validated against the entity metadata. Options: `relations.joinAndSelect` (hydrate related entities), `relations.joinType` (`'left'` default / `'inner'`), and an `onJoin(path, alias, queryBuilder)` hook per applied join. Per-parameter visitors from [@rapiq/sql](https://www.npmjs.com/package/@rapiq/sql) work against the adapter's sub-adapters (`adapter.filters`, `adapter.sort`, …) when only part of a query applies.
35
+
36
+ Typically the query comes from a [URL decoder](https://www.npmjs.com/package/@rapiq/codec-url) validating `req.query` against a schema — see the [end-to-end example](https://rapiq.tada5hi.net/guide/recipes/express-typeorm) in the docs.
37
+
38
+ Migrating from typeorm-extension's `applyQuery`? The defaults mirror its contract (`leftJoinAndSelect`, returned pagination) — see the [migration guide](https://rapiq.tada5hi.net/guide/migration-typeorm-extension).
39
+
40
+ ## Documentation
41
+
42
+ Full guide (options, dialect detection, alias convention): [rapiq.tada5hi.net/packages/typeorm](https://rapiq.tada5hi.net/packages/typeorm)
43
+
44
+ ## License
45
+
46
+ Published under the [MIT License](https://github.com/tada5hi/rapiq/blob/master/LICENSE).
@@ -0,0 +1,116 @@
1
+ import { DialectOptions, ExecuteOptions, FieldsBaseAdapter, FiltersBaseAdapter, IRootAdapter, PaginationBaseAdapter, RelationsAdapterBaseOptions, RelationsBaseAdapter, SortBaseAdapter } from "@rapiq/sql";
2
+ import { IQuery } from "@rapiq/core";
3
+ import { SelectQueryBuilder } from "typeorm";
4
+ //#region src/adapter/types.d.ts
5
+ type RelationsAdapterJoinType = 'left' | 'inner';
6
+ type RelationsAdapterOptions = RelationsAdapterBaseOptions & {
7
+ /**
8
+ * Join strategy for relations.
9
+ * Defaults to 'left' so records with absent relations are kept
10
+ * (matches typeorm-extension's leftJoinAndSelect behavior).
11
+ */
12
+ joinType?: RelationsAdapterJoinType;
13
+ /**
14
+ * Invoked for every join this adapter applies (skipped joins,
15
+ * e.g. pre-existing ones, do not trigger it). Useful to extend
16
+ * the query per join, e.g. `queryBuilder.addGroupBy(`${alias}.id`)`.
17
+ */
18
+ onJoin?: (path: string, alias: string, queryBuilder: SelectQueryBuilder<any>) => void;
19
+ };
20
+ type TypeormAdapterOptions = {
21
+ /**
22
+ * The query builder to apply the parsed query to.
23
+ */
24
+ queryBuilder: SelectQueryBuilder<any>;
25
+ relations?: RelationsAdapterOptions;
26
+ };
27
+ type TypeormAdapterOutput = {
28
+ /**
29
+ * The pagination actually applied to the query builder,
30
+ * e.g. for the response meta block.
31
+ */
32
+ pagination: {
33
+ limit: number | undefined;
34
+ offset: number | undefined;
35
+ };
36
+ };
37
+ //#endregion
38
+ //#region src/adapter/relations.d.ts
39
+ declare class RelationsAdapter extends RelationsBaseAdapter {
40
+ protected queryBuilder: SelectQueryBuilder<any>;
41
+ protected options: RelationsAdapterOptions;
42
+ constructor(queryBuilder: SelectQueryBuilder<any>, options?: RelationsAdapterOptions);
43
+ execute(): void;
44
+ protected join(input: string): boolean;
45
+ protected applyJoin(property: string, alias: string): void;
46
+ }
47
+ //#endregion
48
+ //#region src/adapter/fields.d.ts
49
+ declare class FieldsAdapter extends FieldsBaseAdapter {
50
+ protected queryBuilder: SelectQueryBuilder<any>;
51
+ constructor(queryBuilder: SelectQueryBuilder<any>, relations: RelationsAdapter);
52
+ rootAlias(): string | undefined;
53
+ escapeField(field: string): string;
54
+ execute(): void;
55
+ }
56
+ //#endregion
57
+ //#region src/adapter/filters.d.ts
58
+ declare class FiltersAdapter extends FiltersBaseAdapter<RelationsAdapter> {
59
+ protected queryBuilder: SelectQueryBuilder<any>;
60
+ protected dialect: DialectOptions;
61
+ protected paramNamespace: string;
62
+ constructor(queryBuilder: SelectQueryBuilder<any>, relations: RelationsAdapter);
63
+ clear(): void;
64
+ rootAlias(): string | undefined;
65
+ escapeField(field: string): string;
66
+ paramPlaceholder(index: number): string;
67
+ isRegexpSupported(): boolean;
68
+ regexp(field: string, placeholder: string, ignoreCase: boolean): string;
69
+ caseFold(input: string): string;
70
+ isCaseFoldable(field: string): boolean;
71
+ child(): this;
72
+ execute(): void;
73
+ }
74
+ //#endregion
75
+ //#region src/adapter/sort.d.ts
76
+ declare class SortAdapter extends SortBaseAdapter {
77
+ protected queryBuilder: SelectQueryBuilder<any>;
78
+ constructor(queryBuilder: SelectQueryBuilder<any>, relations: RelationsAdapter);
79
+ rootAlias(): string | undefined;
80
+ escapeField(field: string): string;
81
+ execute(): void;
82
+ }
83
+ //#endregion
84
+ //#region src/adapter/pagination.d.ts
85
+ declare class PaginationAdapter extends PaginationBaseAdapter {
86
+ protected queryBuilder: SelectQueryBuilder<any>;
87
+ constructor(queryBuilder: SelectQueryBuilder<any>);
88
+ execute(): void;
89
+ }
90
+ //#endregion
91
+ //#region src/adapter/module.d.ts
92
+ declare class TypeormAdapter implements IRootAdapter<TypeormAdapterOutput> {
93
+ readonly relations: RelationsAdapter;
94
+ readonly fields: FieldsAdapter;
95
+ readonly filters: FiltersAdapter;
96
+ readonly pagination: PaginationAdapter;
97
+ readonly sort: SortAdapter;
98
+ constructor(options: TypeormAdapterOptions);
99
+ clear(): void;
100
+ /**
101
+ * Walk `query` into the sub-adapters and apply the accumulated state
102
+ * to the queryBuilder query builder (bound at construction).
103
+ */
104
+ execute(query: IQuery, options?: ExecuteOptions): TypeormAdapterOutput;
105
+ }
106
+ //#endregion
107
+ //#region src/dialect.d.ts
108
+ /**
109
+ * Resolve the {@link DialectOptions} preset matching the query builder's
110
+ * connection type. The postgres preset is the documented last-resort
111
+ * default when the connection type has no matching preset.
112
+ */
113
+ declare function resolveQueryDialect(query: SelectQueryBuilder<any>): DialectOptions;
114
+ //#endregion
115
+ export { FieldsAdapter, FiltersAdapter, PaginationAdapter, RelationsAdapter, RelationsAdapterJoinType, RelationsAdapterOptions, SortAdapter, TypeormAdapter, TypeormAdapterOptions, TypeormAdapterOutput, resolveQueryDialect };
116
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/adapter/types.ts","../src/adapter/relations.ts","../src/adapter/fields.ts","../src/adapter/filters.ts","../src/adapter/sort.ts","../src/adapter/pagination.ts","../src/adapter/module.ts","../src/dialect.ts"],"mappings":";;;;KAUY;KAEA,0BAA0B;;;;;;EAMlC,WAAW;;;;;;EAOX,UAAU,cAAc,eAAe,cAAc;;KAG7C;;;;EAIR,cAAc;EACd,YAAY;;KAGJ;;;;;EAKR;IACI;IACA;;;;;cChCK,yBAAyB;YACxB,cAAe;YAEf,SAAU;cAGhB,cAAc,yBACd,UAAS;EAQb;YAYU,KAAK;YA0CL,UAAU,kBAAkB;;;;cCrE7B,sBAAsB;YACrB,cAAe;cAEb,cAAc,yBAAyB,WAAW;EAM9D;EAIA,YAAY;EAOZ;;;;cC+DS,uBAAuB,mBAAmB;YACzC,cAAe;YAEf,SAAU;YAEV;cAEE,cAAc,yBAAyB,WAAW;EAQrD;EAQT;EAIA,YAAY;EAIZ,iBAAiB;EAIR;EAIT,OAAO,eAAe,qBAAqB;EAQlC,SAAS;EAQT,eAAe;EAcxB;EAWA;;;;cCnKS,oBAAoB;YACnB,cAAe;cAEb,cAAc,yBAAyB,WAAW;EAM9D;EAIA,YAAY;EAOZ;;;;cCrBS,0BAA0B;YACzB,cAAe;cAEb,cAAc;EAMjB;;;;cCFA,0BAA0B,aAAa;WAChC,WAAY;WAEZ,QAAS;WAET,SAAU;WAEV,YAAa;WAEb,MAAO;cAEX,SAAS;EAQrB;;;;;EAYA,QACI,OAAO,QACP,UAAS,iBACT;;;;;;;;;iBCnCQ,oBACZ,OAAO,0BACP"}
package/dist/index.mjs ADDED
@@ -0,0 +1,270 @@
1
+ import { FieldsBaseAdapter, FiltersBaseAdapter, PaginationBaseAdapter, QueryVisitor, RelationsBaseAdapter, SortBaseAdapter, pg, resolveDialect, splitFirst } from "@rapiq/sql";
2
+ import { AdapterError } from "@rapiq/core";
3
+ //#region src/adapter/fields.ts
4
+ var FieldsAdapter = class extends FieldsBaseAdapter {
5
+ queryBuilder;
6
+ constructor(queryBuilder, relations) {
7
+ super(relations);
8
+ this.queryBuilder = queryBuilder;
9
+ }
10
+ rootAlias() {
11
+ return this.queryBuilder.alias;
12
+ }
13
+ escapeField(field) {
14
+ return field;
15
+ }
16
+ execute() {
17
+ const columns = this.getColumns();
18
+ if (columns.length > 0) this.queryBuilder.select(columns);
19
+ }
20
+ };
21
+ //#endregion
22
+ //#region src/dialect.ts
23
+ /**
24
+ * Resolve the {@link DialectOptions} preset matching the query builder's
25
+ * connection type. The postgres preset is the documented last-resort
26
+ * default when the connection type has no matching preset.
27
+ */
28
+ function resolveQueryDialect(query) {
29
+ const dialect = resolveDialect(query.connection.options.type);
30
+ if (dialect) return dialect;
31
+ return pg;
32
+ }
33
+ //#endregion
34
+ //#region src/adapter/filters.ts
35
+ /**
36
+ * Column types whose values are strings and therefore participate in
37
+ * case-insensitive equality folding. Non-string columns never fold —
38
+ * lower() on them is wasted work at best and a type error at worst
39
+ * (e.g. `lower(integer)` on postgres).
40
+ */
41
+ const CASE_FOLDABLE_COLUMN_TYPES = /* @__PURE__ */ new Set([
42
+ "varchar",
43
+ "character varying",
44
+ "varying character",
45
+ "char varying",
46
+ "nvarchar",
47
+ "national varchar",
48
+ "char",
49
+ "nchar",
50
+ "national char",
51
+ "character",
52
+ "native character",
53
+ "text",
54
+ "tinytext",
55
+ "mediumtext",
56
+ "longtext",
57
+ "ntext",
58
+ "citext",
59
+ "string"
60
+ ]);
61
+ function isCaseFoldableColumnType(type) {
62
+ if (type === String) return true;
63
+ return typeof type === "string" && CASE_FOLDABLE_COLUMN_TYPES.has(type);
64
+ }
65
+ /**
66
+ * TypeORM parameters are global to the query builder and last-write-wins,
67
+ * so every filter application needs its own namespace: positional names
68
+ * like `:0` would silently rebind a caller-owned `:0` parameter — or, on
69
+ * a re-run, the previous run's clauses.
70
+ */
71
+ let PARAM_NAMESPACE_SEQ = 0;
72
+ function nextParamNamespace() {
73
+ PARAM_NAMESPACE_SEQ += 1;
74
+ return `rapiq_${PARAM_NAMESPACE_SEQ}_`;
75
+ }
76
+ /**
77
+ * Resolve a (possibly relation-dotted) property path to its column,
78
+ * descending through relation metadata segment by segment; embedded
79
+ * paths resolve through the plain column lookup per step.
80
+ */
81
+ function findColumnByPropertyPath(metadata, path) {
82
+ let current = metadata;
83
+ const segments = path.split(".");
84
+ for (let i = 0; i < segments.length; i++) {
85
+ const segment = segments[i];
86
+ if (!segment) return;
87
+ const column = current.findColumnWithPropertyPath(segments.slice(i).join("."));
88
+ if (column) return column;
89
+ const relation = current.findRelationWithPropertyPath(segment);
90
+ if (!relation) return;
91
+ current = relation.inverseEntityMetadata;
92
+ }
93
+ }
94
+ var FiltersAdapter = class FiltersAdapter extends FiltersBaseAdapter {
95
+ queryBuilder;
96
+ dialect;
97
+ paramNamespace;
98
+ constructor(queryBuilder, relations) {
99
+ super(relations);
100
+ this.queryBuilder = queryBuilder;
101
+ this.dialect = resolveQueryDialect(queryBuilder);
102
+ this.paramNamespace = nextParamNamespace();
103
+ }
104
+ clear() {
105
+ super.clear();
106
+ this.paramNamespace = nextParamNamespace();
107
+ }
108
+ rootAlias() {
109
+ return this.queryBuilder.alias;
110
+ }
111
+ escapeField(field) {
112
+ return this.queryBuilder.escape(field);
113
+ }
114
+ paramPlaceholder(index) {
115
+ return `:${this.paramNamespace}${index - 1}`;
116
+ }
117
+ isRegexpSupported() {
118
+ return typeof this.dialect.regexp !== "undefined";
119
+ }
120
+ regexp(field, placeholder, ignoreCase) {
121
+ if (this.dialect.regexp) return this.dialect.regexp(field, placeholder, ignoreCase);
122
+ throw AdapterError.featureUnsupported("regexp");
123
+ }
124
+ caseFold(input) {
125
+ if (this.dialect.caseFold) return this.dialect.caseFold(input);
126
+ return super.caseFold(input);
127
+ }
128
+ isCaseFoldable(field) {
129
+ const { mainAlias } = this.queryBuilder.expressionMap;
130
+ if (!mainAlias || !mainAlias.hasMetadata) return super.isCaseFoldable(field);
131
+ const column = findColumnByPropertyPath(mainAlias.metadata, field);
132
+ if (!column) return super.isCaseFoldable(field);
133
+ return isCaseFoldableColumnType(column.type);
134
+ }
135
+ child() {
136
+ const child = new FiltersAdapter(this.queryBuilder, this.relations);
137
+ this.setChildAttributes(child);
138
+ child.paramNamespace = this.paramNamespace;
139
+ return child;
140
+ }
141
+ execute() {
142
+ const [sql, params] = this.getQueryAndParameters();
143
+ if (sql) {
144
+ const parameters = {};
145
+ for (const [i, param] of params.entries()) parameters[`${this.paramNamespace}${i}`] = param;
146
+ this.queryBuilder.andWhere(sql, parameters);
147
+ }
148
+ }
149
+ };
150
+ //#endregion
151
+ //#region src/adapter/relations.ts
152
+ var RelationsAdapter = class extends RelationsBaseAdapter {
153
+ queryBuilder;
154
+ options;
155
+ constructor(queryBuilder, options = {}) {
156
+ super(options);
157
+ this.queryBuilder = queryBuilder;
158
+ this.options = options;
159
+ }
160
+ execute() {
161
+ for (const relation of this.value) {
162
+ if (relation.executed) continue;
163
+ if (this.join(relation.path)) relation.executed = true;
164
+ }
165
+ }
166
+ join(input) {
167
+ let relationFullName = input;
168
+ let path;
169
+ let meta = this.queryBuilder.expressionMap.mainAlias.metadata;
170
+ let parentAlias = this.queryBuilder.alias;
171
+ const { joinAttributes } = this.queryBuilder.expressionMap;
172
+ while (relationFullName) {
173
+ let relationName;
174
+ [relationName, relationFullName] = splitFirst(relationFullName);
175
+ path = path ? `${path}.${relationName}` : relationName;
176
+ const relation = meta.findRelationWithPropertyPath(relationName);
177
+ if (!relation) return false;
178
+ const alias = this.buildAlias(path);
179
+ if (!joinAttributes.some((joinAttribute) => joinAttribute.alias.name === alias)) {
180
+ this.applyJoin(`${parentAlias}.${relationName}`, alias);
181
+ if (this.options.onJoin) this.options.onJoin(path, alias, this.queryBuilder);
182
+ }
183
+ meta = relation.inverseEntityMetadata;
184
+ parentAlias = alias;
185
+ }
186
+ return true;
187
+ }
188
+ applyJoin(property, alias) {
189
+ const inner = this.options.joinType === "inner";
190
+ if (this.options.joinAndSelect) if (inner) this.queryBuilder.innerJoinAndSelect(property, alias);
191
+ else this.queryBuilder.leftJoinAndSelect(property, alias);
192
+ else if (inner) this.queryBuilder.innerJoin(property, alias);
193
+ else this.queryBuilder.leftJoin(property, alias);
194
+ }
195
+ };
196
+ //#endregion
197
+ //#region src/adapter/sort.ts
198
+ var SortAdapter = class extends SortBaseAdapter {
199
+ queryBuilder;
200
+ constructor(queryBuilder, relations) {
201
+ super(relations);
202
+ this.queryBuilder = queryBuilder;
203
+ }
204
+ rootAlias() {
205
+ return this.queryBuilder.alias;
206
+ }
207
+ escapeField(field) {
208
+ return field;
209
+ }
210
+ execute() {
211
+ if (Object.keys(this.value).length > 0) this.queryBuilder.orderBy(this.value);
212
+ }
213
+ };
214
+ //#endregion
215
+ //#region src/adapter/pagination.ts
216
+ var PaginationAdapter = class extends PaginationBaseAdapter {
217
+ queryBuilder;
218
+ constructor(queryBuilder) {
219
+ super();
220
+ this.queryBuilder = queryBuilder;
221
+ }
222
+ execute() {
223
+ if (typeof this.limit !== "undefined") this.queryBuilder.take(this.limit ?? void 0);
224
+ if (typeof this.offset !== "undefined") this.queryBuilder.skip(this.offset ?? void 0);
225
+ }
226
+ };
227
+ //#endregion
228
+ //#region src/adapter/module.ts
229
+ var TypeormAdapter = class {
230
+ relations;
231
+ fields;
232
+ filters;
233
+ pagination;
234
+ sort;
235
+ constructor(options) {
236
+ this.relations = new RelationsAdapter(options.queryBuilder, options.relations);
237
+ this.fields = new FieldsAdapter(options.queryBuilder, this.relations);
238
+ this.filters = new FiltersAdapter(options.queryBuilder, this.relations);
239
+ this.pagination = new PaginationAdapter(options.queryBuilder);
240
+ this.sort = new SortAdapter(options.queryBuilder, this.relations);
241
+ }
242
+ clear() {
243
+ this.fields.clear();
244
+ this.filters.clear();
245
+ this.pagination.clear();
246
+ this.sort.clear();
247
+ this.relations.clear();
248
+ }
249
+ /**
250
+ * Walk `query` into the sub-adapters and apply the accumulated state
251
+ * to the queryBuilder query builder (bound at construction).
252
+ */
253
+ execute(query, options = {}) {
254
+ if (options.clear ?? true) this.clear();
255
+ query.accept(new QueryVisitor(this, options.visitor));
256
+ this.fields.execute();
257
+ this.filters.execute();
258
+ this.pagination.execute();
259
+ this.sort.execute();
260
+ this.relations.execute();
261
+ return { pagination: {
262
+ limit: this.pagination.limit,
263
+ offset: this.pagination.offset
264
+ } };
265
+ }
266
+ };
267
+ //#endregion
268
+ export { FieldsAdapter, FiltersAdapter, PaginationAdapter, RelationsAdapter, SortAdapter, TypeormAdapter, resolveQueryDialect };
269
+
270
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/adapter/fields.ts","../src/dialect.ts","../src/adapter/filters.ts","../src/adapter/relations.ts","../src/adapter/sort.ts","../src/adapter/pagination.ts","../src/adapter/module.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { FieldsBaseAdapter } from '@rapiq/sql';\nimport type { SelectQueryBuilder } from 'typeorm';\nimport type { RelationsAdapter } from './relations';\n\nexport class FieldsAdapter extends FieldsBaseAdapter {\n protected queryBuilder : SelectQueryBuilder<any>;\n\n constructor(queryBuilder: SelectQueryBuilder<any>, relations: RelationsAdapter) {\n super(relations);\n\n this.queryBuilder = queryBuilder;\n }\n\n rootAlias(): string | undefined {\n return this.queryBuilder.alias;\n }\n\n escapeField(field: string) {\n // selection keys must stay `alias.property` — TypeORM resolves\n // them against its alias map and escapes on its own; pre-escaped\n // names break column resolution and entity hydration.\n return field;\n }\n\n execute() {\n const columns = this.getColumns();\n if (columns.length > 0) {\n this.queryBuilder.select(columns);\n }\n }\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { DialectOptions } from '@rapiq/sql';\nimport { pg, resolveDialect } from '@rapiq/sql';\nimport type { SelectQueryBuilder } from 'typeorm';\n\n/**\n * Resolve the {@link DialectOptions} preset matching the query builder's\n * connection type. The postgres preset is the documented last-resort\n * default when the connection type has no matching preset.\n */\nexport function resolveQueryDialect(\n query: SelectQueryBuilder<any>,\n) : DialectOptions {\n const dialect = resolveDialect(query.connection.options.type);\n if (dialect) {\n return dialect;\n }\n\n return pg;\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { AdapterError } from '@rapiq/core';\nimport type { DialectOptions } from '@rapiq/sql';\nimport { FiltersBaseAdapter } from '@rapiq/sql';\nimport type { ColumnType, EntityMetadata, SelectQueryBuilder } from 'typeorm';\nimport { resolveQueryDialect } from '../dialect';\nimport type { RelationsAdapter } from './relations';\n\n/**\n * Column types whose values are strings and therefore participate in\n * case-insensitive equality folding. Non-string columns never fold —\n * lower() on them is wasted work at best and a type error at worst\n * (e.g. `lower(integer)` on postgres).\n */\nconst CASE_FOLDABLE_COLUMN_TYPES = new Set<string>([\n 'varchar', \n 'character varying', \n 'varying character', \n 'char varying',\n 'nvarchar', \n 'national varchar',\n 'char', \n 'nchar', \n 'national char', \n 'character', \n 'native character',\n 'text', \n 'tinytext', \n 'mediumtext', \n 'longtext', \n 'ntext', \n 'citext',\n 'string',\n]);\n\nfunction isCaseFoldableColumnType(type: ColumnType) : boolean {\n if (type === String) {\n return true;\n }\n\n return typeof type === 'string' && CASE_FOLDABLE_COLUMN_TYPES.has(type);\n}\n\n/**\n * TypeORM parameters are global to the query builder and last-write-wins,\n * so every filter application needs its own namespace: positional names\n * like `:0` would silently rebind a caller-owned `:0` parameter — or, on\n * a re-run, the previous run's clauses.\n */\nlet PARAM_NAMESPACE_SEQ = 0;\n\nfunction nextParamNamespace() : string {\n PARAM_NAMESPACE_SEQ += 1;\n\n return `rapiq_${PARAM_NAMESPACE_SEQ}_`;\n}\n\n/**\n * Resolve a (possibly relation-dotted) property path to its column,\n * descending through relation metadata segment by segment; embedded\n * paths resolve through the plain column lookup per step.\n */\nfunction findColumnByPropertyPath(metadata: EntityMetadata, path: string) {\n let current = metadata;\n const segments = path.split('.');\n\n for (let i = 0; i < segments.length; i++) {\n const segment = segments[i];\n if (!segment) {\n return undefined;\n }\n\n const column = current.findColumnWithPropertyPath(segments.slice(i).join('.'));\n if (column) {\n return column;\n }\n\n const relation = current.findRelationWithPropertyPath(segment);\n if (!relation) {\n return undefined;\n }\n\n current = relation.inverseEntityMetadata;\n }\n\n return undefined;\n}\n\nexport class FiltersAdapter extends FiltersBaseAdapter<RelationsAdapter> {\n protected queryBuilder : SelectQueryBuilder<any>;\n\n protected dialect : DialectOptions;\n\n protected paramNamespace : string;\n\n constructor(queryBuilder: SelectQueryBuilder<any>, relations: RelationsAdapter) {\n super(relations);\n\n this.queryBuilder = queryBuilder;\n this.dialect = resolveQueryDialect(queryBuilder);\n this.paramNamespace = nextParamNamespace();\n }\n\n override clear() {\n super.clear();\n\n // a fresh namespace per run: clauses a previous run left on the\n // builder keep their own bindings instead of being rebound.\n this.paramNamespace = nextParamNamespace();\n }\n\n rootAlias(): string | undefined {\n return this.queryBuilder.alias;\n }\n\n escapeField(field: string) {\n return this.queryBuilder.escape(field);\n }\n\n paramPlaceholder(index: number) : string {\n return `:${this.paramNamespace}${index - 1}`;\n }\n\n override isRegexpSupported() : boolean {\n return typeof this.dialect.regexp !== 'undefined';\n }\n\n regexp(field: string, placeholder: string, ignoreCase: boolean): string {\n if (this.dialect.regexp) {\n return this.dialect.regexp(field, placeholder, ignoreCase);\n }\n\n throw AdapterError.featureUnsupported('regexp');\n }\n\n override caseFold(input: string) : string {\n if (this.dialect.caseFold) {\n return this.dialect.caseFold(input);\n }\n\n return super.caseFold(input);\n }\n\n override isCaseFoldable(field: string) : boolean {\n const { mainAlias } = this.queryBuilder.expressionMap;\n if (!mainAlias || !mainAlias.hasMetadata) {\n return super.isCaseFoldable(field);\n }\n\n const column = findColumnByPropertyPath(mainAlias.metadata, field);\n if (!column) {\n return super.isCaseFoldable(field);\n }\n\n return isCaseFoldableColumnType(column.type);\n }\n\n child(): this {\n const child = new FiltersAdapter(this.queryBuilder, this.relations);\n\n this.setChildAttributes(child);\n // children share the placeholder indexer, so they must also\n // share the namespace their placeholders are rendered with.\n child.paramNamespace = this.paramNamespace;\n\n return child as this;\n }\n\n execute() {\n const [sql, params] = this.getQueryAndParameters();\n\n if (sql) {\n const parameters : Record<string, unknown> = {};\n for (const [i, param] of params.entries()) {\n parameters[`${this.paramNamespace}${i}`] = param;\n }\n\n // The builder may already carry an application-owned predicate\n // (for example a tenant or authorization scope). Rapiq filters\n // narrow that query; they must never replace its baseline WHERE.\n this.queryBuilder.andWhere(sql, parameters);\n }\n }\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { RelationsBaseAdapter, splitFirst } from '@rapiq/sql';\nimport type { SelectQueryBuilder } from 'typeorm';\nimport type { RelationsAdapterOptions } from './types';\n\nexport class RelationsAdapter extends RelationsBaseAdapter {\n protected queryBuilder : SelectQueryBuilder<any>;\n\n protected options : RelationsAdapterOptions;\n\n constructor(\n queryBuilder: SelectQueryBuilder<any>,\n options: RelationsAdapterOptions = {},\n ) {\n super(options);\n\n this.queryBuilder = queryBuilder;\n this.options = options;\n }\n\n execute() : void {\n for (const relation of this.value) {\n if (relation.executed) {\n continue;\n }\n\n if (this.join(relation.path)) {\n relation.executed = true;\n }\n }\n }\n\n protected join(input: string): boolean {\n let relationFullName : string | undefined = input;\n let path : string | undefined;\n let meta = this.queryBuilder.expressionMap.mainAlias!.metadata;\n let parentAlias = this.queryBuilder.alias;\n\n const { joinAttributes } = this.queryBuilder.expressionMap;\n\n while (relationFullName) {\n let relationName : string;\n [relationName, relationFullName] = splitFirst(relationFullName);\n\n path = path ?\n `${path}.${relationName}` :\n relationName;\n\n const relation = meta.findRelationWithPropertyPath(relationName);\n if (!relation) {\n return false;\n }\n\n const alias = this.buildAlias(path);\n\n const joined = joinAttributes.some(\n (joinAttribute) => joinAttribute.alias.name === alias,\n );\n\n if (!joined) {\n this.applyJoin(`${parentAlias}.${relationName}`, alias);\n\n if (this.options.onJoin) {\n this.options.onJoin(path, alias, this.queryBuilder);\n }\n }\n\n meta = relation.inverseEntityMetadata;\n parentAlias = alias;\n }\n\n return true;\n }\n\n protected applyJoin(property: string, alias: string) : void {\n const inner = this.options.joinType === 'inner';\n\n if (this.options.joinAndSelect) {\n if (inner) {\n this.queryBuilder.innerJoinAndSelect(property, alias);\n } else {\n this.queryBuilder.leftJoinAndSelect(property, alias);\n }\n } else if (inner) {\n this.queryBuilder.innerJoin(property, alias);\n } else {\n this.queryBuilder.leftJoin(property, alias);\n }\n }\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { SortBaseAdapter } from '@rapiq/sql';\nimport type { SelectQueryBuilder } from 'typeorm';\nimport type { RelationsAdapter } from './relations';\n\nexport class SortAdapter extends SortBaseAdapter {\n protected queryBuilder : SelectQueryBuilder<any>;\n\n constructor(queryBuilder: SelectQueryBuilder<any>, relations: RelationsAdapter) {\n super(relations);\n\n this.queryBuilder = queryBuilder;\n }\n\n rootAlias(): string | undefined {\n return this.queryBuilder.alias;\n }\n\n escapeField(field: string) {\n // order-by keys must stay `alias.property` — TypeORM resolves\n // them against its alias map and escapes on its own; pre-escaped\n // names break entity hydration as soon as a join is present.\n return field;\n }\n\n execute() {\n // a query without sorts leaves a caller-owned ORDER BY untouched —\n // the same preservation contract the filters adapter applies to\n // WHERE. TypeORM's orderBy({}) would REPLACE the builder state.\n if (Object.keys(this.value).length > 0) {\n this.queryBuilder.orderBy(this.value);\n }\n }\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { PaginationBaseAdapter } from '@rapiq/sql';\nimport type { SelectQueryBuilder } from 'typeorm';\n\nexport class PaginationAdapter extends PaginationBaseAdapter {\n protected queryBuilder : SelectQueryBuilder<any>;\n\n constructor(queryBuilder: SelectQueryBuilder<any>) {\n super();\n\n this.queryBuilder = queryBuilder;\n }\n\n override execute() {\n // a query without pagination leaves caller-owned take/skip\n // untouched — the same preservation contract the filters adapter\n // applies to WHERE. The adapter/builder pair is per-request;\n // resetting a previous run is not this method's job. Nullish\n // (not falsy) coalescing: an explicit 0 is a value, not absence.\n if (typeof this.limit !== 'undefined') {\n this.queryBuilder.take(this.limit ?? undefined);\n }\n\n if (typeof this.offset !== 'undefined') {\n this.queryBuilder.skip(this.offset ?? undefined);\n }\n }\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { IQuery } from '@rapiq/core';\nimport type { ExecuteOptions, IRootAdapter } from '@rapiq/sql';\nimport { QueryVisitor } from '@rapiq/sql';\nimport { RelationsAdapter } from './relations';\nimport { FieldsAdapter } from './fields';\nimport { FiltersAdapter } from './filters';\nimport { SortAdapter } from './sort';\nimport type { TypeormAdapterOptions, TypeormAdapterOutput } from './types';\nimport { PaginationAdapter } from './pagination';\n\nexport class TypeormAdapter implements IRootAdapter<TypeormAdapterOutput> {\n public readonly relations : RelationsAdapter;\n\n public readonly fields : FieldsAdapter;\n\n public readonly filters : FiltersAdapter;\n\n public readonly pagination : PaginationAdapter;\n\n public readonly sort : SortAdapter;\n\n constructor(options: TypeormAdapterOptions) {\n this.relations = new RelationsAdapter(options.queryBuilder, options.relations);\n this.fields = new FieldsAdapter(options.queryBuilder, this.relations);\n this.filters = new FiltersAdapter(options.queryBuilder, this.relations);\n this.pagination = new PaginationAdapter(options.queryBuilder);\n this.sort = new SortAdapter(options.queryBuilder, this.relations);\n }\n\n clear() {\n this.fields.clear();\n this.filters.clear();\n this.pagination.clear();\n this.sort.clear();\n this.relations.clear();\n }\n\n /**\n * Walk `query` into the sub-adapters and apply the accumulated state\n * to the queryBuilder query builder (bound at construction).\n */\n execute(\n query: IQuery,\n options: ExecuteOptions = {},\n ) : TypeormAdapterOutput {\n if (options.clear ?? true) {\n this.clear();\n }\n\n query.accept(new QueryVisitor(this, options.visitor));\n\n this.fields.execute();\n this.filters.execute();\n this.pagination.execute();\n this.sort.execute();\n this.relations.execute();\n\n return {\n pagination: {\n limit: this.pagination.limit,\n offset: this.pagination.offset,\n },\n };\n }\n}\n"],"mappings":";;;AAWA,IAAa,gBAAb,cAAmC,kBAAkB;CACjD;CAEA,YAAY,cAAuC,WAA6B;EAC5E,MAAM,SAAS;EAEf,KAAK,eAAe;CACxB;CAEA,YAAgC;EAC5B,OAAO,KAAK,aAAa;CAC7B;CAEA,YAAY,OAAe;EAIvB,OAAO;CACX;CAEA,UAAU;EACN,MAAM,UAAU,KAAK,WAAW;EAChC,IAAI,QAAQ,SAAS,GACjB,KAAK,aAAa,OAAO,OAAO;CAExC;AACJ;;;;;;;;ACrBA,SAAgB,oBACZ,OACe;CACf,MAAM,UAAU,eAAe,MAAM,WAAW,QAAQ,IAAI;CAC5D,IAAI,SACA,OAAO;CAGX,OAAO;AACX;;;;;;;;;ACLA,MAAM,6CAA6B,IAAI,IAAY;CAC/C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACJ,CAAC;AAED,SAAS,yBAAyB,MAA4B;CAC1D,IAAI,SAAS,QACT,OAAO;CAGX,OAAO,OAAO,SAAS,YAAY,2BAA2B,IAAI,IAAI;AAC1E;;;;;;;AAQA,IAAI,sBAAsB;AAE1B,SAAS,qBAA8B;CACnC,uBAAuB;CAEvB,OAAO,SAAS,oBAAoB;AACxC;;;;;;AAOA,SAAS,yBAAyB,UAA0B,MAAc;CACtE,IAAI,UAAU;CACd,MAAM,WAAW,KAAK,MAAM,GAAG;CAE/B,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;EACtC,MAAM,UAAU,SAAS;EACzB,IAAI,CAAC,SACD;EAGJ,MAAM,SAAS,QAAQ,2BAA2B,SAAS,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;EAC7E,IAAI,QACA,OAAO;EAGX,MAAM,WAAW,QAAQ,6BAA6B,OAAO;EAC7D,IAAI,CAAC,UACD;EAGJ,UAAU,SAAS;CACvB;AAGJ;AAEA,IAAa,iBAAb,MAAa,uBAAuB,mBAAqC;CACrE;CAEA;CAEA;CAEA,YAAY,cAAuC,WAA6B;EAC5E,MAAM,SAAS;EAEf,KAAK,eAAe;EACpB,KAAK,UAAU,oBAAoB,YAAY;EAC/C,KAAK,iBAAiB,mBAAmB;CAC7C;CAEA,QAAiB;EACb,MAAM,MAAM;EAIZ,KAAK,iBAAiB,mBAAmB;CAC7C;CAEA,YAAgC;EAC5B,OAAO,KAAK,aAAa;CAC7B;CAEA,YAAY,OAAe;EACvB,OAAO,KAAK,aAAa,OAAO,KAAK;CACzC;CAEA,iBAAiB,OAAwB;EACrC,OAAO,IAAI,KAAK,iBAAiB,QAAQ;CAC7C;CAEA,oBAAuC;EACnC,OAAO,OAAO,KAAK,QAAQ,WAAW;CAC1C;CAEA,OAAO,OAAe,aAAqB,YAA6B;EACpE,IAAI,KAAK,QAAQ,QACb,OAAO,KAAK,QAAQ,OAAO,OAAO,aAAa,UAAU;EAG7D,MAAM,aAAa,mBAAmB,QAAQ;CAClD;CAEA,SAAkB,OAAwB;EACtC,IAAI,KAAK,QAAQ,UACb,OAAO,KAAK,QAAQ,SAAS,KAAK;EAGtC,OAAO,MAAM,SAAS,KAAK;CAC/B;CAEA,eAAwB,OAAyB;EAC7C,MAAM,EAAE,cAAc,KAAK,aAAa;EACxC,IAAI,CAAC,aAAa,CAAC,UAAU,aACzB,OAAO,MAAM,eAAe,KAAK;EAGrC,MAAM,SAAS,yBAAyB,UAAU,UAAU,KAAK;EACjE,IAAI,CAAC,QACD,OAAO,MAAM,eAAe,KAAK;EAGrC,OAAO,yBAAyB,OAAO,IAAI;CAC/C;CAEA,QAAc;EACV,MAAM,QAAQ,IAAI,eAAe,KAAK,cAAc,KAAK,SAAS;EAElE,KAAK,mBAAmB,KAAK;EAG7B,MAAM,iBAAiB,KAAK;EAE5B,OAAO;CACX;CAEA,UAAU;EACN,MAAM,CAAC,KAAK,UAAU,KAAK,sBAAsB;EAEjD,IAAI,KAAK;GACL,MAAM,aAAuC,CAAC;GAC9C,KAAK,MAAM,CAAC,GAAG,UAAU,OAAO,QAAQ,GACpC,WAAW,GAAG,KAAK,iBAAiB,OAAO;GAM/C,KAAK,aAAa,SAAS,KAAK,UAAU;EAC9C;CACJ;AACJ;;;AClLA,IAAa,mBAAb,cAAsC,qBAAqB;CACvD;CAEA;CAEA,YACI,cACA,UAAmC,CAAC,GACtC;EACE,MAAM,OAAO;EAEb,KAAK,eAAe;EACpB,KAAK,UAAU;CACnB;CAEA,UAAiB;EACb,KAAK,MAAM,YAAY,KAAK,OAAO;GAC/B,IAAI,SAAS,UACT;GAGJ,IAAI,KAAK,KAAK,SAAS,IAAI,GACvB,SAAS,WAAW;EAE5B;CACJ;CAEA,KAAe,OAAwB;EACnC,IAAI,mBAAwC;EAC5C,IAAI;EACJ,IAAI,OAAO,KAAK,aAAa,cAAc,UAAW;EACtD,IAAI,cAAc,KAAK,aAAa;EAEpC,MAAM,EAAE,mBAAmB,KAAK,aAAa;EAE7C,OAAO,kBAAkB;GACrB,IAAI;GACJ,CAAC,cAAc,oBAAoB,WAAW,gBAAgB;GAE9D,OAAO,OACH,GAAG,KAAK,GAAG,iBACX;GAEJ,MAAM,WAAW,KAAK,6BAA6B,YAAY;GAC/D,IAAI,CAAC,UACD,OAAO;GAGX,MAAM,QAAQ,KAAK,WAAW,IAAI;GAMlC,IAAI,CAJW,eAAe,MACzB,kBAAkB,cAAc,MAAM,SAAS,KAG1C,GAAG;IACT,KAAK,UAAU,GAAG,YAAY,GAAG,gBAAgB,KAAK;IAEtD,IAAI,KAAK,QAAQ,QACb,KAAK,QAAQ,OAAO,MAAM,OAAO,KAAK,YAAY;GAE1D;GAEA,OAAO,SAAS;GAChB,cAAc;EAClB;EAEA,OAAO;CACX;CAEA,UAAoB,UAAkB,OAAsB;EACxD,MAAM,QAAQ,KAAK,QAAQ,aAAa;EAExC,IAAI,KAAK,QAAQ,eACb,IAAI,OACA,KAAK,aAAa,mBAAmB,UAAU,KAAK;OAEpD,KAAK,aAAa,kBAAkB,UAAU,KAAK;OAEpD,IAAI,OACP,KAAK,aAAa,UAAU,UAAU,KAAK;OAE3C,KAAK,aAAa,SAAS,UAAU,KAAK;CAElD;AACJ;;;ACpFA,IAAa,cAAb,cAAiC,gBAAgB;CAC7C;CAEA,YAAY,cAAuC,WAA6B;EAC5E,MAAM,SAAS;EAEf,KAAK,eAAe;CACxB;CAEA,YAAgC;EAC5B,OAAO,KAAK,aAAa;CAC7B;CAEA,YAAY,OAAe;EAIvB,OAAO;CACX;CAEA,UAAU;EAIN,IAAI,OAAO,KAAK,KAAK,KAAK,CAAC,CAAC,SAAS,GACjC,KAAK,aAAa,QAAQ,KAAK,KAAK;CAE5C;AACJ;;;AC7BA,IAAa,oBAAb,cAAuC,sBAAsB;CACzD;CAEA,YAAY,cAAuC;EAC/C,MAAM;EAEN,KAAK,eAAe;CACxB;CAEA,UAAmB;EAMf,IAAI,OAAO,KAAK,UAAU,aACtB,KAAK,aAAa,KAAK,KAAK,SAAS,KAAA,CAAS;EAGlD,IAAI,OAAO,KAAK,WAAW,aACvB,KAAK,aAAa,KAAK,KAAK,UAAU,KAAA,CAAS;CAEvD;AACJ;;;AChBA,IAAa,iBAAb,MAA0E;CACtE;CAEA;CAEA;CAEA;CAEA;CAEA,YAAY,SAAgC;EACxC,KAAK,YAAY,IAAI,iBAAiB,QAAQ,cAAc,QAAQ,SAAS;EAC7E,KAAK,SAAS,IAAI,cAAc,QAAQ,cAAc,KAAK,SAAS;EACpE,KAAK,UAAU,IAAI,eAAe,QAAQ,cAAc,KAAK,SAAS;EACtE,KAAK,aAAa,IAAI,kBAAkB,QAAQ,YAAY;EAC5D,KAAK,OAAO,IAAI,YAAY,QAAQ,cAAc,KAAK,SAAS;CACpE;CAEA,QAAQ;EACJ,KAAK,OAAO,MAAM;EAClB,KAAK,QAAQ,MAAM;EACnB,KAAK,WAAW,MAAM;EACtB,KAAK,KAAK,MAAM;EAChB,KAAK,UAAU,MAAM;CACzB;;;;;CAMA,QACI,OACA,UAA0B,CAAC,GACN;EACrB,IAAI,QAAQ,SAAS,MACjB,KAAK,MAAM;EAGf,MAAM,OAAO,IAAI,aAAa,MAAM,QAAQ,OAAO,CAAC;EAEpD,KAAK,OAAO,QAAQ;EACpB,KAAK,QAAQ,QAAQ;EACrB,KAAK,WAAW,QAAQ;EACxB,KAAK,KAAK,QAAQ;EAClB,KAAK,UAAU,QAAQ;EAEvB,OAAO,EACH,YAAY;GACR,OAAO,KAAK,WAAW;GACvB,QAAQ,KAAK,WAAW;EAC5B,EACJ;CACJ;AACJ"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@rapiq/typeorm",
3
+ "version": "2.0.0-beta.0",
4
+ "description": "A typeorm adapter for rapiq.",
5
+ "type": "module",
6
+ "main": "dist/index.mjs",
7
+ "types": "dist/index.d.mts",
8
+ "exports": {
9
+ "./package.json": "./package.json",
10
+ ".": {
11
+ "types": "./dist/index.d.mts",
12
+ "import": "./dist/index.mjs"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist/"
17
+ ],
18
+ "devDependencies": {
19
+ "@rapiq/core": "^2.0.0-beta.0",
20
+ "@rapiq/parser-simple": "^2.0.0-beta.0",
21
+ "@rapiq/sql": "^2.0.0-beta.0",
22
+ "@swc/core": "^1.15.43",
23
+ "ansis": "^4.2.0",
24
+ "better-sqlite3": "^12.6.0",
25
+ "mysql2": "^3.22.6",
26
+ "reflect-metadata": "^0.2.2",
27
+ "typeorm": "^1.1.0",
28
+ "unplugin-swc": "^1.5.9"
29
+ },
30
+ "peerDependencies": {
31
+ "@rapiq/core": "^2.0.0-beta.0",
32
+ "@rapiq/sql": "^2.0.0-beta.0",
33
+ "typeorm": "^1.1.0"
34
+ },
35
+ "scripts": {
36
+ "build:types": "tsc --noEmit -p tsconfig.build.json",
37
+ "build:js": "tsdown",
38
+ "build": "npm run build:types && npm run build:js",
39
+ "test": "vitest --config test/vitest.config.ts --run",
40
+ "test:coverage": "vitest --config test/vitest.config.ts --run --coverage",
41
+ "prepublishOnly": "npm run build"
42
+ },
43
+ "author": {
44
+ "name": "Peter Placzek",
45
+ "email": "contact@tada5hi.net",
46
+ "url": "https://github.com/tada5hi"
47
+ },
48
+ "license": "MIT",
49
+ "publishConfig": {
50
+ "access": "public",
51
+ "tag": "beta"
52
+ },
53
+ "keywords": [],
54
+ "repository": {
55
+ "type": "git",
56
+ "url": "git+https://github.com/Tada5hi/rapiq.git",
57
+ "directory": "packages/typeorm"
58
+ },
59
+ "bugs": {
60
+ "url": "https://github.com/Tada5hi/rapiq/issues"
61
+ },
62
+ "homepage": "https://github.com/Tada5hi/rapiq#readme"
63
+ }