metal-orm 1.0.42 → 1.0.43
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 +22 -7
- package/dist/index.cjs +130 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +121 -96
- package/dist/index.d.ts +121 -96
- package/dist/index.js +128 -74
- package/dist/index.js.map +1 -1
- package/package.json +8 -2
- package/scripts/run-eslint.mjs +34 -0
- package/src/codegen/typescript.ts +32 -15
- package/src/core/ast/builders.ts +7 -2
- package/src/core/ast/expression-builders.ts +0 -2
- package/src/core/ast/expression-nodes.ts +14 -5
- package/src/core/ast/expression-visitor.ts +11 -8
- package/src/core/ast/join-node.ts +1 -1
- package/src/core/ast/query.ts +6 -6
- package/src/core/ast/window-functions.ts +10 -2
- package/src/core/ddl/dialects/base-schema-dialect.ts +30 -3
- package/src/core/ddl/dialects/mssql-schema-dialect.ts +4 -0
- package/src/core/ddl/dialects/mysql-schema-dialect.ts +2 -0
- package/src/core/ddl/dialects/postgres-schema-dialect.ts +13 -1
- package/src/core/ddl/dialects/render-reference.test.ts +69 -0
- package/src/core/ddl/dialects/sqlite-schema-dialect.ts +9 -0
- package/src/core/ddl/introspect/mssql.ts +42 -8
- package/src/core/ddl/introspect/mysql.ts +30 -6
- package/src/core/ddl/introspect/postgres.ts +88 -34
- package/src/core/ddl/introspect/run-select.ts +6 -4
- package/src/core/ddl/introspect/sqlite.ts +56 -11
- package/src/core/ddl/introspect/types.ts +0 -1
- package/src/core/ddl/introspect/utils.ts +3 -3
- package/src/core/ddl/schema-dialect.ts +1 -0
- package/src/core/ddl/schema-generator.ts +4 -12
- package/src/core/ddl/sql-writing.ts +4 -4
- package/src/core/dialect/abstract.ts +18 -6
- package/src/core/dialect/base/function-table-formatter.ts +3 -2
- package/src/core/dialect/base/join-compiler.ts +5 -3
- package/src/core/dialect/base/returning-strategy.ts +1 -0
- package/src/core/dialect/base/sql-dialect.ts +3 -3
- package/src/core/dialect/mssql/functions.ts +24 -25
- package/src/core/dialect/mssql/index.ts +1 -4
- package/src/core/dialect/mysql/functions.ts +0 -1
- package/src/core/dialect/postgres/functions.ts +33 -34
- package/src/core/dialect/postgres/index.ts +1 -0
- package/src/core/dialect/sqlite/functions.ts +18 -19
- package/src/core/dialect/sqlite/index.ts +2 -0
- package/src/core/execution/db-executor.ts +1 -1
- package/src/core/execution/executors/mysql-executor.ts +2 -2
- package/src/core/execution/executors/postgres-executor.ts +1 -1
- package/src/core/execution/pooling/pool.ts +2 -0
- package/src/core/functions/datetime.ts +1 -1
- package/src/core/functions/numeric.ts +1 -1
- package/src/core/functions/text.ts +1 -1
- package/src/decorators/bootstrap.ts +27 -8
- package/src/decorators/column.ts +3 -11
- package/src/decorators/decorator-metadata.ts +3 -9
- package/src/decorators/entity.ts +21 -5
- package/src/decorators/relations.ts +2 -11
- package/src/orm/entity-context.ts +8 -8
- package/src/orm/entity-meta.ts +8 -8
- package/src/orm/entity-metadata.ts +11 -9
- package/src/orm/entity.ts +28 -29
- package/src/orm/execute.ts +4 -4
- package/src/orm/hydration.ts +42 -39
- package/src/orm/identity-map.ts +1 -1
- package/src/orm/lazy-batch.ts +9 -9
- package/src/orm/orm-session.ts +24 -23
- package/src/orm/orm.ts +2 -5
- package/src/orm/relation-change-processor.ts +12 -11
- package/src/orm/relations/belongs-to.ts +11 -11
- package/src/orm/relations/has-many.ts +10 -10
- package/src/orm/relations/has-one.ts +8 -7
- package/src/orm/relations/many-to-many.ts +13 -13
- package/src/orm/runtime-types.ts +4 -4
- package/src/orm/save-graph.ts +31 -25
- package/src/orm/unit-of-work.ts +17 -17
- package/src/query-builder/delete.ts +4 -3
- package/src/query-builder/hydration-manager.ts +6 -5
- package/src/query-builder/insert.ts +12 -8
- package/src/query-builder/query-ast-service.ts +2 -2
- package/src/query-builder/raw-column-parser.ts +2 -1
- package/src/query-builder/select-helpers.ts +2 -2
- package/src/query-builder/select.ts +31 -31
- package/src/query-builder/update.ts +4 -3
- package/src/schema/column.ts +26 -26
- package/src/schema/table.ts +47 -18
- package/src/schema/types.ts +22 -22
package/README.md
CHANGED
|
@@ -269,6 +269,7 @@ import {
|
|
|
269
269
|
eq,
|
|
270
270
|
count,
|
|
271
271
|
rowNumber,
|
|
272
|
+
MySqlDialect,
|
|
272
273
|
sel,
|
|
273
274
|
hydrateRows,
|
|
274
275
|
} from 'metal-orm';
|
|
@@ -298,18 +299,24 @@ users.columns.name.notNull = true;
|
|
|
298
299
|
users.columns.email.unique = true;
|
|
299
300
|
|
|
300
301
|
// Build a query with relation & window function
|
|
302
|
+
const u = sel(users, 'id', 'name', 'email');
|
|
303
|
+
const p = sel(posts, 'id', 'userId');
|
|
304
|
+
|
|
301
305
|
const builder = new SelectQueryBuilder(users)
|
|
302
306
|
.select({
|
|
303
|
-
...
|
|
304
|
-
postCount: count(
|
|
307
|
+
...u,
|
|
308
|
+
postCount: count(p.id),
|
|
305
309
|
rank: rowNumber(), // window function helper
|
|
306
310
|
})
|
|
307
|
-
.leftJoin(posts, eq(
|
|
308
|
-
.groupBy(
|
|
309
|
-
.
|
|
311
|
+
.leftJoin(posts, eq(p.userId, u.id))
|
|
312
|
+
.groupBy(u.id)
|
|
313
|
+
.groupBy(u.name)
|
|
314
|
+
.groupBy(u.email)
|
|
315
|
+
.orderBy(count(p.id), 'DESC')
|
|
310
316
|
.limit(10)
|
|
311
317
|
.includePick('posts', ['id', 'title', 'createdAt']); // eager relation for hydration
|
|
312
318
|
|
|
319
|
+
const dialect = new MySqlDialect();
|
|
313
320
|
const { sql, params } = builder.compile(dialect);
|
|
314
321
|
const [rows] = await connection.execute(sql, params);
|
|
315
322
|
|
|
@@ -353,6 +360,7 @@ import {
|
|
|
353
360
|
MySqlDialect,
|
|
354
361
|
SelectQueryBuilder,
|
|
355
362
|
eq,
|
|
363
|
+
tableRef,
|
|
356
364
|
createMysqlExecutor,
|
|
357
365
|
} from 'metal-orm';
|
|
358
366
|
|
|
@@ -365,16 +373,19 @@ const orm = new Orm({
|
|
|
365
373
|
executorFactory: {
|
|
366
374
|
createExecutor: () => executor,
|
|
367
375
|
createTransactionalExecutor: () => executor,
|
|
376
|
+
dispose: async () => {},
|
|
368
377
|
},
|
|
369
378
|
});
|
|
370
379
|
const session = new OrmSession({ orm, executor });
|
|
371
380
|
|
|
381
|
+
const u = tableRef(users);
|
|
382
|
+
|
|
372
383
|
// 2) Load entities with lazy relations
|
|
373
384
|
const [user] = await new SelectQueryBuilder(users)
|
|
374
385
|
.selectColumns('id', 'name', 'email')
|
|
375
386
|
.includeLazy('posts') // HasMany as a lazy collection
|
|
376
387
|
.includeLazy('roles') // BelongsToMany as a lazy collection
|
|
377
|
-
.where(eq(
|
|
388
|
+
.where(eq(u.id, 1))
|
|
378
389
|
.execute(session);
|
|
379
390
|
|
|
380
391
|
// user is an EntityInstance<typeof users>
|
|
@@ -422,6 +433,8 @@ import {
|
|
|
422
433
|
BelongsTo,
|
|
423
434
|
bootstrapEntities,
|
|
424
435
|
selectFromEntity,
|
|
436
|
+
entityRef,
|
|
437
|
+
eq,
|
|
425
438
|
} from 'metal-orm';
|
|
426
439
|
|
|
427
440
|
@Entity()
|
|
@@ -472,15 +485,17 @@ const orm = new Orm({
|
|
|
472
485
|
executorFactory: {
|
|
473
486
|
createExecutor: () => executor,
|
|
474
487
|
createTransactionalExecutor: () => executor,
|
|
488
|
+
dispose: async () => {},
|
|
475
489
|
},
|
|
476
490
|
});
|
|
477
491
|
const session = new OrmSession({ orm, executor });
|
|
478
492
|
|
|
479
493
|
// 3) Query starting from the entity class
|
|
494
|
+
const U = entityRef(User);
|
|
480
495
|
const [user] = await selectFromEntity(User)
|
|
481
496
|
.selectColumns('id', 'name')
|
|
482
497
|
.includeLazy('posts')
|
|
483
|
-
.where(
|
|
498
|
+
.where(eq(U.id, 1))
|
|
484
499
|
.execute(session);
|
|
485
500
|
|
|
486
501
|
user.posts.add({ title: 'From decorators' });
|
package/dist/index.cjs
CHANGED
|
@@ -127,6 +127,7 @@ __export(index_exports, {
|
|
|
127
127
|
diffSchema: () => diffSchema,
|
|
128
128
|
div: () => div,
|
|
129
129
|
endOfMonth: () => endOfMonth,
|
|
130
|
+
entityRef: () => entityRef,
|
|
130
131
|
eq: () => eq,
|
|
131
132
|
esel: () => esel,
|
|
132
133
|
executeHydrated: () => executeHydrated,
|
|
@@ -139,6 +140,7 @@ __export(index_exports, {
|
|
|
139
140
|
fromUnixTime: () => fromUnixTime,
|
|
140
141
|
generateCreateTableSql: () => generateCreateTableSql,
|
|
141
142
|
generateSchemaSql: () => generateSchemaSql,
|
|
143
|
+
getColumn: () => getColumn,
|
|
142
144
|
getSchemaIntrospector: () => getSchemaIntrospector,
|
|
143
145
|
getTableDefFromEntity: () => getTableDefFromEntity,
|
|
144
146
|
groupConcat: () => groupConcat,
|
|
@@ -247,7 +249,8 @@ module.exports = __toCommonJS(index_exports);
|
|
|
247
249
|
// src/schema/table.ts
|
|
248
250
|
var defineTable = (name, columns, relations = {}, hooks, options = {}) => {
|
|
249
251
|
const colsWithNames = Object.entries(columns).reduce((acc, [key, def]) => {
|
|
250
|
-
|
|
252
|
+
const colDef = { ...def, name: key, table: name };
|
|
253
|
+
acc[key] = colDef;
|
|
251
254
|
return acc;
|
|
252
255
|
}, {});
|
|
253
256
|
return {
|
|
@@ -271,17 +274,20 @@ var withColumnProps = (table) => {
|
|
|
271
274
|
if (cached) return cached;
|
|
272
275
|
const proxy = new Proxy(table, {
|
|
273
276
|
get(target, prop, receiver) {
|
|
274
|
-
|
|
277
|
+
const t = target;
|
|
278
|
+
if (prop === "$") return t.columns;
|
|
275
279
|
if (Reflect.has(target, prop)) return Reflect.get(target, prop, receiver);
|
|
276
|
-
if (typeof prop === "string" && prop in
|
|
280
|
+
if (typeof prop === "string" && prop in t.columns) return t.columns[prop];
|
|
277
281
|
return void 0;
|
|
278
282
|
},
|
|
279
283
|
has(target, prop) {
|
|
280
|
-
|
|
284
|
+
const t = target;
|
|
285
|
+
return prop === "$" || Reflect.has(target, prop) || typeof prop === "string" && prop in t.columns;
|
|
281
286
|
},
|
|
282
287
|
ownKeys(target) {
|
|
288
|
+
const t = target;
|
|
283
289
|
const base = Reflect.ownKeys(target);
|
|
284
|
-
const cols = Object.keys(
|
|
290
|
+
const cols = Object.keys(t.columns);
|
|
285
291
|
for (const k of cols) {
|
|
286
292
|
if (!base.includes(k)) base.push(k);
|
|
287
293
|
}
|
|
@@ -313,6 +319,14 @@ var withColumnProps = (table) => {
|
|
|
313
319
|
return proxy;
|
|
314
320
|
};
|
|
315
321
|
var tableRef = (table) => withColumnProps(table);
|
|
322
|
+
function getColumn(table, key) {
|
|
323
|
+
const col2 = table.columns[key];
|
|
324
|
+
if (!col2) {
|
|
325
|
+
const tableName = table.name || "<unknown>";
|
|
326
|
+
throw new Error(`Column '${key}' does not exist on table '${tableName}'`);
|
|
327
|
+
}
|
|
328
|
+
return col2;
|
|
329
|
+
}
|
|
316
330
|
|
|
317
331
|
// src/schema/column.ts
|
|
318
332
|
var col = {
|
|
@@ -517,10 +531,14 @@ var operandTypes = /* @__PURE__ */ new Set([
|
|
|
517
531
|
"CaseExpression",
|
|
518
532
|
"WindowFunction"
|
|
519
533
|
]);
|
|
520
|
-
var
|
|
521
|
-
var
|
|
522
|
-
|
|
523
|
-
|
|
534
|
+
var hasTypeProperty = (value) => typeof value === "object" && value !== null && "type" in value;
|
|
535
|
+
var isOperandNode = (node) => {
|
|
536
|
+
if (!hasTypeProperty(node)) return false;
|
|
537
|
+
return operandTypes.has(node.type);
|
|
538
|
+
};
|
|
539
|
+
var isFunctionNode = (node) => isOperandNode(node) && node.type === "Function";
|
|
540
|
+
var isCaseExpressionNode = (node) => isOperandNode(node) && node.type === "CaseExpression";
|
|
541
|
+
var isWindowFunctionNode = (node) => isOperandNode(node) && node.type === "WindowFunction";
|
|
524
542
|
var isExpressionSelectionNode = (node) => isFunctionNode(node) || isCaseExpressionNode(node) || isWindowFunctionNode(node);
|
|
525
543
|
|
|
526
544
|
// src/core/ast/expression-builders.ts
|
|
@@ -810,14 +828,15 @@ var registerOperandDispatcher = (type, dispatcher) => {
|
|
|
810
828
|
};
|
|
811
829
|
var clearExpressionDispatchers = () => expressionDispatchers.clear();
|
|
812
830
|
var clearOperandDispatchers = () => operandDispatchers.clear();
|
|
831
|
+
var getNodeType = (node) => typeof node === "object" && node !== null && typeof node.type === "string" ? node.type : void 0;
|
|
813
832
|
var unsupportedExpression = (node) => {
|
|
814
|
-
throw new Error(`Unsupported expression type "${node
|
|
833
|
+
throw new Error(`Unsupported expression type "${getNodeType(node) ?? "unknown"}"`);
|
|
815
834
|
};
|
|
816
835
|
var unsupportedOperand = (node) => {
|
|
817
|
-
throw new Error(`Unsupported operand type "${node
|
|
836
|
+
throw new Error(`Unsupported operand type "${getNodeType(node) ?? "unknown"}"`);
|
|
818
837
|
};
|
|
819
838
|
var visitExpression = (node, visitor) => {
|
|
820
|
-
const dynamic = expressionDispatchers.get(node
|
|
839
|
+
const dynamic = expressionDispatchers.get(node.type);
|
|
821
840
|
if (dynamic) return dynamic(node, visitor);
|
|
822
841
|
switch (node.type) {
|
|
823
842
|
case "BinaryExpression":
|
|
@@ -848,7 +867,7 @@ var visitExpression = (node, visitor) => {
|
|
|
848
867
|
return unsupportedExpression(node);
|
|
849
868
|
};
|
|
850
869
|
var visitOperand = (node, visitor) => {
|
|
851
|
-
const dynamic = operandDispatchers.get(node
|
|
870
|
+
const dynamic = operandDispatchers.get(node.type);
|
|
852
871
|
if (dynamic) return dynamic(node, visitor);
|
|
853
872
|
switch (node.type) {
|
|
854
873
|
case "Column":
|
|
@@ -1075,7 +1094,8 @@ var Dialect = class _Dialect {
|
|
|
1075
1094
|
if (!where) return "";
|
|
1076
1095
|
return ` WHERE ${this.compileExpression(where, ctx)}`;
|
|
1077
1096
|
}
|
|
1078
|
-
compileReturning(returning,
|
|
1097
|
+
compileReturning(returning, _ctx) {
|
|
1098
|
+
void _ctx;
|
|
1079
1099
|
if (!returning || returning.length === 0) return "";
|
|
1080
1100
|
throw new Error("RETURNING is not supported by this dialect.");
|
|
1081
1101
|
}
|
|
@@ -1123,14 +1143,16 @@ var Dialect = class _Dialect {
|
|
|
1123
1143
|
* @param index - Parameter index
|
|
1124
1144
|
* @returns Formatted placeholder string
|
|
1125
1145
|
*/
|
|
1126
|
-
formatPlaceholder(
|
|
1146
|
+
formatPlaceholder(_index) {
|
|
1147
|
+
void _index;
|
|
1127
1148
|
return "?";
|
|
1128
1149
|
}
|
|
1129
1150
|
/**
|
|
1130
1151
|
* Whether the current dialect supports a given set operation.
|
|
1131
1152
|
* Override in concrete dialects to restrict support.
|
|
1132
1153
|
*/
|
|
1133
|
-
supportsSetOperation(
|
|
1154
|
+
supportsSetOperation(_kind) {
|
|
1155
|
+
void _kind;
|
|
1134
1156
|
return true;
|
|
1135
1157
|
}
|
|
1136
1158
|
/**
|
|
@@ -1323,15 +1345,22 @@ var Dialect = class _Dialect {
|
|
|
1323
1345
|
}
|
|
1324
1346
|
registerDefaultOperandCompilers() {
|
|
1325
1347
|
this.registerOperandCompiler("Literal", (literal, ctx) => ctx.addParameter(literal.value));
|
|
1326
|
-
this.registerOperandCompiler("AliasRef", (alias, _ctx) =>
|
|
1348
|
+
this.registerOperandCompiler("AliasRef", (alias, _ctx) => {
|
|
1349
|
+
void _ctx;
|
|
1350
|
+
return this.quoteIdentifier(alias.name);
|
|
1351
|
+
});
|
|
1327
1352
|
this.registerOperandCompiler("Column", (column, _ctx) => {
|
|
1353
|
+
void _ctx;
|
|
1328
1354
|
return `${this.quoteIdentifier(column.table)}.${this.quoteIdentifier(column.name)}`;
|
|
1329
1355
|
});
|
|
1330
1356
|
this.registerOperandCompiler(
|
|
1331
1357
|
"Function",
|
|
1332
1358
|
(fnNode, ctx) => this.compileFunctionOperand(fnNode, ctx)
|
|
1333
1359
|
);
|
|
1334
|
-
this.registerOperandCompiler("JsonPath", (path, _ctx) =>
|
|
1360
|
+
this.registerOperandCompiler("JsonPath", (path, _ctx) => {
|
|
1361
|
+
void _ctx;
|
|
1362
|
+
return this.compileJsonPath(path);
|
|
1363
|
+
});
|
|
1335
1364
|
this.registerOperandCompiler("ScalarSubquery", (node, ctx) => {
|
|
1336
1365
|
const sql = this.compileSelectAst(node.query, ctx).trim().replace(/;$/, "");
|
|
1337
1366
|
return `(${sql})`;
|
|
@@ -1375,7 +1404,8 @@ var Dialect = class _Dialect {
|
|
|
1375
1404
|
});
|
|
1376
1405
|
}
|
|
1377
1406
|
// Default fallback, should be overridden by dialects if supported
|
|
1378
|
-
compileJsonPath(
|
|
1407
|
+
compileJsonPath(_node) {
|
|
1408
|
+
void _node;
|
|
1379
1409
|
throw new Error("JSON Path not supported by this dialect");
|
|
1380
1410
|
}
|
|
1381
1411
|
/**
|
|
@@ -1541,6 +1571,7 @@ var NoReturningStrategy = class {
|
|
|
1541
1571
|
* @throws Error indicating RETURNING is not supported.
|
|
1542
1572
|
*/
|
|
1543
1573
|
compileReturning(returning, _ctx) {
|
|
1574
|
+
void _ctx;
|
|
1544
1575
|
if (!returning || returning.length === 0) return "";
|
|
1545
1576
|
throw new Error("RETURNING is not supported by this dialect.");
|
|
1546
1577
|
}
|
|
@@ -1942,6 +1973,7 @@ var PostgresDialect = class extends SqlDialectBase {
|
|
|
1942
1973
|
return `${col2}->>'${node.path}'`;
|
|
1943
1974
|
}
|
|
1944
1975
|
compileReturning(returning, ctx) {
|
|
1976
|
+
void ctx;
|
|
1945
1977
|
if (!returning || returning.length === 0) return "";
|
|
1946
1978
|
const columns = this.formatReturningColumns(returning);
|
|
1947
1979
|
return ` RETURNING ${columns}`;
|
|
@@ -2192,9 +2224,11 @@ var SqliteDialect = class extends SqlDialectBase {
|
|
|
2192
2224
|
return `json_extract(${col2}, '${node.path}')`;
|
|
2193
2225
|
}
|
|
2194
2226
|
compileQualifiedColumn(column, _table) {
|
|
2227
|
+
void _table;
|
|
2195
2228
|
return this.quoteIdentifier(column.name);
|
|
2196
2229
|
}
|
|
2197
2230
|
compileReturning(returning, ctx) {
|
|
2231
|
+
void ctx;
|
|
2198
2232
|
if (!returning || returning.length === 0) return "";
|
|
2199
2233
|
const columns = this.formatReturningColumns(returning);
|
|
2200
2234
|
return ` RETURNING ${columns}`;
|
|
@@ -2847,7 +2881,8 @@ var HydrationManager = class _HydrationManager {
|
|
|
2847
2881
|
getProjectionNames(columns) {
|
|
2848
2882
|
const names = [];
|
|
2849
2883
|
for (const col2 of columns) {
|
|
2850
|
-
const
|
|
2884
|
+
const node = col2;
|
|
2885
|
+
const alias = node.alias ?? node.name;
|
|
2851
2886
|
if (!alias) return void 0;
|
|
2852
2887
|
names.push(alias);
|
|
2853
2888
|
}
|
|
@@ -3064,7 +3099,8 @@ var buildDefaultHydrationPlan = (table) => ({
|
|
|
3064
3099
|
// src/query-builder/raw-column-parser.ts
|
|
3065
3100
|
var parseRawColumn = (col2, tableName, ctes) => {
|
|
3066
3101
|
if (col2.includes("(")) {
|
|
3067
|
-
const [
|
|
3102
|
+
const [_fn, rest] = col2.split("(");
|
|
3103
|
+
void _fn;
|
|
3068
3104
|
const colName = rest.replace(")", "");
|
|
3069
3105
|
const [table, name] = colName.includes(".") ? colName.split(".") : [tableName, colName];
|
|
3070
3106
|
return { type: "Column", table, name, alias: col2 };
|
|
@@ -3264,7 +3300,7 @@ var QueryAstService = class {
|
|
|
3264
3300
|
normalizeOrderingTerm(term) {
|
|
3265
3301
|
const from = this.state.ast.from;
|
|
3266
3302
|
const tableRef2 = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
|
|
3267
|
-
const termType = term
|
|
3303
|
+
const termType = term.type;
|
|
3268
3304
|
if (termType === "Column") {
|
|
3269
3305
|
return term;
|
|
3270
3306
|
}
|
|
@@ -4264,7 +4300,6 @@ var DefaultManyToManyCollection = class {
|
|
|
4264
4300
|
}
|
|
4265
4301
|
async syncByIds(ids) {
|
|
4266
4302
|
await this.load();
|
|
4267
|
-
const targetKey = this.relation.targetKey || findPrimaryKey(this.relation.target);
|
|
4268
4303
|
const normalized = new Set(ids.map((id) => toKey5(id)));
|
|
4269
4304
|
const currentIds = new Set(this.items.map((item) => toKey5(this.extractId(item))));
|
|
4270
4305
|
for (const id of normalized) {
|
|
@@ -4535,7 +4570,6 @@ var createEntityProxy = (ctx, table, row, lazyRelations = []) => {
|
|
|
4535
4570
|
enumerable: false,
|
|
4536
4571
|
writable: false
|
|
4537
4572
|
});
|
|
4538
|
-
let proxy;
|
|
4539
4573
|
const handler = {
|
|
4540
4574
|
get(targetObj, prop, receiver) {
|
|
4541
4575
|
if (prop === ENTITY_META) {
|
|
@@ -4543,7 +4577,7 @@ var createEntityProxy = (ctx, table, row, lazyRelations = []) => {
|
|
|
4543
4577
|
}
|
|
4544
4578
|
if (prop === "$load") {
|
|
4545
4579
|
return async (relationName) => {
|
|
4546
|
-
const wrapper = getRelationWrapper(meta, relationName,
|
|
4580
|
+
const wrapper = getRelationWrapper(meta, relationName, receiver);
|
|
4547
4581
|
if (wrapper && typeof wrapper.load === "function") {
|
|
4548
4582
|
return wrapper.load();
|
|
4549
4583
|
}
|
|
@@ -4551,19 +4585,19 @@ var createEntityProxy = (ctx, table, row, lazyRelations = []) => {
|
|
|
4551
4585
|
};
|
|
4552
4586
|
}
|
|
4553
4587
|
if (typeof prop === "string" && table.relations[prop]) {
|
|
4554
|
-
return getRelationWrapper(meta, prop,
|
|
4588
|
+
return getRelationWrapper(meta, prop, receiver);
|
|
4555
4589
|
}
|
|
4556
4590
|
return Reflect.get(targetObj, prop, receiver);
|
|
4557
4591
|
},
|
|
4558
4592
|
set(targetObj, prop, value, receiver) {
|
|
4559
4593
|
const result = Reflect.set(targetObj, prop, value, receiver);
|
|
4560
4594
|
if (typeof prop === "string" && table.columns[prop]) {
|
|
4561
|
-
ctx.markDirty(
|
|
4595
|
+
ctx.markDirty(receiver);
|
|
4562
4596
|
}
|
|
4563
4597
|
return result;
|
|
4564
4598
|
}
|
|
4565
4599
|
};
|
|
4566
|
-
proxy = new Proxy(target, handler);
|
|
4600
|
+
const proxy = new Proxy(target, handler);
|
|
4567
4601
|
populateHydrationCache(proxy, row, meta);
|
|
4568
4602
|
return proxy;
|
|
4569
4603
|
};
|
|
@@ -4805,7 +4839,8 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4805
4839
|
return this.clone(nextContext);
|
|
4806
4840
|
}
|
|
4807
4841
|
resolveQueryNode(query) {
|
|
4808
|
-
|
|
4842
|
+
const candidate = query;
|
|
4843
|
+
return typeof candidate.getAST === "function" && candidate.getAST ? candidate.getAST() : query;
|
|
4809
4844
|
}
|
|
4810
4845
|
applyCorrelation(ast, correlation) {
|
|
4811
4846
|
if (!correlation) return ast;
|
|
@@ -5074,18 +5109,18 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
5074
5109
|
* Selects columns for the root table and relations from a single config object.
|
|
5075
5110
|
*/
|
|
5076
5111
|
selectColumnsDeep(config) {
|
|
5077
|
-
let
|
|
5112
|
+
let currBuilder = this;
|
|
5078
5113
|
if (config.root?.length) {
|
|
5079
|
-
|
|
5114
|
+
currBuilder = currBuilder.selectColumns(...config.root);
|
|
5080
5115
|
}
|
|
5081
5116
|
for (const key of Object.keys(config)) {
|
|
5082
5117
|
if (key === "root") continue;
|
|
5083
5118
|
const relName = key;
|
|
5084
5119
|
const cols = config[relName];
|
|
5085
5120
|
if (!cols || !cols.length) continue;
|
|
5086
|
-
|
|
5121
|
+
currBuilder = currBuilder.selectRelationColumns(relName, ...cols);
|
|
5087
5122
|
}
|
|
5088
|
-
return
|
|
5123
|
+
return currBuilder;
|
|
5089
5124
|
}
|
|
5090
5125
|
getLazyRelations() {
|
|
5091
5126
|
return Array.from(this.lazyRelations);
|
|
@@ -5520,6 +5555,13 @@ var selectFromEntity = (ctor) => {
|
|
|
5520
5555
|
}
|
|
5521
5556
|
return new SelectQueryBuilder(table);
|
|
5522
5557
|
};
|
|
5558
|
+
var entityRef = (ctor) => {
|
|
5559
|
+
const table = getTableDefFromEntity(ctor);
|
|
5560
|
+
if (!table) {
|
|
5561
|
+
throw new Error(`Entity '${ctor.name}' is not registered with decorators or has not been bootstrapped`);
|
|
5562
|
+
}
|
|
5563
|
+
return tableRef(table);
|
|
5564
|
+
};
|
|
5523
5565
|
|
|
5524
5566
|
// src/query-builder/select-helpers.ts
|
|
5525
5567
|
function sel(table, ...cols) {
|
|
@@ -5672,11 +5714,13 @@ var InsertQueryBuilder = class _InsertQueryBuilder {
|
|
|
5672
5714
|
return columns.map((column) => buildColumnNode(this.table, column));
|
|
5673
5715
|
}
|
|
5674
5716
|
resolveSelectQuery(query) {
|
|
5675
|
-
|
|
5717
|
+
const candidate = query;
|
|
5718
|
+
return typeof candidate.getAST === "function" && candidate.getAST ? candidate.getAST() : query;
|
|
5676
5719
|
}
|
|
5677
5720
|
compile(arg) {
|
|
5678
|
-
|
|
5679
|
-
|
|
5721
|
+
const candidate = arg;
|
|
5722
|
+
if (typeof candidate.compileInsert === "function") {
|
|
5723
|
+
return candidate.compileInsert(this.state.ast);
|
|
5680
5724
|
}
|
|
5681
5725
|
const dialect = resolveDialectInput(arg);
|
|
5682
5726
|
return dialect.compileInsert(this.state.ast);
|
|
@@ -5813,8 +5857,9 @@ var UpdateQueryBuilder = class _UpdateQueryBuilder {
|
|
|
5813
5857
|
return this.resolveTableSource(table);
|
|
5814
5858
|
}
|
|
5815
5859
|
compile(arg) {
|
|
5816
|
-
|
|
5817
|
-
|
|
5860
|
+
const candidate = arg;
|
|
5861
|
+
if (typeof candidate.compileUpdate === "function") {
|
|
5862
|
+
return candidate.compileUpdate(this.state.ast);
|
|
5818
5863
|
}
|
|
5819
5864
|
const dialect = resolveDialectInput(arg);
|
|
5820
5865
|
return dialect.compileUpdate(this.state.ast);
|
|
@@ -5915,8 +5960,9 @@ var DeleteQueryBuilder = class _DeleteQueryBuilder {
|
|
|
5915
5960
|
return this.resolveTableSource(table);
|
|
5916
5961
|
}
|
|
5917
5962
|
compile(arg) {
|
|
5918
|
-
|
|
5919
|
-
|
|
5963
|
+
const candidate = arg;
|
|
5964
|
+
if (typeof candidate.compileDelete === "function") {
|
|
5965
|
+
return candidate.compileDelete(this.state.ast);
|
|
5920
5966
|
}
|
|
5921
5967
|
const dialect = resolveDialectInput(arg);
|
|
5922
5968
|
return dialect.compileDelete(this.state.ast);
|
|
@@ -5966,7 +6012,7 @@ var generateCreateTableSql = (table, dialect) => {
|
|
|
5966
6012
|
const pk = resolvePrimaryKey(table);
|
|
5967
6013
|
const inlinePkColumns = /* @__PURE__ */ new Set();
|
|
5968
6014
|
const columnLines = Object.values(table.columns).map((col2) => {
|
|
5969
|
-
const includePk = dialect.preferInlinePkAutoincrement
|
|
6015
|
+
const includePk = dialect.preferInlinePkAutoincrement(col2, table, pk) && pk.includes(col2.name);
|
|
5970
6016
|
if (includePk) {
|
|
5971
6017
|
inlinePkColumns.add(col2.name);
|
|
5972
6018
|
}
|
|
@@ -6471,7 +6517,7 @@ var postgresIntrospector = {
|
|
|
6471
6517
|
],
|
|
6472
6518
|
where: and(
|
|
6473
6519
|
eq({ table: "ns", name: "nspname" }, schema),
|
|
6474
|
-
eq({ table: "i", name: "indisprimary" },
|
|
6520
|
+
eq({ table: "i", name: "indisprimary" }, false)
|
|
6475
6521
|
)
|
|
6476
6522
|
};
|
|
6477
6523
|
const indexQueryRows = await runSelectNode(indexQuery, ctx);
|
|
@@ -6635,6 +6681,14 @@ var mysqlIntrospector = {
|
|
|
6635
6681
|
};
|
|
6636
6682
|
|
|
6637
6683
|
// src/core/ddl/introspect/sqlite.ts
|
|
6684
|
+
var toReferentialAction = (value) => {
|
|
6685
|
+
if (!value) return void 0;
|
|
6686
|
+
const normalized = value.toUpperCase();
|
|
6687
|
+
if (normalized === "NO ACTION" || normalized === "RESTRICT" || normalized === "CASCADE" || normalized === "SET NULL" || normalized === "SET DEFAULT") {
|
|
6688
|
+
return normalized;
|
|
6689
|
+
}
|
|
6690
|
+
return void 0;
|
|
6691
|
+
};
|
|
6638
6692
|
var escapeSingleQuotes = (name) => name.replace(/'/g, "''");
|
|
6639
6693
|
var sqliteIntrospector = {
|
|
6640
6694
|
async introspect(ctx, options) {
|
|
@@ -6668,8 +6722,8 @@ var sqliteIntrospector = {
|
|
|
6668
6722
|
col2.references = {
|
|
6669
6723
|
table: fk.table,
|
|
6670
6724
|
column: fk.to,
|
|
6671
|
-
onDelete: fk.on_delete
|
|
6672
|
-
onUpdate: fk.on_update
|
|
6725
|
+
onDelete: toReferentialAction(fk.on_delete),
|
|
6726
|
+
onUpdate: toReferentialAction(fk.on_update)
|
|
6673
6727
|
};
|
|
6674
6728
|
}
|
|
6675
6729
|
});
|
|
@@ -7079,11 +7133,7 @@ var TypeScriptGenerator = class {
|
|
|
7079
7133
|
const lines = [];
|
|
7080
7134
|
const hydration = ast.meta?.hydration;
|
|
7081
7135
|
const hydratedRelations = new Set(hydration?.relations?.map((r) => r.name) ?? []);
|
|
7082
|
-
const selections = ast.columns.filter((col2) => !(hydration && isRelationAlias(col2.alias))).map((col2) => {
|
|
7083
|
-
const key = col2.alias || col2.name;
|
|
7084
|
-
const operand = col2;
|
|
7085
|
-
return `${key}: ${this.printOperand(operand)}`;
|
|
7086
|
-
});
|
|
7136
|
+
const selections = ast.columns.filter((col2) => !(hydration && isRelationAlias(col2.alias))).map((col2, index) => `${this.getSelectionKey(col2, index)}: ${this.printOperand(col2)}`);
|
|
7087
7137
|
lines.push(`db.select({`);
|
|
7088
7138
|
selections.forEach((sel2, index) => {
|
|
7089
7139
|
lines.push(` ${sel2}${index < selections.length - 1 ? "," : ""}`);
|
|
@@ -7171,7 +7221,7 @@ var TypeScriptGenerator = class {
|
|
|
7171
7221
|
* Prints an ordering term (operand/expression/alias) to TypeScript code.
|
|
7172
7222
|
*/
|
|
7173
7223
|
printOrderingTerm(term) {
|
|
7174
|
-
if (!term || !term
|
|
7224
|
+
if (!term || !("type" in term)) {
|
|
7175
7225
|
throw new Error("Unsupported ordering term");
|
|
7176
7226
|
}
|
|
7177
7227
|
switch (term.type) {
|
|
@@ -7190,6 +7240,18 @@ var TypeScriptGenerator = class {
|
|
|
7190
7240
|
return this.printExpression(term);
|
|
7191
7241
|
}
|
|
7192
7242
|
}
|
|
7243
|
+
getSelectionKey(selection, index) {
|
|
7244
|
+
if (selection.alias) {
|
|
7245
|
+
return selection.alias;
|
|
7246
|
+
}
|
|
7247
|
+
if (this.isNamedSelection(selection)) {
|
|
7248
|
+
return selection.name;
|
|
7249
|
+
}
|
|
7250
|
+
return `selection${index + 1}`;
|
|
7251
|
+
}
|
|
7252
|
+
isNamedSelection(selection) {
|
|
7253
|
+
return "name" in selection;
|
|
7254
|
+
}
|
|
7193
7255
|
visitBinaryExpression(binary) {
|
|
7194
7256
|
return this.printBinaryExpression(binary);
|
|
7195
7257
|
}
|
|
@@ -7973,6 +8035,7 @@ var RelationChangeProcessor = class {
|
|
|
7973
8035
|
* @param _entry - The relation change entry (reserved for future use)
|
|
7974
8036
|
*/
|
|
7975
8037
|
async handleBelongsToChange(_entry) {
|
|
8038
|
+
void _entry;
|
|
7976
8039
|
}
|
|
7977
8040
|
/**
|
|
7978
8041
|
* Handles changes for belongs-to-many relations.
|
|
@@ -8086,7 +8149,7 @@ var RelationChangeProcessor = class {
|
|
|
8086
8149
|
const key = findPrimaryKey(table);
|
|
8087
8150
|
const value = entity[key];
|
|
8088
8151
|
if (value === void 0 || value === null) return null;
|
|
8089
|
-
return value;
|
|
8152
|
+
return value ?? null;
|
|
8090
8153
|
}
|
|
8091
8154
|
};
|
|
8092
8155
|
|
|
@@ -8678,8 +8741,6 @@ var Orm = class {
|
|
|
8678
8741
|
const session = new OrmSession({ orm: this, executor });
|
|
8679
8742
|
try {
|
|
8680
8743
|
return await session.transaction(() => fn4(session));
|
|
8681
|
-
} catch (err) {
|
|
8682
|
-
throw err;
|
|
8683
8744
|
} finally {
|
|
8684
8745
|
await session.dispose();
|
|
8685
8746
|
}
|
|
@@ -8710,9 +8771,6 @@ var getOrCreateMetadataBag = (context) => {
|
|
|
8710
8771
|
var readMetadataBag = (context) => {
|
|
8711
8772
|
return context.metadata?.[METADATA_KEY];
|
|
8712
8773
|
};
|
|
8713
|
-
var registerInitializer = (context, initializer) => {
|
|
8714
|
-
context.addInitializer?.(initializer);
|
|
8715
|
-
};
|
|
8716
8774
|
|
|
8717
8775
|
// src/decorators/entity.ts
|
|
8718
8776
|
var toSnakeCase = (value) => {
|
|
@@ -8742,14 +8800,24 @@ function Entity(options = {}) {
|
|
|
8742
8800
|
if (bag) {
|
|
8743
8801
|
const meta = ensureEntityMetadata(ctor);
|
|
8744
8802
|
for (const entry of bag.columns) {
|
|
8745
|
-
if (
|
|
8746
|
-
|
|
8803
|
+
if (meta.columns[entry.propertyName]) {
|
|
8804
|
+
throw new Error(
|
|
8805
|
+
`Column '${entry.propertyName}' is already defined on entity '${ctor.name}'.`
|
|
8806
|
+
);
|
|
8747
8807
|
}
|
|
8808
|
+
addColumnMetadata(ctor, entry.propertyName, { ...entry.column });
|
|
8748
8809
|
}
|
|
8749
8810
|
for (const entry of bag.relations) {
|
|
8750
|
-
if (
|
|
8751
|
-
|
|
8811
|
+
if (meta.relations[entry.propertyName]) {
|
|
8812
|
+
throw new Error(
|
|
8813
|
+
`Relation '${entry.propertyName}' is already defined on entity '${ctor.name}'.`
|
|
8814
|
+
);
|
|
8752
8815
|
}
|
|
8816
|
+
const relationCopy = entry.relation.kind === RelationKinds.BelongsToMany ? {
|
|
8817
|
+
...entry.relation,
|
|
8818
|
+
defaultPivotColumns: entry.relation.defaultPivotColumns ? [...entry.relation.defaultPivotColumns] : void 0
|
|
8819
|
+
} : { ...entry.relation };
|
|
8820
|
+
addRelationMetadata(ctor, entry.propertyName, relationCopy);
|
|
8753
8821
|
}
|
|
8754
8822
|
}
|
|
8755
8823
|
}
|
|
@@ -8812,13 +8880,6 @@ var registerColumnFromContext = (context, column) => {
|
|
|
8812
8880
|
if (!bag.columns.some((entry) => entry.propertyName === propertyName)) {
|
|
8813
8881
|
bag.columns.push({ propertyName, column: { ...column } });
|
|
8814
8882
|
}
|
|
8815
|
-
registerInitializer(context, function() {
|
|
8816
|
-
const ctor = resolveConstructor(this);
|
|
8817
|
-
if (!ctor) {
|
|
8818
|
-
return;
|
|
8819
|
-
}
|
|
8820
|
-
registerColumn(ctor, propertyName, column);
|
|
8821
|
-
});
|
|
8822
8883
|
};
|
|
8823
8884
|
function Column(definition) {
|
|
8824
8885
|
const normalized = normalizeColumnInput(definition);
|
|
@@ -8874,13 +8935,6 @@ var createFieldDecorator = (metadataFactory) => {
|
|
|
8874
8935
|
if (!bag.relations.some((entry) => entry.propertyName === propertyName2)) {
|
|
8875
8936
|
bag.relations.push({ propertyName: propertyName2, relation: relationMetadata });
|
|
8876
8937
|
}
|
|
8877
|
-
registerInitializer(ctx, function() {
|
|
8878
|
-
const ctor2 = resolveConstructor2(this);
|
|
8879
|
-
if (!ctor2) {
|
|
8880
|
-
return;
|
|
8881
|
-
}
|
|
8882
|
-
registerRelation(ctor2, propertyName2, relationMetadata);
|
|
8883
|
-
});
|
|
8884
8938
|
return;
|
|
8885
8939
|
}
|
|
8886
8940
|
const propertyName = normalizePropertyName2(propertyKeyOrContext);
|
|
@@ -9546,6 +9600,7 @@ function createPooledExecutorFactory(opts) {
|
|
|
9546
9600
|
diffSchema,
|
|
9547
9601
|
div,
|
|
9548
9602
|
endOfMonth,
|
|
9603
|
+
entityRef,
|
|
9549
9604
|
eq,
|
|
9550
9605
|
esel,
|
|
9551
9606
|
executeHydrated,
|
|
@@ -9558,6 +9613,7 @@ function createPooledExecutorFactory(opts) {
|
|
|
9558
9613
|
fromUnixTime,
|
|
9559
9614
|
generateCreateTableSql,
|
|
9560
9615
|
generateSchemaSql,
|
|
9616
|
+
getColumn,
|
|
9561
9617
|
getSchemaIntrospector,
|
|
9562
9618
|
getTableDefFromEntity,
|
|
9563
9619
|
groupConcat,
|