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.cjs
CHANGED
|
@@ -112,6 +112,7 @@ __export(index_exports, {
|
|
|
112
112
|
diffSchema: () => diffSchema,
|
|
113
113
|
endOfMonth: () => endOfMonth,
|
|
114
114
|
eq: () => eq,
|
|
115
|
+
esel: () => esel,
|
|
115
116
|
executeHydrated: () => executeHydrated,
|
|
116
117
|
executeHydratedWithContexts: () => executeHydratedWithContexts,
|
|
117
118
|
exists: () => exists,
|
|
@@ -123,6 +124,7 @@ __export(index_exports, {
|
|
|
123
124
|
generateCreateTableSql: () => generateCreateTableSql,
|
|
124
125
|
generateSchemaSql: () => generateSchemaSql,
|
|
125
126
|
getSchemaIntrospector: () => getSchemaIntrospector,
|
|
127
|
+
groupConcat: () => groupConcat,
|
|
126
128
|
gt: () => gt,
|
|
127
129
|
gte: () => gte,
|
|
128
130
|
hasMany: () => hasMany,
|
|
@@ -137,6 +139,7 @@ __export(index_exports, {
|
|
|
137
139
|
isNotNull: () => isNotNull,
|
|
138
140
|
isNull: () => isNull,
|
|
139
141
|
isOperandNode: () => isOperandNode,
|
|
142
|
+
isValueOperandInput: () => isValueOperandInput,
|
|
140
143
|
isWindowFunctionNode: () => isWindowFunctionNode,
|
|
141
144
|
jsonPath: () => jsonPath,
|
|
142
145
|
lag: () => lag,
|
|
@@ -159,6 +162,8 @@ __export(index_exports, {
|
|
|
159
162
|
lt: () => lt,
|
|
160
163
|
lte: () => lte,
|
|
161
164
|
ltrim: () => ltrim,
|
|
165
|
+
max: () => max,
|
|
166
|
+
min: () => min,
|
|
162
167
|
mod: () => mod,
|
|
163
168
|
month: () => month,
|
|
164
169
|
neq: () => neq,
|
|
@@ -189,6 +194,7 @@ __export(index_exports, {
|
|
|
189
194
|
rowsToQueryResult: () => rowsToQueryResult,
|
|
190
195
|
rpad: () => rpad,
|
|
191
196
|
rtrim: () => rtrim,
|
|
197
|
+
sel: () => sel,
|
|
192
198
|
sign: () => sign,
|
|
193
199
|
sin: () => sin,
|
|
194
200
|
space: () => space,
|
|
@@ -422,10 +428,13 @@ var isExpressionSelectionNode = (node) => isFunctionNode(node) || isCaseExpressi
|
|
|
422
428
|
|
|
423
429
|
// src/core/ast/expression-builders.ts
|
|
424
430
|
var valueToOperand = (value) => {
|
|
425
|
-
if (value
|
|
426
|
-
return
|
|
431
|
+
if (isOperandNode(value)) {
|
|
432
|
+
return value;
|
|
427
433
|
}
|
|
428
|
-
return
|
|
434
|
+
return {
|
|
435
|
+
type: "Literal",
|
|
436
|
+
value
|
|
437
|
+
};
|
|
429
438
|
};
|
|
430
439
|
var toNode = (col2) => {
|
|
431
440
|
if (isOperandNode(col2)) return col2;
|
|
@@ -436,10 +445,11 @@ var toLiteralNode = (value) => ({
|
|
|
436
445
|
type: "Literal",
|
|
437
446
|
value
|
|
438
447
|
});
|
|
448
|
+
var isLiteralValue = (value) => value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
449
|
+
var isValueOperandInput = (value) => isOperandNode(value) || isLiteralValue(value);
|
|
439
450
|
var toOperand = (val) => {
|
|
440
|
-
if (val
|
|
441
|
-
|
|
442
|
-
return { type: "Literal", value: val };
|
|
451
|
+
if (isLiteralValue(val)) {
|
|
452
|
+
return valueToOperand(val);
|
|
443
453
|
}
|
|
444
454
|
return toNode(val);
|
|
445
455
|
};
|
|
@@ -585,6 +595,62 @@ var windowFunction = (name, args = [], partitionBy, orderBy) => {
|
|
|
585
595
|
return buildWindowFunction(name, nodeArgs, partitionNodes, orderNodes);
|
|
586
596
|
};
|
|
587
597
|
|
|
598
|
+
// src/core/sql/sql.ts
|
|
599
|
+
var SQL_OPERATORS = {
|
|
600
|
+
/** Equality operator */
|
|
601
|
+
EQUALS: "=",
|
|
602
|
+
/** Not equals operator */
|
|
603
|
+
NOT_EQUALS: "!=",
|
|
604
|
+
/** Greater than operator */
|
|
605
|
+
GREATER_THAN: ">",
|
|
606
|
+
/** Greater than or equal operator */
|
|
607
|
+
GREATER_OR_EQUAL: ">=",
|
|
608
|
+
/** Less than operator */
|
|
609
|
+
LESS_THAN: "<",
|
|
610
|
+
/** Less than or equal operator */
|
|
611
|
+
LESS_OR_EQUAL: "<=",
|
|
612
|
+
/** LIKE pattern matching operator */
|
|
613
|
+
LIKE: "LIKE",
|
|
614
|
+
/** NOT LIKE pattern matching operator */
|
|
615
|
+
NOT_LIKE: "NOT LIKE",
|
|
616
|
+
/** IN membership operator */
|
|
617
|
+
IN: "IN",
|
|
618
|
+
/** NOT IN membership operator */
|
|
619
|
+
NOT_IN: "NOT IN",
|
|
620
|
+
/** BETWEEN range operator */
|
|
621
|
+
BETWEEN: "BETWEEN",
|
|
622
|
+
/** NOT BETWEEN range operator */
|
|
623
|
+
NOT_BETWEEN: "NOT BETWEEN",
|
|
624
|
+
/** IS NULL null check operator */
|
|
625
|
+
IS_NULL: "IS NULL",
|
|
626
|
+
/** IS NOT NULL null check operator */
|
|
627
|
+
IS_NOT_NULL: "IS NOT NULL",
|
|
628
|
+
/** Logical AND operator */
|
|
629
|
+
AND: "AND",
|
|
630
|
+
/** Logical OR operator */
|
|
631
|
+
OR: "OR",
|
|
632
|
+
/** EXISTS operator */
|
|
633
|
+
EXISTS: "EXISTS",
|
|
634
|
+
/** NOT EXISTS operator */
|
|
635
|
+
NOT_EXISTS: "NOT EXISTS"
|
|
636
|
+
};
|
|
637
|
+
var JOIN_KINDS = {
|
|
638
|
+
/** INNER JOIN type */
|
|
639
|
+
INNER: "INNER",
|
|
640
|
+
/** LEFT JOIN type */
|
|
641
|
+
LEFT: "LEFT",
|
|
642
|
+
/** RIGHT JOIN type */
|
|
643
|
+
RIGHT: "RIGHT",
|
|
644
|
+
/** CROSS JOIN type */
|
|
645
|
+
CROSS: "CROSS"
|
|
646
|
+
};
|
|
647
|
+
var ORDER_DIRECTIONS = {
|
|
648
|
+
/** Ascending order */
|
|
649
|
+
ASC: "ASC",
|
|
650
|
+
/** Descending order */
|
|
651
|
+
DESC: "DESC"
|
|
652
|
+
};
|
|
653
|
+
|
|
588
654
|
// src/core/ast/aggregate-functions.ts
|
|
589
655
|
var buildAggregate = (name) => (col2) => ({
|
|
590
656
|
type: "Function",
|
|
@@ -594,6 +660,20 @@ var buildAggregate = (name) => (col2) => ({
|
|
|
594
660
|
var count = buildAggregate("COUNT");
|
|
595
661
|
var sum = buildAggregate("SUM");
|
|
596
662
|
var avg = buildAggregate("AVG");
|
|
663
|
+
var min = buildAggregate("MIN");
|
|
664
|
+
var max = buildAggregate("MAX");
|
|
665
|
+
var toOrderByNode = (order) => ({
|
|
666
|
+
type: "OrderBy",
|
|
667
|
+
column: columnOperand(order.column),
|
|
668
|
+
direction: order.direction ?? ORDER_DIRECTIONS.ASC
|
|
669
|
+
});
|
|
670
|
+
var groupConcat = (col2, options) => ({
|
|
671
|
+
type: "Function",
|
|
672
|
+
name: "GROUP_CONCAT",
|
|
673
|
+
args: [columnOperand(col2)],
|
|
674
|
+
orderBy: options?.orderBy?.map(toOrderByNode),
|
|
675
|
+
separator: options?.separator !== void 0 ? valueToOperand(options.separator) : void 0
|
|
676
|
+
});
|
|
597
677
|
|
|
598
678
|
// src/core/ast/expression-visitor.ts
|
|
599
679
|
var expressionDispatchers = /* @__PURE__ */ new Map();
|
|
@@ -685,12 +765,17 @@ var toTableRef = (table) => ({
|
|
|
685
765
|
});
|
|
686
766
|
|
|
687
767
|
// src/core/functions/standard-strategy.ts
|
|
688
|
-
var StandardFunctionStrategy = class {
|
|
768
|
+
var StandardFunctionStrategy = class _StandardFunctionStrategy {
|
|
689
769
|
constructor() {
|
|
690
770
|
this.renderers = /* @__PURE__ */ new Map();
|
|
691
771
|
this.registerStandard();
|
|
692
772
|
}
|
|
693
773
|
registerStandard() {
|
|
774
|
+
this.add("COUNT", ({ compiledArgs }) => `COUNT(${compiledArgs.join(", ")})`);
|
|
775
|
+
this.add("SUM", ({ compiledArgs }) => `SUM(${compiledArgs[0]})`);
|
|
776
|
+
this.add("AVG", ({ compiledArgs }) => `AVG(${compiledArgs[0]})`);
|
|
777
|
+
this.add("MIN", ({ compiledArgs }) => `MIN(${compiledArgs[0]})`);
|
|
778
|
+
this.add("MAX", ({ compiledArgs }) => `MAX(${compiledArgs[0]})`);
|
|
694
779
|
this.add("ABS", ({ compiledArgs }) => `ABS(${compiledArgs[0]})`);
|
|
695
780
|
this.add("UPPER", ({ compiledArgs }) => `UPPER(${compiledArgs[0]})`);
|
|
696
781
|
this.add("LOWER", ({ compiledArgs }) => `LOWER(${compiledArgs[0]})`);
|
|
@@ -717,6 +802,7 @@ var StandardFunctionStrategy = class {
|
|
|
717
802
|
this.add("DAY_OF_WEEK", ({ compiledArgs }) => `DAYOFWEEK(${compiledArgs[0]})`);
|
|
718
803
|
this.add("WEEK_OF_YEAR", ({ compiledArgs }) => `WEEKOFYEAR(${compiledArgs[0]})`);
|
|
719
804
|
this.add("DATE_TRUNC", ({ compiledArgs }) => `DATE_TRUNC(${compiledArgs[0]}, ${compiledArgs[1]})`);
|
|
805
|
+
this.add("GROUP_CONCAT", (ctx) => this.renderGroupConcat(ctx));
|
|
720
806
|
}
|
|
721
807
|
add(name, renderer) {
|
|
722
808
|
this.renderers.set(name, renderer);
|
|
@@ -724,6 +810,36 @@ var StandardFunctionStrategy = class {
|
|
|
724
810
|
getRenderer(name) {
|
|
725
811
|
return this.renderers.get(name);
|
|
726
812
|
}
|
|
813
|
+
renderGroupConcat(ctx) {
|
|
814
|
+
const arg = ctx.compiledArgs[0];
|
|
815
|
+
const orderClause = this.buildOrderByExpression(ctx);
|
|
816
|
+
const orderSegment = orderClause ? ` ${orderClause}` : "";
|
|
817
|
+
const separatorClause = this.formatGroupConcatSeparator(ctx);
|
|
818
|
+
return `GROUP_CONCAT(${arg}${orderSegment}${separatorClause})`;
|
|
819
|
+
}
|
|
820
|
+
buildOrderByExpression(ctx) {
|
|
821
|
+
const orderBy = ctx.node.orderBy;
|
|
822
|
+
if (!orderBy || orderBy.length === 0) {
|
|
823
|
+
return "";
|
|
824
|
+
}
|
|
825
|
+
const parts = orderBy.map((order) => `${ctx.compileOperand(order.column)} ${order.direction}`);
|
|
826
|
+
return `ORDER BY ${parts.join(", ")}`;
|
|
827
|
+
}
|
|
828
|
+
formatGroupConcatSeparator(ctx) {
|
|
829
|
+
if (!ctx.node.separator) {
|
|
830
|
+
return "";
|
|
831
|
+
}
|
|
832
|
+
return ` SEPARATOR ${ctx.compileOperand(ctx.node.separator)}`;
|
|
833
|
+
}
|
|
834
|
+
getGroupConcatSeparatorOperand(ctx) {
|
|
835
|
+
return ctx.node.separator ?? _StandardFunctionStrategy.DEFAULT_GROUP_CONCAT_SEPARATOR;
|
|
836
|
+
}
|
|
837
|
+
static {
|
|
838
|
+
this.DEFAULT_GROUP_CONCAT_SEPARATOR = {
|
|
839
|
+
type: "Literal",
|
|
840
|
+
value: ","
|
|
841
|
+
};
|
|
842
|
+
}
|
|
727
843
|
};
|
|
728
844
|
|
|
729
845
|
// src/core/dialect/abstract.ts
|
|
@@ -1070,7 +1186,11 @@ var Dialect = class _Dialect {
|
|
|
1070
1186
|
const compiledArgs = fnNode.args.map((arg) => this.compileOperand(arg, ctx));
|
|
1071
1187
|
const renderer = this.functionStrategy.getRenderer(fnNode.name);
|
|
1072
1188
|
if (renderer) {
|
|
1073
|
-
return renderer({
|
|
1189
|
+
return renderer({
|
|
1190
|
+
node: fnNode,
|
|
1191
|
+
compiledArgs,
|
|
1192
|
+
compileOperand: (operand) => this.compileOperand(operand, ctx)
|
|
1193
|
+
});
|
|
1074
1194
|
}
|
|
1075
1195
|
return `${fnNode.name}(${compiledArgs.join(", ")})`;
|
|
1076
1196
|
}
|
|
@@ -1493,6 +1613,14 @@ var PostgresFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
1493
1613
|
const partClean = String(partArg.value).replace(/['"]/g, "").toLowerCase();
|
|
1494
1614
|
return `DATE_TRUNC('${partClean}', ${date})`;
|
|
1495
1615
|
});
|
|
1616
|
+
this.add("GROUP_CONCAT", (ctx) => {
|
|
1617
|
+
const arg = ctx.compiledArgs[0];
|
|
1618
|
+
const orderClause = this.buildOrderByExpression(ctx);
|
|
1619
|
+
const orderSegment = orderClause ? ` ${orderClause}` : "";
|
|
1620
|
+
const separatorOperand = this.getGroupConcatSeparatorOperand(ctx);
|
|
1621
|
+
const separator = ctx.compileOperand(separatorOperand);
|
|
1622
|
+
return `STRING_AGG(${arg}, ${separator}${orderSegment})`;
|
|
1623
|
+
});
|
|
1496
1624
|
}
|
|
1497
1625
|
};
|
|
1498
1626
|
|
|
@@ -1737,6 +1865,12 @@ var SqliteFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
1737
1865
|
}
|
|
1738
1866
|
return `date(${date}, 'start of ${partClean}')`;
|
|
1739
1867
|
});
|
|
1868
|
+
this.add("GROUP_CONCAT", (ctx) => {
|
|
1869
|
+
const arg = ctx.compiledArgs[0];
|
|
1870
|
+
const separatorOperand = this.getGroupConcatSeparatorOperand(ctx);
|
|
1871
|
+
const separator = ctx.compileOperand(separatorOperand);
|
|
1872
|
+
return `GROUP_CONCAT(${arg}, ${separator})`;
|
|
1873
|
+
});
|
|
1740
1874
|
}
|
|
1741
1875
|
};
|
|
1742
1876
|
|
|
@@ -1853,6 +1987,14 @@ var MssqlFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
1853
1987
|
const partClean = String(partArg.value).replace(/['"]/g, "").toLowerCase();
|
|
1854
1988
|
return `DATETRUNC(${partClean}, ${date})`;
|
|
1855
1989
|
});
|
|
1990
|
+
this.add("GROUP_CONCAT", (ctx) => {
|
|
1991
|
+
const arg = ctx.compiledArgs[0];
|
|
1992
|
+
const separatorOperand = this.getGroupConcatSeparatorOperand(ctx);
|
|
1993
|
+
const separator = ctx.compileOperand(separatorOperand);
|
|
1994
|
+
const orderClause = this.buildOrderByExpression(ctx);
|
|
1995
|
+
const withinGroup = orderClause ? ` WITHIN GROUP (${orderClause})` : "";
|
|
1996
|
+
return `STRING_AGG(${arg}, ${separator})${withinGroup}`;
|
|
1997
|
+
});
|
|
1856
1998
|
}
|
|
1857
1999
|
};
|
|
1858
2000
|
|
|
@@ -2222,62 +2364,6 @@ var createJoinNode = (kind, tableName, condition, relationName) => ({
|
|
|
2222
2364
|
meta: relationName ? { relationName } : void 0
|
|
2223
2365
|
});
|
|
2224
2366
|
|
|
2225
|
-
// src/core/sql/sql.ts
|
|
2226
|
-
var SQL_OPERATORS = {
|
|
2227
|
-
/** Equality operator */
|
|
2228
|
-
EQUALS: "=",
|
|
2229
|
-
/** Not equals operator */
|
|
2230
|
-
NOT_EQUALS: "!=",
|
|
2231
|
-
/** Greater than operator */
|
|
2232
|
-
GREATER_THAN: ">",
|
|
2233
|
-
/** Greater than or equal operator */
|
|
2234
|
-
GREATER_OR_EQUAL: ">=",
|
|
2235
|
-
/** Less than operator */
|
|
2236
|
-
LESS_THAN: "<",
|
|
2237
|
-
/** Less than or equal operator */
|
|
2238
|
-
LESS_OR_EQUAL: "<=",
|
|
2239
|
-
/** LIKE pattern matching operator */
|
|
2240
|
-
LIKE: "LIKE",
|
|
2241
|
-
/** NOT LIKE pattern matching operator */
|
|
2242
|
-
NOT_LIKE: "NOT LIKE",
|
|
2243
|
-
/** IN membership operator */
|
|
2244
|
-
IN: "IN",
|
|
2245
|
-
/** NOT IN membership operator */
|
|
2246
|
-
NOT_IN: "NOT IN",
|
|
2247
|
-
/** BETWEEN range operator */
|
|
2248
|
-
BETWEEN: "BETWEEN",
|
|
2249
|
-
/** NOT BETWEEN range operator */
|
|
2250
|
-
NOT_BETWEEN: "NOT BETWEEN",
|
|
2251
|
-
/** IS NULL null check operator */
|
|
2252
|
-
IS_NULL: "IS NULL",
|
|
2253
|
-
/** IS NOT NULL null check operator */
|
|
2254
|
-
IS_NOT_NULL: "IS NOT NULL",
|
|
2255
|
-
/** Logical AND operator */
|
|
2256
|
-
AND: "AND",
|
|
2257
|
-
/** Logical OR operator */
|
|
2258
|
-
OR: "OR",
|
|
2259
|
-
/** EXISTS operator */
|
|
2260
|
-
EXISTS: "EXISTS",
|
|
2261
|
-
/** NOT EXISTS operator */
|
|
2262
|
-
NOT_EXISTS: "NOT EXISTS"
|
|
2263
|
-
};
|
|
2264
|
-
var JOIN_KINDS = {
|
|
2265
|
-
/** INNER JOIN type */
|
|
2266
|
-
INNER: "INNER",
|
|
2267
|
-
/** LEFT JOIN type */
|
|
2268
|
-
LEFT: "LEFT",
|
|
2269
|
-
/** RIGHT JOIN type */
|
|
2270
|
-
RIGHT: "RIGHT",
|
|
2271
|
-
/** CROSS JOIN type */
|
|
2272
|
-
CROSS: "CROSS"
|
|
2273
|
-
};
|
|
2274
|
-
var ORDER_DIRECTIONS = {
|
|
2275
|
-
/** Ascending order */
|
|
2276
|
-
ASC: "ASC",
|
|
2277
|
-
/** Descending order */
|
|
2278
|
-
DESC: "DESC"
|
|
2279
|
-
};
|
|
2280
|
-
|
|
2281
2367
|
// src/query-builder/hydration-manager.ts
|
|
2282
2368
|
var HydrationManager = class _HydrationManager {
|
|
2283
2369
|
/**
|
|
@@ -4405,6 +4491,21 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4405
4491
|
select(columns) {
|
|
4406
4492
|
return this.clone(this.columnSelector.select(this.context, columns));
|
|
4407
4493
|
}
|
|
4494
|
+
/**
|
|
4495
|
+
* Selects columns from the root table by name (typed).
|
|
4496
|
+
* @param cols - Column names on the root table
|
|
4497
|
+
*/
|
|
4498
|
+
selectColumns(...cols) {
|
|
4499
|
+
const selection = {};
|
|
4500
|
+
for (const key of cols) {
|
|
4501
|
+
const col2 = this.env.table.columns[key];
|
|
4502
|
+
if (!col2) {
|
|
4503
|
+
throw new Error(`Column '${key}' not found on table '${this.env.table.name}'`);
|
|
4504
|
+
}
|
|
4505
|
+
selection[key] = col2;
|
|
4506
|
+
}
|
|
4507
|
+
return this.select(selection);
|
|
4508
|
+
}
|
|
4408
4509
|
/**
|
|
4409
4510
|
|
|
4410
4511
|
* Selects raw column expressions
|
|
@@ -4565,6 +4666,47 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4565
4666
|
nextLazy.add(relationName);
|
|
4566
4667
|
return this.clone(this.context, nextLazy);
|
|
4567
4668
|
}
|
|
4669
|
+
/**
|
|
4670
|
+
* Selects columns for a related table in a single hop.
|
|
4671
|
+
*/
|
|
4672
|
+
selectRelationColumns(relationName, ...cols) {
|
|
4673
|
+
const relation = this.env.table.relations[relationName];
|
|
4674
|
+
if (!relation) {
|
|
4675
|
+
throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
|
|
4676
|
+
}
|
|
4677
|
+
const target = relation.target;
|
|
4678
|
+
for (const col2 of cols) {
|
|
4679
|
+
if (!target.columns[col2]) {
|
|
4680
|
+
throw new Error(
|
|
4681
|
+
`Column '${col2}' not found on related table '${target.name}' for relation '${relationName}'`
|
|
4682
|
+
);
|
|
4683
|
+
}
|
|
4684
|
+
}
|
|
4685
|
+
return this.include(relationName, { columns: cols });
|
|
4686
|
+
}
|
|
4687
|
+
/**
|
|
4688
|
+
* Convenience alias for selecting specific columns from a relation.
|
|
4689
|
+
*/
|
|
4690
|
+
includePick(relationName, cols) {
|
|
4691
|
+
return this.selectRelationColumns(relationName, ...cols);
|
|
4692
|
+
}
|
|
4693
|
+
/**
|
|
4694
|
+
* Selects columns for the root table and relations from a single config object.
|
|
4695
|
+
*/
|
|
4696
|
+
selectColumnsDeep(config) {
|
|
4697
|
+
let qb = this;
|
|
4698
|
+
if (config.root?.length) {
|
|
4699
|
+
qb = qb.selectColumns(...config.root);
|
|
4700
|
+
}
|
|
4701
|
+
for (const key of Object.keys(config)) {
|
|
4702
|
+
if (key === "root") continue;
|
|
4703
|
+
const relName = key;
|
|
4704
|
+
const cols = config[relName];
|
|
4705
|
+
if (!cols || !cols.length) continue;
|
|
4706
|
+
qb = qb.selectRelationColumns(relName, ...cols);
|
|
4707
|
+
}
|
|
4708
|
+
return qb;
|
|
4709
|
+
}
|
|
4568
4710
|
getLazyRelations() {
|
|
4569
4711
|
return Array.from(this.lazyRelations);
|
|
4570
4712
|
}
|
|
@@ -4840,6 +4982,54 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4840
4982
|
var createColumn = (table, name) => ({ type: "Column", table, name });
|
|
4841
4983
|
var createLiteral = (val) => ({ type: "Literal", value: val });
|
|
4842
4984
|
|
|
4985
|
+
// src/orm/entity-metadata.ts
|
|
4986
|
+
var metadataMap = /* @__PURE__ */ new Map();
|
|
4987
|
+
var getEntityMetadata = (target) => {
|
|
4988
|
+
return metadataMap.get(target);
|
|
4989
|
+
};
|
|
4990
|
+
|
|
4991
|
+
// src/decorators/bootstrap.ts
|
|
4992
|
+
var getTableDefFromEntity = (ctor) => {
|
|
4993
|
+
const meta = getEntityMetadata(ctor);
|
|
4994
|
+
if (!meta) return void 0;
|
|
4995
|
+
return meta.table;
|
|
4996
|
+
};
|
|
4997
|
+
var selectFromEntity = (ctor) => {
|
|
4998
|
+
const table = getTableDefFromEntity(ctor);
|
|
4999
|
+
if (!table) {
|
|
5000
|
+
throw new Error("Entity metadata has not been bootstrapped");
|
|
5001
|
+
}
|
|
5002
|
+
return new SelectQueryBuilder(table);
|
|
5003
|
+
};
|
|
5004
|
+
|
|
5005
|
+
// src/query-builder/select-helpers.ts
|
|
5006
|
+
function sel(table, ...cols) {
|
|
5007
|
+
const selection = {};
|
|
5008
|
+
for (const col2 of cols) {
|
|
5009
|
+
const def = table.columns[col2];
|
|
5010
|
+
if (!def) {
|
|
5011
|
+
throw new Error(`Column '${col2}' not found on table '${table.name}'`);
|
|
5012
|
+
}
|
|
5013
|
+
selection[col2] = def;
|
|
5014
|
+
}
|
|
5015
|
+
return selection;
|
|
5016
|
+
}
|
|
5017
|
+
function esel(entity, ...props) {
|
|
5018
|
+
const table = getTableDefFromEntity(entity);
|
|
5019
|
+
if (!table) {
|
|
5020
|
+
throw new Error(`No table definition registered for entity '${entity.name}'`);
|
|
5021
|
+
}
|
|
5022
|
+
const selection = {};
|
|
5023
|
+
for (const prop of props) {
|
|
5024
|
+
const col2 = table.columns[prop];
|
|
5025
|
+
if (!col2) {
|
|
5026
|
+
throw new Error(`No column '${prop}' found for entity '${entity.name}'`);
|
|
5027
|
+
}
|
|
5028
|
+
selection[prop] = col2;
|
|
5029
|
+
}
|
|
5030
|
+
return selection;
|
|
5031
|
+
}
|
|
5032
|
+
|
|
4843
5033
|
// src/query-builder/insert-query-state.ts
|
|
4844
5034
|
var InsertQueryState = class _InsertQueryState {
|
|
4845
5035
|
constructor(table, ast) {
|
|
@@ -4858,7 +5048,15 @@ var InsertQueryState = class _InsertQueryState {
|
|
|
4858
5048
|
if (!rows.length) return this;
|
|
4859
5049
|
const definedColumns = this.ast.columns.length ? this.ast.columns : buildColumnNodes(this.table, Object.keys(rows[0]));
|
|
4860
5050
|
const newRows = rows.map(
|
|
4861
|
-
(row) => definedColumns.map((column) =>
|
|
5051
|
+
(row, rowIndex) => definedColumns.map((column) => {
|
|
5052
|
+
const rawValue = row[column.name];
|
|
5053
|
+
if (!isValueOperandInput(rawValue)) {
|
|
5054
|
+
throw new Error(
|
|
5055
|
+
`Invalid insert value for column "${column.name}" in row ${rowIndex}: only primitives, null, or OperandNodes are allowed`
|
|
5056
|
+
);
|
|
5057
|
+
}
|
|
5058
|
+
return valueToOperand(rawValue);
|
|
5059
|
+
})
|
|
4862
5060
|
);
|
|
4863
5061
|
return this.clone({
|
|
4864
5062
|
...this.ast,
|
|
@@ -4909,6 +5107,17 @@ var InsertQueryBuilder = class _InsertQueryBuilder {
|
|
|
4909
5107
|
};
|
|
4910
5108
|
|
|
4911
5109
|
// src/query-builder/update-query-state.ts
|
|
5110
|
+
var isUpdateValue = (value) => {
|
|
5111
|
+
if (value === null) return true;
|
|
5112
|
+
switch (typeof value) {
|
|
5113
|
+
case "string":
|
|
5114
|
+
case "number":
|
|
5115
|
+
case "boolean":
|
|
5116
|
+
return true;
|
|
5117
|
+
default:
|
|
5118
|
+
return isOperandNode(value);
|
|
5119
|
+
}
|
|
5120
|
+
};
|
|
4912
5121
|
var UpdateQueryState = class _UpdateQueryState {
|
|
4913
5122
|
constructor(table, ast) {
|
|
4914
5123
|
this.table = table;
|
|
@@ -4922,14 +5131,21 @@ var UpdateQueryState = class _UpdateQueryState {
|
|
|
4922
5131
|
return new _UpdateQueryState(this.table, nextAst);
|
|
4923
5132
|
}
|
|
4924
5133
|
withSet(values) {
|
|
4925
|
-
const assignments = Object.entries(values).map(([column,
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
}
|
|
4931
|
-
|
|
4932
|
-
|
|
5134
|
+
const assignments = Object.entries(values).map(([column, rawValue]) => {
|
|
5135
|
+
if (!isUpdateValue(rawValue)) {
|
|
5136
|
+
throw new Error(
|
|
5137
|
+
`Invalid update value for column "${column}": only primitives, null, or OperandNodes are allowed`
|
|
5138
|
+
);
|
|
5139
|
+
}
|
|
5140
|
+
return {
|
|
5141
|
+
column: {
|
|
5142
|
+
type: "Column",
|
|
5143
|
+
table: this.table.name,
|
|
5144
|
+
name: column
|
|
5145
|
+
},
|
|
5146
|
+
value: valueToOperand(rawValue)
|
|
5147
|
+
};
|
|
5148
|
+
});
|
|
4933
5149
|
return this.clone({
|
|
4934
5150
|
...this.ast,
|
|
4935
5151
|
set: assignments
|
|
@@ -6197,8 +6413,8 @@ var TypeScriptGenerator = class {
|
|
|
6197
6413
|
return `${key}: ${this.printOperand(operand)}`;
|
|
6198
6414
|
});
|
|
6199
6415
|
lines.push(`db.select({`);
|
|
6200
|
-
selections.forEach((
|
|
6201
|
-
lines.push(` ${
|
|
6416
|
+
selections.forEach((sel2, index) => {
|
|
6417
|
+
lines.push(` ${sel2}${index < selections.length - 1 ? "," : ""}`);
|
|
6202
6418
|
});
|
|
6203
6419
|
lines.push(`})`);
|
|
6204
6420
|
lines.push(`.from(${this.namingStrategy.tableToSymbol(ast.from)})`);
|
|
@@ -6481,26 +6697,6 @@ var TypeScriptGenerator = class {
|
|
|
6481
6697
|
}
|
|
6482
6698
|
};
|
|
6483
6699
|
|
|
6484
|
-
// src/orm/entity-metadata.ts
|
|
6485
|
-
var metadataMap = /* @__PURE__ */ new Map();
|
|
6486
|
-
var getEntityMetadata = (target) => {
|
|
6487
|
-
return metadataMap.get(target);
|
|
6488
|
-
};
|
|
6489
|
-
|
|
6490
|
-
// src/decorators/bootstrap.ts
|
|
6491
|
-
var getTableDefFromEntity = (ctor) => {
|
|
6492
|
-
const meta = getEntityMetadata(ctor);
|
|
6493
|
-
if (!meta) return void 0;
|
|
6494
|
-
return meta.table;
|
|
6495
|
-
};
|
|
6496
|
-
var selectFromEntity = (ctor) => {
|
|
6497
|
-
const table = getTableDefFromEntity(ctor);
|
|
6498
|
-
if (!table) {
|
|
6499
|
-
throw new Error("Entity metadata has not been bootstrapped");
|
|
6500
|
-
}
|
|
6501
|
-
return new SelectQueryBuilder(table);
|
|
6502
|
-
};
|
|
6503
|
-
|
|
6504
6700
|
// src/orm/identity-map.ts
|
|
6505
6701
|
var IdentityMap = class {
|
|
6506
6702
|
constructor() {
|
|
@@ -6713,6 +6909,7 @@ var UnitOfWork = class {
|
|
|
6713
6909
|
extractColumns(table, entity) {
|
|
6714
6910
|
const payload = {};
|
|
6715
6911
|
for (const column of Object.keys(table.columns)) {
|
|
6912
|
+
if (entity[column] === void 0) continue;
|
|
6716
6913
|
payload[column] = entity[column];
|
|
6717
6914
|
}
|
|
6718
6915
|
return payload;
|
|
@@ -6767,24 +6964,30 @@ var UnitOfWork = class {
|
|
|
6767
6964
|
var DomainEventBus = class {
|
|
6768
6965
|
constructor(initialHandlers) {
|
|
6769
6966
|
this.handlers = /* @__PURE__ */ new Map();
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6967
|
+
if (initialHandlers) {
|
|
6968
|
+
for (const key in initialHandlers) {
|
|
6969
|
+
const type = key;
|
|
6970
|
+
const list = initialHandlers[type] ?? [];
|
|
6971
|
+
this.handlers.set(type, [...list]);
|
|
6972
|
+
}
|
|
6973
|
+
}
|
|
6774
6974
|
}
|
|
6775
|
-
|
|
6776
|
-
const
|
|
6975
|
+
on(type, handler) {
|
|
6976
|
+
const key = type;
|
|
6977
|
+
const existing = this.handlers.get(key) ?? [];
|
|
6777
6978
|
existing.push(handler);
|
|
6778
|
-
this.handlers.set(
|
|
6979
|
+
this.handlers.set(key, existing);
|
|
6980
|
+
}
|
|
6981
|
+
register(type, handler) {
|
|
6982
|
+
this.on(type, handler);
|
|
6779
6983
|
}
|
|
6780
6984
|
async dispatch(trackedEntities, ctx) {
|
|
6781
6985
|
for (const tracked of trackedEntities) {
|
|
6782
6986
|
const entity = tracked.entity;
|
|
6783
|
-
if (!entity.domainEvents
|
|
6987
|
+
if (!entity.domainEvents?.length) continue;
|
|
6784
6988
|
for (const event of entity.domainEvents) {
|
|
6785
|
-
const
|
|
6786
|
-
|
|
6787
|
-
if (!handlers) continue;
|
|
6989
|
+
const handlers = this.handlers.get(event.type);
|
|
6990
|
+
if (!handlers?.length) continue;
|
|
6788
6991
|
for (const handler of handlers) {
|
|
6789
6992
|
await handler(event, ctx);
|
|
6790
6993
|
}
|
|
@@ -6792,11 +6995,6 @@ var DomainEventBus = class {
|
|
|
6792
6995
|
entity.domainEvents = [];
|
|
6793
6996
|
}
|
|
6794
6997
|
}
|
|
6795
|
-
getEventName(event) {
|
|
6796
|
-
if (!event) return "Unknown";
|
|
6797
|
-
if (typeof event === "string") return event;
|
|
6798
|
-
return event.constructor?.name ?? "Unknown";
|
|
6799
|
-
}
|
|
6800
6998
|
};
|
|
6801
6999
|
var addDomainEvent = (entity, event) => {
|
|
6802
7000
|
if (!entity.domainEvents) {
|
|
@@ -7038,8 +7236,8 @@ var OrmSession = class {
|
|
|
7038
7236
|
registerInterceptor(interceptor) {
|
|
7039
7237
|
this.interceptors.push(interceptor);
|
|
7040
7238
|
}
|
|
7041
|
-
registerDomainEventHandler(
|
|
7042
|
-
this.domainEvents.
|
|
7239
|
+
registerDomainEventHandler(type, handler) {
|
|
7240
|
+
this.domainEvents.on(type, handler);
|
|
7043
7241
|
}
|
|
7044
7242
|
async find(entityClass, id) {
|
|
7045
7243
|
const table = getTableDefFromEntity(entityClass);
|
|
@@ -7051,7 +7249,11 @@ var OrmSession = class {
|
|
|
7051
7249
|
if (!column) {
|
|
7052
7250
|
throw new Error("Entity table does not expose a primary key");
|
|
7053
7251
|
}
|
|
7054
|
-
const
|
|
7252
|
+
const columnSelections = Object.values(table.columns).reduce((acc, col2) => {
|
|
7253
|
+
acc[col2.name] = col2;
|
|
7254
|
+
return acc;
|
|
7255
|
+
}, {});
|
|
7256
|
+
const qb = selectFromEntity(entityClass).select(columnSelections).where(eq(column, id)).limit(1);
|
|
7055
7257
|
const rows = await executeHydrated(this, qb);
|
|
7056
7258
|
return rows[0] ?? null;
|
|
7057
7259
|
}
|
|
@@ -7163,7 +7365,6 @@ var Orm = class {
|
|
|
7163
7365
|
const executor = this.executorFactory.createExecutor(options?.tx);
|
|
7164
7366
|
return new OrmSession({ orm: this, executor });
|
|
7165
7367
|
}
|
|
7166
|
-
// Nice convenience:
|
|
7167
7368
|
async transaction(fn4) {
|
|
7168
7369
|
const executor = this.executorFactory.createTransactionalExecutor();
|
|
7169
7370
|
const session = new OrmSession({ orm: this, executor });
|
|
@@ -7355,6 +7556,7 @@ function createMssqlExecutor(client) {
|
|
|
7355
7556
|
diffSchema,
|
|
7356
7557
|
endOfMonth,
|
|
7357
7558
|
eq,
|
|
7559
|
+
esel,
|
|
7358
7560
|
executeHydrated,
|
|
7359
7561
|
executeHydratedWithContexts,
|
|
7360
7562
|
exists,
|
|
@@ -7366,6 +7568,7 @@ function createMssqlExecutor(client) {
|
|
|
7366
7568
|
generateCreateTableSql,
|
|
7367
7569
|
generateSchemaSql,
|
|
7368
7570
|
getSchemaIntrospector,
|
|
7571
|
+
groupConcat,
|
|
7369
7572
|
gt,
|
|
7370
7573
|
gte,
|
|
7371
7574
|
hasMany,
|
|
@@ -7380,6 +7583,7 @@ function createMssqlExecutor(client) {
|
|
|
7380
7583
|
isNotNull,
|
|
7381
7584
|
isNull,
|
|
7382
7585
|
isOperandNode,
|
|
7586
|
+
isValueOperandInput,
|
|
7383
7587
|
isWindowFunctionNode,
|
|
7384
7588
|
jsonPath,
|
|
7385
7589
|
lag,
|
|
@@ -7402,6 +7606,8 @@ function createMssqlExecutor(client) {
|
|
|
7402
7606
|
lt,
|
|
7403
7607
|
lte,
|
|
7404
7608
|
ltrim,
|
|
7609
|
+
max,
|
|
7610
|
+
min,
|
|
7405
7611
|
mod,
|
|
7406
7612
|
month,
|
|
7407
7613
|
neq,
|
|
@@ -7432,6 +7638,7 @@ function createMssqlExecutor(client) {
|
|
|
7432
7638
|
rowsToQueryResult,
|
|
7433
7639
|
rpad,
|
|
7434
7640
|
rtrim,
|
|
7641
|
+
sel,
|
|
7435
7642
|
sign,
|
|
7436
7643
|
sin,
|
|
7437
7644
|
space,
|