metal-orm 1.0.16 → 1.0.17
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 +33 -37
- package/dist/decorators/index.cjs +152 -23
- package/dist/decorators/index.cjs.map +1 -1
- package/dist/decorators/index.d.cts +1 -1
- package/dist/decorators/index.d.ts +1 -1
- package/dist/decorators/index.js +152 -23
- package/dist/decorators/index.js.map +1 -1
- package/dist/index.cjs +322 -115
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +53 -4
- package/dist/index.d.ts +53 -4
- package/dist/index.js +316 -115
- package/dist/index.js.map +1 -1
- package/dist/{select-BKZrMRCQ.d.cts → select-BPCn6MOH.d.cts} +183 -64
- package/dist/{select-BKZrMRCQ.d.ts → select-BPCn6MOH.d.ts} +183 -64
- package/package.json +2 -1
- package/src/core/ast/aggregate-functions.ts +50 -4
- package/src/core/ast/expression-builders.ts +22 -15
- package/src/core/ast/expression-nodes.ts +6 -0
- package/src/core/ddl/introspect/functions/postgres.ts +2 -6
- package/src/core/dialect/abstract.ts +12 -8
- package/src/core/dialect/mssql/functions.ts +24 -15
- package/src/core/dialect/postgres/functions.ts +33 -24
- package/src/core/dialect/sqlite/functions.ts +19 -12
- package/src/core/functions/datetime.ts +2 -1
- package/src/core/functions/numeric.ts +2 -1
- package/src/core/functions/standard-strategy.ts +52 -12
- package/src/core/functions/text.ts +2 -1
- package/src/core/functions/types.ts +8 -8
- package/src/index.ts +5 -4
- package/src/orm/domain-event-bus.ts +43 -25
- package/src/orm/entity-meta.ts +40 -0
- package/src/orm/execution-context.ts +6 -0
- package/src/orm/hydration-context.ts +6 -4
- package/src/orm/orm-session.ts +35 -24
- package/src/orm/orm.ts +10 -10
- package/src/orm/query-logger.ts +15 -0
- package/src/orm/runtime-types.ts +60 -2
- package/src/orm/transaction-runner.ts +7 -0
- package/src/orm/unit-of-work.ts +1 -0
- package/src/query-builder/insert-query-state.ts +13 -3
- package/src/query-builder/select-helpers.ts +50 -0
- package/src/query-builder/select.ts +122 -30
- package/src/query-builder/update-query-state.ts +31 -9
- package/src/schema/types.ts +16 -6
package/dist/index.js
CHANGED
|
@@ -237,10 +237,13 @@ var isExpressionSelectionNode = (node) => isFunctionNode(node) || isCaseExpressi
|
|
|
237
237
|
|
|
238
238
|
// src/core/ast/expression-builders.ts
|
|
239
239
|
var valueToOperand = (value) => {
|
|
240
|
-
if (value
|
|
241
|
-
return
|
|
240
|
+
if (isOperandNode(value)) {
|
|
241
|
+
return value;
|
|
242
242
|
}
|
|
243
|
-
return
|
|
243
|
+
return {
|
|
244
|
+
type: "Literal",
|
|
245
|
+
value
|
|
246
|
+
};
|
|
244
247
|
};
|
|
245
248
|
var toNode = (col2) => {
|
|
246
249
|
if (isOperandNode(col2)) return col2;
|
|
@@ -251,10 +254,11 @@ var toLiteralNode = (value) => ({
|
|
|
251
254
|
type: "Literal",
|
|
252
255
|
value
|
|
253
256
|
});
|
|
257
|
+
var isLiteralValue = (value) => value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
258
|
+
var isValueOperandInput = (value) => isOperandNode(value) || isLiteralValue(value);
|
|
254
259
|
var toOperand = (val) => {
|
|
255
|
-
if (val
|
|
256
|
-
|
|
257
|
-
return { type: "Literal", value: val };
|
|
260
|
+
if (isLiteralValue(val)) {
|
|
261
|
+
return valueToOperand(val);
|
|
258
262
|
}
|
|
259
263
|
return toNode(val);
|
|
260
264
|
};
|
|
@@ -400,6 +404,62 @@ var windowFunction = (name, args = [], partitionBy, orderBy) => {
|
|
|
400
404
|
return buildWindowFunction(name, nodeArgs, partitionNodes, orderNodes);
|
|
401
405
|
};
|
|
402
406
|
|
|
407
|
+
// src/core/sql/sql.ts
|
|
408
|
+
var SQL_OPERATORS = {
|
|
409
|
+
/** Equality operator */
|
|
410
|
+
EQUALS: "=",
|
|
411
|
+
/** Not equals operator */
|
|
412
|
+
NOT_EQUALS: "!=",
|
|
413
|
+
/** Greater than operator */
|
|
414
|
+
GREATER_THAN: ">",
|
|
415
|
+
/** Greater than or equal operator */
|
|
416
|
+
GREATER_OR_EQUAL: ">=",
|
|
417
|
+
/** Less than operator */
|
|
418
|
+
LESS_THAN: "<",
|
|
419
|
+
/** Less than or equal operator */
|
|
420
|
+
LESS_OR_EQUAL: "<=",
|
|
421
|
+
/** LIKE pattern matching operator */
|
|
422
|
+
LIKE: "LIKE",
|
|
423
|
+
/** NOT LIKE pattern matching operator */
|
|
424
|
+
NOT_LIKE: "NOT LIKE",
|
|
425
|
+
/** IN membership operator */
|
|
426
|
+
IN: "IN",
|
|
427
|
+
/** NOT IN membership operator */
|
|
428
|
+
NOT_IN: "NOT IN",
|
|
429
|
+
/** BETWEEN range operator */
|
|
430
|
+
BETWEEN: "BETWEEN",
|
|
431
|
+
/** NOT BETWEEN range operator */
|
|
432
|
+
NOT_BETWEEN: "NOT BETWEEN",
|
|
433
|
+
/** IS NULL null check operator */
|
|
434
|
+
IS_NULL: "IS NULL",
|
|
435
|
+
/** IS NOT NULL null check operator */
|
|
436
|
+
IS_NOT_NULL: "IS NOT NULL",
|
|
437
|
+
/** Logical AND operator */
|
|
438
|
+
AND: "AND",
|
|
439
|
+
/** Logical OR operator */
|
|
440
|
+
OR: "OR",
|
|
441
|
+
/** EXISTS operator */
|
|
442
|
+
EXISTS: "EXISTS",
|
|
443
|
+
/** NOT EXISTS operator */
|
|
444
|
+
NOT_EXISTS: "NOT EXISTS"
|
|
445
|
+
};
|
|
446
|
+
var JOIN_KINDS = {
|
|
447
|
+
/** INNER JOIN type */
|
|
448
|
+
INNER: "INNER",
|
|
449
|
+
/** LEFT JOIN type */
|
|
450
|
+
LEFT: "LEFT",
|
|
451
|
+
/** RIGHT JOIN type */
|
|
452
|
+
RIGHT: "RIGHT",
|
|
453
|
+
/** CROSS JOIN type */
|
|
454
|
+
CROSS: "CROSS"
|
|
455
|
+
};
|
|
456
|
+
var ORDER_DIRECTIONS = {
|
|
457
|
+
/** Ascending order */
|
|
458
|
+
ASC: "ASC",
|
|
459
|
+
/** Descending order */
|
|
460
|
+
DESC: "DESC"
|
|
461
|
+
};
|
|
462
|
+
|
|
403
463
|
// src/core/ast/aggregate-functions.ts
|
|
404
464
|
var buildAggregate = (name) => (col2) => ({
|
|
405
465
|
type: "Function",
|
|
@@ -409,6 +469,20 @@ var buildAggregate = (name) => (col2) => ({
|
|
|
409
469
|
var count = buildAggregate("COUNT");
|
|
410
470
|
var sum = buildAggregate("SUM");
|
|
411
471
|
var avg = buildAggregate("AVG");
|
|
472
|
+
var min = buildAggregate("MIN");
|
|
473
|
+
var max = buildAggregate("MAX");
|
|
474
|
+
var toOrderByNode = (order) => ({
|
|
475
|
+
type: "OrderBy",
|
|
476
|
+
column: columnOperand(order.column),
|
|
477
|
+
direction: order.direction ?? ORDER_DIRECTIONS.ASC
|
|
478
|
+
});
|
|
479
|
+
var groupConcat = (col2, options) => ({
|
|
480
|
+
type: "Function",
|
|
481
|
+
name: "GROUP_CONCAT",
|
|
482
|
+
args: [columnOperand(col2)],
|
|
483
|
+
orderBy: options?.orderBy?.map(toOrderByNode),
|
|
484
|
+
separator: options?.separator !== void 0 ? valueToOperand(options.separator) : void 0
|
|
485
|
+
});
|
|
412
486
|
|
|
413
487
|
// src/core/ast/expression-visitor.ts
|
|
414
488
|
var expressionDispatchers = /* @__PURE__ */ new Map();
|
|
@@ -500,12 +574,17 @@ var toTableRef = (table) => ({
|
|
|
500
574
|
});
|
|
501
575
|
|
|
502
576
|
// src/core/functions/standard-strategy.ts
|
|
503
|
-
var StandardFunctionStrategy = class {
|
|
577
|
+
var StandardFunctionStrategy = class _StandardFunctionStrategy {
|
|
504
578
|
constructor() {
|
|
505
579
|
this.renderers = /* @__PURE__ */ new Map();
|
|
506
580
|
this.registerStandard();
|
|
507
581
|
}
|
|
508
582
|
registerStandard() {
|
|
583
|
+
this.add("COUNT", ({ compiledArgs }) => `COUNT(${compiledArgs.join(", ")})`);
|
|
584
|
+
this.add("SUM", ({ compiledArgs }) => `SUM(${compiledArgs[0]})`);
|
|
585
|
+
this.add("AVG", ({ compiledArgs }) => `AVG(${compiledArgs[0]})`);
|
|
586
|
+
this.add("MIN", ({ compiledArgs }) => `MIN(${compiledArgs[0]})`);
|
|
587
|
+
this.add("MAX", ({ compiledArgs }) => `MAX(${compiledArgs[0]})`);
|
|
509
588
|
this.add("ABS", ({ compiledArgs }) => `ABS(${compiledArgs[0]})`);
|
|
510
589
|
this.add("UPPER", ({ compiledArgs }) => `UPPER(${compiledArgs[0]})`);
|
|
511
590
|
this.add("LOWER", ({ compiledArgs }) => `LOWER(${compiledArgs[0]})`);
|
|
@@ -532,6 +611,7 @@ var StandardFunctionStrategy = class {
|
|
|
532
611
|
this.add("DAY_OF_WEEK", ({ compiledArgs }) => `DAYOFWEEK(${compiledArgs[0]})`);
|
|
533
612
|
this.add("WEEK_OF_YEAR", ({ compiledArgs }) => `WEEKOFYEAR(${compiledArgs[0]})`);
|
|
534
613
|
this.add("DATE_TRUNC", ({ compiledArgs }) => `DATE_TRUNC(${compiledArgs[0]}, ${compiledArgs[1]})`);
|
|
614
|
+
this.add("GROUP_CONCAT", (ctx) => this.renderGroupConcat(ctx));
|
|
535
615
|
}
|
|
536
616
|
add(name, renderer) {
|
|
537
617
|
this.renderers.set(name, renderer);
|
|
@@ -539,6 +619,36 @@ var StandardFunctionStrategy = class {
|
|
|
539
619
|
getRenderer(name) {
|
|
540
620
|
return this.renderers.get(name);
|
|
541
621
|
}
|
|
622
|
+
renderGroupConcat(ctx) {
|
|
623
|
+
const arg = ctx.compiledArgs[0];
|
|
624
|
+
const orderClause = this.buildOrderByExpression(ctx);
|
|
625
|
+
const orderSegment = orderClause ? ` ${orderClause}` : "";
|
|
626
|
+
const separatorClause = this.formatGroupConcatSeparator(ctx);
|
|
627
|
+
return `GROUP_CONCAT(${arg}${orderSegment}${separatorClause})`;
|
|
628
|
+
}
|
|
629
|
+
buildOrderByExpression(ctx) {
|
|
630
|
+
const orderBy = ctx.node.orderBy;
|
|
631
|
+
if (!orderBy || orderBy.length === 0) {
|
|
632
|
+
return "";
|
|
633
|
+
}
|
|
634
|
+
const parts = orderBy.map((order) => `${ctx.compileOperand(order.column)} ${order.direction}`);
|
|
635
|
+
return `ORDER BY ${parts.join(", ")}`;
|
|
636
|
+
}
|
|
637
|
+
formatGroupConcatSeparator(ctx) {
|
|
638
|
+
if (!ctx.node.separator) {
|
|
639
|
+
return "";
|
|
640
|
+
}
|
|
641
|
+
return ` SEPARATOR ${ctx.compileOperand(ctx.node.separator)}`;
|
|
642
|
+
}
|
|
643
|
+
getGroupConcatSeparatorOperand(ctx) {
|
|
644
|
+
return ctx.node.separator ?? _StandardFunctionStrategy.DEFAULT_GROUP_CONCAT_SEPARATOR;
|
|
645
|
+
}
|
|
646
|
+
static {
|
|
647
|
+
this.DEFAULT_GROUP_CONCAT_SEPARATOR = {
|
|
648
|
+
type: "Literal",
|
|
649
|
+
value: ","
|
|
650
|
+
};
|
|
651
|
+
}
|
|
542
652
|
};
|
|
543
653
|
|
|
544
654
|
// src/core/dialect/abstract.ts
|
|
@@ -885,7 +995,11 @@ var Dialect = class _Dialect {
|
|
|
885
995
|
const compiledArgs = fnNode.args.map((arg) => this.compileOperand(arg, ctx));
|
|
886
996
|
const renderer = this.functionStrategy.getRenderer(fnNode.name);
|
|
887
997
|
if (renderer) {
|
|
888
|
-
return renderer({
|
|
998
|
+
return renderer({
|
|
999
|
+
node: fnNode,
|
|
1000
|
+
compiledArgs,
|
|
1001
|
+
compileOperand: (operand) => this.compileOperand(operand, ctx)
|
|
1002
|
+
});
|
|
889
1003
|
}
|
|
890
1004
|
return `${fnNode.name}(${compiledArgs.join(", ")})`;
|
|
891
1005
|
}
|
|
@@ -1308,6 +1422,14 @@ var PostgresFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
1308
1422
|
const partClean = String(partArg.value).replace(/['"]/g, "").toLowerCase();
|
|
1309
1423
|
return `DATE_TRUNC('${partClean}', ${date})`;
|
|
1310
1424
|
});
|
|
1425
|
+
this.add("GROUP_CONCAT", (ctx) => {
|
|
1426
|
+
const arg = ctx.compiledArgs[0];
|
|
1427
|
+
const orderClause = this.buildOrderByExpression(ctx);
|
|
1428
|
+
const orderSegment = orderClause ? ` ${orderClause}` : "";
|
|
1429
|
+
const separatorOperand = this.getGroupConcatSeparatorOperand(ctx);
|
|
1430
|
+
const separator = ctx.compileOperand(separatorOperand);
|
|
1431
|
+
return `STRING_AGG(${arg}, ${separator}${orderSegment})`;
|
|
1432
|
+
});
|
|
1311
1433
|
}
|
|
1312
1434
|
};
|
|
1313
1435
|
|
|
@@ -1552,6 +1674,12 @@ var SqliteFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
1552
1674
|
}
|
|
1553
1675
|
return `date(${date}, 'start of ${partClean}')`;
|
|
1554
1676
|
});
|
|
1677
|
+
this.add("GROUP_CONCAT", (ctx) => {
|
|
1678
|
+
const arg = ctx.compiledArgs[0];
|
|
1679
|
+
const separatorOperand = this.getGroupConcatSeparatorOperand(ctx);
|
|
1680
|
+
const separator = ctx.compileOperand(separatorOperand);
|
|
1681
|
+
return `GROUP_CONCAT(${arg}, ${separator})`;
|
|
1682
|
+
});
|
|
1555
1683
|
}
|
|
1556
1684
|
};
|
|
1557
1685
|
|
|
@@ -1668,6 +1796,14 @@ var MssqlFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
1668
1796
|
const partClean = String(partArg.value).replace(/['"]/g, "").toLowerCase();
|
|
1669
1797
|
return `DATETRUNC(${partClean}, ${date})`;
|
|
1670
1798
|
});
|
|
1799
|
+
this.add("GROUP_CONCAT", (ctx) => {
|
|
1800
|
+
const arg = ctx.compiledArgs[0];
|
|
1801
|
+
const separatorOperand = this.getGroupConcatSeparatorOperand(ctx);
|
|
1802
|
+
const separator = ctx.compileOperand(separatorOperand);
|
|
1803
|
+
const orderClause = this.buildOrderByExpression(ctx);
|
|
1804
|
+
const withinGroup = orderClause ? ` WITHIN GROUP (${orderClause})` : "";
|
|
1805
|
+
return `STRING_AGG(${arg}, ${separator})${withinGroup}`;
|
|
1806
|
+
});
|
|
1671
1807
|
}
|
|
1672
1808
|
};
|
|
1673
1809
|
|
|
@@ -2037,62 +2173,6 @@ var createJoinNode = (kind, tableName, condition, relationName) => ({
|
|
|
2037
2173
|
meta: relationName ? { relationName } : void 0
|
|
2038
2174
|
});
|
|
2039
2175
|
|
|
2040
|
-
// src/core/sql/sql.ts
|
|
2041
|
-
var SQL_OPERATORS = {
|
|
2042
|
-
/** Equality operator */
|
|
2043
|
-
EQUALS: "=",
|
|
2044
|
-
/** Not equals operator */
|
|
2045
|
-
NOT_EQUALS: "!=",
|
|
2046
|
-
/** Greater than operator */
|
|
2047
|
-
GREATER_THAN: ">",
|
|
2048
|
-
/** Greater than or equal operator */
|
|
2049
|
-
GREATER_OR_EQUAL: ">=",
|
|
2050
|
-
/** Less than operator */
|
|
2051
|
-
LESS_THAN: "<",
|
|
2052
|
-
/** Less than or equal operator */
|
|
2053
|
-
LESS_OR_EQUAL: "<=",
|
|
2054
|
-
/** LIKE pattern matching operator */
|
|
2055
|
-
LIKE: "LIKE",
|
|
2056
|
-
/** NOT LIKE pattern matching operator */
|
|
2057
|
-
NOT_LIKE: "NOT LIKE",
|
|
2058
|
-
/** IN membership operator */
|
|
2059
|
-
IN: "IN",
|
|
2060
|
-
/** NOT IN membership operator */
|
|
2061
|
-
NOT_IN: "NOT IN",
|
|
2062
|
-
/** BETWEEN range operator */
|
|
2063
|
-
BETWEEN: "BETWEEN",
|
|
2064
|
-
/** NOT BETWEEN range operator */
|
|
2065
|
-
NOT_BETWEEN: "NOT BETWEEN",
|
|
2066
|
-
/** IS NULL null check operator */
|
|
2067
|
-
IS_NULL: "IS NULL",
|
|
2068
|
-
/** IS NOT NULL null check operator */
|
|
2069
|
-
IS_NOT_NULL: "IS NOT NULL",
|
|
2070
|
-
/** Logical AND operator */
|
|
2071
|
-
AND: "AND",
|
|
2072
|
-
/** Logical OR operator */
|
|
2073
|
-
OR: "OR",
|
|
2074
|
-
/** EXISTS operator */
|
|
2075
|
-
EXISTS: "EXISTS",
|
|
2076
|
-
/** NOT EXISTS operator */
|
|
2077
|
-
NOT_EXISTS: "NOT EXISTS"
|
|
2078
|
-
};
|
|
2079
|
-
var JOIN_KINDS = {
|
|
2080
|
-
/** INNER JOIN type */
|
|
2081
|
-
INNER: "INNER",
|
|
2082
|
-
/** LEFT JOIN type */
|
|
2083
|
-
LEFT: "LEFT",
|
|
2084
|
-
/** RIGHT JOIN type */
|
|
2085
|
-
RIGHT: "RIGHT",
|
|
2086
|
-
/** CROSS JOIN type */
|
|
2087
|
-
CROSS: "CROSS"
|
|
2088
|
-
};
|
|
2089
|
-
var ORDER_DIRECTIONS = {
|
|
2090
|
-
/** Ascending order */
|
|
2091
|
-
ASC: "ASC",
|
|
2092
|
-
/** Descending order */
|
|
2093
|
-
DESC: "DESC"
|
|
2094
|
-
};
|
|
2095
|
-
|
|
2096
2176
|
// src/query-builder/hydration-manager.ts
|
|
2097
2177
|
var HydrationManager = class _HydrationManager {
|
|
2098
2178
|
/**
|
|
@@ -4220,6 +4300,21 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4220
4300
|
select(columns) {
|
|
4221
4301
|
return this.clone(this.columnSelector.select(this.context, columns));
|
|
4222
4302
|
}
|
|
4303
|
+
/**
|
|
4304
|
+
* Selects columns from the root table by name (typed).
|
|
4305
|
+
* @param cols - Column names on the root table
|
|
4306
|
+
*/
|
|
4307
|
+
selectColumns(...cols) {
|
|
4308
|
+
const selection = {};
|
|
4309
|
+
for (const key of cols) {
|
|
4310
|
+
const col2 = this.env.table.columns[key];
|
|
4311
|
+
if (!col2) {
|
|
4312
|
+
throw new Error(`Column '${key}' not found on table '${this.env.table.name}'`);
|
|
4313
|
+
}
|
|
4314
|
+
selection[key] = col2;
|
|
4315
|
+
}
|
|
4316
|
+
return this.select(selection);
|
|
4317
|
+
}
|
|
4223
4318
|
/**
|
|
4224
4319
|
|
|
4225
4320
|
* Selects raw column expressions
|
|
@@ -4380,6 +4475,47 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4380
4475
|
nextLazy.add(relationName);
|
|
4381
4476
|
return this.clone(this.context, nextLazy);
|
|
4382
4477
|
}
|
|
4478
|
+
/**
|
|
4479
|
+
* Selects columns for a related table in a single hop.
|
|
4480
|
+
*/
|
|
4481
|
+
selectRelationColumns(relationName, ...cols) {
|
|
4482
|
+
const relation = this.env.table.relations[relationName];
|
|
4483
|
+
if (!relation) {
|
|
4484
|
+
throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
|
|
4485
|
+
}
|
|
4486
|
+
const target = relation.target;
|
|
4487
|
+
for (const col2 of cols) {
|
|
4488
|
+
if (!target.columns[col2]) {
|
|
4489
|
+
throw new Error(
|
|
4490
|
+
`Column '${col2}' not found on related table '${target.name}' for relation '${relationName}'`
|
|
4491
|
+
);
|
|
4492
|
+
}
|
|
4493
|
+
}
|
|
4494
|
+
return this.include(relationName, { columns: cols });
|
|
4495
|
+
}
|
|
4496
|
+
/**
|
|
4497
|
+
* Convenience alias for selecting specific columns from a relation.
|
|
4498
|
+
*/
|
|
4499
|
+
includePick(relationName, cols) {
|
|
4500
|
+
return this.selectRelationColumns(relationName, ...cols);
|
|
4501
|
+
}
|
|
4502
|
+
/**
|
|
4503
|
+
* Selects columns for the root table and relations from a single config object.
|
|
4504
|
+
*/
|
|
4505
|
+
selectColumnsDeep(config) {
|
|
4506
|
+
let qb = this;
|
|
4507
|
+
if (config.root?.length) {
|
|
4508
|
+
qb = qb.selectColumns(...config.root);
|
|
4509
|
+
}
|
|
4510
|
+
for (const key of Object.keys(config)) {
|
|
4511
|
+
if (key === "root") continue;
|
|
4512
|
+
const relName = key;
|
|
4513
|
+
const cols = config[relName];
|
|
4514
|
+
if (!cols || !cols.length) continue;
|
|
4515
|
+
qb = qb.selectRelationColumns(relName, ...cols);
|
|
4516
|
+
}
|
|
4517
|
+
return qb;
|
|
4518
|
+
}
|
|
4383
4519
|
getLazyRelations() {
|
|
4384
4520
|
return Array.from(this.lazyRelations);
|
|
4385
4521
|
}
|
|
@@ -4655,6 +4791,54 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4655
4791
|
var createColumn = (table, name) => ({ type: "Column", table, name });
|
|
4656
4792
|
var createLiteral = (val) => ({ type: "Literal", value: val });
|
|
4657
4793
|
|
|
4794
|
+
// src/orm/entity-metadata.ts
|
|
4795
|
+
var metadataMap = /* @__PURE__ */ new Map();
|
|
4796
|
+
var getEntityMetadata = (target) => {
|
|
4797
|
+
return metadataMap.get(target);
|
|
4798
|
+
};
|
|
4799
|
+
|
|
4800
|
+
// src/decorators/bootstrap.ts
|
|
4801
|
+
var getTableDefFromEntity = (ctor) => {
|
|
4802
|
+
const meta = getEntityMetadata(ctor);
|
|
4803
|
+
if (!meta) return void 0;
|
|
4804
|
+
return meta.table;
|
|
4805
|
+
};
|
|
4806
|
+
var selectFromEntity = (ctor) => {
|
|
4807
|
+
const table = getTableDefFromEntity(ctor);
|
|
4808
|
+
if (!table) {
|
|
4809
|
+
throw new Error("Entity metadata has not been bootstrapped");
|
|
4810
|
+
}
|
|
4811
|
+
return new SelectQueryBuilder(table);
|
|
4812
|
+
};
|
|
4813
|
+
|
|
4814
|
+
// src/query-builder/select-helpers.ts
|
|
4815
|
+
function sel(table, ...cols) {
|
|
4816
|
+
const selection = {};
|
|
4817
|
+
for (const col2 of cols) {
|
|
4818
|
+
const def = table.columns[col2];
|
|
4819
|
+
if (!def) {
|
|
4820
|
+
throw new Error(`Column '${col2}' not found on table '${table.name}'`);
|
|
4821
|
+
}
|
|
4822
|
+
selection[col2] = def;
|
|
4823
|
+
}
|
|
4824
|
+
return selection;
|
|
4825
|
+
}
|
|
4826
|
+
function esel(entity, ...props) {
|
|
4827
|
+
const table = getTableDefFromEntity(entity);
|
|
4828
|
+
if (!table) {
|
|
4829
|
+
throw new Error(`No table definition registered for entity '${entity.name}'`);
|
|
4830
|
+
}
|
|
4831
|
+
const selection = {};
|
|
4832
|
+
for (const prop of props) {
|
|
4833
|
+
const col2 = table.columns[prop];
|
|
4834
|
+
if (!col2) {
|
|
4835
|
+
throw new Error(`No column '${prop}' found for entity '${entity.name}'`);
|
|
4836
|
+
}
|
|
4837
|
+
selection[prop] = col2;
|
|
4838
|
+
}
|
|
4839
|
+
return selection;
|
|
4840
|
+
}
|
|
4841
|
+
|
|
4658
4842
|
// src/query-builder/insert-query-state.ts
|
|
4659
4843
|
var InsertQueryState = class _InsertQueryState {
|
|
4660
4844
|
constructor(table, ast) {
|
|
@@ -4673,7 +4857,15 @@ var InsertQueryState = class _InsertQueryState {
|
|
|
4673
4857
|
if (!rows.length) return this;
|
|
4674
4858
|
const definedColumns = this.ast.columns.length ? this.ast.columns : buildColumnNodes(this.table, Object.keys(rows[0]));
|
|
4675
4859
|
const newRows = rows.map(
|
|
4676
|
-
(row) => definedColumns.map((column) =>
|
|
4860
|
+
(row, rowIndex) => definedColumns.map((column) => {
|
|
4861
|
+
const rawValue = row[column.name];
|
|
4862
|
+
if (!isValueOperandInput(rawValue)) {
|
|
4863
|
+
throw new Error(
|
|
4864
|
+
`Invalid insert value for column "${column.name}" in row ${rowIndex}: only primitives, null, or OperandNodes are allowed`
|
|
4865
|
+
);
|
|
4866
|
+
}
|
|
4867
|
+
return valueToOperand(rawValue);
|
|
4868
|
+
})
|
|
4677
4869
|
);
|
|
4678
4870
|
return this.clone({
|
|
4679
4871
|
...this.ast,
|
|
@@ -4724,6 +4916,17 @@ var InsertQueryBuilder = class _InsertQueryBuilder {
|
|
|
4724
4916
|
};
|
|
4725
4917
|
|
|
4726
4918
|
// src/query-builder/update-query-state.ts
|
|
4919
|
+
var isUpdateValue = (value) => {
|
|
4920
|
+
if (value === null) return true;
|
|
4921
|
+
switch (typeof value) {
|
|
4922
|
+
case "string":
|
|
4923
|
+
case "number":
|
|
4924
|
+
case "boolean":
|
|
4925
|
+
return true;
|
|
4926
|
+
default:
|
|
4927
|
+
return isOperandNode(value);
|
|
4928
|
+
}
|
|
4929
|
+
};
|
|
4727
4930
|
var UpdateQueryState = class _UpdateQueryState {
|
|
4728
4931
|
constructor(table, ast) {
|
|
4729
4932
|
this.table = table;
|
|
@@ -4737,14 +4940,21 @@ var UpdateQueryState = class _UpdateQueryState {
|
|
|
4737
4940
|
return new _UpdateQueryState(this.table, nextAst);
|
|
4738
4941
|
}
|
|
4739
4942
|
withSet(values) {
|
|
4740
|
-
const assignments = Object.entries(values).map(([column,
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
}
|
|
4746
|
-
|
|
4747
|
-
|
|
4943
|
+
const assignments = Object.entries(values).map(([column, rawValue]) => {
|
|
4944
|
+
if (!isUpdateValue(rawValue)) {
|
|
4945
|
+
throw new Error(
|
|
4946
|
+
`Invalid update value for column "${column}": only primitives, null, or OperandNodes are allowed`
|
|
4947
|
+
);
|
|
4948
|
+
}
|
|
4949
|
+
return {
|
|
4950
|
+
column: {
|
|
4951
|
+
type: "Column",
|
|
4952
|
+
table: this.table.name,
|
|
4953
|
+
name: column
|
|
4954
|
+
},
|
|
4955
|
+
value: valueToOperand(rawValue)
|
|
4956
|
+
};
|
|
4957
|
+
});
|
|
4748
4958
|
return this.clone({
|
|
4749
4959
|
...this.ast,
|
|
4750
4960
|
set: assignments
|
|
@@ -6012,8 +6222,8 @@ var TypeScriptGenerator = class {
|
|
|
6012
6222
|
return `${key}: ${this.printOperand(operand)}`;
|
|
6013
6223
|
});
|
|
6014
6224
|
lines.push(`db.select({`);
|
|
6015
|
-
selections.forEach((
|
|
6016
|
-
lines.push(` ${
|
|
6225
|
+
selections.forEach((sel2, index) => {
|
|
6226
|
+
lines.push(` ${sel2}${index < selections.length - 1 ? "," : ""}`);
|
|
6017
6227
|
});
|
|
6018
6228
|
lines.push(`})`);
|
|
6019
6229
|
lines.push(`.from(${this.namingStrategy.tableToSymbol(ast.from)})`);
|
|
@@ -6296,26 +6506,6 @@ var TypeScriptGenerator = class {
|
|
|
6296
6506
|
}
|
|
6297
6507
|
};
|
|
6298
6508
|
|
|
6299
|
-
// src/orm/entity-metadata.ts
|
|
6300
|
-
var metadataMap = /* @__PURE__ */ new Map();
|
|
6301
|
-
var getEntityMetadata = (target) => {
|
|
6302
|
-
return metadataMap.get(target);
|
|
6303
|
-
};
|
|
6304
|
-
|
|
6305
|
-
// src/decorators/bootstrap.ts
|
|
6306
|
-
var getTableDefFromEntity = (ctor) => {
|
|
6307
|
-
const meta = getEntityMetadata(ctor);
|
|
6308
|
-
if (!meta) return void 0;
|
|
6309
|
-
return meta.table;
|
|
6310
|
-
};
|
|
6311
|
-
var selectFromEntity = (ctor) => {
|
|
6312
|
-
const table = getTableDefFromEntity(ctor);
|
|
6313
|
-
if (!table) {
|
|
6314
|
-
throw new Error("Entity metadata has not been bootstrapped");
|
|
6315
|
-
}
|
|
6316
|
-
return new SelectQueryBuilder(table);
|
|
6317
|
-
};
|
|
6318
|
-
|
|
6319
6509
|
// src/orm/identity-map.ts
|
|
6320
6510
|
var IdentityMap = class {
|
|
6321
6511
|
constructor() {
|
|
@@ -6528,6 +6718,7 @@ var UnitOfWork = class {
|
|
|
6528
6718
|
extractColumns(table, entity) {
|
|
6529
6719
|
const payload = {};
|
|
6530
6720
|
for (const column of Object.keys(table.columns)) {
|
|
6721
|
+
if (entity[column] === void 0) continue;
|
|
6531
6722
|
payload[column] = entity[column];
|
|
6532
6723
|
}
|
|
6533
6724
|
return payload;
|
|
@@ -6582,24 +6773,30 @@ var UnitOfWork = class {
|
|
|
6582
6773
|
var DomainEventBus = class {
|
|
6583
6774
|
constructor(initialHandlers) {
|
|
6584
6775
|
this.handlers = /* @__PURE__ */ new Map();
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6776
|
+
if (initialHandlers) {
|
|
6777
|
+
for (const key in initialHandlers) {
|
|
6778
|
+
const type = key;
|
|
6779
|
+
const list = initialHandlers[type] ?? [];
|
|
6780
|
+
this.handlers.set(type, [...list]);
|
|
6781
|
+
}
|
|
6782
|
+
}
|
|
6589
6783
|
}
|
|
6590
|
-
|
|
6591
|
-
const
|
|
6784
|
+
on(type, handler) {
|
|
6785
|
+
const key = type;
|
|
6786
|
+
const existing = this.handlers.get(key) ?? [];
|
|
6592
6787
|
existing.push(handler);
|
|
6593
|
-
this.handlers.set(
|
|
6788
|
+
this.handlers.set(key, existing);
|
|
6789
|
+
}
|
|
6790
|
+
register(type, handler) {
|
|
6791
|
+
this.on(type, handler);
|
|
6594
6792
|
}
|
|
6595
6793
|
async dispatch(trackedEntities, ctx) {
|
|
6596
6794
|
for (const tracked of trackedEntities) {
|
|
6597
6795
|
const entity = tracked.entity;
|
|
6598
|
-
if (!entity.domainEvents
|
|
6796
|
+
if (!entity.domainEvents?.length) continue;
|
|
6599
6797
|
for (const event of entity.domainEvents) {
|
|
6600
|
-
const
|
|
6601
|
-
|
|
6602
|
-
if (!handlers) continue;
|
|
6798
|
+
const handlers = this.handlers.get(event.type);
|
|
6799
|
+
if (!handlers?.length) continue;
|
|
6603
6800
|
for (const handler of handlers) {
|
|
6604
6801
|
await handler(event, ctx);
|
|
6605
6802
|
}
|
|
@@ -6607,11 +6804,6 @@ var DomainEventBus = class {
|
|
|
6607
6804
|
entity.domainEvents = [];
|
|
6608
6805
|
}
|
|
6609
6806
|
}
|
|
6610
|
-
getEventName(event) {
|
|
6611
|
-
if (!event) return "Unknown";
|
|
6612
|
-
if (typeof event === "string") return event;
|
|
6613
|
-
return event.constructor?.name ?? "Unknown";
|
|
6614
|
-
}
|
|
6615
6807
|
};
|
|
6616
6808
|
var addDomainEvent = (entity, event) => {
|
|
6617
6809
|
if (!entity.domainEvents) {
|
|
@@ -6853,8 +7045,8 @@ var OrmSession = class {
|
|
|
6853
7045
|
registerInterceptor(interceptor) {
|
|
6854
7046
|
this.interceptors.push(interceptor);
|
|
6855
7047
|
}
|
|
6856
|
-
registerDomainEventHandler(
|
|
6857
|
-
this.domainEvents.
|
|
7048
|
+
registerDomainEventHandler(type, handler) {
|
|
7049
|
+
this.domainEvents.on(type, handler);
|
|
6858
7050
|
}
|
|
6859
7051
|
async find(entityClass, id) {
|
|
6860
7052
|
const table = getTableDefFromEntity(entityClass);
|
|
@@ -6866,7 +7058,11 @@ var OrmSession = class {
|
|
|
6866
7058
|
if (!column) {
|
|
6867
7059
|
throw new Error("Entity table does not expose a primary key");
|
|
6868
7060
|
}
|
|
6869
|
-
const
|
|
7061
|
+
const columnSelections = Object.values(table.columns).reduce((acc, col2) => {
|
|
7062
|
+
acc[col2.name] = col2;
|
|
7063
|
+
return acc;
|
|
7064
|
+
}, {});
|
|
7065
|
+
const qb = selectFromEntity(entityClass).select(columnSelections).where(eq(column, id)).limit(1);
|
|
6870
7066
|
const rows = await executeHydrated(this, qb);
|
|
6871
7067
|
return rows[0] ?? null;
|
|
6872
7068
|
}
|
|
@@ -6978,7 +7174,6 @@ var Orm = class {
|
|
|
6978
7174
|
const executor = this.executorFactory.createExecutor(options?.tx);
|
|
6979
7175
|
return new OrmSession({ orm: this, executor });
|
|
6980
7176
|
}
|
|
6981
|
-
// Nice convenience:
|
|
6982
7177
|
async transaction(fn4) {
|
|
6983
7178
|
const executor = this.executorFactory.createTransactionalExecutor();
|
|
6984
7179
|
const session = new OrmSession({ orm: this, executor });
|
|
@@ -7169,6 +7364,7 @@ export {
|
|
|
7169
7364
|
diffSchema,
|
|
7170
7365
|
endOfMonth,
|
|
7171
7366
|
eq,
|
|
7367
|
+
esel,
|
|
7172
7368
|
executeHydrated,
|
|
7173
7369
|
executeHydratedWithContexts,
|
|
7174
7370
|
exists,
|
|
@@ -7180,6 +7376,7 @@ export {
|
|
|
7180
7376
|
generateCreateTableSql,
|
|
7181
7377
|
generateSchemaSql,
|
|
7182
7378
|
getSchemaIntrospector,
|
|
7379
|
+
groupConcat,
|
|
7183
7380
|
gt,
|
|
7184
7381
|
gte,
|
|
7185
7382
|
hasMany,
|
|
@@ -7194,6 +7391,7 @@ export {
|
|
|
7194
7391
|
isNotNull,
|
|
7195
7392
|
isNull,
|
|
7196
7393
|
isOperandNode,
|
|
7394
|
+
isValueOperandInput,
|
|
7197
7395
|
isWindowFunctionNode,
|
|
7198
7396
|
jsonPath,
|
|
7199
7397
|
lag,
|
|
@@ -7216,6 +7414,8 @@ export {
|
|
|
7216
7414
|
lt,
|
|
7217
7415
|
lte,
|
|
7218
7416
|
ltrim,
|
|
7417
|
+
max,
|
|
7418
|
+
min,
|
|
7219
7419
|
mod,
|
|
7220
7420
|
month,
|
|
7221
7421
|
neq,
|
|
@@ -7246,6 +7446,7 @@ export {
|
|
|
7246
7446
|
rowsToQueryResult,
|
|
7247
7447
|
rpad,
|
|
7248
7448
|
rtrim,
|
|
7449
|
+
sel,
|
|
7249
7450
|
sign,
|
|
7250
7451
|
sin,
|
|
7251
7452
|
space,
|