metal-orm 1.0.40 → 1.0.42
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 +53 -14
- package/dist/index.cjs +1298 -126
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +676 -30
- package/dist/index.d.ts +676 -30
- package/dist/index.js +1293 -126
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/codegen/typescript.ts +6 -2
- package/src/core/ast/expression-builders.ts +25 -4
- package/src/core/ast/expression-nodes.ts +3 -1
- package/src/core/ast/expression.ts +2 -2
- package/src/core/ast/query.ts +24 -2
- package/src/core/dialect/abstract.ts +6 -2
- package/src/core/dialect/base/join-compiler.ts +9 -12
- package/src/core/dialect/base/sql-dialect.ts +98 -17
- package/src/core/dialect/mssql/index.ts +30 -62
- package/src/core/dialect/sqlite/index.ts +39 -34
- package/src/core/execution/db-executor.ts +46 -6
- package/src/core/execution/executors/mssql-executor.ts +39 -22
- package/src/core/execution/executors/mysql-executor.ts +23 -6
- package/src/core/execution/executors/sqlite-executor.ts +29 -3
- package/src/core/execution/pooling/pool-types.ts +30 -0
- package/src/core/execution/pooling/pool.ts +268 -0
- package/src/decorators/bootstrap.ts +7 -7
- package/src/index.ts +6 -0
- package/src/orm/domain-event-bus.ts +49 -0
- package/src/orm/entity-metadata.ts +9 -9
- package/src/orm/entity.ts +58 -0
- package/src/orm/orm-session.ts +465 -270
- package/src/orm/orm.ts +61 -11
- package/src/orm/pooled-executor-factory.ts +131 -0
- package/src/orm/query-logger.ts +6 -12
- package/src/orm/relation-change-processor.ts +75 -0
- package/src/orm/relations/many-to-many.ts +4 -2
- package/src/orm/save-graph.ts +303 -0
- package/src/orm/transaction-runner.ts +3 -3
- package/src/orm/unit-of-work.ts +128 -0
- package/src/query-builder/delete-query-state.ts +67 -38
- package/src/query-builder/delete.ts +37 -1
- package/src/query-builder/insert-query-state.ts +131 -61
- package/src/query-builder/insert.ts +27 -1
- package/src/query-builder/update-query-state.ts +114 -77
- package/src/query-builder/update.ts +38 -1
- package/src/schema/table.ts +210 -115
package/dist/index.js
CHANGED
|
@@ -50,6 +50,54 @@ var defineTable = (name, columns, relations = {}, hooks, options = {}) => {
|
|
|
50
50
|
collation: options.collation
|
|
51
51
|
};
|
|
52
52
|
};
|
|
53
|
+
var TABLE_REF_CACHE = /* @__PURE__ */ new WeakMap();
|
|
54
|
+
var withColumnProps = (table) => {
|
|
55
|
+
const cached = TABLE_REF_CACHE.get(table);
|
|
56
|
+
if (cached) return cached;
|
|
57
|
+
const proxy = new Proxy(table, {
|
|
58
|
+
get(target, prop, receiver) {
|
|
59
|
+
if (prop === "$") return target.columns;
|
|
60
|
+
if (Reflect.has(target, prop)) return Reflect.get(target, prop, receiver);
|
|
61
|
+
if (typeof prop === "string" && prop in target.columns) return target.columns[prop];
|
|
62
|
+
return void 0;
|
|
63
|
+
},
|
|
64
|
+
has(target, prop) {
|
|
65
|
+
return prop === "$" || Reflect.has(target, prop) || typeof prop === "string" && prop in target.columns;
|
|
66
|
+
},
|
|
67
|
+
ownKeys(target) {
|
|
68
|
+
const base = Reflect.ownKeys(target);
|
|
69
|
+
const cols = Object.keys(target.columns);
|
|
70
|
+
for (const k of cols) {
|
|
71
|
+
if (!base.includes(k)) base.push(k);
|
|
72
|
+
}
|
|
73
|
+
if (!base.includes("$")) base.push("$");
|
|
74
|
+
return base;
|
|
75
|
+
},
|
|
76
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
77
|
+
if (prop === "$") {
|
|
78
|
+
return {
|
|
79
|
+
configurable: true,
|
|
80
|
+
enumerable: false,
|
|
81
|
+
get() {
|
|
82
|
+
return target.columns;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (typeof prop === "string" && prop in target.columns && !Reflect.has(target, prop)) {
|
|
87
|
+
return {
|
|
88
|
+
configurable: true,
|
|
89
|
+
enumerable: true,
|
|
90
|
+
value: target.columns[prop],
|
|
91
|
+
writable: false
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return Reflect.getOwnPropertyDescriptor(target, prop);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
TABLE_REF_CACHE.set(table, proxy);
|
|
98
|
+
return proxy;
|
|
99
|
+
};
|
|
100
|
+
var tableRef = (table) => withColumnProps(table);
|
|
53
101
|
|
|
54
102
|
// src/schema/column.ts
|
|
55
103
|
var col = {
|
|
@@ -287,6 +335,12 @@ var toOperand = (val) => {
|
|
|
287
335
|
}
|
|
288
336
|
return toNode(val);
|
|
289
337
|
};
|
|
338
|
+
var hasQueryAst = (value) => typeof value.getAST === "function";
|
|
339
|
+
var resolveSelectQueryNode = (query) => hasQueryAst(query) ? query.getAST() : query;
|
|
340
|
+
var toScalarSubqueryNode = (query) => ({
|
|
341
|
+
type: "ScalarSubquery",
|
|
342
|
+
query: resolveSelectQueryNode(query)
|
|
343
|
+
});
|
|
290
344
|
var columnOperand = (col2) => toNode(col2);
|
|
291
345
|
var outerRef = (col2) => ({
|
|
292
346
|
...columnOperand(col2),
|
|
@@ -337,14 +391,16 @@ var isNotNull = (left2) => ({
|
|
|
337
391
|
left: toNode(left2),
|
|
338
392
|
operator: "IS NOT NULL"
|
|
339
393
|
});
|
|
340
|
-
var createInExpression = (operator, left2,
|
|
394
|
+
var createInExpression = (operator, left2, right2) => ({
|
|
341
395
|
type: "InExpression",
|
|
342
396
|
left: toNode(left2),
|
|
343
397
|
operator,
|
|
344
|
-
right:
|
|
398
|
+
right: right2
|
|
345
399
|
});
|
|
346
|
-
var inList = (left2, values) => createInExpression("IN", left2, values);
|
|
347
|
-
var notInList = (left2, values) => createInExpression("NOT IN", left2, values);
|
|
400
|
+
var inList = (left2, values) => createInExpression("IN", left2, values.map((v) => toOperand(v)));
|
|
401
|
+
var notInList = (left2, values) => createInExpression("NOT IN", left2, values.map((v) => toOperand(v)));
|
|
402
|
+
var inSubquery = (left2, subquery) => createInExpression("IN", left2, toScalarSubqueryNode(subquery));
|
|
403
|
+
var notInSubquery = (left2, subquery) => createInExpression("NOT IN", left2, toScalarSubqueryNode(subquery));
|
|
348
404
|
var createBetweenExpression = (operator, left2, lower2, upper2) => ({
|
|
349
405
|
type: "BetweenExpression",
|
|
350
406
|
left: toNode(left2),
|
|
@@ -1027,8 +1083,12 @@ var Dialect = class _Dialect {
|
|
|
1027
1083
|
});
|
|
1028
1084
|
this.registerExpressionCompiler("InExpression", (inExpr, ctx) => {
|
|
1029
1085
|
const left2 = this.compileOperand(inExpr.left, ctx);
|
|
1030
|
-
|
|
1031
|
-
|
|
1086
|
+
if (Array.isArray(inExpr.right)) {
|
|
1087
|
+
const values = inExpr.right.map((v) => this.compileOperand(v, ctx)).join(", ");
|
|
1088
|
+
return `${left2} ${inExpr.operator} (${values})`;
|
|
1089
|
+
}
|
|
1090
|
+
const subquerySql = this.compileSelectAst(inExpr.right.query, ctx).trim().replace(/;$/, "");
|
|
1091
|
+
return `${left2} ${inExpr.operator} (${subquerySql})`;
|
|
1032
1092
|
});
|
|
1033
1093
|
this.registerExpressionCompiler("ExistsExpression", (existsExpr, ctx) => {
|
|
1034
1094
|
const subquerySql = this.compileSelectForExists(existsExpr.subquery, ctx);
|
|
@@ -1286,17 +1346,9 @@ var NoReturningStrategy = class {
|
|
|
1286
1346
|
|
|
1287
1347
|
// src/core/dialect/base/join-compiler.ts
|
|
1288
1348
|
var JoinCompiler = class {
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
* @param ctx - The compiler context for expression compilation.
|
|
1293
|
-
* @param compileFrom - Function to compile table sources (tables or subqueries).
|
|
1294
|
-
* @param compileExpression - Function to compile join condition expressions.
|
|
1295
|
-
* @returns SQL JOIN clauses (e.g., " LEFT JOIN table ON condition") or empty string if no joins.
|
|
1296
|
-
*/
|
|
1297
|
-
static compileJoins(ast, ctx, compileFrom, compileExpression) {
|
|
1298
|
-
if (!ast.joins || ast.joins.length === 0) return "";
|
|
1299
|
-
const parts = ast.joins.map((j) => {
|
|
1349
|
+
static compileJoins(joins, ctx, compileFrom, compileExpression) {
|
|
1350
|
+
if (!joins || joins.length === 0) return "";
|
|
1351
|
+
const parts = joins.map((j) => {
|
|
1300
1352
|
const table = compileFrom(j.table, ctx);
|
|
1301
1353
|
const cond = compileExpression(j.condition, ctx);
|
|
1302
1354
|
return `${j.kind} JOIN ${table} ON ${cond}`;
|
|
@@ -1379,25 +1431,41 @@ var SqlDialectBase = class extends Dialect {
|
|
|
1379
1431
|
return `${ctes}${combined}${orderBy}${pagination}`;
|
|
1380
1432
|
}
|
|
1381
1433
|
compileInsertAst(ast, ctx) {
|
|
1434
|
+
if (!ast.columns.length) {
|
|
1435
|
+
throw new Error("INSERT queries must specify columns.");
|
|
1436
|
+
}
|
|
1382
1437
|
const table = this.compileTableName(ast.into);
|
|
1383
1438
|
const columnList = this.compileInsertColumnList(ast.columns);
|
|
1384
|
-
const
|
|
1439
|
+
const source = this.compileInsertSource(ast.source, ctx);
|
|
1385
1440
|
const returning = this.compileReturning(ast.returning, ctx);
|
|
1386
|
-
return `INSERT INTO ${table} (${columnList})
|
|
1441
|
+
return `INSERT INTO ${table} (${columnList}) ${source}${returning}`;
|
|
1387
1442
|
}
|
|
1388
1443
|
compileReturning(returning, ctx) {
|
|
1389
1444
|
return this.returningStrategy.compileReturning(returning, ctx);
|
|
1390
1445
|
}
|
|
1446
|
+
compileInsertSource(source, ctx) {
|
|
1447
|
+
if (source.type === "InsertValues") {
|
|
1448
|
+
if (!source.rows.length) {
|
|
1449
|
+
throw new Error("INSERT ... VALUES requires at least one row.");
|
|
1450
|
+
}
|
|
1451
|
+
const values = source.rows.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
|
|
1452
|
+
return `VALUES ${values}`;
|
|
1453
|
+
}
|
|
1454
|
+
const normalized = this.normalizeSelectAst(source.query);
|
|
1455
|
+
return this.compileSelectAst(normalized, ctx).trim();
|
|
1456
|
+
}
|
|
1391
1457
|
compileInsertColumnList(columns) {
|
|
1392
1458
|
return columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
|
|
1393
1459
|
}
|
|
1394
|
-
compileInsertValues(values, ctx) {
|
|
1395
|
-
return values.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
|
|
1396
|
-
}
|
|
1397
1460
|
compileSelectCore(ast, ctx) {
|
|
1398
1461
|
const columns = this.compileSelectColumns(ast, ctx);
|
|
1399
1462
|
const from = this.compileFrom(ast.from, ctx);
|
|
1400
|
-
const joins = JoinCompiler.compileJoins(
|
|
1463
|
+
const joins = JoinCompiler.compileJoins(
|
|
1464
|
+
ast.joins,
|
|
1465
|
+
ctx,
|
|
1466
|
+
this.compileFrom.bind(this),
|
|
1467
|
+
this.compileExpression.bind(this)
|
|
1468
|
+
);
|
|
1401
1469
|
const whereClause = this.compileWhere(ast.where, ctx);
|
|
1402
1470
|
const groupBy = GroupByCompiler.compileGroupBy(ast, (term) => this.compileOrderingTerm(term, ctx));
|
|
1403
1471
|
const having = this.compileHaving(ast, ctx);
|
|
@@ -1411,25 +1479,37 @@ var SqlDialectBase = class extends Dialect {
|
|
|
1411
1479
|
return `SELECT ${this.compileDistinct(ast)}${columns} FROM ${from}${joins}${whereClause}${groupBy}${having}${orderBy}${pagination}`;
|
|
1412
1480
|
}
|
|
1413
1481
|
compileUpdateAst(ast, ctx) {
|
|
1414
|
-
const
|
|
1415
|
-
const assignments = this.compileUpdateAssignments(ast.set, ctx);
|
|
1482
|
+
const target = this.compileTableReference(ast.table);
|
|
1483
|
+
const assignments = this.compileUpdateAssignments(ast.set, ast.table, ctx);
|
|
1484
|
+
const fromClause = this.compileUpdateFromClause(ast, ctx);
|
|
1416
1485
|
const whereClause = this.compileWhere(ast.where, ctx);
|
|
1417
1486
|
const returning = this.compileReturning(ast.returning, ctx);
|
|
1418
|
-
return `UPDATE ${
|
|
1487
|
+
return `UPDATE ${target} SET ${assignments}${fromClause}${whereClause}${returning}`;
|
|
1419
1488
|
}
|
|
1420
|
-
compileUpdateAssignments(assignments, ctx) {
|
|
1489
|
+
compileUpdateAssignments(assignments, table, ctx) {
|
|
1421
1490
|
return assignments.map((assignment) => {
|
|
1422
1491
|
const col2 = assignment.column;
|
|
1423
|
-
const target = this.
|
|
1492
|
+
const target = this.compileQualifiedColumn(col2, table);
|
|
1424
1493
|
const value = this.compileOperand(assignment.value, ctx);
|
|
1425
1494
|
return `${target} = ${value}`;
|
|
1426
1495
|
}).join(", ");
|
|
1427
1496
|
}
|
|
1497
|
+
compileQualifiedColumn(column, table) {
|
|
1498
|
+
const baseTableName = table.name;
|
|
1499
|
+
const alias = table.alias;
|
|
1500
|
+
const columnTable = column.table ?? alias ?? baseTableName;
|
|
1501
|
+
const tableQualifier = alias && column.table === baseTableName ? alias : columnTable;
|
|
1502
|
+
if (!tableQualifier) {
|
|
1503
|
+
return this.quoteIdentifier(column.name);
|
|
1504
|
+
}
|
|
1505
|
+
return `${this.quoteIdentifier(tableQualifier)}.${this.quoteIdentifier(column.name)}`;
|
|
1506
|
+
}
|
|
1428
1507
|
compileDeleteAst(ast, ctx) {
|
|
1429
|
-
const
|
|
1508
|
+
const target = this.compileTableReference(ast.from);
|
|
1509
|
+
const usingClause = this.compileDeleteUsingClause(ast, ctx);
|
|
1430
1510
|
const whereClause = this.compileWhere(ast.where, ctx);
|
|
1431
1511
|
const returning = this.compileReturning(ast.returning, ctx);
|
|
1432
|
-
return `DELETE FROM ${
|
|
1512
|
+
return `DELETE FROM ${target}${usingClause}${whereClause}${returning}`;
|
|
1433
1513
|
}
|
|
1434
1514
|
formatReturningColumns(returning) {
|
|
1435
1515
|
return this.returningStrategy.formatReturningColumns(returning, this.quoteIdentifier.bind(this));
|
|
@@ -1484,6 +1564,38 @@ var SqlDialectBase = class extends Dialect {
|
|
|
1484
1564
|
}
|
|
1485
1565
|
return this.quoteIdentifier(table.name);
|
|
1486
1566
|
}
|
|
1567
|
+
compileTableReference(table) {
|
|
1568
|
+
const base = this.compileTableName(table);
|
|
1569
|
+
return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
|
|
1570
|
+
}
|
|
1571
|
+
compileUpdateFromClause(ast, ctx) {
|
|
1572
|
+
if (!ast.from && (!ast.joins || ast.joins.length === 0)) return "";
|
|
1573
|
+
if (!ast.from) {
|
|
1574
|
+
throw new Error("UPDATE with JOINs requires an explicit FROM clause.");
|
|
1575
|
+
}
|
|
1576
|
+
const from = this.compileFrom(ast.from, ctx);
|
|
1577
|
+
const joins = JoinCompiler.compileJoins(
|
|
1578
|
+
ast.joins,
|
|
1579
|
+
ctx,
|
|
1580
|
+
this.compileFrom.bind(this),
|
|
1581
|
+
this.compileExpression.bind(this)
|
|
1582
|
+
);
|
|
1583
|
+
return ` FROM ${from}${joins}`;
|
|
1584
|
+
}
|
|
1585
|
+
compileDeleteUsingClause(ast, ctx) {
|
|
1586
|
+
if (!ast.using && (!ast.joins || ast.joins.length === 0)) return "";
|
|
1587
|
+
if (!ast.using) {
|
|
1588
|
+
throw new Error("DELETE with JOINs requires a USING clause.");
|
|
1589
|
+
}
|
|
1590
|
+
const usingTable = this.compileFrom(ast.using, ctx);
|
|
1591
|
+
const joins = JoinCompiler.compileJoins(
|
|
1592
|
+
ast.joins,
|
|
1593
|
+
ctx,
|
|
1594
|
+
this.compileFrom.bind(this),
|
|
1595
|
+
this.compileExpression.bind(this)
|
|
1596
|
+
);
|
|
1597
|
+
return ` USING ${usingTable}${joins}`;
|
|
1598
|
+
}
|
|
1487
1599
|
compileHaving(ast, ctx) {
|
|
1488
1600
|
if (!ast.having) return "";
|
|
1489
1601
|
return ` HAVING ${this.compileExpression(ast.having, ctx)}`;
|
|
@@ -1864,6 +1976,9 @@ var SqliteDialect = class extends SqlDialectBase {
|
|
|
1864
1976
|
const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
|
|
1865
1977
|
return `json_extract(${col2}, '${node.path}')`;
|
|
1866
1978
|
}
|
|
1979
|
+
compileQualifiedColumn(column, _table) {
|
|
1980
|
+
return this.quoteIdentifier(column.name);
|
|
1981
|
+
}
|
|
1867
1982
|
compileReturning(returning, ctx) {
|
|
1868
1983
|
if (!returning || returning.length === 0) return "";
|
|
1869
1984
|
const columns = this.formatReturningColumns(returning);
|
|
@@ -1969,7 +2084,7 @@ var MssqlFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
1969
2084
|
};
|
|
1970
2085
|
|
|
1971
2086
|
// src/core/dialect/mssql/index.ts
|
|
1972
|
-
var SqlServerDialect = class extends
|
|
2087
|
+
var SqlServerDialect = class extends SqlDialectBase {
|
|
1973
2088
|
/**
|
|
1974
2089
|
* Creates a new SqlServerDialect instance
|
|
1975
2090
|
*/
|
|
@@ -2012,7 +2127,7 @@ var SqlServerDialect = class extends Dialect {
|
|
|
2012
2127
|
const hasSetOps = !!(ast.setOps && ast.setOps.length);
|
|
2013
2128
|
const ctes = this.compileCtes(ast, ctx);
|
|
2014
2129
|
const baseAst = hasSetOps ? { ...ast, setOps: void 0, orderBy: void 0, limit: void 0, offset: void 0 } : ast;
|
|
2015
|
-
const baseSelect = this.
|
|
2130
|
+
const baseSelect = this.compileSelectCoreForMssql(baseAst, ctx);
|
|
2016
2131
|
if (!hasSetOps) {
|
|
2017
2132
|
return `${ctes}${baseSelect}`;
|
|
2018
2133
|
}
|
|
@@ -2023,32 +2138,26 @@ var SqlServerDialect = class extends Dialect {
|
|
|
2023
2138
|
const tail = pagination || orderBy;
|
|
2024
2139
|
return `${ctes}${combined}${tail}`;
|
|
2025
2140
|
}
|
|
2026
|
-
compileInsertAst(ast, ctx) {
|
|
2027
|
-
const table = this.quoteIdentifier(ast.into.name);
|
|
2028
|
-
const columnList = ast.columns.map((column) => `${this.quoteIdentifier(column.table)}.${this.quoteIdentifier(column.name)}`).join(", ");
|
|
2029
|
-
const values = ast.values.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
|
|
2030
|
-
return `INSERT INTO ${table} (${columnList}) VALUES ${values};`;
|
|
2031
|
-
}
|
|
2032
|
-
compileUpdateAst(ast, ctx) {
|
|
2033
|
-
const table = this.quoteIdentifier(ast.table.name);
|
|
2034
|
-
const assignments = ast.set.map((assignment) => {
|
|
2035
|
-
const col2 = assignment.column;
|
|
2036
|
-
const target = `${this.quoteIdentifier(col2.table)}.${this.quoteIdentifier(col2.name)}`;
|
|
2037
|
-
const value = this.compileOperand(assignment.value, ctx);
|
|
2038
|
-
return `${target} = ${value}`;
|
|
2039
|
-
}).join(", ");
|
|
2040
|
-
const whereClause = this.compileWhere(ast.where, ctx);
|
|
2041
|
-
return `UPDATE ${table} SET ${assignments}${whereClause};`;
|
|
2042
|
-
}
|
|
2043
2141
|
compileDeleteAst(ast, ctx) {
|
|
2142
|
+
if (ast.using) {
|
|
2143
|
+
throw new Error("DELETE ... USING is not supported in the MSSQL dialect; use join() instead.");
|
|
2144
|
+
}
|
|
2044
2145
|
if (ast.from.type !== "Table") {
|
|
2045
2146
|
throw new Error("DELETE only supports base tables in the MSSQL dialect.");
|
|
2046
2147
|
}
|
|
2047
|
-
const
|
|
2148
|
+
const alias = ast.from.alias ?? ast.from.name;
|
|
2149
|
+
const target = this.compileTableReference(ast.from);
|
|
2150
|
+
const joins = JoinCompiler.compileJoins(
|
|
2151
|
+
ast.joins,
|
|
2152
|
+
ctx,
|
|
2153
|
+
this.compileFrom.bind(this),
|
|
2154
|
+
this.compileExpression.bind(this)
|
|
2155
|
+
);
|
|
2048
2156
|
const whereClause = this.compileWhere(ast.where, ctx);
|
|
2049
|
-
|
|
2157
|
+
const returning = this.compileReturning(ast.returning, ctx);
|
|
2158
|
+
return `DELETE ${this.quoteIdentifier(alias)} FROM ${target}${joins}${whereClause}${returning}`;
|
|
2050
2159
|
}
|
|
2051
|
-
|
|
2160
|
+
compileSelectCoreForMssql(ast, ctx) {
|
|
2052
2161
|
const columns = ast.columns.map((c) => {
|
|
2053
2162
|
let expr = "";
|
|
2054
2163
|
if (c.type === "Function") {
|
|
@@ -2067,9 +2176,9 @@ var SqlServerDialect = class extends Dialect {
|
|
|
2067
2176
|
return expr;
|
|
2068
2177
|
}).join(", ");
|
|
2069
2178
|
const distinct = ast.distinct ? "DISTINCT " : "";
|
|
2070
|
-
const from = this.compileTableSource(ast.from
|
|
2179
|
+
const from = this.compileTableSource(ast.from);
|
|
2071
2180
|
const joins = ast.joins.map((j) => {
|
|
2072
|
-
const table = this.compileTableSource(j.table
|
|
2181
|
+
const table = this.compileTableSource(j.table);
|
|
2073
2182
|
const cond = this.compileExpression(j.condition, ctx);
|
|
2074
2183
|
return `${j.kind} JOIN ${table} ON ${cond}`;
|
|
2075
2184
|
}).join(" ");
|
|
@@ -2103,27 +2212,6 @@ var SqlServerDialect = class extends Dialect {
|
|
|
2103
2212
|
}
|
|
2104
2213
|
return pagination;
|
|
2105
2214
|
}
|
|
2106
|
-
renderOrderByNulls(order) {
|
|
2107
|
-
return order.nulls ? ` NULLS ${order.nulls}` : "";
|
|
2108
|
-
}
|
|
2109
|
-
renderOrderByCollation(order) {
|
|
2110
|
-
return order.collation ? ` COLLATE ${order.collation}` : "";
|
|
2111
|
-
}
|
|
2112
|
-
compileTableSource(table, ctx) {
|
|
2113
|
-
if (table.type === "FunctionTable") {
|
|
2114
|
-
return FunctionTableFormatter.format(table, ctx, this);
|
|
2115
|
-
}
|
|
2116
|
-
if (table.type === "DerivedTable") {
|
|
2117
|
-
return this.compileDerivedTable(table, ctx);
|
|
2118
|
-
}
|
|
2119
|
-
const base = table.schema ? `${this.quoteIdentifier(table.schema)}.${this.quoteIdentifier(table.name)}` : this.quoteIdentifier(table.name);
|
|
2120
|
-
return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
|
|
2121
|
-
}
|
|
2122
|
-
compileDerivedTable(table, ctx) {
|
|
2123
|
-
const sub2 = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
|
|
2124
|
-
const cols = table.columnAliases?.length ? ` (${table.columnAliases.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
|
|
2125
|
-
return `(${sub2}) AS ${this.quoteIdentifier(table.alias)}${cols}`;
|
|
2126
|
-
}
|
|
2127
2215
|
compileCtes(ast, ctx) {
|
|
2128
2216
|
if (!ast.ctes || ast.ctes.length === 0) return "";
|
|
2129
2217
|
const defs = ast.ctes.map((cte) => {
|
|
@@ -2134,10 +2222,6 @@ var SqlServerDialect = class extends Dialect {
|
|
|
2134
2222
|
}).join(", ");
|
|
2135
2223
|
return `WITH ${defs} `;
|
|
2136
2224
|
}
|
|
2137
|
-
wrapSetOperand(sql) {
|
|
2138
|
-
const trimmed = sql.trim().replace(/;$/, "");
|
|
2139
|
-
return `(${trimmed})`;
|
|
2140
|
-
}
|
|
2141
2225
|
};
|
|
2142
2226
|
|
|
2143
2227
|
// src/core/dialect/dialect-factory.ts
|
|
@@ -2964,7 +3048,7 @@ var QueryAstService = class {
|
|
|
2964
3048
|
}
|
|
2965
3049
|
normalizeOrderingTerm(term) {
|
|
2966
3050
|
const from = this.state.ast.from;
|
|
2967
|
-
const
|
|
3051
|
+
const tableRef2 = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
|
|
2968
3052
|
const termType = term?.type;
|
|
2969
3053
|
if (termType === "Column") {
|
|
2970
3054
|
return term;
|
|
@@ -2978,7 +3062,7 @@ var QueryAstService = class {
|
|
|
2978
3062
|
if (termType === "BinaryExpression" || termType === "LogicalExpression" || termType === "NullExpression" || termType === "InExpression" || termType === "ExistsExpression" || termType === "BetweenExpression" || termType === "ArithmeticExpression") {
|
|
2979
3063
|
return term;
|
|
2980
3064
|
}
|
|
2981
|
-
return buildColumnNode(
|
|
3065
|
+
return buildColumnNode(tableRef2, term);
|
|
2982
3066
|
}
|
|
2983
3067
|
};
|
|
2984
3068
|
|
|
@@ -3384,8 +3468,8 @@ var ColumnSelector = class {
|
|
|
3384
3468
|
*/
|
|
3385
3469
|
distinct(context, columns) {
|
|
3386
3470
|
const from = context.state.ast.from;
|
|
3387
|
-
const
|
|
3388
|
-
const nodes = columns.map((col2) => buildColumnNode(
|
|
3471
|
+
const tableRef2 = from.type === "Table" && from.alias ? { ...this.env.table, alias: from.alias } : this.env.table;
|
|
3472
|
+
const nodes = columns.map((col2) => buildColumnNode(tableRef2, col2));
|
|
3389
3473
|
const astService = this.env.deps.createQueryAstService(this.env.table, context.state);
|
|
3390
3474
|
const nextState = astService.withDistinct(nodes);
|
|
3391
3475
|
return { state: nextState, hydration: context.hydration };
|
|
@@ -3932,8 +4016,10 @@ var DefaultManyToManyCollection = class {
|
|
|
3932
4016
|
attach(target) {
|
|
3933
4017
|
const entity = this.ensureEntity(target);
|
|
3934
4018
|
const id = this.extractId(entity);
|
|
3935
|
-
if (id
|
|
3936
|
-
|
|
4019
|
+
if (id != null && this.items.some((item) => this.extractId(item) === id)) {
|
|
4020
|
+
return;
|
|
4021
|
+
}
|
|
4022
|
+
if (id == null && this.items.includes(entity)) {
|
|
3937
4023
|
return;
|
|
3938
4024
|
}
|
|
3939
4025
|
this.items.push(entity);
|
|
@@ -5256,15 +5342,36 @@ var InsertQueryState = class _InsertQueryState {
|
|
|
5256
5342
|
type: "InsertQuery",
|
|
5257
5343
|
into: createTableNode(table),
|
|
5258
5344
|
columns: [],
|
|
5259
|
-
|
|
5345
|
+
source: {
|
|
5346
|
+
type: "InsertValues",
|
|
5347
|
+
rows: []
|
|
5348
|
+
}
|
|
5260
5349
|
};
|
|
5261
5350
|
}
|
|
5262
5351
|
clone(nextAst) {
|
|
5263
5352
|
return new _InsertQueryState(this.table, nextAst);
|
|
5264
5353
|
}
|
|
5354
|
+
ensureColumnsFromRow(rows) {
|
|
5355
|
+
if (this.ast.columns.length) return this.ast.columns;
|
|
5356
|
+
return buildColumnNodes(this.table, Object.keys(rows[0]));
|
|
5357
|
+
}
|
|
5358
|
+
appendValues(rows) {
|
|
5359
|
+
if (this.ast.source.type === "InsertValues") {
|
|
5360
|
+
return [...this.ast.source.rows, ...rows];
|
|
5361
|
+
}
|
|
5362
|
+
return rows;
|
|
5363
|
+
}
|
|
5364
|
+
getTableColumns() {
|
|
5365
|
+
const names = Object.keys(this.table.columns);
|
|
5366
|
+
if (!names.length) return [];
|
|
5367
|
+
return buildColumnNodes(this.table, names);
|
|
5368
|
+
}
|
|
5265
5369
|
withValues(rows) {
|
|
5266
5370
|
if (!rows.length) return this;
|
|
5267
|
-
|
|
5371
|
+
if (this.ast.source.type === "InsertSelect") {
|
|
5372
|
+
throw new Error("Cannot mix INSERT ... VALUES with INSERT ... SELECT source.");
|
|
5373
|
+
}
|
|
5374
|
+
const definedColumns = this.ensureColumnsFromRow(rows);
|
|
5268
5375
|
const newRows = rows.map(
|
|
5269
5376
|
(row, rowIndex) => definedColumns.map((column) => {
|
|
5270
5377
|
const rawValue = row[column.name];
|
|
@@ -5279,7 +5386,34 @@ var InsertQueryState = class _InsertQueryState {
|
|
|
5279
5386
|
return this.clone({
|
|
5280
5387
|
...this.ast,
|
|
5281
5388
|
columns: definedColumns,
|
|
5282
|
-
|
|
5389
|
+
source: {
|
|
5390
|
+
type: "InsertValues",
|
|
5391
|
+
rows: this.appendValues(newRows)
|
|
5392
|
+
}
|
|
5393
|
+
});
|
|
5394
|
+
}
|
|
5395
|
+
withColumns(columns) {
|
|
5396
|
+
if (!columns.length) return this;
|
|
5397
|
+
return this.clone({
|
|
5398
|
+
...this.ast,
|
|
5399
|
+
columns: [...columns]
|
|
5400
|
+
});
|
|
5401
|
+
}
|
|
5402
|
+
withSelect(query, columns) {
|
|
5403
|
+
const targetColumns = columns.length ? columns : this.ast.columns.length ? this.ast.columns : this.getTableColumns();
|
|
5404
|
+
if (!targetColumns.length) {
|
|
5405
|
+
throw new Error("INSERT ... SELECT requires specifying destination columns.");
|
|
5406
|
+
}
|
|
5407
|
+
if (this.ast.source.type === "InsertValues" && this.ast.source.rows.length) {
|
|
5408
|
+
throw new Error("Cannot mix INSERT ... SELECT with INSERT ... VALUES source.");
|
|
5409
|
+
}
|
|
5410
|
+
return this.clone({
|
|
5411
|
+
...this.ast,
|
|
5412
|
+
columns: [...targetColumns],
|
|
5413
|
+
source: {
|
|
5414
|
+
type: "InsertSelect",
|
|
5415
|
+
query
|
|
5416
|
+
}
|
|
5283
5417
|
});
|
|
5284
5418
|
}
|
|
5285
5419
|
withReturning(columns) {
|
|
@@ -5304,11 +5438,27 @@ var InsertQueryBuilder = class _InsertQueryBuilder {
|
|
|
5304
5438
|
if (!rows.length) return this;
|
|
5305
5439
|
return this.clone(this.state.withValues(rows));
|
|
5306
5440
|
}
|
|
5441
|
+
columns(...columns) {
|
|
5442
|
+
if (!columns.length) return this;
|
|
5443
|
+
return this.clone(this.state.withColumns(this.resolveColumnNodes(columns)));
|
|
5444
|
+
}
|
|
5445
|
+
fromSelect(query, columns = []) {
|
|
5446
|
+
const ast = this.resolveSelectQuery(query);
|
|
5447
|
+
const nodes = columns.length ? this.resolveColumnNodes(columns) : [];
|
|
5448
|
+
return this.clone(this.state.withSelect(ast, nodes));
|
|
5449
|
+
}
|
|
5307
5450
|
returning(...columns) {
|
|
5308
5451
|
if (!columns.length) return this;
|
|
5309
5452
|
const nodes = columns.map((column) => buildColumnNode(this.table, column));
|
|
5310
5453
|
return this.clone(this.state.withReturning(nodes));
|
|
5311
5454
|
}
|
|
5455
|
+
// Helpers for column/AST resolution
|
|
5456
|
+
resolveColumnNodes(columns) {
|
|
5457
|
+
return columns.map((column) => buildColumnNode(this.table, column));
|
|
5458
|
+
}
|
|
5459
|
+
resolveSelectQuery(query) {
|
|
5460
|
+
return typeof query.getAST === "function" ? query.getAST() : query;
|
|
5461
|
+
}
|
|
5312
5462
|
compile(arg) {
|
|
5313
5463
|
if (typeof arg.compileInsert === "function") {
|
|
5314
5464
|
return arg.compileInsert(this.state.ast);
|
|
@@ -5342,7 +5492,8 @@ var UpdateQueryState = class _UpdateQueryState {
|
|
|
5342
5492
|
this.ast = ast ?? {
|
|
5343
5493
|
type: "UpdateQuery",
|
|
5344
5494
|
table: createTableNode(table),
|
|
5345
|
-
set: []
|
|
5495
|
+
set: [],
|
|
5496
|
+
joins: []
|
|
5346
5497
|
};
|
|
5347
5498
|
}
|
|
5348
5499
|
clone(nextAst) {
|
|
@@ -5381,6 +5532,27 @@ var UpdateQueryState = class _UpdateQueryState {
|
|
|
5381
5532
|
returning: [...columns]
|
|
5382
5533
|
});
|
|
5383
5534
|
}
|
|
5535
|
+
withFrom(from) {
|
|
5536
|
+
return this.clone({
|
|
5537
|
+
...this.ast,
|
|
5538
|
+
from
|
|
5539
|
+
});
|
|
5540
|
+
}
|
|
5541
|
+
withJoin(join) {
|
|
5542
|
+
return this.clone({
|
|
5543
|
+
...this.ast,
|
|
5544
|
+
joins: [...this.ast.joins ?? [], join]
|
|
5545
|
+
});
|
|
5546
|
+
}
|
|
5547
|
+
withTableAlias(alias) {
|
|
5548
|
+
return this.clone({
|
|
5549
|
+
...this.ast,
|
|
5550
|
+
table: {
|
|
5551
|
+
...this.ast.table,
|
|
5552
|
+
alias
|
|
5553
|
+
}
|
|
5554
|
+
});
|
|
5555
|
+
}
|
|
5384
5556
|
};
|
|
5385
5557
|
|
|
5386
5558
|
// src/query-builder/update.ts
|
|
@@ -5392,6 +5564,18 @@ var UpdateQueryBuilder = class _UpdateQueryBuilder {
|
|
|
5392
5564
|
clone(state) {
|
|
5393
5565
|
return new _UpdateQueryBuilder(this.table, state);
|
|
5394
5566
|
}
|
|
5567
|
+
as(alias) {
|
|
5568
|
+
return this.clone(this.state.withTableAlias(alias));
|
|
5569
|
+
}
|
|
5570
|
+
from(source) {
|
|
5571
|
+
const tableSource = this.resolveTableSource(source);
|
|
5572
|
+
return this.clone(this.state.withFrom(tableSource));
|
|
5573
|
+
}
|
|
5574
|
+
join(table, condition, kind = JOIN_KINDS.INNER, relationName) {
|
|
5575
|
+
const joinTarget = this.resolveJoinTarget(table);
|
|
5576
|
+
const joinNode = createJoinNode(kind, joinTarget, condition, relationName);
|
|
5577
|
+
return this.clone(this.state.withJoin(joinNode));
|
|
5578
|
+
}
|
|
5395
5579
|
set(values) {
|
|
5396
5580
|
return this.clone(this.state.withSet(values));
|
|
5397
5581
|
}
|
|
@@ -5403,6 +5587,16 @@ var UpdateQueryBuilder = class _UpdateQueryBuilder {
|
|
|
5403
5587
|
const nodes = columns.map((column) => buildColumnNode(this.table, column));
|
|
5404
5588
|
return this.clone(this.state.withReturning(nodes));
|
|
5405
5589
|
}
|
|
5590
|
+
resolveTableSource(source) {
|
|
5591
|
+
if (isTableSourceNode(source)) {
|
|
5592
|
+
return source;
|
|
5593
|
+
}
|
|
5594
|
+
return { type: "Table", name: source.name, schema: source.schema };
|
|
5595
|
+
}
|
|
5596
|
+
resolveJoinTarget(table) {
|
|
5597
|
+
if (typeof table === "string") return table;
|
|
5598
|
+
return this.resolveTableSource(table);
|
|
5599
|
+
}
|
|
5406
5600
|
compile(arg) {
|
|
5407
5601
|
if (typeof arg.compileUpdate === "function") {
|
|
5408
5602
|
return arg.compileUpdate(this.state.ast);
|
|
@@ -5417,6 +5611,7 @@ var UpdateQueryBuilder = class _UpdateQueryBuilder {
|
|
|
5417
5611
|
return this.state.ast;
|
|
5418
5612
|
}
|
|
5419
5613
|
};
|
|
5614
|
+
var isTableSourceNode = (source) => typeof source.type === "string";
|
|
5420
5615
|
|
|
5421
5616
|
// src/query-builder/delete-query-state.ts
|
|
5422
5617
|
var DeleteQueryState = class _DeleteQueryState {
|
|
@@ -5424,7 +5619,8 @@ var DeleteQueryState = class _DeleteQueryState {
|
|
|
5424
5619
|
this.table = table;
|
|
5425
5620
|
this.ast = ast ?? {
|
|
5426
5621
|
type: "DeleteQuery",
|
|
5427
|
-
from: createTableNode(table)
|
|
5622
|
+
from: createTableNode(table),
|
|
5623
|
+
joins: []
|
|
5428
5624
|
};
|
|
5429
5625
|
}
|
|
5430
5626
|
clone(nextAst) {
|
|
@@ -5442,6 +5638,27 @@ var DeleteQueryState = class _DeleteQueryState {
|
|
|
5442
5638
|
returning: [...columns]
|
|
5443
5639
|
});
|
|
5444
5640
|
}
|
|
5641
|
+
withUsing(source) {
|
|
5642
|
+
return this.clone({
|
|
5643
|
+
...this.ast,
|
|
5644
|
+
using: source
|
|
5645
|
+
});
|
|
5646
|
+
}
|
|
5647
|
+
withJoin(join) {
|
|
5648
|
+
return this.clone({
|
|
5649
|
+
...this.ast,
|
|
5650
|
+
joins: [...this.ast.joins ?? [], join]
|
|
5651
|
+
});
|
|
5652
|
+
}
|
|
5653
|
+
withTableAlias(alias) {
|
|
5654
|
+
return this.clone({
|
|
5655
|
+
...this.ast,
|
|
5656
|
+
from: {
|
|
5657
|
+
...this.ast.from,
|
|
5658
|
+
alias
|
|
5659
|
+
}
|
|
5660
|
+
});
|
|
5661
|
+
}
|
|
5445
5662
|
};
|
|
5446
5663
|
|
|
5447
5664
|
// src/query-builder/delete.ts
|
|
@@ -5456,11 +5673,32 @@ var DeleteQueryBuilder = class _DeleteQueryBuilder {
|
|
|
5456
5673
|
where(expr) {
|
|
5457
5674
|
return this.clone(this.state.withWhere(expr));
|
|
5458
5675
|
}
|
|
5676
|
+
as(alias) {
|
|
5677
|
+
return this.clone(this.state.withTableAlias(alias));
|
|
5678
|
+
}
|
|
5679
|
+
using(source) {
|
|
5680
|
+
return this.clone(this.state.withUsing(this.resolveTableSource(source)));
|
|
5681
|
+
}
|
|
5682
|
+
join(table, condition, kind = JOIN_KINDS.INNER, relationName) {
|
|
5683
|
+
const target = this.resolveJoinTarget(table);
|
|
5684
|
+
const joinNode = createJoinNode(kind, target, condition, relationName);
|
|
5685
|
+
return this.clone(this.state.withJoin(joinNode));
|
|
5686
|
+
}
|
|
5459
5687
|
returning(...columns) {
|
|
5460
5688
|
if (!columns.length) return this;
|
|
5461
5689
|
const nodes = columns.map((column) => buildColumnNode(this.table, column));
|
|
5462
5690
|
return this.clone(this.state.withReturning(nodes));
|
|
5463
5691
|
}
|
|
5692
|
+
resolveTableSource(source) {
|
|
5693
|
+
if (isTableSourceNode2(source)) {
|
|
5694
|
+
return source;
|
|
5695
|
+
}
|
|
5696
|
+
return { type: "Table", name: source.name, schema: source.schema };
|
|
5697
|
+
}
|
|
5698
|
+
resolveJoinTarget(table) {
|
|
5699
|
+
if (typeof table === "string") return table;
|
|
5700
|
+
return this.resolveTableSource(table);
|
|
5701
|
+
}
|
|
5464
5702
|
compile(arg) {
|
|
5465
5703
|
if (typeof arg.compileDelete === "function") {
|
|
5466
5704
|
return arg.compileDelete(this.state.ast);
|
|
@@ -5475,6 +5713,7 @@ var DeleteQueryBuilder = class _DeleteQueryBuilder {
|
|
|
5475
5713
|
return this.state.ast;
|
|
5476
5714
|
}
|
|
5477
5715
|
};
|
|
5716
|
+
var isTableSourceNode2 = (source) => typeof source.type === "string";
|
|
5478
5717
|
|
|
5479
5718
|
// src/core/ddl/sql-writing.ts
|
|
5480
5719
|
var resolvePrimaryKey = (table) => {
|
|
@@ -6823,9 +7062,13 @@ var TypeScriptGenerator = class {
|
|
|
6823
7062
|
*/
|
|
6824
7063
|
printInExpression(inExpr) {
|
|
6825
7064
|
const left2 = this.printOperand(inExpr.left);
|
|
6826
|
-
const values = inExpr.right.map((v) => this.printOperand(v)).join(", ");
|
|
6827
7065
|
const fn4 = this.mapOp(inExpr.operator);
|
|
6828
|
-
|
|
7066
|
+
if (Array.isArray(inExpr.right)) {
|
|
7067
|
+
const values = inExpr.right.map((v) => this.printOperand(v)).join(", ");
|
|
7068
|
+
return `${fn4}(${left2}, [${values}])`;
|
|
7069
|
+
}
|
|
7070
|
+
const subquery = this.inlineChain(this.buildSelectLines(inExpr.right.query));
|
|
7071
|
+
return `${fn4}(${left2}, (${subquery}))`;
|
|
6829
7072
|
}
|
|
6830
7073
|
/**
|
|
6831
7074
|
* Prints a null expression to TypeScript code
|
|
@@ -7010,6 +7253,13 @@ var EntityStatus = /* @__PURE__ */ ((EntityStatus2) => {
|
|
|
7010
7253
|
|
|
7011
7254
|
// src/orm/unit-of-work.ts
|
|
7012
7255
|
var UnitOfWork = class {
|
|
7256
|
+
/**
|
|
7257
|
+
* Creates a new UnitOfWork instance.
|
|
7258
|
+
* @param dialect - The database dialect
|
|
7259
|
+
* @param executor - The database executor
|
|
7260
|
+
* @param identityMap - The identity map
|
|
7261
|
+
* @param hookContext - Function to get the hook context
|
|
7262
|
+
*/
|
|
7013
7263
|
constructor(dialect, executor, identityMap, hookContext) {
|
|
7014
7264
|
this.dialect = dialect;
|
|
7015
7265
|
this.executor = executor;
|
|
@@ -7017,21 +7267,50 @@ var UnitOfWork = class {
|
|
|
7017
7267
|
this.hookContext = hookContext;
|
|
7018
7268
|
this.trackedEntities = /* @__PURE__ */ new Map();
|
|
7019
7269
|
}
|
|
7270
|
+
/**
|
|
7271
|
+
* Gets the identity buckets map.
|
|
7272
|
+
*/
|
|
7020
7273
|
get identityBuckets() {
|
|
7021
7274
|
return this.identityMap.bucketsMap;
|
|
7022
7275
|
}
|
|
7276
|
+
/**
|
|
7277
|
+
* Gets all tracked entities.
|
|
7278
|
+
* @returns Array of tracked entities
|
|
7279
|
+
*/
|
|
7023
7280
|
getTracked() {
|
|
7024
7281
|
return Array.from(this.trackedEntities.values());
|
|
7025
7282
|
}
|
|
7283
|
+
/**
|
|
7284
|
+
* Gets an entity by table and primary key.
|
|
7285
|
+
* @param table - The table definition
|
|
7286
|
+
* @param pk - The primary key value
|
|
7287
|
+
* @returns The entity or undefined if not found
|
|
7288
|
+
*/
|
|
7026
7289
|
getEntity(table, pk) {
|
|
7027
7290
|
return this.identityMap.getEntity(table, pk);
|
|
7028
7291
|
}
|
|
7292
|
+
/**
|
|
7293
|
+
* Gets all tracked entities for a specific table.
|
|
7294
|
+
* @param table - The table definition
|
|
7295
|
+
* @returns Array of tracked entities
|
|
7296
|
+
*/
|
|
7029
7297
|
getEntitiesForTable(table) {
|
|
7030
7298
|
return this.identityMap.getEntitiesForTable(table);
|
|
7031
7299
|
}
|
|
7300
|
+
/**
|
|
7301
|
+
* Finds a tracked entity.
|
|
7302
|
+
* @param entity - The entity to find
|
|
7303
|
+
* @returns The tracked entity or undefined if not found
|
|
7304
|
+
*/
|
|
7032
7305
|
findTracked(entity) {
|
|
7033
7306
|
return this.trackedEntities.get(entity);
|
|
7034
7307
|
}
|
|
7308
|
+
/**
|
|
7309
|
+
* Sets an entity in the identity map.
|
|
7310
|
+
* @param table - The table definition
|
|
7311
|
+
* @param pk - The primary key value
|
|
7312
|
+
* @param entity - The entity instance
|
|
7313
|
+
*/
|
|
7035
7314
|
setEntity(table, pk, entity) {
|
|
7036
7315
|
if (pk === null || pk === void 0) return;
|
|
7037
7316
|
let tracked = this.trackedEntities.get(entity);
|
|
@@ -7049,6 +7328,12 @@ var UnitOfWork = class {
|
|
|
7049
7328
|
}
|
|
7050
7329
|
this.registerIdentity(tracked);
|
|
7051
7330
|
}
|
|
7331
|
+
/**
|
|
7332
|
+
* Tracks a new entity.
|
|
7333
|
+
* @param table - The table definition
|
|
7334
|
+
* @param entity - The entity instance
|
|
7335
|
+
* @param pk - Optional primary key value
|
|
7336
|
+
*/
|
|
7052
7337
|
trackNew(table, entity, pk) {
|
|
7053
7338
|
const tracked = {
|
|
7054
7339
|
table,
|
|
@@ -7062,6 +7347,12 @@ var UnitOfWork = class {
|
|
|
7062
7347
|
this.registerIdentity(tracked);
|
|
7063
7348
|
}
|
|
7064
7349
|
}
|
|
7350
|
+
/**
|
|
7351
|
+
* Tracks a managed entity.
|
|
7352
|
+
* @param table - The table definition
|
|
7353
|
+
* @param pk - The primary key value
|
|
7354
|
+
* @param entity - The entity instance
|
|
7355
|
+
*/
|
|
7065
7356
|
trackManaged(table, pk, entity) {
|
|
7066
7357
|
const tracked = {
|
|
7067
7358
|
table,
|
|
@@ -7073,17 +7364,28 @@ var UnitOfWork = class {
|
|
|
7073
7364
|
this.trackedEntities.set(entity, tracked);
|
|
7074
7365
|
this.registerIdentity(tracked);
|
|
7075
7366
|
}
|
|
7367
|
+
/**
|
|
7368
|
+
* Marks an entity as dirty (modified).
|
|
7369
|
+
* @param entity - The entity to mark as dirty
|
|
7370
|
+
*/
|
|
7076
7371
|
markDirty(entity) {
|
|
7077
7372
|
const tracked = this.trackedEntities.get(entity);
|
|
7078
7373
|
if (!tracked) return;
|
|
7079
7374
|
if (tracked.status === "new" /* New */ || tracked.status === "removed" /* Removed */) return;
|
|
7080
7375
|
tracked.status = "dirty" /* Dirty */;
|
|
7081
7376
|
}
|
|
7377
|
+
/**
|
|
7378
|
+
* Marks an entity as removed.
|
|
7379
|
+
* @param entity - The entity to mark as removed
|
|
7380
|
+
*/
|
|
7082
7381
|
markRemoved(entity) {
|
|
7083
7382
|
const tracked = this.trackedEntities.get(entity);
|
|
7084
7383
|
if (!tracked) return;
|
|
7085
7384
|
tracked.status = "removed" /* Removed */;
|
|
7086
7385
|
}
|
|
7386
|
+
/**
|
|
7387
|
+
* Flushes pending changes to the database.
|
|
7388
|
+
*/
|
|
7087
7389
|
async flush() {
|
|
7088
7390
|
const toFlush = Array.from(this.trackedEntities.values());
|
|
7089
7391
|
for (const tracked of toFlush) {
|
|
@@ -7102,10 +7404,17 @@ var UnitOfWork = class {
|
|
|
7102
7404
|
}
|
|
7103
7405
|
}
|
|
7104
7406
|
}
|
|
7407
|
+
/**
|
|
7408
|
+
* Resets the unit of work by clearing all tracked entities and identity map.
|
|
7409
|
+
*/
|
|
7105
7410
|
reset() {
|
|
7106
7411
|
this.trackedEntities.clear();
|
|
7107
7412
|
this.identityMap.clear();
|
|
7108
7413
|
}
|
|
7414
|
+
/**
|
|
7415
|
+
* Flushes an insert operation for a new entity.
|
|
7416
|
+
* @param tracked - The tracked entity to insert
|
|
7417
|
+
*/
|
|
7109
7418
|
async flushInsert(tracked) {
|
|
7110
7419
|
await this.runHook(tracked.table.hooks?.beforeInsert, tracked);
|
|
7111
7420
|
const payload = this.extractColumns(tracked.table, tracked.entity);
|
|
@@ -7122,6 +7431,10 @@ var UnitOfWork = class {
|
|
|
7122
7431
|
this.registerIdentity(tracked);
|
|
7123
7432
|
await this.runHook(tracked.table.hooks?.afterInsert, tracked);
|
|
7124
7433
|
}
|
|
7434
|
+
/**
|
|
7435
|
+
* Flushes an update operation for a modified entity.
|
|
7436
|
+
* @param tracked - The tracked entity to update
|
|
7437
|
+
*/
|
|
7125
7438
|
async flushUpdate(tracked) {
|
|
7126
7439
|
if (tracked.pk == null) return;
|
|
7127
7440
|
const changes = this.computeChanges(tracked);
|
|
@@ -7144,6 +7457,10 @@ var UnitOfWork = class {
|
|
|
7144
7457
|
this.registerIdentity(tracked);
|
|
7145
7458
|
await this.runHook(tracked.table.hooks?.afterUpdate, tracked);
|
|
7146
7459
|
}
|
|
7460
|
+
/**
|
|
7461
|
+
* Flushes a delete operation for a removed entity.
|
|
7462
|
+
* @param tracked - The tracked entity to delete
|
|
7463
|
+
*/
|
|
7147
7464
|
async flushDelete(tracked) {
|
|
7148
7465
|
if (tracked.pk == null) return;
|
|
7149
7466
|
await this.runHook(tracked.table.hooks?.beforeDelete, tracked);
|
|
@@ -7157,10 +7474,20 @@ var UnitOfWork = class {
|
|
|
7157
7474
|
this.identityMap.remove(tracked);
|
|
7158
7475
|
await this.runHook(tracked.table.hooks?.afterDelete, tracked);
|
|
7159
7476
|
}
|
|
7477
|
+
/**
|
|
7478
|
+
* Runs a table hook if defined.
|
|
7479
|
+
* @param hook - The hook function
|
|
7480
|
+
* @param tracked - The tracked entity
|
|
7481
|
+
*/
|
|
7160
7482
|
async runHook(hook, tracked) {
|
|
7161
7483
|
if (!hook) return;
|
|
7162
7484
|
await hook(this.hookContext(), tracked.entity);
|
|
7163
7485
|
}
|
|
7486
|
+
/**
|
|
7487
|
+
* Computes changes between current entity state and original snapshot.
|
|
7488
|
+
* @param tracked - The tracked entity
|
|
7489
|
+
* @returns Object with changed column values
|
|
7490
|
+
*/
|
|
7164
7491
|
computeChanges(tracked) {
|
|
7165
7492
|
const snapshot = tracked.original ?? {};
|
|
7166
7493
|
const changes = {};
|
|
@@ -7172,6 +7499,12 @@ var UnitOfWork = class {
|
|
|
7172
7499
|
}
|
|
7173
7500
|
return changes;
|
|
7174
7501
|
}
|
|
7502
|
+
/**
|
|
7503
|
+
* Extracts column values from an entity.
|
|
7504
|
+
* @param table - The table definition
|
|
7505
|
+
* @param entity - The entity instance
|
|
7506
|
+
* @returns Object with column values
|
|
7507
|
+
*/
|
|
7175
7508
|
extractColumns(table, entity) {
|
|
7176
7509
|
const payload = {};
|
|
7177
7510
|
for (const column of Object.keys(table.columns)) {
|
|
@@ -7180,9 +7513,19 @@ var UnitOfWork = class {
|
|
|
7180
7513
|
}
|
|
7181
7514
|
return payload;
|
|
7182
7515
|
}
|
|
7516
|
+
/**
|
|
7517
|
+
* Executes a compiled query.
|
|
7518
|
+
* @param compiled - The compiled query
|
|
7519
|
+
* @returns Query results
|
|
7520
|
+
*/
|
|
7183
7521
|
async executeCompiled(compiled) {
|
|
7184
7522
|
return this.executor.executeSql(compiled.sql, compiled.params);
|
|
7185
7523
|
}
|
|
7524
|
+
/**
|
|
7525
|
+
* Gets columns for RETURNING clause.
|
|
7526
|
+
* @param table - The table definition
|
|
7527
|
+
* @returns Array of column nodes
|
|
7528
|
+
*/
|
|
7186
7529
|
getReturningColumns(table) {
|
|
7187
7530
|
return Object.values(table.columns).map((column) => ({
|
|
7188
7531
|
type: "Column",
|
|
@@ -7191,6 +7534,11 @@ var UnitOfWork = class {
|
|
|
7191
7534
|
alias: column.name
|
|
7192
7535
|
}));
|
|
7193
7536
|
}
|
|
7537
|
+
/**
|
|
7538
|
+
* Applies RETURNING clause results to the tracked entity.
|
|
7539
|
+
* @param tracked - The tracked entity
|
|
7540
|
+
* @param results - Query results
|
|
7541
|
+
*/
|
|
7194
7542
|
applyReturningResults(tracked, results) {
|
|
7195
7543
|
if (!this.dialect.supportsReturning()) return;
|
|
7196
7544
|
const first = results[0];
|
|
@@ -7202,15 +7550,30 @@ var UnitOfWork = class {
|
|
|
7202
7550
|
tracked.entity[columnName] = row[i];
|
|
7203
7551
|
}
|
|
7204
7552
|
}
|
|
7553
|
+
/**
|
|
7554
|
+
* Normalizes a column name by removing quotes and table prefixes.
|
|
7555
|
+
* @param column - The column name to normalize
|
|
7556
|
+
* @returns Normalized column name
|
|
7557
|
+
*/
|
|
7205
7558
|
normalizeColumnName(column) {
|
|
7206
7559
|
const parts = column.split(".");
|
|
7207
7560
|
const candidate = parts[parts.length - 1];
|
|
7208
7561
|
return candidate.replace(/^["`[\]]+|["`[\]]+$/g, "");
|
|
7209
7562
|
}
|
|
7563
|
+
/**
|
|
7564
|
+
* Registers an entity in the identity map.
|
|
7565
|
+
* @param tracked - The tracked entity to register
|
|
7566
|
+
*/
|
|
7210
7567
|
registerIdentity(tracked) {
|
|
7211
7568
|
if (tracked.pk == null) return;
|
|
7212
7569
|
this.identityMap.register(tracked);
|
|
7213
7570
|
}
|
|
7571
|
+
/**
|
|
7572
|
+
* Creates a snapshot of an entity's current state.
|
|
7573
|
+
* @param table - The table definition
|
|
7574
|
+
* @param entity - The entity instance
|
|
7575
|
+
* @returns Object with entity state
|
|
7576
|
+
*/
|
|
7214
7577
|
createSnapshot(table, entity) {
|
|
7215
7578
|
const snapshot = {};
|
|
7216
7579
|
for (const column of Object.keys(table.columns)) {
|
|
@@ -7218,6 +7581,11 @@ var UnitOfWork = class {
|
|
|
7218
7581
|
}
|
|
7219
7582
|
return snapshot;
|
|
7220
7583
|
}
|
|
7584
|
+
/**
|
|
7585
|
+
* Gets the primary key value from a tracked entity.
|
|
7586
|
+
* @param tracked - The tracked entity
|
|
7587
|
+
* @returns Primary key value or null
|
|
7588
|
+
*/
|
|
7221
7589
|
getPrimaryKeyValue(tracked) {
|
|
7222
7590
|
const key = findPrimaryKey(tracked.table);
|
|
7223
7591
|
const val = tracked.entity[key];
|
|
@@ -7228,6 +7596,10 @@ var UnitOfWork = class {
|
|
|
7228
7596
|
|
|
7229
7597
|
// src/orm/domain-event-bus.ts
|
|
7230
7598
|
var DomainEventBus = class {
|
|
7599
|
+
/**
|
|
7600
|
+
* Creates a new DomainEventBus instance.
|
|
7601
|
+
* @param initialHandlers - Optional initial event handlers
|
|
7602
|
+
*/
|
|
7231
7603
|
constructor(initialHandlers) {
|
|
7232
7604
|
this.handlers = /* @__PURE__ */ new Map();
|
|
7233
7605
|
if (initialHandlers) {
|
|
@@ -7238,15 +7610,32 @@ var DomainEventBus = class {
|
|
|
7238
7610
|
}
|
|
7239
7611
|
}
|
|
7240
7612
|
}
|
|
7613
|
+
/**
|
|
7614
|
+
* Registers an event handler for a specific event type.
|
|
7615
|
+
* @template TType - The event type
|
|
7616
|
+
* @param type - The event type
|
|
7617
|
+
* @param handler - The event handler
|
|
7618
|
+
*/
|
|
7241
7619
|
on(type, handler) {
|
|
7242
7620
|
const key = type;
|
|
7243
7621
|
const existing = this.handlers.get(key) ?? [];
|
|
7244
7622
|
existing.push(handler);
|
|
7245
7623
|
this.handlers.set(key, existing);
|
|
7246
7624
|
}
|
|
7625
|
+
/**
|
|
7626
|
+
* Registers an event handler for a specific event type (alias for on).
|
|
7627
|
+
* @template TType - The event type
|
|
7628
|
+
* @param type - The event type
|
|
7629
|
+
* @param handler - The event handler
|
|
7630
|
+
*/
|
|
7247
7631
|
register(type, handler) {
|
|
7248
7632
|
this.on(type, handler);
|
|
7249
7633
|
}
|
|
7634
|
+
/**
|
|
7635
|
+
* Dispatches domain events for tracked entities.
|
|
7636
|
+
* @param trackedEntities - Iterable of tracked entities
|
|
7637
|
+
* @param ctx - The context to pass to handlers
|
|
7638
|
+
*/
|
|
7250
7639
|
async dispatch(trackedEntities, ctx) {
|
|
7251
7640
|
for (const tracked of trackedEntities) {
|
|
7252
7641
|
const entity = tracked.entity;
|
|
@@ -7271,18 +7660,34 @@ var addDomainEvent = (entity, event) => {
|
|
|
7271
7660
|
|
|
7272
7661
|
// src/orm/relation-change-processor.ts
|
|
7273
7662
|
var RelationChangeProcessor = class {
|
|
7663
|
+
/**
|
|
7664
|
+
* Creates a new RelationChangeProcessor instance.
|
|
7665
|
+
* @param unitOfWork - The unit of work instance
|
|
7666
|
+
* @param dialect - The database dialect
|
|
7667
|
+
* @param executor - The database executor
|
|
7668
|
+
*/
|
|
7274
7669
|
constructor(unitOfWork, dialect, executor) {
|
|
7275
7670
|
this.unitOfWork = unitOfWork;
|
|
7276
7671
|
this.dialect = dialect;
|
|
7277
7672
|
this.executor = executor;
|
|
7278
7673
|
this.relationChanges = [];
|
|
7279
7674
|
}
|
|
7675
|
+
/**
|
|
7676
|
+
* Registers a relation change for processing.
|
|
7677
|
+
* @param entry - The relation change entry
|
|
7678
|
+
*/
|
|
7280
7679
|
registerChange(entry) {
|
|
7281
7680
|
this.relationChanges.push(entry);
|
|
7282
7681
|
}
|
|
7682
|
+
/**
|
|
7683
|
+
* Resets the relation change processor by clearing all pending changes.
|
|
7684
|
+
*/
|
|
7283
7685
|
reset() {
|
|
7284
7686
|
this.relationChanges.length = 0;
|
|
7285
7687
|
}
|
|
7688
|
+
/**
|
|
7689
|
+
* Processes all pending relation changes.
|
|
7690
|
+
*/
|
|
7286
7691
|
async process() {
|
|
7287
7692
|
if (!this.relationChanges.length) return;
|
|
7288
7693
|
const entries = [...this.relationChanges];
|
|
@@ -7304,6 +7709,10 @@ var RelationChangeProcessor = class {
|
|
|
7304
7709
|
}
|
|
7305
7710
|
}
|
|
7306
7711
|
}
|
|
7712
|
+
/**
|
|
7713
|
+
* Handles changes for has-many relations.
|
|
7714
|
+
* @param entry - The relation change entry
|
|
7715
|
+
*/
|
|
7307
7716
|
async handleHasManyChange(entry) {
|
|
7308
7717
|
const relation = entry.relation;
|
|
7309
7718
|
const target = entry.change.entity;
|
|
@@ -7322,6 +7731,10 @@ var RelationChangeProcessor = class {
|
|
|
7322
7731
|
this.detachHasManyChild(tracked.entity, relation);
|
|
7323
7732
|
}
|
|
7324
7733
|
}
|
|
7734
|
+
/**
|
|
7735
|
+
* Handles changes for has-one relations.
|
|
7736
|
+
* @param entry - The relation change entry
|
|
7737
|
+
*/
|
|
7325
7738
|
async handleHasOneChange(entry) {
|
|
7326
7739
|
const relation = entry.relation;
|
|
7327
7740
|
const target = entry.change.entity;
|
|
@@ -7340,8 +7753,16 @@ var RelationChangeProcessor = class {
|
|
|
7340
7753
|
this.detachHasOneChild(tracked.entity, relation);
|
|
7341
7754
|
}
|
|
7342
7755
|
}
|
|
7756
|
+
/**
|
|
7757
|
+
* Handles changes for belongs-to relations.
|
|
7758
|
+
* @param _entry - The relation change entry (reserved for future use)
|
|
7759
|
+
*/
|
|
7343
7760
|
async handleBelongsToChange(_entry) {
|
|
7344
7761
|
}
|
|
7762
|
+
/**
|
|
7763
|
+
* Handles changes for belongs-to-many relations.
|
|
7764
|
+
* @param entry - The relation change entry
|
|
7765
|
+
*/
|
|
7345
7766
|
async handleBelongsToManyChange(entry) {
|
|
7346
7767
|
const relation = entry.relation;
|
|
7347
7768
|
const rootKey = relation.localKey || findPrimaryKey(entry.rootTable);
|
|
@@ -7360,11 +7781,22 @@ var RelationChangeProcessor = class {
|
|
|
7360
7781
|
}
|
|
7361
7782
|
}
|
|
7362
7783
|
}
|
|
7784
|
+
/**
|
|
7785
|
+
* Assigns a foreign key for has-many relations.
|
|
7786
|
+
* @param child - The child entity
|
|
7787
|
+
* @param relation - The has-many relation
|
|
7788
|
+
* @param rootValue - The root entity's primary key value
|
|
7789
|
+
*/
|
|
7363
7790
|
assignHasManyForeignKey(child, relation, rootValue) {
|
|
7364
7791
|
const current = child[relation.foreignKey];
|
|
7365
7792
|
if (current === rootValue) return;
|
|
7366
7793
|
child[relation.foreignKey] = rootValue;
|
|
7367
7794
|
}
|
|
7795
|
+
/**
|
|
7796
|
+
* Detaches a child entity from has-many relations.
|
|
7797
|
+
* @param child - The child entity
|
|
7798
|
+
* @param relation - The has-many relation
|
|
7799
|
+
*/
|
|
7368
7800
|
detachHasManyChild(child, relation) {
|
|
7369
7801
|
if (relation.cascade === "all" || relation.cascade === "remove") {
|
|
7370
7802
|
this.unitOfWork.markRemoved(child);
|
|
@@ -7373,11 +7805,22 @@ var RelationChangeProcessor = class {
|
|
|
7373
7805
|
child[relation.foreignKey] = null;
|
|
7374
7806
|
this.unitOfWork.markDirty(child);
|
|
7375
7807
|
}
|
|
7808
|
+
/**
|
|
7809
|
+
* Assigns a foreign key for has-one relations.
|
|
7810
|
+
* @param child - The child entity
|
|
7811
|
+
* @param relation - The has-one relation
|
|
7812
|
+
* @param rootValue - The root entity's primary key value
|
|
7813
|
+
*/
|
|
7376
7814
|
assignHasOneForeignKey(child, relation, rootValue) {
|
|
7377
7815
|
const current = child[relation.foreignKey];
|
|
7378
7816
|
if (current === rootValue) return;
|
|
7379
7817
|
child[relation.foreignKey] = rootValue;
|
|
7380
7818
|
}
|
|
7819
|
+
/**
|
|
7820
|
+
* Detaches a child entity from has-one relations.
|
|
7821
|
+
* @param child - The child entity
|
|
7822
|
+
* @param relation - The has-one relation
|
|
7823
|
+
*/
|
|
7381
7824
|
detachHasOneChild(child, relation) {
|
|
7382
7825
|
if (relation.cascade === "all" || relation.cascade === "remove") {
|
|
7383
7826
|
this.unitOfWork.markRemoved(child);
|
|
@@ -7386,6 +7829,12 @@ var RelationChangeProcessor = class {
|
|
|
7386
7829
|
child[relation.foreignKey] = null;
|
|
7387
7830
|
this.unitOfWork.markDirty(child);
|
|
7388
7831
|
}
|
|
7832
|
+
/**
|
|
7833
|
+
* Inserts a pivot row for belongs-to-many relations.
|
|
7834
|
+
* @param relation - The belongs-to-many relation
|
|
7835
|
+
* @param rootId - The root entity's primary key value
|
|
7836
|
+
* @param targetId - The target entity's primary key value
|
|
7837
|
+
*/
|
|
7389
7838
|
async insertPivotRow(relation, rootId, targetId) {
|
|
7390
7839
|
const payload = {
|
|
7391
7840
|
[relation.pivotForeignKeyToRoot]: rootId,
|
|
@@ -7395,6 +7844,12 @@ var RelationChangeProcessor = class {
|
|
|
7395
7844
|
const compiled = builder.compile(this.dialect);
|
|
7396
7845
|
await this.executor.executeSql(compiled.sql, compiled.params);
|
|
7397
7846
|
}
|
|
7847
|
+
/**
|
|
7848
|
+
* Deletes a pivot row for belongs-to-many relations.
|
|
7849
|
+
* @param relation - The belongs-to-many relation
|
|
7850
|
+
* @param rootId - The root entity's primary key value
|
|
7851
|
+
* @param targetId - The target entity's primary key value
|
|
7852
|
+
*/
|
|
7398
7853
|
async deletePivotRow(relation, rootId, targetId) {
|
|
7399
7854
|
const rootCol = relation.pivotTable.columns[relation.pivotForeignKeyToRoot];
|
|
7400
7855
|
const targetCol = relation.pivotTable.columns[relation.pivotForeignKeyToTarget];
|
|
@@ -7405,6 +7860,12 @@ var RelationChangeProcessor = class {
|
|
|
7405
7860
|
const compiled = builder.compile(this.dialect);
|
|
7406
7861
|
await this.executor.executeSql(compiled.sql, compiled.params);
|
|
7407
7862
|
}
|
|
7863
|
+
/**
|
|
7864
|
+
* Resolves the primary key value from an entity.
|
|
7865
|
+
* @param entity - The entity
|
|
7866
|
+
* @param table - The table definition
|
|
7867
|
+
* @returns The primary key value or null
|
|
7868
|
+
*/
|
|
7408
7869
|
resolvePrimaryKeyValue(entity, table) {
|
|
7409
7870
|
if (!entity) return null;
|
|
7410
7871
|
const key = findPrimaryKey(table);
|
|
@@ -7420,42 +7881,231 @@ var createQueryLoggingExecutor = (executor, logger) => {
|
|
|
7420
7881
|
return executor;
|
|
7421
7882
|
}
|
|
7422
7883
|
const wrapped = {
|
|
7884
|
+
capabilities: executor.capabilities,
|
|
7423
7885
|
async executeSql(sql, params) {
|
|
7424
7886
|
logger({ sql, params });
|
|
7425
7887
|
return executor.executeSql(sql, params);
|
|
7426
|
-
}
|
|
7888
|
+
},
|
|
7889
|
+
beginTransaction: () => executor.beginTransaction(),
|
|
7890
|
+
commitTransaction: () => executor.commitTransaction(),
|
|
7891
|
+
rollbackTransaction: () => executor.rollbackTransaction(),
|
|
7892
|
+
dispose: () => executor.dispose()
|
|
7427
7893
|
};
|
|
7428
|
-
if (executor.beginTransaction) {
|
|
7429
|
-
wrapped.beginTransaction = executor.beginTransaction.bind(executor);
|
|
7430
|
-
}
|
|
7431
|
-
if (executor.commitTransaction) {
|
|
7432
|
-
wrapped.commitTransaction = executor.commitTransaction.bind(executor);
|
|
7433
|
-
}
|
|
7434
|
-
if (executor.rollbackTransaction) {
|
|
7435
|
-
wrapped.rollbackTransaction = executor.rollbackTransaction.bind(executor);
|
|
7436
|
-
}
|
|
7437
7894
|
return wrapped;
|
|
7438
7895
|
};
|
|
7439
7896
|
|
|
7440
7897
|
// src/orm/transaction-runner.ts
|
|
7441
7898
|
var runInTransaction = async (executor, action) => {
|
|
7442
|
-
if (!executor.
|
|
7899
|
+
if (!executor.capabilities.transactions) {
|
|
7443
7900
|
await action();
|
|
7444
7901
|
return;
|
|
7445
7902
|
}
|
|
7446
7903
|
await executor.beginTransaction();
|
|
7447
7904
|
try {
|
|
7448
7905
|
await action();
|
|
7449
|
-
await executor.commitTransaction
|
|
7906
|
+
await executor.commitTransaction();
|
|
7450
7907
|
} catch (error) {
|
|
7451
|
-
await executor.rollbackTransaction
|
|
7908
|
+
await executor.rollbackTransaction();
|
|
7452
7909
|
throw error;
|
|
7453
7910
|
}
|
|
7454
7911
|
};
|
|
7455
7912
|
|
|
7913
|
+
// src/orm/save-graph.ts
|
|
7914
|
+
var toKey8 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
7915
|
+
var pickColumns = (table, payload) => {
|
|
7916
|
+
const columns = {};
|
|
7917
|
+
for (const key of Object.keys(table.columns)) {
|
|
7918
|
+
if (payload[key] !== void 0) {
|
|
7919
|
+
columns[key] = payload[key];
|
|
7920
|
+
}
|
|
7921
|
+
}
|
|
7922
|
+
return columns;
|
|
7923
|
+
};
|
|
7924
|
+
var ensureEntity = (session, table, payload) => {
|
|
7925
|
+
const pk = findPrimaryKey(table);
|
|
7926
|
+
const row = pickColumns(table, payload);
|
|
7927
|
+
const pkValue = payload[pk];
|
|
7928
|
+
if (pkValue !== void 0 && pkValue !== null) {
|
|
7929
|
+
const tracked = session.getEntity(table, pkValue);
|
|
7930
|
+
if (tracked) {
|
|
7931
|
+
return tracked;
|
|
7932
|
+
}
|
|
7933
|
+
if (row[pk] === void 0) {
|
|
7934
|
+
row[pk] = pkValue;
|
|
7935
|
+
}
|
|
7936
|
+
}
|
|
7937
|
+
return createEntityFromRow(session, table, row);
|
|
7938
|
+
};
|
|
7939
|
+
var assignColumns = (table, entity, payload) => {
|
|
7940
|
+
for (const key of Object.keys(table.columns)) {
|
|
7941
|
+
if (payload[key] !== void 0) {
|
|
7942
|
+
entity[key] = payload[key];
|
|
7943
|
+
}
|
|
7944
|
+
}
|
|
7945
|
+
};
|
|
7946
|
+
var isEntityInCollection = (items, pkName, entity) => {
|
|
7947
|
+
if (items.includes(entity)) return true;
|
|
7948
|
+
const entityPk = entity[pkName];
|
|
7949
|
+
if (entityPk === void 0 || entityPk === null) return false;
|
|
7950
|
+
return items.some((item) => toKey8(item[pkName]) === toKey8(entityPk));
|
|
7951
|
+
};
|
|
7952
|
+
var findInCollectionByPk = (items, pkName, pkValue) => {
|
|
7953
|
+
if (pkValue === void 0 || pkValue === null) return void 0;
|
|
7954
|
+
return items.find((item) => toKey8(item[pkName]) === toKey8(pkValue));
|
|
7955
|
+
};
|
|
7956
|
+
var handleHasMany = async (session, root, relationName, relation, payload, options) => {
|
|
7957
|
+
if (!Array.isArray(payload)) return;
|
|
7958
|
+
const collection = root[relationName];
|
|
7959
|
+
await collection.load();
|
|
7960
|
+
const targetTable = relation.target;
|
|
7961
|
+
const targetPk = findPrimaryKey(targetTable);
|
|
7962
|
+
const existing = collection.getItems();
|
|
7963
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7964
|
+
for (const item of payload) {
|
|
7965
|
+
if (item === null || item === void 0) continue;
|
|
7966
|
+
const asObj = typeof item === "object" ? item : { [targetPk]: item };
|
|
7967
|
+
const pkValue = asObj[targetPk];
|
|
7968
|
+
const current = findInCollectionByPk(existing, targetPk, pkValue) ?? (pkValue !== void 0 && pkValue !== null ? session.getEntity(targetTable, pkValue) : void 0);
|
|
7969
|
+
const entity = current ?? ensureEntity(session, targetTable, asObj);
|
|
7970
|
+
assignColumns(targetTable, entity, asObj);
|
|
7971
|
+
await applyGraphToEntity(session, targetTable, entity, asObj, options);
|
|
7972
|
+
if (!isEntityInCollection(collection.getItems(), targetPk, entity)) {
|
|
7973
|
+
collection.attach(entity);
|
|
7974
|
+
}
|
|
7975
|
+
if (pkValue !== void 0 && pkValue !== null) {
|
|
7976
|
+
seen.add(toKey8(pkValue));
|
|
7977
|
+
}
|
|
7978
|
+
}
|
|
7979
|
+
if (options.pruneMissing) {
|
|
7980
|
+
for (const item of [...collection.getItems()]) {
|
|
7981
|
+
const pkValue = item[targetPk];
|
|
7982
|
+
if (pkValue !== void 0 && pkValue !== null && !seen.has(toKey8(pkValue))) {
|
|
7983
|
+
collection.remove(item);
|
|
7984
|
+
}
|
|
7985
|
+
}
|
|
7986
|
+
}
|
|
7987
|
+
};
|
|
7988
|
+
var handleHasOne = async (session, root, relationName, relation, payload, options) => {
|
|
7989
|
+
const ref = root[relationName];
|
|
7990
|
+
if (payload === void 0) return;
|
|
7991
|
+
if (payload === null) {
|
|
7992
|
+
ref.set(null);
|
|
7993
|
+
return;
|
|
7994
|
+
}
|
|
7995
|
+
const pk = findPrimaryKey(relation.target);
|
|
7996
|
+
if (typeof payload === "number" || typeof payload === "string") {
|
|
7997
|
+
const entity = ref.set({ [pk]: payload });
|
|
7998
|
+
if (entity) {
|
|
7999
|
+
await applyGraphToEntity(session, relation.target, entity, { [pk]: payload }, options);
|
|
8000
|
+
}
|
|
8001
|
+
return;
|
|
8002
|
+
}
|
|
8003
|
+
const attached = ref.set(payload);
|
|
8004
|
+
if (attached) {
|
|
8005
|
+
await applyGraphToEntity(session, relation.target, attached, payload, options);
|
|
8006
|
+
}
|
|
8007
|
+
};
|
|
8008
|
+
var handleBelongsTo = async (session, root, relationName, relation, payload, options) => {
|
|
8009
|
+
const ref = root[relationName];
|
|
8010
|
+
if (payload === void 0) return;
|
|
8011
|
+
if (payload === null) {
|
|
8012
|
+
ref.set(null);
|
|
8013
|
+
return;
|
|
8014
|
+
}
|
|
8015
|
+
const pk = relation.localKey || findPrimaryKey(relation.target);
|
|
8016
|
+
if (typeof payload === "number" || typeof payload === "string") {
|
|
8017
|
+
const entity = ref.set({ [pk]: payload });
|
|
8018
|
+
if (entity) {
|
|
8019
|
+
await applyGraphToEntity(session, relation.target, entity, { [pk]: payload }, options);
|
|
8020
|
+
}
|
|
8021
|
+
return;
|
|
8022
|
+
}
|
|
8023
|
+
const attached = ref.set(payload);
|
|
8024
|
+
if (attached) {
|
|
8025
|
+
await applyGraphToEntity(session, relation.target, attached, payload, options);
|
|
8026
|
+
}
|
|
8027
|
+
};
|
|
8028
|
+
var handleBelongsToMany = async (session, root, relationName, relation, payload, options) => {
|
|
8029
|
+
if (!Array.isArray(payload)) return;
|
|
8030
|
+
const collection = root[relationName];
|
|
8031
|
+
await collection.load();
|
|
8032
|
+
const targetTable = relation.target;
|
|
8033
|
+
const targetPk = relation.targetKey || findPrimaryKey(targetTable);
|
|
8034
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8035
|
+
for (const item of payload) {
|
|
8036
|
+
if (item === null || item === void 0) continue;
|
|
8037
|
+
if (typeof item === "number" || typeof item === "string") {
|
|
8038
|
+
const id = item;
|
|
8039
|
+
collection.attach(id);
|
|
8040
|
+
seen.add(toKey8(id));
|
|
8041
|
+
continue;
|
|
8042
|
+
}
|
|
8043
|
+
const asObj = item;
|
|
8044
|
+
const pkValue = asObj[targetPk];
|
|
8045
|
+
const entity = pkValue !== void 0 && pkValue !== null ? session.getEntity(targetTable, pkValue) ?? ensureEntity(session, targetTable, asObj) : ensureEntity(session, targetTable, asObj);
|
|
8046
|
+
assignColumns(targetTable, entity, asObj);
|
|
8047
|
+
await applyGraphToEntity(session, targetTable, entity, asObj, options);
|
|
8048
|
+
if (!isEntityInCollection(collection.getItems(), targetPk, entity)) {
|
|
8049
|
+
collection.attach(entity);
|
|
8050
|
+
}
|
|
8051
|
+
if (pkValue !== void 0 && pkValue !== null) {
|
|
8052
|
+
seen.add(toKey8(pkValue));
|
|
8053
|
+
}
|
|
8054
|
+
}
|
|
8055
|
+
if (options.pruneMissing) {
|
|
8056
|
+
for (const item of [...collection.getItems()]) {
|
|
8057
|
+
const pkValue = item[targetPk];
|
|
8058
|
+
if (pkValue !== void 0 && pkValue !== null && !seen.has(toKey8(pkValue))) {
|
|
8059
|
+
collection.detach(item);
|
|
8060
|
+
}
|
|
8061
|
+
}
|
|
8062
|
+
}
|
|
8063
|
+
};
|
|
8064
|
+
var applyRelation = async (session, table, entity, relationName, relation, payload, options) => {
|
|
8065
|
+
switch (relation.type) {
|
|
8066
|
+
case RelationKinds.HasMany:
|
|
8067
|
+
return handleHasMany(session, entity, relationName, relation, payload, options);
|
|
8068
|
+
case RelationKinds.HasOne:
|
|
8069
|
+
return handleHasOne(session, entity, relationName, relation, payload, options);
|
|
8070
|
+
case RelationKinds.BelongsTo:
|
|
8071
|
+
return handleBelongsTo(session, entity, relationName, relation, payload, options);
|
|
8072
|
+
case RelationKinds.BelongsToMany:
|
|
8073
|
+
return handleBelongsToMany(session, entity, relationName, relation, payload, options);
|
|
8074
|
+
}
|
|
8075
|
+
};
|
|
8076
|
+
var applyGraphToEntity = async (session, table, entity, payload, options) => {
|
|
8077
|
+
assignColumns(table, entity, payload);
|
|
8078
|
+
for (const [relationName, relation] of Object.entries(table.relations)) {
|
|
8079
|
+
if (!(relationName in payload)) continue;
|
|
8080
|
+
await applyRelation(session, table, entity, relationName, relation, payload[relationName], options);
|
|
8081
|
+
}
|
|
8082
|
+
};
|
|
8083
|
+
var saveGraphInternal = async (session, entityClass, payload, options = {}) => {
|
|
8084
|
+
const table = getTableDefFromEntity(entityClass);
|
|
8085
|
+
if (!table) {
|
|
8086
|
+
throw new Error("Entity metadata has not been bootstrapped");
|
|
8087
|
+
}
|
|
8088
|
+
const root = ensureEntity(session, table, payload);
|
|
8089
|
+
await applyGraphToEntity(session, table, root, payload, options);
|
|
8090
|
+
return root;
|
|
8091
|
+
};
|
|
8092
|
+
|
|
7456
8093
|
// src/orm/orm-session.ts
|
|
7457
8094
|
var OrmSession = class {
|
|
8095
|
+
/**
|
|
8096
|
+
* Creates a new OrmSession instance.
|
|
8097
|
+
* @param opts - Session options
|
|
8098
|
+
*/
|
|
7458
8099
|
constructor(opts) {
|
|
8100
|
+
/**
|
|
8101
|
+
* Registers a relation change.
|
|
8102
|
+
* @param root - The root entity
|
|
8103
|
+
* @param relationKey - The relation key
|
|
8104
|
+
* @param rootTable - The root table definition
|
|
8105
|
+
* @param relationName - The relation name
|
|
8106
|
+
* @param relation - The relation definition
|
|
8107
|
+
* @param change - The relation change
|
|
8108
|
+
*/
|
|
7459
8109
|
this.registerRelationChange = (root, relationKey, rootTable, relationName, relation, change) => {
|
|
7460
8110
|
this.relationChanges.registerChange(
|
|
7461
8111
|
buildRelationChangeEntry(root, relationKey, rootTable, relationName, relation, change)
|
|
@@ -7469,42 +8119,117 @@ var OrmSession = class {
|
|
|
7469
8119
|
this.relationChanges = new RelationChangeProcessor(this.unitOfWork, this.orm.dialect, this.executor);
|
|
7470
8120
|
this.domainEvents = new DomainEventBus(opts.domainEventHandlers);
|
|
7471
8121
|
}
|
|
8122
|
+
/**
|
|
8123
|
+
* Releases resources associated with this session (executor/pool leases) and resets tracking.
|
|
8124
|
+
* Must be safe to call multiple times.
|
|
8125
|
+
*/
|
|
8126
|
+
async dispose() {
|
|
8127
|
+
try {
|
|
8128
|
+
await this.executor.dispose();
|
|
8129
|
+
} finally {
|
|
8130
|
+
this.unitOfWork.reset();
|
|
8131
|
+
this.relationChanges.reset();
|
|
8132
|
+
}
|
|
8133
|
+
}
|
|
8134
|
+
/**
|
|
8135
|
+
* Gets the database dialect.
|
|
8136
|
+
*/
|
|
7472
8137
|
get dialect() {
|
|
7473
8138
|
return this.orm.dialect;
|
|
7474
8139
|
}
|
|
8140
|
+
/**
|
|
8141
|
+
* Gets the identity buckets map.
|
|
8142
|
+
*/
|
|
7475
8143
|
get identityBuckets() {
|
|
7476
8144
|
return this.unitOfWork.identityBuckets;
|
|
7477
8145
|
}
|
|
8146
|
+
/**
|
|
8147
|
+
* Gets all tracked entities.
|
|
8148
|
+
*/
|
|
7478
8149
|
get tracked() {
|
|
7479
8150
|
return this.unitOfWork.getTracked();
|
|
7480
8151
|
}
|
|
8152
|
+
/**
|
|
8153
|
+
* Gets an entity by table and primary key.
|
|
8154
|
+
* @param table - The table definition
|
|
8155
|
+
* @param pk - The primary key value
|
|
8156
|
+
* @returns The entity or undefined if not found
|
|
8157
|
+
*/
|
|
7481
8158
|
getEntity(table, pk) {
|
|
7482
8159
|
return this.unitOfWork.getEntity(table, pk);
|
|
7483
8160
|
}
|
|
8161
|
+
/**
|
|
8162
|
+
* Sets an entity in the identity map.
|
|
8163
|
+
* @param table - The table definition
|
|
8164
|
+
* @param pk - The primary key value
|
|
8165
|
+
* @param entity - The entity instance
|
|
8166
|
+
*/
|
|
7484
8167
|
setEntity(table, pk, entity) {
|
|
7485
8168
|
this.unitOfWork.setEntity(table, pk, entity);
|
|
7486
8169
|
}
|
|
8170
|
+
/**
|
|
8171
|
+
* Tracks a new entity.
|
|
8172
|
+
* @param table - The table definition
|
|
8173
|
+
* @param entity - The entity instance
|
|
8174
|
+
* @param pk - Optional primary key value
|
|
8175
|
+
*/
|
|
7487
8176
|
trackNew(table, entity, pk) {
|
|
7488
8177
|
this.unitOfWork.trackNew(table, entity, pk);
|
|
7489
8178
|
}
|
|
8179
|
+
/**
|
|
8180
|
+
* Tracks a managed entity.
|
|
8181
|
+
* @param table - The table definition
|
|
8182
|
+
* @param pk - The primary key value
|
|
8183
|
+
* @param entity - The entity instance
|
|
8184
|
+
*/
|
|
7490
8185
|
trackManaged(table, pk, entity) {
|
|
7491
8186
|
this.unitOfWork.trackManaged(table, pk, entity);
|
|
7492
8187
|
}
|
|
8188
|
+
/**
|
|
8189
|
+
* Marks an entity as dirty (modified).
|
|
8190
|
+
* @param entity - The entity to mark as dirty
|
|
8191
|
+
*/
|
|
7493
8192
|
markDirty(entity) {
|
|
7494
8193
|
this.unitOfWork.markDirty(entity);
|
|
7495
8194
|
}
|
|
8195
|
+
/**
|
|
8196
|
+
* Marks an entity as removed.
|
|
8197
|
+
* @param entity - The entity to mark as removed
|
|
8198
|
+
*/
|
|
7496
8199
|
markRemoved(entity) {
|
|
7497
8200
|
this.unitOfWork.markRemoved(entity);
|
|
7498
8201
|
}
|
|
8202
|
+
/**
|
|
8203
|
+
* Gets all tracked entities for a specific table.
|
|
8204
|
+
* @param table - The table definition
|
|
8205
|
+
* @returns Array of tracked entities
|
|
8206
|
+
*/
|
|
7499
8207
|
getEntitiesForTable(table) {
|
|
7500
8208
|
return this.unitOfWork.getEntitiesForTable(table);
|
|
7501
8209
|
}
|
|
8210
|
+
/**
|
|
8211
|
+
* Registers an interceptor for flush lifecycle hooks.
|
|
8212
|
+
* @param interceptor - The interceptor to register
|
|
8213
|
+
*/
|
|
7502
8214
|
registerInterceptor(interceptor) {
|
|
7503
8215
|
this.interceptors.push(interceptor);
|
|
7504
8216
|
}
|
|
8217
|
+
/**
|
|
8218
|
+
* Registers a domain event handler.
|
|
8219
|
+
* @param type - The event type
|
|
8220
|
+
* @param handler - The event handler
|
|
8221
|
+
*/
|
|
7505
8222
|
registerDomainEventHandler(type, handler) {
|
|
7506
8223
|
this.domainEvents.on(type, handler);
|
|
7507
8224
|
}
|
|
8225
|
+
/**
|
|
8226
|
+
* Finds an entity by its primary key.
|
|
8227
|
+
* @template TCtor - The entity constructor type
|
|
8228
|
+
* @param entityClass - The entity constructor
|
|
8229
|
+
* @param id - The primary key value
|
|
8230
|
+
* @returns The entity instance or null if not found
|
|
8231
|
+
* @throws If entity metadata is not bootstrapped or table has no primary key
|
|
8232
|
+
*/
|
|
7508
8233
|
async find(entityClass, id) {
|
|
7509
8234
|
const table = getTableDefFromEntity(entityClass);
|
|
7510
8235
|
if (!table) {
|
|
@@ -7523,14 +8248,46 @@ var OrmSession = class {
|
|
|
7523
8248
|
const rows = await executeHydrated(this, qb);
|
|
7524
8249
|
return rows[0] ?? null;
|
|
7525
8250
|
}
|
|
8251
|
+
/**
|
|
8252
|
+
* Finds a single entity using a query builder.
|
|
8253
|
+
* @template TTable - The table type
|
|
8254
|
+
* @param qb - The query builder
|
|
8255
|
+
* @returns The first entity instance or null if not found
|
|
8256
|
+
*/
|
|
7526
8257
|
async findOne(qb) {
|
|
7527
8258
|
const limited = qb.limit(1);
|
|
7528
8259
|
const rows = await executeHydrated(this, limited);
|
|
7529
8260
|
return rows[0] ?? null;
|
|
7530
8261
|
}
|
|
8262
|
+
/**
|
|
8263
|
+
* Finds multiple entities using a query builder.
|
|
8264
|
+
* @template TTable - The table type
|
|
8265
|
+
* @param qb - The query builder
|
|
8266
|
+
* @returns Array of entity instances
|
|
8267
|
+
*/
|
|
7531
8268
|
async findMany(qb) {
|
|
7532
8269
|
return executeHydrated(this, qb);
|
|
7533
8270
|
}
|
|
8271
|
+
/**
|
|
8272
|
+
* Saves an entity graph (root + nested relations) based on a DTO-like payload.
|
|
8273
|
+
* @param entityClass - Root entity constructor
|
|
8274
|
+
* @param payload - DTO payload containing column values and nested relations
|
|
8275
|
+
* @param options - Graph save options
|
|
8276
|
+
* @returns The root entity instance
|
|
8277
|
+
*/
|
|
8278
|
+
async saveGraph(entityClass, payload, options) {
|
|
8279
|
+
const { transactional = true, ...graphOptions } = options ?? {};
|
|
8280
|
+
const execute = () => saveGraphInternal(this, entityClass, payload, graphOptions);
|
|
8281
|
+
if (!transactional) {
|
|
8282
|
+
return execute();
|
|
8283
|
+
}
|
|
8284
|
+
return this.transaction(() => execute());
|
|
8285
|
+
}
|
|
8286
|
+
/**
|
|
8287
|
+
* Persists an entity (either inserts or updates).
|
|
8288
|
+
* @param entity - The entity to persist
|
|
8289
|
+
* @throws If entity metadata is not bootstrapped
|
|
8290
|
+
*/
|
|
7534
8291
|
async persist(entity) {
|
|
7535
8292
|
if (this.unitOfWork.findTracked(entity)) {
|
|
7536
8293
|
return;
|
|
@@ -7547,12 +8304,22 @@ var OrmSession = class {
|
|
|
7547
8304
|
this.trackNew(table, entity);
|
|
7548
8305
|
}
|
|
7549
8306
|
}
|
|
8307
|
+
/**
|
|
8308
|
+
* Marks an entity for removal.
|
|
8309
|
+
* @param entity - The entity to remove
|
|
8310
|
+
*/
|
|
7550
8311
|
async remove(entity) {
|
|
7551
8312
|
this.markRemoved(entity);
|
|
7552
8313
|
}
|
|
8314
|
+
/**
|
|
8315
|
+
* Flushes pending changes to the database.
|
|
8316
|
+
*/
|
|
7553
8317
|
async flush() {
|
|
7554
8318
|
await this.unitOfWork.flush();
|
|
7555
8319
|
}
|
|
8320
|
+
/**
|
|
8321
|
+
* Flushes pending changes with interceptors and relation processing.
|
|
8322
|
+
*/
|
|
7556
8323
|
async flushWithHooks() {
|
|
7557
8324
|
for (const interceptor of this.interceptors) {
|
|
7558
8325
|
await interceptor.beforeFlush?.(this);
|
|
@@ -7564,14 +8331,24 @@ var OrmSession = class {
|
|
|
7564
8331
|
await interceptor.afterFlush?.(this);
|
|
7565
8332
|
}
|
|
7566
8333
|
}
|
|
8334
|
+
/**
|
|
8335
|
+
* Commits the current transaction.
|
|
8336
|
+
*/
|
|
7567
8337
|
async commit() {
|
|
7568
8338
|
await runInTransaction(this.executor, async () => {
|
|
7569
8339
|
await this.flushWithHooks();
|
|
7570
8340
|
});
|
|
7571
8341
|
await this.domainEvents.dispatch(this.unitOfWork.getTracked(), this);
|
|
7572
8342
|
}
|
|
8343
|
+
/**
|
|
8344
|
+
* Executes a function within a transaction.
|
|
8345
|
+
* @template T - The return type
|
|
8346
|
+
* @param fn - The function to execute
|
|
8347
|
+
* @returns The result of the function
|
|
8348
|
+
* @throws If the transaction fails
|
|
8349
|
+
*/
|
|
7573
8350
|
async transaction(fn4) {
|
|
7574
|
-
if (!this.executor.
|
|
8351
|
+
if (!this.executor.capabilities.transactions) {
|
|
7575
8352
|
const result = await fn4(this);
|
|
7576
8353
|
await this.commit();
|
|
7577
8354
|
return result;
|
|
@@ -7580,7 +8357,7 @@ var OrmSession = class {
|
|
|
7580
8357
|
try {
|
|
7581
8358
|
const result = await fn4(this);
|
|
7582
8359
|
await this.flushWithHooks();
|
|
7583
|
-
await this.executor.commitTransaction
|
|
8360
|
+
await this.executor.commitTransaction();
|
|
7584
8361
|
await this.domainEvents.dispatch(this.unitOfWork.getTracked(), this);
|
|
7585
8362
|
return result;
|
|
7586
8363
|
} catch (err) {
|
|
@@ -7588,11 +8365,20 @@ var OrmSession = class {
|
|
|
7588
8365
|
throw err;
|
|
7589
8366
|
}
|
|
7590
8367
|
}
|
|
8368
|
+
/**
|
|
8369
|
+
* Rolls back the current transaction.
|
|
8370
|
+
*/
|
|
7591
8371
|
async rollback() {
|
|
7592
|
-
|
|
8372
|
+
if (this.executor.capabilities.transactions) {
|
|
8373
|
+
await this.executor.rollbackTransaction();
|
|
8374
|
+
}
|
|
7593
8375
|
this.unitOfWork.reset();
|
|
7594
8376
|
this.relationChanges.reset();
|
|
7595
8377
|
}
|
|
8378
|
+
/**
|
|
8379
|
+
* Gets the execution context.
|
|
8380
|
+
* @returns The execution context
|
|
8381
|
+
*/
|
|
7596
8382
|
getExecutionContext() {
|
|
7597
8383
|
return {
|
|
7598
8384
|
dialect: this.orm.dialect,
|
|
@@ -7600,6 +8386,10 @@ var OrmSession = class {
|
|
|
7600
8386
|
interceptors: this.orm.interceptors
|
|
7601
8387
|
};
|
|
7602
8388
|
}
|
|
8389
|
+
/**
|
|
8390
|
+
* Gets the hydration context.
|
|
8391
|
+
* @returns The hydration context
|
|
8392
|
+
*/
|
|
7603
8393
|
getHydrationContext() {
|
|
7604
8394
|
return {
|
|
7605
8395
|
identityMap: this.identityMap,
|
|
@@ -7642,29 +8432,49 @@ var InterceptorPipeline = class {
|
|
|
7642
8432
|
|
|
7643
8433
|
// src/orm/orm.ts
|
|
7644
8434
|
var Orm = class {
|
|
8435
|
+
/**
|
|
8436
|
+
* Creates a new ORM instance.
|
|
8437
|
+
* @param opts - ORM options
|
|
8438
|
+
*/
|
|
7645
8439
|
constructor(opts) {
|
|
7646
8440
|
this.dialect = opts.dialect;
|
|
7647
8441
|
this.interceptors = opts.interceptors ?? new InterceptorPipeline();
|
|
7648
8442
|
this.namingStrategy = opts.namingStrategy ?? new DefaultNamingStrategy();
|
|
7649
8443
|
this.executorFactory = opts.executorFactory;
|
|
7650
8444
|
}
|
|
7651
|
-
|
|
7652
|
-
|
|
8445
|
+
/**
|
|
8446
|
+
* Creates a new ORM session.
|
|
8447
|
+
* @param options - Optional session options
|
|
8448
|
+
* @returns The ORM session
|
|
8449
|
+
*/
|
|
8450
|
+
createSession() {
|
|
8451
|
+
const executor = this.executorFactory.createExecutor();
|
|
7653
8452
|
return new OrmSession({ orm: this, executor });
|
|
7654
8453
|
}
|
|
8454
|
+
/**
|
|
8455
|
+
* Executes a function within a transaction.
|
|
8456
|
+
* @template T - The return type
|
|
8457
|
+
* @param fn - The function to execute
|
|
8458
|
+
* @returns The result of the function
|
|
8459
|
+
* @throws If the transaction fails
|
|
8460
|
+
*/
|
|
7655
8461
|
async transaction(fn4) {
|
|
7656
8462
|
const executor = this.executorFactory.createTransactionalExecutor();
|
|
7657
8463
|
const session = new OrmSession({ orm: this, executor });
|
|
7658
8464
|
try {
|
|
7659
|
-
|
|
7660
|
-
await session.commit();
|
|
7661
|
-
return result;
|
|
8465
|
+
return await session.transaction(() => fn4(session));
|
|
7662
8466
|
} catch (err) {
|
|
7663
|
-
await session.rollback();
|
|
7664
8467
|
throw err;
|
|
7665
8468
|
} finally {
|
|
8469
|
+
await session.dispose();
|
|
7666
8470
|
}
|
|
7667
8471
|
}
|
|
8472
|
+
/**
|
|
8473
|
+
* Shuts down the ORM and releases underlying resources (pools, timers).
|
|
8474
|
+
*/
|
|
8475
|
+
async dispose() {
|
|
8476
|
+
await this.executorFactory.dispose();
|
|
8477
|
+
}
|
|
7668
8478
|
};
|
|
7669
8479
|
|
|
7670
8480
|
// src/decorators/decorator-metadata.ts
|
|
@@ -7923,18 +8733,245 @@ function rowsToQueryResult(rows) {
|
|
|
7923
8733
|
return { columns, values };
|
|
7924
8734
|
}
|
|
7925
8735
|
function createExecutorFromQueryRunner(runner) {
|
|
8736
|
+
const supportsTransactions = typeof runner.beginTransaction === "function" && typeof runner.commitTransaction === "function" && typeof runner.rollbackTransaction === "function";
|
|
7926
8737
|
return {
|
|
8738
|
+
capabilities: {
|
|
8739
|
+
transactions: supportsTransactions
|
|
8740
|
+
},
|
|
7927
8741
|
async executeSql(sql, params) {
|
|
7928
8742
|
const rows = await runner.query(sql, params);
|
|
7929
8743
|
const result = rowsToQueryResult(rows);
|
|
7930
8744
|
return [result];
|
|
7931
8745
|
},
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
8746
|
+
async beginTransaction() {
|
|
8747
|
+
if (!supportsTransactions) {
|
|
8748
|
+
throw new Error("Transactions are not supported by this executor");
|
|
8749
|
+
}
|
|
8750
|
+
await runner.beginTransaction.call(runner);
|
|
8751
|
+
},
|
|
8752
|
+
async commitTransaction() {
|
|
8753
|
+
if (!supportsTransactions) {
|
|
8754
|
+
throw new Error("Transactions are not supported by this executor");
|
|
8755
|
+
}
|
|
8756
|
+
await runner.commitTransaction.call(runner);
|
|
8757
|
+
},
|
|
8758
|
+
async rollbackTransaction() {
|
|
8759
|
+
if (!supportsTransactions) {
|
|
8760
|
+
throw new Error("Transactions are not supported by this executor");
|
|
8761
|
+
}
|
|
8762
|
+
await runner.rollbackTransaction.call(runner);
|
|
8763
|
+
},
|
|
8764
|
+
async dispose() {
|
|
8765
|
+
await runner.dispose?.call(runner);
|
|
8766
|
+
}
|
|
7935
8767
|
};
|
|
7936
8768
|
}
|
|
7937
8769
|
|
|
8770
|
+
// src/core/execution/pooling/pool.ts
|
|
8771
|
+
var deferred = () => {
|
|
8772
|
+
let resolve;
|
|
8773
|
+
let reject;
|
|
8774
|
+
const promise = new Promise((res, rej) => {
|
|
8775
|
+
resolve = res;
|
|
8776
|
+
reject = rej;
|
|
8777
|
+
});
|
|
8778
|
+
return { promise, resolve, reject };
|
|
8779
|
+
};
|
|
8780
|
+
var Pool = class {
|
|
8781
|
+
constructor(adapter, options) {
|
|
8782
|
+
this.destroyed = false;
|
|
8783
|
+
this.creating = 0;
|
|
8784
|
+
this.leased = 0;
|
|
8785
|
+
this.idle = [];
|
|
8786
|
+
this.waiters = [];
|
|
8787
|
+
this.reapTimer = null;
|
|
8788
|
+
if (!Number.isFinite(options.max) || options.max <= 0) {
|
|
8789
|
+
throw new Error("Pool options.max must be a positive number");
|
|
8790
|
+
}
|
|
8791
|
+
this.adapter = adapter;
|
|
8792
|
+
this.options = { max: options.max, ...options };
|
|
8793
|
+
const idleTimeout = this.options.idleTimeoutMillis;
|
|
8794
|
+
if (idleTimeout && idleTimeout > 0) {
|
|
8795
|
+
const interval = this.options.reapIntervalMillis ?? Math.max(1e3, Math.floor(idleTimeout / 2));
|
|
8796
|
+
this.reapTimer = setInterval(() => {
|
|
8797
|
+
void this.reapIdle();
|
|
8798
|
+
}, interval);
|
|
8799
|
+
this.reapTimer.unref?.();
|
|
8800
|
+
}
|
|
8801
|
+
const min2 = this.options.min ?? 0;
|
|
8802
|
+
if (min2 > 0) {
|
|
8803
|
+
void this.warm(min2);
|
|
8804
|
+
}
|
|
8805
|
+
}
|
|
8806
|
+
/**
|
|
8807
|
+
* Acquire a resource lease.
|
|
8808
|
+
* The returned lease MUST be released or destroyed.
|
|
8809
|
+
*/
|
|
8810
|
+
async acquire() {
|
|
8811
|
+
if (this.destroyed) {
|
|
8812
|
+
throw new Error("Pool is destroyed");
|
|
8813
|
+
}
|
|
8814
|
+
const idle = await this.takeIdleValidated();
|
|
8815
|
+
if (idle) {
|
|
8816
|
+
this.leased++;
|
|
8817
|
+
return this.makeLease(idle);
|
|
8818
|
+
}
|
|
8819
|
+
if (this.totalLive() < this.options.max) {
|
|
8820
|
+
this.creating++;
|
|
8821
|
+
try {
|
|
8822
|
+
const created = await this.adapter.create();
|
|
8823
|
+
this.leased++;
|
|
8824
|
+
return this.makeLease(created);
|
|
8825
|
+
} finally {
|
|
8826
|
+
this.creating--;
|
|
8827
|
+
}
|
|
8828
|
+
}
|
|
8829
|
+
const waiter = deferred();
|
|
8830
|
+
this.waiters.push(waiter);
|
|
8831
|
+
const timeout = this.options.acquireTimeoutMillis;
|
|
8832
|
+
let timer = null;
|
|
8833
|
+
if (timeout && timeout > 0) {
|
|
8834
|
+
timer = setTimeout(() => {
|
|
8835
|
+
const idx = this.waiters.indexOf(waiter);
|
|
8836
|
+
if (idx >= 0) this.waiters.splice(idx, 1);
|
|
8837
|
+
waiter.reject(new Error("Pool acquire timeout"));
|
|
8838
|
+
}, timeout);
|
|
8839
|
+
timer.unref?.();
|
|
8840
|
+
}
|
|
8841
|
+
try {
|
|
8842
|
+
return await waiter.promise;
|
|
8843
|
+
} finally {
|
|
8844
|
+
if (timer) clearTimeout(timer);
|
|
8845
|
+
}
|
|
8846
|
+
}
|
|
8847
|
+
/** Destroy pool and all idle resources; waits for in-flight creations to settle. */
|
|
8848
|
+
async destroy() {
|
|
8849
|
+
if (this.destroyed) return;
|
|
8850
|
+
this.destroyed = true;
|
|
8851
|
+
if (this.reapTimer) {
|
|
8852
|
+
clearInterval(this.reapTimer);
|
|
8853
|
+
this.reapTimer = null;
|
|
8854
|
+
}
|
|
8855
|
+
while (this.waiters.length) {
|
|
8856
|
+
this.waiters.shift().reject(new Error("Pool destroyed"));
|
|
8857
|
+
}
|
|
8858
|
+
while (this.idle.length) {
|
|
8859
|
+
const entry = this.idle.shift();
|
|
8860
|
+
await this.adapter.destroy(entry.resource);
|
|
8861
|
+
}
|
|
8862
|
+
}
|
|
8863
|
+
totalLive() {
|
|
8864
|
+
return this.idle.length + this.leased + this.creating;
|
|
8865
|
+
}
|
|
8866
|
+
makeLease(resource) {
|
|
8867
|
+
let done = false;
|
|
8868
|
+
return {
|
|
8869
|
+
resource,
|
|
8870
|
+
release: async () => {
|
|
8871
|
+
if (done) return;
|
|
8872
|
+
done = true;
|
|
8873
|
+
await this.releaseResource(resource);
|
|
8874
|
+
},
|
|
8875
|
+
destroy: async () => {
|
|
8876
|
+
if (done) return;
|
|
8877
|
+
done = true;
|
|
8878
|
+
await this.destroyResource(resource);
|
|
8879
|
+
}
|
|
8880
|
+
};
|
|
8881
|
+
}
|
|
8882
|
+
async releaseResource(resource) {
|
|
8883
|
+
this.leased = Math.max(0, this.leased - 1);
|
|
8884
|
+
if (this.destroyed) {
|
|
8885
|
+
await this.adapter.destroy(resource);
|
|
8886
|
+
return;
|
|
8887
|
+
}
|
|
8888
|
+
const next = this.waiters.shift();
|
|
8889
|
+
if (next) {
|
|
8890
|
+
this.leased++;
|
|
8891
|
+
next.resolve(this.makeLease(resource));
|
|
8892
|
+
return;
|
|
8893
|
+
}
|
|
8894
|
+
this.idle.push({ resource, lastUsedAt: Date.now() });
|
|
8895
|
+
await this.trimToMinMax();
|
|
8896
|
+
}
|
|
8897
|
+
async destroyResource(resource) {
|
|
8898
|
+
this.leased = Math.max(0, this.leased - 1);
|
|
8899
|
+
await this.adapter.destroy(resource);
|
|
8900
|
+
if (!this.destroyed && this.waiters.length && this.totalLive() < this.options.max) {
|
|
8901
|
+
const waiter = this.waiters.shift();
|
|
8902
|
+
this.creating++;
|
|
8903
|
+
try {
|
|
8904
|
+
const created = await this.adapter.create();
|
|
8905
|
+
this.leased++;
|
|
8906
|
+
waiter.resolve(this.makeLease(created));
|
|
8907
|
+
} catch (err) {
|
|
8908
|
+
waiter.reject(err);
|
|
8909
|
+
} finally {
|
|
8910
|
+
this.creating--;
|
|
8911
|
+
}
|
|
8912
|
+
}
|
|
8913
|
+
}
|
|
8914
|
+
async takeIdleValidated() {
|
|
8915
|
+
while (this.idle.length) {
|
|
8916
|
+
const entry = this.idle.pop();
|
|
8917
|
+
if (!this.adapter.validate) {
|
|
8918
|
+
return entry.resource;
|
|
8919
|
+
}
|
|
8920
|
+
const ok = await this.adapter.validate(entry.resource);
|
|
8921
|
+
if (ok) {
|
|
8922
|
+
return entry.resource;
|
|
8923
|
+
}
|
|
8924
|
+
await this.adapter.destroy(entry.resource);
|
|
8925
|
+
}
|
|
8926
|
+
return null;
|
|
8927
|
+
}
|
|
8928
|
+
async reapIdle() {
|
|
8929
|
+
if (this.destroyed) return;
|
|
8930
|
+
const idleTimeout = this.options.idleTimeoutMillis;
|
|
8931
|
+
if (!idleTimeout || idleTimeout <= 0) return;
|
|
8932
|
+
const now2 = Date.now();
|
|
8933
|
+
const min2 = this.options.min ?? 0;
|
|
8934
|
+
const keep = [];
|
|
8935
|
+
const kill = [];
|
|
8936
|
+
for (const entry of this.idle) {
|
|
8937
|
+
const expired = now2 - entry.lastUsedAt >= idleTimeout;
|
|
8938
|
+
if (expired) kill.push(entry);
|
|
8939
|
+
else keep.push(entry);
|
|
8940
|
+
}
|
|
8941
|
+
while (keep.length < min2 && kill.length) {
|
|
8942
|
+
keep.push(kill.pop());
|
|
8943
|
+
}
|
|
8944
|
+
this.idle.length = 0;
|
|
8945
|
+
this.idle.push(...keep);
|
|
8946
|
+
for (const entry of kill) {
|
|
8947
|
+
await this.adapter.destroy(entry.resource);
|
|
8948
|
+
}
|
|
8949
|
+
}
|
|
8950
|
+
async warm(targetMin) {
|
|
8951
|
+
const min2 = Math.max(0, targetMin);
|
|
8952
|
+
while (!this.destroyed && this.idle.length < min2 && this.totalLive() < this.options.max) {
|
|
8953
|
+
this.creating++;
|
|
8954
|
+
try {
|
|
8955
|
+
const created = await this.adapter.create();
|
|
8956
|
+
this.idle.push({ resource: created, lastUsedAt: Date.now() });
|
|
8957
|
+
} catch {
|
|
8958
|
+
break;
|
|
8959
|
+
} finally {
|
|
8960
|
+
this.creating--;
|
|
8961
|
+
}
|
|
8962
|
+
}
|
|
8963
|
+
}
|
|
8964
|
+
async trimToMinMax() {
|
|
8965
|
+
const max2 = this.options.max;
|
|
8966
|
+
const min2 = this.options.min ?? 0;
|
|
8967
|
+
while (this.totalLive() > max2 && this.idle.length > min2) {
|
|
8968
|
+
const entry = this.idle.shift();
|
|
8969
|
+
if (!entry) break;
|
|
8970
|
+
await this.adapter.destroy(entry.resource);
|
|
8971
|
+
}
|
|
8972
|
+
}
|
|
8973
|
+
};
|
|
8974
|
+
|
|
7938
8975
|
// src/core/execution/executors/postgres-executor.ts
|
|
7939
8976
|
function createPostgresExecutor(client) {
|
|
7940
8977
|
return createExecutorFromQueryRunner({
|
|
@@ -7956,7 +8993,11 @@ function createPostgresExecutor(client) {
|
|
|
7956
8993
|
|
|
7957
8994
|
// src/core/execution/executors/mysql-executor.ts
|
|
7958
8995
|
function createMysqlExecutor(client) {
|
|
8996
|
+
const supportsTransactions = typeof client.beginTransaction === "function" && typeof client.commit === "function" && typeof client.rollback === "function";
|
|
7959
8997
|
return {
|
|
8998
|
+
capabilities: {
|
|
8999
|
+
transactions: supportsTransactions
|
|
9000
|
+
},
|
|
7960
9001
|
async executeSql(sql, params) {
|
|
7961
9002
|
const [rows] = await client.query(sql, params);
|
|
7962
9003
|
if (!Array.isArray(rows)) {
|
|
@@ -7968,53 +9009,94 @@ function createMysqlExecutor(client) {
|
|
|
7968
9009
|
return [result];
|
|
7969
9010
|
},
|
|
7970
9011
|
async beginTransaction() {
|
|
7971
|
-
if (!
|
|
9012
|
+
if (!supportsTransactions) {
|
|
9013
|
+
throw new Error("Transactions are not supported by this executor");
|
|
9014
|
+
}
|
|
7972
9015
|
await client.beginTransaction();
|
|
7973
9016
|
},
|
|
7974
9017
|
async commitTransaction() {
|
|
7975
|
-
if (!
|
|
9018
|
+
if (!supportsTransactions) {
|
|
9019
|
+
throw new Error("Transactions are not supported by this executor");
|
|
9020
|
+
}
|
|
7976
9021
|
await client.commit();
|
|
7977
9022
|
},
|
|
7978
9023
|
async rollbackTransaction() {
|
|
7979
|
-
if (!
|
|
9024
|
+
if (!supportsTransactions) {
|
|
9025
|
+
throw new Error("Transactions are not supported by this executor");
|
|
9026
|
+
}
|
|
7980
9027
|
await client.rollback();
|
|
9028
|
+
},
|
|
9029
|
+
async dispose() {
|
|
7981
9030
|
}
|
|
7982
9031
|
};
|
|
7983
9032
|
}
|
|
7984
9033
|
|
|
7985
9034
|
// src/core/execution/executors/sqlite-executor.ts
|
|
7986
9035
|
function createSqliteExecutor(client) {
|
|
9036
|
+
const supportsTransactions = typeof client.beginTransaction === "function" && typeof client.commitTransaction === "function" && typeof client.rollbackTransaction === "function";
|
|
7987
9037
|
return {
|
|
9038
|
+
capabilities: {
|
|
9039
|
+
transactions: supportsTransactions
|
|
9040
|
+
},
|
|
7988
9041
|
async executeSql(sql, params) {
|
|
7989
9042
|
const rows = await client.all(sql, params);
|
|
7990
9043
|
const result = rowsToQueryResult(rows);
|
|
7991
9044
|
return [result];
|
|
7992
9045
|
},
|
|
7993
|
-
|
|
7994
|
-
|
|
7995
|
-
|
|
9046
|
+
async beginTransaction() {
|
|
9047
|
+
if (!supportsTransactions) {
|
|
9048
|
+
throw new Error("Transactions are not supported by this executor");
|
|
9049
|
+
}
|
|
9050
|
+
await client.beginTransaction();
|
|
9051
|
+
},
|
|
9052
|
+
async commitTransaction() {
|
|
9053
|
+
if (!supportsTransactions) {
|
|
9054
|
+
throw new Error("Transactions are not supported by this executor");
|
|
9055
|
+
}
|
|
9056
|
+
await client.commitTransaction();
|
|
9057
|
+
},
|
|
9058
|
+
async rollbackTransaction() {
|
|
9059
|
+
if (!supportsTransactions) {
|
|
9060
|
+
throw new Error("Transactions are not supported by this executor");
|
|
9061
|
+
}
|
|
9062
|
+
await client.rollbackTransaction();
|
|
9063
|
+
},
|
|
9064
|
+
async dispose() {
|
|
9065
|
+
}
|
|
7996
9066
|
};
|
|
7997
9067
|
}
|
|
7998
9068
|
|
|
7999
9069
|
// src/core/execution/executors/mssql-executor.ts
|
|
8000
9070
|
function createMssqlExecutor(client) {
|
|
9071
|
+
const supportsTransactions = typeof client.beginTransaction === "function" && typeof client.commit === "function" && typeof client.rollback === "function";
|
|
8001
9072
|
return {
|
|
9073
|
+
capabilities: {
|
|
9074
|
+
transactions: supportsTransactions
|
|
9075
|
+
},
|
|
8002
9076
|
async executeSql(sql, params) {
|
|
8003
9077
|
const { recordset } = await client.query(sql, params);
|
|
8004
9078
|
const result = rowsToQueryResult(recordset ?? []);
|
|
8005
9079
|
return [result];
|
|
8006
9080
|
},
|
|
8007
9081
|
async beginTransaction() {
|
|
8008
|
-
if (!
|
|
9082
|
+
if (!supportsTransactions) {
|
|
9083
|
+
throw new Error("Transactions are not supported by this executor");
|
|
9084
|
+
}
|
|
8009
9085
|
await client.beginTransaction();
|
|
8010
9086
|
},
|
|
8011
9087
|
async commitTransaction() {
|
|
8012
|
-
if (!
|
|
9088
|
+
if (!supportsTransactions) {
|
|
9089
|
+
throw new Error("Transactions are not supported by this executor");
|
|
9090
|
+
}
|
|
8013
9091
|
await client.commit();
|
|
8014
9092
|
},
|
|
8015
9093
|
async rollbackTransaction() {
|
|
8016
|
-
if (!
|
|
9094
|
+
if (!supportsTransactions) {
|
|
9095
|
+
throw new Error("Transactions are not supported by this executor");
|
|
9096
|
+
}
|
|
8017
9097
|
await client.rollback();
|
|
9098
|
+
},
|
|
9099
|
+
async dispose() {
|
|
8018
9100
|
}
|
|
8019
9101
|
};
|
|
8020
9102
|
}
|
|
@@ -8083,6 +9165,86 @@ function createTediousExecutor(connection, module, options) {
|
|
|
8083
9165
|
const client = createTediousMssqlClient(connection, module, options);
|
|
8084
9166
|
return createMssqlExecutor(client);
|
|
8085
9167
|
}
|
|
9168
|
+
|
|
9169
|
+
// src/orm/pooled-executor-factory.ts
|
|
9170
|
+
function createPooledExecutorFactory(opts) {
|
|
9171
|
+
const { pool, adapter } = opts;
|
|
9172
|
+
const makeExecutor = (mode) => {
|
|
9173
|
+
let lease = null;
|
|
9174
|
+
const getLease = async () => {
|
|
9175
|
+
if (lease) return lease;
|
|
9176
|
+
lease = await pool.acquire();
|
|
9177
|
+
return lease;
|
|
9178
|
+
};
|
|
9179
|
+
const executeWithConn = async (conn, sql, params) => {
|
|
9180
|
+
const rows = await adapter.query(conn, sql, params);
|
|
9181
|
+
return [rowsToQueryResult(rows)];
|
|
9182
|
+
};
|
|
9183
|
+
return {
|
|
9184
|
+
capabilities: { transactions: true },
|
|
9185
|
+
async executeSql(sql, params) {
|
|
9186
|
+
if (mode === "sticky") {
|
|
9187
|
+
const l2 = await getLease();
|
|
9188
|
+
return executeWithConn(l2.resource, sql, params);
|
|
9189
|
+
}
|
|
9190
|
+
if (lease) {
|
|
9191
|
+
return executeWithConn(lease.resource, sql, params);
|
|
9192
|
+
}
|
|
9193
|
+
const l = await pool.acquire();
|
|
9194
|
+
try {
|
|
9195
|
+
return await executeWithConn(l.resource, sql, params);
|
|
9196
|
+
} finally {
|
|
9197
|
+
await l.release();
|
|
9198
|
+
}
|
|
9199
|
+
},
|
|
9200
|
+
async beginTransaction() {
|
|
9201
|
+
const l = await getLease();
|
|
9202
|
+
await adapter.beginTransaction(l.resource);
|
|
9203
|
+
},
|
|
9204
|
+
async commitTransaction() {
|
|
9205
|
+
if (!lease) {
|
|
9206
|
+
throw new Error("commitTransaction called without an active transaction");
|
|
9207
|
+
}
|
|
9208
|
+
const l = lease;
|
|
9209
|
+
try {
|
|
9210
|
+
await adapter.commitTransaction(l.resource);
|
|
9211
|
+
} finally {
|
|
9212
|
+
lease = null;
|
|
9213
|
+
await l.release();
|
|
9214
|
+
}
|
|
9215
|
+
},
|
|
9216
|
+
async rollbackTransaction() {
|
|
9217
|
+
if (!lease) {
|
|
9218
|
+
return;
|
|
9219
|
+
}
|
|
9220
|
+
const l = lease;
|
|
9221
|
+
try {
|
|
9222
|
+
await adapter.rollbackTransaction(l.resource);
|
|
9223
|
+
} finally {
|
|
9224
|
+
lease = null;
|
|
9225
|
+
await l.release();
|
|
9226
|
+
}
|
|
9227
|
+
},
|
|
9228
|
+
async dispose() {
|
|
9229
|
+
if (!lease) return;
|
|
9230
|
+
const l = lease;
|
|
9231
|
+
lease = null;
|
|
9232
|
+
await l.release();
|
|
9233
|
+
}
|
|
9234
|
+
};
|
|
9235
|
+
};
|
|
9236
|
+
return {
|
|
9237
|
+
createExecutor() {
|
|
9238
|
+
return makeExecutor("session");
|
|
9239
|
+
},
|
|
9240
|
+
createTransactionalExecutor() {
|
|
9241
|
+
return makeExecutor("sticky");
|
|
9242
|
+
},
|
|
9243
|
+
async dispose() {
|
|
9244
|
+
await pool.destroy();
|
|
9245
|
+
}
|
|
9246
|
+
};
|
|
9247
|
+
}
|
|
8086
9248
|
export {
|
|
8087
9249
|
AsyncLocalStorage,
|
|
8088
9250
|
BelongsTo,
|
|
@@ -8101,6 +9263,7 @@ export {
|
|
|
8101
9263
|
MySqlDialect,
|
|
8102
9264
|
Orm,
|
|
8103
9265
|
OrmSession,
|
|
9266
|
+
Pool,
|
|
8104
9267
|
PostgresDialect,
|
|
8105
9268
|
PrimaryKey,
|
|
8106
9269
|
RelationKinds,
|
|
@@ -8146,6 +9309,7 @@ export {
|
|
|
8146
9309
|
createLiteral,
|
|
8147
9310
|
createMssqlExecutor,
|
|
8148
9311
|
createMysqlExecutor,
|
|
9312
|
+
createPooledExecutorFactory,
|
|
8149
9313
|
createPostgresExecutor,
|
|
8150
9314
|
createQueryLoggingExecutor,
|
|
8151
9315
|
createSqliteExecutor,
|
|
@@ -8187,6 +9351,7 @@ export {
|
|
|
8187
9351
|
hasOne,
|
|
8188
9352
|
hydrateRows,
|
|
8189
9353
|
inList,
|
|
9354
|
+
inSubquery,
|
|
8190
9355
|
instr,
|
|
8191
9356
|
introspectSchema,
|
|
8192
9357
|
isCaseExpressionNode,
|
|
@@ -8227,6 +9392,7 @@ export {
|
|
|
8227
9392
|
notBetween,
|
|
8228
9393
|
notExists,
|
|
8229
9394
|
notInList,
|
|
9395
|
+
notInSubquery,
|
|
8230
9396
|
notLike,
|
|
8231
9397
|
now,
|
|
8232
9398
|
ntile,
|
|
@@ -8262,6 +9428,7 @@ export {
|
|
|
8262
9428
|
substr,
|
|
8263
9429
|
sum,
|
|
8264
9430
|
synchronizeSchema,
|
|
9431
|
+
tableRef,
|
|
8265
9432
|
tan,
|
|
8266
9433
|
toColumnRef,
|
|
8267
9434
|
toTableRef,
|