@cheetah.js/orm 0.1.136 → 0.1.141
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/README.md +1 -0
- package/dist/driver/bun-driver.base.d.ts +16 -3
- package/dist/driver/bun-driver.base.js +60 -44
- package/dist/driver/driver.interface.d.ts +25 -20
- package/dist/orm.service.d.ts +1 -0
- package/dist/orm.service.js +20 -4
- package/dist/testing/with-database.js +10 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -39,6 +39,7 @@ export default config;
|
|
|
39
39
|
Actually, the ORM only supports PostgreSQL, but in the future it will support other databases.
|
|
40
40
|
- Entities: Path to entities. Accepts glob patterns or an array of Entity classes.
|
|
41
41
|
- MigrationPath: Path to migrations. Accepts glob patterns. Is optional.
|
|
42
|
+
- Connection pool (optional): `max`, `idleTimeout`, `maxLifetime`, `connectionTimeout` in seconds control the Bun SQL pool. Defaults are 20 connections, 20s idle timeout, 300s max lifetime, and 10s connection timeout.
|
|
42
43
|
<br/>
|
|
43
44
|
<br/>
|
|
44
45
|
After that, you need to import the ORM into the project and add it to the Cheetah.js instance:
|
|
@@ -1,14 +1,27 @@
|
|
|
1
|
-
import { SQL } from
|
|
2
|
-
import { ConnectionSettings, DriverInterface, Statement, SnapshotConstraintInfo, ColDiff } from
|
|
1
|
+
import { SQL } from "bun";
|
|
2
|
+
import { ConnectionSettings, DriverInterface, Statement, SnapshotConstraintInfo, ColDiff } from "./driver.interface";
|
|
3
3
|
export declare abstract class BunDriverBase implements Partial<DriverInterface> {
|
|
4
4
|
protected sql: SQL;
|
|
5
5
|
connectionString: string;
|
|
6
|
-
|
|
6
|
+
protected readonly poolOptions: {
|
|
7
|
+
max: number;
|
|
8
|
+
idleTimeout: number;
|
|
9
|
+
maxLifetime: number;
|
|
10
|
+
connectionTimeout: number;
|
|
11
|
+
};
|
|
12
|
+
abstract readonly dbType: "postgres" | "mysql";
|
|
7
13
|
constructor(options: ConnectionSettings);
|
|
8
14
|
protected buildConnectionString(options: ConnectionSettings): string;
|
|
9
15
|
protected abstract getProtocol(): string;
|
|
10
16
|
protected abstract getIdentifierQuote(): string;
|
|
11
17
|
connect(): Promise<void>;
|
|
18
|
+
protected buildPoolOptions(options: ConnectionSettings): {
|
|
19
|
+
max: number;
|
|
20
|
+
idleTimeout: number;
|
|
21
|
+
maxLifetime: number;
|
|
22
|
+
connectionTimeout: number;
|
|
23
|
+
};
|
|
24
|
+
private createSqlInstance;
|
|
12
25
|
protected validateConnection(): Promise<void>;
|
|
13
26
|
disconnect(): Promise<void>;
|
|
14
27
|
executeSql(sqlString: string): Promise<any>;
|
|
@@ -6,6 +6,7 @@ const transaction_context_1 = require("../transaction/transaction-context");
|
|
|
6
6
|
class BunDriverBase {
|
|
7
7
|
constructor(options) {
|
|
8
8
|
this.connectionString = this.buildConnectionString(options);
|
|
9
|
+
this.poolOptions = this.buildPoolOptions(options);
|
|
9
10
|
}
|
|
10
11
|
buildConnectionString(options) {
|
|
11
12
|
if (options.connectionString) {
|
|
@@ -19,23 +20,35 @@ class BunDriverBase {
|
|
|
19
20
|
if (this.sql) {
|
|
20
21
|
return;
|
|
21
22
|
}
|
|
22
|
-
this.sql =
|
|
23
|
+
this.sql = this.createSqlInstance();
|
|
24
|
+
await this.validateConnection();
|
|
25
|
+
}
|
|
26
|
+
buildPoolOptions(options) {
|
|
27
|
+
return {
|
|
28
|
+
max: options.max ?? undefined,
|
|
29
|
+
idleTimeout: options.idleTimeout ?? undefined,
|
|
30
|
+
maxLifetime: options.maxLifetime ?? undefined,
|
|
31
|
+
connectionTimeout: options.connectionTimeout ?? undefined,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
createSqlInstance() {
|
|
35
|
+
return new bun_1.SQL({
|
|
23
36
|
url: this.connectionString,
|
|
24
|
-
max:
|
|
25
|
-
idleTimeout:
|
|
26
|
-
maxLifetime:
|
|
27
|
-
connectionTimeout:
|
|
37
|
+
max: this.poolOptions.max,
|
|
38
|
+
idleTimeout: this.poolOptions.idleTimeout,
|
|
39
|
+
maxLifetime: this.poolOptions.maxLifetime,
|
|
40
|
+
connectionTimeout: this.poolOptions.connectionTimeout,
|
|
28
41
|
});
|
|
29
|
-
await this.validateConnection();
|
|
30
42
|
}
|
|
31
43
|
async validateConnection() {
|
|
32
|
-
await this.sql.unsafe(
|
|
44
|
+
await this.sql.unsafe("SELECT 1");
|
|
33
45
|
}
|
|
34
46
|
async disconnect() {
|
|
35
47
|
if (!this.sql) {
|
|
36
48
|
return;
|
|
37
49
|
}
|
|
38
50
|
await this.sql.close();
|
|
51
|
+
this.sql = null;
|
|
39
52
|
}
|
|
40
53
|
async executeSql(sqlString) {
|
|
41
54
|
const context = this.getExecutionContext();
|
|
@@ -47,31 +60,31 @@ class BunDriverBase {
|
|
|
47
60
|
return txContext;
|
|
48
61
|
}
|
|
49
62
|
if (!this.sql) {
|
|
50
|
-
throw new Error(
|
|
63
|
+
throw new Error("Database not connected");
|
|
51
64
|
}
|
|
52
65
|
return this.sql;
|
|
53
66
|
}
|
|
54
67
|
async transaction(callback) {
|
|
55
68
|
if (!this.sql) {
|
|
56
|
-
throw new Error(
|
|
69
|
+
throw new Error("Database not connected");
|
|
57
70
|
}
|
|
58
71
|
return await this.sql.begin(callback);
|
|
59
72
|
}
|
|
60
73
|
toDatabaseValue(value) {
|
|
61
74
|
if (value === null || value === undefined) {
|
|
62
|
-
return
|
|
75
|
+
return "NULL";
|
|
63
76
|
}
|
|
64
77
|
if (value instanceof Date) {
|
|
65
78
|
return `'${value.toISOString()}'`;
|
|
66
79
|
}
|
|
67
80
|
switch (typeof value) {
|
|
68
|
-
case
|
|
81
|
+
case "string":
|
|
69
82
|
return `'${this.escapeString(value)}'`;
|
|
70
|
-
case
|
|
83
|
+
case "number":
|
|
71
84
|
return value;
|
|
72
|
-
case
|
|
85
|
+
case "boolean":
|
|
73
86
|
return value;
|
|
74
|
-
case
|
|
87
|
+
case "object":
|
|
75
88
|
return `'${this.escapeString(JSON.stringify(value))}'`;
|
|
76
89
|
default:
|
|
77
90
|
return `'${this.escapeString(String(value))}'`;
|
|
@@ -85,25 +98,25 @@ class BunDriverBase {
|
|
|
85
98
|
}
|
|
86
99
|
buildWhereClause(where) {
|
|
87
100
|
if (!where) {
|
|
88
|
-
return
|
|
101
|
+
return "";
|
|
89
102
|
}
|
|
90
103
|
return ` WHERE ${where}`;
|
|
91
104
|
}
|
|
92
105
|
buildOrderByClause(orderBy) {
|
|
93
106
|
if (!orderBy || orderBy.length === 0) {
|
|
94
|
-
return
|
|
107
|
+
return "";
|
|
95
108
|
}
|
|
96
|
-
return ` ORDER BY ${orderBy.join(
|
|
109
|
+
return ` ORDER BY ${orderBy.join(", ")}`;
|
|
97
110
|
}
|
|
98
111
|
buildLimitClause(limit) {
|
|
99
112
|
if (!limit) {
|
|
100
|
-
return
|
|
113
|
+
return "";
|
|
101
114
|
}
|
|
102
115
|
return ` LIMIT ${limit}`;
|
|
103
116
|
}
|
|
104
117
|
buildOffsetClause(offset) {
|
|
105
118
|
if (!offset) {
|
|
106
|
-
return
|
|
119
|
+
return "";
|
|
107
120
|
}
|
|
108
121
|
return ` OFFSET ${offset}`;
|
|
109
122
|
}
|
|
@@ -119,23 +132,23 @@ class BunDriverBase {
|
|
|
119
132
|
buildColumnConstraints(colDiff) {
|
|
120
133
|
const parts = [];
|
|
121
134
|
if (!colDiff.colChanges?.nullable) {
|
|
122
|
-
parts.push(
|
|
135
|
+
parts.push("NOT NULL");
|
|
123
136
|
}
|
|
124
137
|
if (colDiff.colChanges?.primary) {
|
|
125
|
-
parts.push(
|
|
138
|
+
parts.push("PRIMARY KEY");
|
|
126
139
|
}
|
|
127
140
|
if (colDiff.colChanges?.unique) {
|
|
128
|
-
parts.push(
|
|
141
|
+
parts.push("UNIQUE");
|
|
129
142
|
}
|
|
130
143
|
if (colDiff.colChanges?.default) {
|
|
131
144
|
parts.push(`DEFAULT ${colDiff.colChanges.default}`);
|
|
132
145
|
}
|
|
133
|
-
return parts.length > 0 ?
|
|
146
|
+
return parts.length > 0 ? " " + parts.join(" ") : "";
|
|
134
147
|
}
|
|
135
148
|
async executeStatement(statement) {
|
|
136
149
|
const startTime = Date.now();
|
|
137
150
|
const context = this.getExecutionContext();
|
|
138
|
-
if (statement.statement ===
|
|
151
|
+
if (statement.statement === "insert") {
|
|
139
152
|
const sql = this.buildInsertSqlWithReturn(statement);
|
|
140
153
|
const result = await context.unsafe(sql);
|
|
141
154
|
return this.handleInsertReturn(statement, result, sql, startTime);
|
|
@@ -161,34 +174,34 @@ class BunDriverBase {
|
|
|
161
174
|
buildBaseSql(statement) {
|
|
162
175
|
const { statement: type, table, columns, values, alias } = statement;
|
|
163
176
|
switch (type) {
|
|
164
|
-
case
|
|
165
|
-
return `SELECT ${columns ? columns.join(
|
|
166
|
-
case
|
|
177
|
+
case "select":
|
|
178
|
+
return `SELECT ${columns ? columns.join(", ") : "*"} FROM ${table} ${alias}`;
|
|
179
|
+
case "insert":
|
|
167
180
|
return this.buildInsertSql(table, values, columns, alias);
|
|
168
|
-
case
|
|
181
|
+
case "update":
|
|
169
182
|
return this.buildUpdateSql(table, values, alias);
|
|
170
|
-
case
|
|
183
|
+
case "delete":
|
|
171
184
|
return this.buildDeleteSql(table, alias);
|
|
172
|
-
case
|
|
185
|
+
case "count":
|
|
173
186
|
return `SELECT COUNT(*) as count FROM ${table} ${alias}`;
|
|
174
187
|
default:
|
|
175
|
-
return
|
|
188
|
+
return "";
|
|
176
189
|
}
|
|
177
190
|
}
|
|
178
191
|
buildInsertSql(table, values, columns, alias) {
|
|
179
192
|
const q = this.getIdentifierQuote();
|
|
180
193
|
const fields = Object.keys(values)
|
|
181
194
|
.map((v) => `${q}${v}${q}`)
|
|
182
|
-
.join(
|
|
195
|
+
.join(", ");
|
|
183
196
|
const vals = Object.values(values)
|
|
184
197
|
.map((value) => this.toDatabaseValue(value))
|
|
185
|
-
.join(
|
|
198
|
+
.join(", ");
|
|
186
199
|
return `INSERT INTO ${table} (${fields}) VALUES (${vals})`;
|
|
187
200
|
}
|
|
188
201
|
buildUpdateSql(table, values, alias) {
|
|
189
202
|
const sets = Object.entries(values)
|
|
190
203
|
.map(([key, value]) => `${key} = ${this.toDatabaseValue(value)}`)
|
|
191
|
-
.join(
|
|
204
|
+
.join(", ");
|
|
192
205
|
return `UPDATE ${table} as ${alias} SET ${sets}`;
|
|
193
206
|
}
|
|
194
207
|
buildDeleteSql(table, alias) {
|
|
@@ -196,17 +209,17 @@ class BunDriverBase {
|
|
|
196
209
|
}
|
|
197
210
|
buildJoinClause(statement) {
|
|
198
211
|
if (!statement.join)
|
|
199
|
-
return
|
|
212
|
+
return "";
|
|
200
213
|
return statement.join
|
|
201
214
|
.map((join) => {
|
|
202
215
|
const table = `${join.joinSchema}.${join.joinTable}`;
|
|
203
216
|
return ` ${join.type} JOIN ${table} ${join.joinAlias} ON ${join.on}`;
|
|
204
217
|
})
|
|
205
|
-
.join(
|
|
218
|
+
.join("");
|
|
206
219
|
}
|
|
207
220
|
buildWhereAndOrderClauses(statement) {
|
|
208
|
-
if (statement.statement ===
|
|
209
|
-
return
|
|
221
|
+
if (statement.statement === "insert")
|
|
222
|
+
return "";
|
|
210
223
|
let sql = this.buildWhereClause(statement.where);
|
|
211
224
|
sql += this.buildOrderByClause(statement.orderBy);
|
|
212
225
|
sql += this.buildLimitAndOffsetClause(statement);
|
|
@@ -220,7 +233,7 @@ class BunDriverBase {
|
|
|
220
233
|
if (limit) {
|
|
221
234
|
return this.buildLimitClause(limit);
|
|
222
235
|
}
|
|
223
|
-
return
|
|
236
|
+
return "";
|
|
224
237
|
}
|
|
225
238
|
getForeignKeysFromConstraints(constraints, row, columnNameField) {
|
|
226
239
|
const columnName = row[columnNameField];
|
|
@@ -230,25 +243,28 @@ class BunDriverBase {
|
|
|
230
243
|
.filter(Boolean);
|
|
231
244
|
}
|
|
232
245
|
isForeignKeyConstraint(constraint, columnName) {
|
|
233
|
-
return (constraint.type ===
|
|
246
|
+
return (constraint.type === "FOREIGN KEY" &&
|
|
234
247
|
constraint.consDef.includes(columnName));
|
|
235
248
|
}
|
|
236
249
|
parseForeignKeyDefinition(consDef) {
|
|
237
250
|
const quote = this.getIdentifierQuote();
|
|
238
251
|
const escapedQuote = this.escapeRegex(quote);
|
|
239
|
-
const pattern = new RegExp(`REFERENCES\\s+(?:${escapedQuote}([^${escapedQuote}]+)${escapedQuote}|([\\w.]+))\\s*\\(([^)]+)\\)`,
|
|
252
|
+
const pattern = new RegExp(`REFERENCES\\s+(?:${escapedQuote}([^${escapedQuote}]+)${escapedQuote}|([\\w.]+))\\s*\\(([^)]+)\\)`, "i");
|
|
240
253
|
const match = consDef.match(pattern);
|
|
241
254
|
if (!match)
|
|
242
255
|
return null;
|
|
243
256
|
const tableName = (match[1] || match[2]).trim();
|
|
244
|
-
const columnName = match[3]
|
|
257
|
+
const columnName = match[3]
|
|
258
|
+
.split(",")[0]
|
|
259
|
+
.trim()
|
|
260
|
+
.replace(new RegExp(escapedQuote, "g"), "");
|
|
245
261
|
return {
|
|
246
262
|
referencedColumnName: columnName,
|
|
247
|
-
referencedTableName: tableName
|
|
263
|
+
referencedTableName: tableName,
|
|
248
264
|
};
|
|
249
265
|
}
|
|
250
266
|
escapeRegex(str) {
|
|
251
|
-
return str.replace(/[.*+?^${}()|[\]\\]/g,
|
|
267
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
252
268
|
}
|
|
253
269
|
}
|
|
254
270
|
exports.BunDriverBase = BunDriverBase;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { PropertyOptions } from
|
|
2
|
-
import { Collection } from
|
|
3
|
-
import { Reference } from
|
|
4
|
-
import { ValueObject } from
|
|
1
|
+
import { PropertyOptions } from "../decorators/property.decorator";
|
|
2
|
+
import { Collection } from "../domain/collection";
|
|
3
|
+
import { Reference } from "../domain/reference";
|
|
4
|
+
import { ValueObject } from "../common/value-object";
|
|
5
5
|
export interface DriverInterface {
|
|
6
6
|
connectionString: string;
|
|
7
|
-
readonly dbType:
|
|
7
|
+
readonly dbType: "postgres" | "mysql";
|
|
8
8
|
executeStatement(statement: Statement<any>): Promise<{
|
|
9
9
|
query: any;
|
|
10
10
|
startTime: number;
|
|
@@ -41,7 +41,8 @@ export interface DriverInterface {
|
|
|
41
41
|
}, schema: string | undefined, tableName: string): string;
|
|
42
42
|
transaction<T>(callback: (tx: any) => Promise<T>): Promise<T>;
|
|
43
43
|
}
|
|
44
|
-
export type ValueOrInstance<T> = T extends ValueObject<any, any> ?
|
|
44
|
+
export type ValueOrInstance<T> = T extends ValueObject<any, any> ? // @ts-ignore
|
|
45
|
+
T | T["value"] : NonNullable<T>;
|
|
45
46
|
export type SnapshotConstraintInfo = {
|
|
46
47
|
indexName: string;
|
|
47
48
|
consDef: string;
|
|
@@ -54,6 +55,10 @@ export interface ConnectionSettings<T extends DriverInterface = DriverInterface>
|
|
|
54
55
|
password?: string;
|
|
55
56
|
database?: string;
|
|
56
57
|
connectionString?: string;
|
|
58
|
+
max?: number;
|
|
59
|
+
idleTimeout?: number;
|
|
60
|
+
maxLifetime?: number;
|
|
61
|
+
connectionTimeout?: number;
|
|
57
62
|
ssl?: boolean;
|
|
58
63
|
driver: new (options: ConnectionSettings<T>) => T;
|
|
59
64
|
entities?: Function[] | string;
|
|
@@ -85,7 +90,7 @@ export interface EnumOptions<T> extends PropertyOptions {
|
|
|
85
90
|
array?: boolean;
|
|
86
91
|
}
|
|
87
92
|
export type JoinStatement<T> = {
|
|
88
|
-
type:
|
|
93
|
+
type: "INNER" | "LEFT" | "RIGHT";
|
|
89
94
|
originalEntity?: Function;
|
|
90
95
|
originTable: string;
|
|
91
96
|
originSchema: string;
|
|
@@ -104,14 +109,14 @@ export type JoinStatement<T> = {
|
|
|
104
109
|
}[];
|
|
105
110
|
};
|
|
106
111
|
export type Statement<T> = {
|
|
107
|
-
statement?:
|
|
112
|
+
statement?: "select" | "insert" | "update" | "delete" | "count";
|
|
108
113
|
table?: string;
|
|
109
114
|
alias?: string;
|
|
110
115
|
customSchema?: string;
|
|
111
116
|
columns?: string[];
|
|
112
117
|
join?: JoinStatement<T>[];
|
|
113
118
|
selectJoin?: Statement<T>[];
|
|
114
|
-
strategy?:
|
|
119
|
+
strategy?: "select" | "joined";
|
|
115
120
|
where?: string;
|
|
116
121
|
values?: any;
|
|
117
122
|
groupBy?: string[];
|
|
@@ -161,10 +166,10 @@ export type ColumnsInfo = {
|
|
|
161
166
|
precision?: number;
|
|
162
167
|
scale?: number;
|
|
163
168
|
isDecimal?: boolean;
|
|
164
|
-
enumItems?: string[] | number[] |
|
|
169
|
+
enumItems?: string[] | number[] | "__AUTO_DETECT__";
|
|
165
170
|
foreignKeys?: ForeignKeyInfo[];
|
|
166
171
|
};
|
|
167
|
-
export type SqlActionType =
|
|
172
|
+
export type SqlActionType = "CREATE" | "DELETE" | "ALTER" | "INDEX";
|
|
168
173
|
export type ColDiff = {
|
|
169
174
|
actionType: SqlActionType;
|
|
170
175
|
colName: string;
|
|
@@ -209,11 +214,11 @@ export type PrimaryProperty<T> = T extends {
|
|
|
209
214
|
[PrimaryKeyProp]?: infer PK;
|
|
210
215
|
} ? PK : T extends {
|
|
211
216
|
_id?: any;
|
|
212
|
-
} ?
|
|
217
|
+
} ? "_id" | string : T extends {
|
|
213
218
|
uuid?: any;
|
|
214
|
-
} ?
|
|
219
|
+
} ? "uuid" : T extends {
|
|
215
220
|
id?: any;
|
|
216
|
-
} ?
|
|
221
|
+
} ? "id" : never;
|
|
217
222
|
export type IPrimaryKeyValue = number | string | bigint | Date | {
|
|
218
223
|
toHexString(): string;
|
|
219
224
|
};
|
|
@@ -232,7 +237,7 @@ export type OperatorMap<T> = {
|
|
|
232
237
|
$lte?: ExpandScalar<T>;
|
|
233
238
|
$like?: string;
|
|
234
239
|
};
|
|
235
|
-
export type ExcludeFunctions<T, K extends keyof T> = T[K] extends Function ? never :
|
|
240
|
+
export type ExcludeFunctions<T, K extends keyof T> = T[K] extends Function ? never : K extends symbol ? never : K;
|
|
236
241
|
export type Scalar = boolean | number | string | bigint | symbol | Date | RegExp | Uint8Array | {
|
|
237
242
|
toHexString(): string;
|
|
238
243
|
};
|
|
@@ -257,7 +262,7 @@ export type ObjectQuery<T> = ExpandObject<T> & OperatorMap<T>;
|
|
|
257
262
|
export type FilterQuery<T> = ObjectQuery<T> | NonNullable<ExpandScalar<Primary<T>>> | NonNullable<EntityProps<T> & OperatorMap<T>> | FilterQuery<T>[];
|
|
258
263
|
export type Relationship<T> = {
|
|
259
264
|
isRelation?: boolean;
|
|
260
|
-
relation:
|
|
265
|
+
relation: "one-to-many" | "many-to-one";
|
|
261
266
|
type: Function;
|
|
262
267
|
fkKey?: (string & keyof T) | ((e: T) => any);
|
|
263
268
|
entity: () => EntityName<T>;
|
|
@@ -271,7 +276,7 @@ type Loadable<T extends object> = Collection<T, any> | Reference<T> | readonly T
|
|
|
271
276
|
type ExtractType<T> = T extends Loadable<infer U> ? U : T;
|
|
272
277
|
type StringKeys<T, E extends string = never> = T extends Collection<any, any> ? `${Exclude<keyof ExtractType<T> | E, symbol>}` : T extends Reference<any> ? `${Exclude<keyof ExtractType<T> | E, symbol>}` : T extends object ? `${Exclude<keyof ExtractType<T> | E, symbol>}` : never;
|
|
273
278
|
type Defined<T> = Exclude<T, null | undefined>;
|
|
274
|
-
type GetStringKey<T, K extends StringKeys<T, string>, E extends string> = K extends keyof T ? ExtractType<T[K]> :
|
|
279
|
+
type GetStringKey<T, K extends StringKeys<T, string>, E extends string> = K extends keyof T ? ExtractType<T[K]> : K extends E ? keyof T : never;
|
|
275
280
|
type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
276
281
|
export type AutoPath<O, P extends string, E extends string = never, D extends Prev[number] = 5> = [D] extends [never] ? string : P extends any ? (P & `${string}.` extends never ? P : P & `${string}.`) extends infer Q ? Q extends `${infer A}.${infer B}` ? A extends StringKeys<O, E> ? `${A}.${AutoPath<Defined<GetStringKey<O, A, E>>, B, E, Prev[D]>}` : never : Q extends StringKeys<O, E> ? (Defined<GetStringKey<O, Q, E>> extends unknown ? Exclude<P, `${string}.`> : never) | (StringKeys<Defined<GetStringKey<O, Q, E>>, E> extends never ? never : `${Q}.`) : keyof ExtractType<O> : never : never;
|
|
277
282
|
export declare enum QueryOrder {
|
|
@@ -297,7 +302,7 @@ export type QueryOrderKeys<T> = QueryOrderKeysFlat | QueryOrderMap<T>;
|
|
|
297
302
|
export type QueryOrderMap<T> = {
|
|
298
303
|
[K in keyof T as ExcludeFunctions<T, K>]?: QueryOrderKeys<ExpandProperty<T[K]>>;
|
|
299
304
|
};
|
|
300
|
-
export type EntityField<T, P extends string = never> = AutoPath<T, P,
|
|
305
|
+
export type EntityField<T, P extends string = never> = AutoPath<T, P, "*">;
|
|
301
306
|
export interface FindOptions<T, P extends string = never> {
|
|
302
307
|
load?: readonly AutoPath<T, P>[];
|
|
303
308
|
orderBy?: (QueryOrderMap<T> & {
|
|
@@ -308,7 +313,7 @@ export interface FindOptions<T, P extends string = never> {
|
|
|
308
313
|
offset?: number;
|
|
309
314
|
fields?: readonly EntityField<T, P>[];
|
|
310
315
|
schema?: string;
|
|
311
|
-
loadStrategy?:
|
|
316
|
+
loadStrategy?: "select" | "joined";
|
|
312
317
|
}
|
|
313
|
-
export type FindOneOption<T, P extends string = never> = Omit<FindOptions<T, P>,
|
|
318
|
+
export type FindOneOption<T, P extends string = never> = Omit<FindOptions<T, P>, "limit" | "offset">;
|
|
314
319
|
export {};
|
package/dist/orm.service.d.ts
CHANGED
package/dist/orm.service.js
CHANGED
|
@@ -58,7 +58,8 @@ let OrmService = class OrmService {
|
|
|
58
58
|
this.orm = orm;
|
|
59
59
|
this.storage = storage;
|
|
60
60
|
this.allEntities = new Map();
|
|
61
|
-
|
|
61
|
+
this.project = new ts_morph_1.Project({ skipLoadingLibFiles: true });
|
|
62
|
+
const files = this.project.addSourceFilesAtPaths(entityFile ?? this.getSourceFilePaths());
|
|
62
63
|
files.forEach(file => {
|
|
63
64
|
file.getClasses().forEach(classDeclaration => {
|
|
64
65
|
if (classDeclaration.getDecorator('Entity')) {
|
|
@@ -281,8 +282,7 @@ let OrmService = class OrmService {
|
|
|
281
282
|
console.log('No entities found!');
|
|
282
283
|
return;
|
|
283
284
|
}
|
|
284
|
-
const files =
|
|
285
|
-
.addSourceFilesAtPaths(this.getSourceFilePaths());
|
|
285
|
+
const files = this.project.getSourceFiles();
|
|
286
286
|
this.discoverRelationshipTypes(files);
|
|
287
287
|
this.discoverEnumTypes(files, entities);
|
|
288
288
|
for (const entity of entities) {
|
|
@@ -320,7 +320,23 @@ let OrmService = class OrmService {
|
|
|
320
320
|
}
|
|
321
321
|
getSourceFilePaths() {
|
|
322
322
|
const projectRoot = process.cwd();
|
|
323
|
-
const patterns = [
|
|
323
|
+
const patterns = [
|
|
324
|
+
'**/*.entity.ts',
|
|
325
|
+
'**/entities/**/*.ts',
|
|
326
|
+
'**/entity/**/*.ts',
|
|
327
|
+
'**/*.entity.js',
|
|
328
|
+
'**/entities/**/*.js',
|
|
329
|
+
'**/entity/**/*.js',
|
|
330
|
+
'!**/node_modules/**',
|
|
331
|
+
'!**/test/**',
|
|
332
|
+
'!**/tests/**',
|
|
333
|
+
'!**/*.spec.ts',
|
|
334
|
+
'!**/*.test.ts',
|
|
335
|
+
'!**/*.spec.js',
|
|
336
|
+
'!**/*.test.js',
|
|
337
|
+
'!**/dist/**',
|
|
338
|
+
'!**/build/**'
|
|
339
|
+
];
|
|
324
340
|
try {
|
|
325
341
|
return globby
|
|
326
342
|
.sync(patterns, { cwd: projectRoot, gitignore: true, absolute: false })
|
|
@@ -75,11 +75,12 @@ async function withDatabase(arg1, arg2, arg3) {
|
|
|
75
75
|
const session = await createSession(targetOptions);
|
|
76
76
|
cachedSession = {
|
|
77
77
|
orm: session.orm,
|
|
78
|
-
tables: [],
|
|
79
78
|
schema: session.schema,
|
|
79
|
+
storage: session.storage,
|
|
80
80
|
};
|
|
81
81
|
sessionCache.set(cacheKey, cachedSession);
|
|
82
82
|
}
|
|
83
|
+
activateSession(cachedSession);
|
|
83
84
|
const context = buildContext(cachedSession.orm);
|
|
84
85
|
await dropAndRecreateSchema(context, cachedSession.schema);
|
|
85
86
|
await prepareSchema(context, cachedSession.schema);
|
|
@@ -89,8 +90,9 @@ async function withDatabase(arg1, arg2, arg3) {
|
|
|
89
90
|
async function createSession(options) {
|
|
90
91
|
const logger = selectLogger(options);
|
|
91
92
|
const orm = new orm_1.Orm(logger);
|
|
92
|
-
|
|
93
|
-
|
|
93
|
+
const storage = new entities_1.EntityStorage();
|
|
94
|
+
await initializeOrm(orm, storage, options);
|
|
95
|
+
return { orm, schema: options.schema ?? DEFAULT_SCHEMA, storage };
|
|
94
96
|
}
|
|
95
97
|
function selectLogger(options) {
|
|
96
98
|
if (options.logger) {
|
|
@@ -99,8 +101,7 @@ function selectLogger(options) {
|
|
|
99
101
|
const config = { applicationConfig: { logger: { level: 'info' } } };
|
|
100
102
|
return new core_1.LoggerService(config);
|
|
101
103
|
}
|
|
102
|
-
async function initializeOrm(orm, options) {
|
|
103
|
-
const storage = new entities_1.EntityStorage();
|
|
104
|
+
async function initializeOrm(orm, storage, options) {
|
|
104
105
|
if (options.entityFile) {
|
|
105
106
|
const entityFiles = await (0, globby_1.default)(options.entityFile, { absolute: true });
|
|
106
107
|
for (const file of entityFiles) {
|
|
@@ -111,6 +112,10 @@ async function initializeOrm(orm, options) {
|
|
|
111
112
|
const connection = resolveConnection(options.connection);
|
|
112
113
|
await service.onInit(connection);
|
|
113
114
|
}
|
|
115
|
+
function activateSession(session) {
|
|
116
|
+
orm_1.Orm.instance = session.orm;
|
|
117
|
+
entities_1.EntityStorage.instance = session.storage;
|
|
118
|
+
}
|
|
114
119
|
function resolveConnection(overrides) {
|
|
115
120
|
if (!overrides) {
|
|
116
121
|
return DEFAULT_CONNECTION;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cheetah.js/orm",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.141",
|
|
4
4
|
"description": "A simple ORM for Cheetah.js.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -55,5 +55,5 @@
|
|
|
55
55
|
"bun",
|
|
56
56
|
"value-object"
|
|
57
57
|
],
|
|
58
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "f3f3004bde2d552db43db3ac56b4d286bbfbc7f6"
|
|
59
59
|
}
|