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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as TableHooks, a1 as ColumnType, h as ColumnDef,
|
|
1
|
+
import { $ as TableHooks, a1 as ColumnType, h as ColumnDef, aS as EntityOrTableTargetResolver, a8 as CascadeMode, i as TableDef, aT as EntityConstructor, V as SelectQueryBuilder } from '../select-BPCn6MOH.cjs';
|
|
2
2
|
|
|
3
3
|
interface EntityOptions {
|
|
4
4
|
tableName?: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as TableHooks, a1 as ColumnType, h as ColumnDef,
|
|
1
|
+
import { $ as TableHooks, a1 as ColumnType, h as ColumnDef, aS as EntityOrTableTargetResolver, a8 as CascadeMode, i as TableDef, aT as EntityConstructor, V as SelectQueryBuilder } from '../select-BPCn6MOH.js';
|
|
2
2
|
|
|
3
3
|
interface EntityOptions {
|
|
4
4
|
tableName?: string;
|
package/dist/decorators/index.js
CHANGED
|
@@ -298,6 +298,15 @@ var isWindowFunctionNode = (node) => node?.type === "WindowFunction";
|
|
|
298
298
|
var isExpressionSelectionNode = (node) => isFunctionNode(node) || isCaseExpressionNode(node) || isWindowFunctionNode(node);
|
|
299
299
|
|
|
300
300
|
// src/core/ast/expression-builders.ts
|
|
301
|
+
var valueToOperand = (value) => {
|
|
302
|
+
if (isOperandNode(value)) {
|
|
303
|
+
return value;
|
|
304
|
+
}
|
|
305
|
+
return {
|
|
306
|
+
type: "Literal",
|
|
307
|
+
value
|
|
308
|
+
};
|
|
309
|
+
};
|
|
301
310
|
var toNode = (col) => {
|
|
302
311
|
if (isOperandNode(col)) return col;
|
|
303
312
|
const def = col;
|
|
@@ -307,10 +316,10 @@ var toLiteralNode = (value) => ({
|
|
|
307
316
|
type: "Literal",
|
|
308
317
|
value
|
|
309
318
|
});
|
|
319
|
+
var isLiteralValue = (value) => value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
310
320
|
var toOperand = (val) => {
|
|
311
|
-
if (val
|
|
312
|
-
|
|
313
|
-
return { type: "Literal", value: val };
|
|
321
|
+
if (isLiteralValue(val)) {
|
|
322
|
+
return valueToOperand(val);
|
|
314
323
|
}
|
|
315
324
|
return toNode(val);
|
|
316
325
|
};
|
|
@@ -351,6 +360,24 @@ var notExists = (subquery) => ({
|
|
|
351
360
|
subquery
|
|
352
361
|
});
|
|
353
362
|
|
|
363
|
+
// src/core/sql/sql.ts
|
|
364
|
+
var JOIN_KINDS = {
|
|
365
|
+
/** INNER JOIN type */
|
|
366
|
+
INNER: "INNER",
|
|
367
|
+
/** LEFT JOIN type */
|
|
368
|
+
LEFT: "LEFT",
|
|
369
|
+
/** RIGHT JOIN type */
|
|
370
|
+
RIGHT: "RIGHT",
|
|
371
|
+
/** CROSS JOIN type */
|
|
372
|
+
CROSS: "CROSS"
|
|
373
|
+
};
|
|
374
|
+
var ORDER_DIRECTIONS = {
|
|
375
|
+
/** Ascending order */
|
|
376
|
+
ASC: "ASC",
|
|
377
|
+
/** Descending order */
|
|
378
|
+
DESC: "DESC"
|
|
379
|
+
};
|
|
380
|
+
|
|
354
381
|
// src/core/ast/aggregate-functions.ts
|
|
355
382
|
var buildAggregate = (name) => (col) => ({
|
|
356
383
|
type: "Function",
|
|
@@ -360,14 +387,21 @@ var buildAggregate = (name) => (col) => ({
|
|
|
360
387
|
var count = buildAggregate("COUNT");
|
|
361
388
|
var sum = buildAggregate("SUM");
|
|
362
389
|
var avg = buildAggregate("AVG");
|
|
390
|
+
var min = buildAggregate("MIN");
|
|
391
|
+
var max = buildAggregate("MAX");
|
|
363
392
|
|
|
364
393
|
// src/core/functions/standard-strategy.ts
|
|
365
|
-
var StandardFunctionStrategy = class {
|
|
394
|
+
var StandardFunctionStrategy = class _StandardFunctionStrategy {
|
|
366
395
|
constructor() {
|
|
367
396
|
this.renderers = /* @__PURE__ */ new Map();
|
|
368
397
|
this.registerStandard();
|
|
369
398
|
}
|
|
370
399
|
registerStandard() {
|
|
400
|
+
this.add("COUNT", ({ compiledArgs }) => `COUNT(${compiledArgs.join(", ")})`);
|
|
401
|
+
this.add("SUM", ({ compiledArgs }) => `SUM(${compiledArgs[0]})`);
|
|
402
|
+
this.add("AVG", ({ compiledArgs }) => `AVG(${compiledArgs[0]})`);
|
|
403
|
+
this.add("MIN", ({ compiledArgs }) => `MIN(${compiledArgs[0]})`);
|
|
404
|
+
this.add("MAX", ({ compiledArgs }) => `MAX(${compiledArgs[0]})`);
|
|
371
405
|
this.add("ABS", ({ compiledArgs }) => `ABS(${compiledArgs[0]})`);
|
|
372
406
|
this.add("UPPER", ({ compiledArgs }) => `UPPER(${compiledArgs[0]})`);
|
|
373
407
|
this.add("LOWER", ({ compiledArgs }) => `LOWER(${compiledArgs[0]})`);
|
|
@@ -394,6 +428,7 @@ var StandardFunctionStrategy = class {
|
|
|
394
428
|
this.add("DAY_OF_WEEK", ({ compiledArgs }) => `DAYOFWEEK(${compiledArgs[0]})`);
|
|
395
429
|
this.add("WEEK_OF_YEAR", ({ compiledArgs }) => `WEEKOFYEAR(${compiledArgs[0]})`);
|
|
396
430
|
this.add("DATE_TRUNC", ({ compiledArgs }) => `DATE_TRUNC(${compiledArgs[0]}, ${compiledArgs[1]})`);
|
|
431
|
+
this.add("GROUP_CONCAT", (ctx) => this.renderGroupConcat(ctx));
|
|
397
432
|
}
|
|
398
433
|
add(name, renderer) {
|
|
399
434
|
this.renderers.set(name, renderer);
|
|
@@ -401,6 +436,36 @@ var StandardFunctionStrategy = class {
|
|
|
401
436
|
getRenderer(name) {
|
|
402
437
|
return this.renderers.get(name);
|
|
403
438
|
}
|
|
439
|
+
renderGroupConcat(ctx) {
|
|
440
|
+
const arg = ctx.compiledArgs[0];
|
|
441
|
+
const orderClause = this.buildOrderByExpression(ctx);
|
|
442
|
+
const orderSegment = orderClause ? ` ${orderClause}` : "";
|
|
443
|
+
const separatorClause = this.formatGroupConcatSeparator(ctx);
|
|
444
|
+
return `GROUP_CONCAT(${arg}${orderSegment}${separatorClause})`;
|
|
445
|
+
}
|
|
446
|
+
buildOrderByExpression(ctx) {
|
|
447
|
+
const orderBy = ctx.node.orderBy;
|
|
448
|
+
if (!orderBy || orderBy.length === 0) {
|
|
449
|
+
return "";
|
|
450
|
+
}
|
|
451
|
+
const parts = orderBy.map((order) => `${ctx.compileOperand(order.column)} ${order.direction}`);
|
|
452
|
+
return `ORDER BY ${parts.join(", ")}`;
|
|
453
|
+
}
|
|
454
|
+
formatGroupConcatSeparator(ctx) {
|
|
455
|
+
if (!ctx.node.separator) {
|
|
456
|
+
return "";
|
|
457
|
+
}
|
|
458
|
+
return ` SEPARATOR ${ctx.compileOperand(ctx.node.separator)}`;
|
|
459
|
+
}
|
|
460
|
+
getGroupConcatSeparatorOperand(ctx) {
|
|
461
|
+
return ctx.node.separator ?? _StandardFunctionStrategy.DEFAULT_GROUP_CONCAT_SEPARATOR;
|
|
462
|
+
}
|
|
463
|
+
static {
|
|
464
|
+
this.DEFAULT_GROUP_CONCAT_SEPARATOR = {
|
|
465
|
+
type: "Literal",
|
|
466
|
+
value: ","
|
|
467
|
+
};
|
|
468
|
+
}
|
|
404
469
|
};
|
|
405
470
|
|
|
406
471
|
// src/core/dialect/abstract.ts
|
|
@@ -747,7 +812,11 @@ var Dialect = class _Dialect {
|
|
|
747
812
|
const compiledArgs = fnNode.args.map((arg) => this.compileOperand(arg, ctx));
|
|
748
813
|
const renderer = this.functionStrategy.getRenderer(fnNode.name);
|
|
749
814
|
if (renderer) {
|
|
750
|
-
return renderer({
|
|
815
|
+
return renderer({
|
|
816
|
+
node: fnNode,
|
|
817
|
+
compiledArgs,
|
|
818
|
+
compileOperand: (operand) => this.compileOperand(operand, ctx)
|
|
819
|
+
});
|
|
751
820
|
}
|
|
752
821
|
return `${fnNode.name}(${compiledArgs.join(", ")})`;
|
|
753
822
|
}
|
|
@@ -1170,6 +1239,14 @@ var PostgresFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
1170
1239
|
const partClean = String(partArg.value).replace(/['"]/g, "").toLowerCase();
|
|
1171
1240
|
return `DATE_TRUNC('${partClean}', ${date})`;
|
|
1172
1241
|
});
|
|
1242
|
+
this.add("GROUP_CONCAT", (ctx) => {
|
|
1243
|
+
const arg = ctx.compiledArgs[0];
|
|
1244
|
+
const orderClause = this.buildOrderByExpression(ctx);
|
|
1245
|
+
const orderSegment = orderClause ? ` ${orderClause}` : "";
|
|
1246
|
+
const separatorOperand = this.getGroupConcatSeparatorOperand(ctx);
|
|
1247
|
+
const separator = ctx.compileOperand(separatorOperand);
|
|
1248
|
+
return `STRING_AGG(${arg}, ${separator}${orderSegment})`;
|
|
1249
|
+
});
|
|
1173
1250
|
}
|
|
1174
1251
|
};
|
|
1175
1252
|
|
|
@@ -1414,6 +1491,12 @@ var SqliteFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
1414
1491
|
}
|
|
1415
1492
|
return `date(${date}, 'start of ${partClean}')`;
|
|
1416
1493
|
});
|
|
1494
|
+
this.add("GROUP_CONCAT", (ctx) => {
|
|
1495
|
+
const arg = ctx.compiledArgs[0];
|
|
1496
|
+
const separatorOperand = this.getGroupConcatSeparatorOperand(ctx);
|
|
1497
|
+
const separator = ctx.compileOperand(separatorOperand);
|
|
1498
|
+
return `GROUP_CONCAT(${arg}, ${separator})`;
|
|
1499
|
+
});
|
|
1417
1500
|
}
|
|
1418
1501
|
};
|
|
1419
1502
|
|
|
@@ -1530,6 +1613,14 @@ var MssqlFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
1530
1613
|
const partClean = String(partArg.value).replace(/['"]/g, "").toLowerCase();
|
|
1531
1614
|
return `DATETRUNC(${partClean}, ${date})`;
|
|
1532
1615
|
});
|
|
1616
|
+
this.add("GROUP_CONCAT", (ctx) => {
|
|
1617
|
+
const arg = ctx.compiledArgs[0];
|
|
1618
|
+
const separatorOperand = this.getGroupConcatSeparatorOperand(ctx);
|
|
1619
|
+
const separator = ctx.compileOperand(separatorOperand);
|
|
1620
|
+
const orderClause = this.buildOrderByExpression(ctx);
|
|
1621
|
+
const withinGroup = orderClause ? ` WITHIN GROUP (${orderClause})` : "";
|
|
1622
|
+
return `STRING_AGG(${arg}, ${separator})${withinGroup}`;
|
|
1623
|
+
});
|
|
1533
1624
|
}
|
|
1534
1625
|
};
|
|
1535
1626
|
|
|
@@ -1899,24 +1990,6 @@ var createJoinNode = (kind, tableName, condition, relationName) => ({
|
|
|
1899
1990
|
meta: relationName ? { relationName } : void 0
|
|
1900
1991
|
});
|
|
1901
1992
|
|
|
1902
|
-
// src/core/sql/sql.ts
|
|
1903
|
-
var JOIN_KINDS = {
|
|
1904
|
-
/** INNER JOIN type */
|
|
1905
|
-
INNER: "INNER",
|
|
1906
|
-
/** LEFT JOIN type */
|
|
1907
|
-
LEFT: "LEFT",
|
|
1908
|
-
/** RIGHT JOIN type */
|
|
1909
|
-
RIGHT: "RIGHT",
|
|
1910
|
-
/** CROSS JOIN type */
|
|
1911
|
-
CROSS: "CROSS"
|
|
1912
|
-
};
|
|
1913
|
-
var ORDER_DIRECTIONS = {
|
|
1914
|
-
/** Ascending order */
|
|
1915
|
-
ASC: "ASC",
|
|
1916
|
-
/** Descending order */
|
|
1917
|
-
DESC: "DESC"
|
|
1918
|
-
};
|
|
1919
|
-
|
|
1920
1993
|
// src/query-builder/hydration-manager.ts
|
|
1921
1994
|
var HydrationManager = class _HydrationManager {
|
|
1922
1995
|
/**
|
|
@@ -4025,6 +4098,21 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4025
4098
|
select(columns) {
|
|
4026
4099
|
return this.clone(this.columnSelector.select(this.context, columns));
|
|
4027
4100
|
}
|
|
4101
|
+
/**
|
|
4102
|
+
* Selects columns from the root table by name (typed).
|
|
4103
|
+
* @param cols - Column names on the root table
|
|
4104
|
+
*/
|
|
4105
|
+
selectColumns(...cols) {
|
|
4106
|
+
const selection = {};
|
|
4107
|
+
for (const key of cols) {
|
|
4108
|
+
const col = this.env.table.columns[key];
|
|
4109
|
+
if (!col) {
|
|
4110
|
+
throw new Error(`Column '${key}' not found on table '${this.env.table.name}'`);
|
|
4111
|
+
}
|
|
4112
|
+
selection[key] = col;
|
|
4113
|
+
}
|
|
4114
|
+
return this.select(selection);
|
|
4115
|
+
}
|
|
4028
4116
|
/**
|
|
4029
4117
|
|
|
4030
4118
|
* Selects raw column expressions
|
|
@@ -4185,6 +4273,47 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4185
4273
|
nextLazy.add(relationName);
|
|
4186
4274
|
return this.clone(this.context, nextLazy);
|
|
4187
4275
|
}
|
|
4276
|
+
/**
|
|
4277
|
+
* Selects columns for a related table in a single hop.
|
|
4278
|
+
*/
|
|
4279
|
+
selectRelationColumns(relationName, ...cols) {
|
|
4280
|
+
const relation = this.env.table.relations[relationName];
|
|
4281
|
+
if (!relation) {
|
|
4282
|
+
throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
|
|
4283
|
+
}
|
|
4284
|
+
const target = relation.target;
|
|
4285
|
+
for (const col of cols) {
|
|
4286
|
+
if (!target.columns[col]) {
|
|
4287
|
+
throw new Error(
|
|
4288
|
+
`Column '${col}' not found on related table '${target.name}' for relation '${relationName}'`
|
|
4289
|
+
);
|
|
4290
|
+
}
|
|
4291
|
+
}
|
|
4292
|
+
return this.include(relationName, { columns: cols });
|
|
4293
|
+
}
|
|
4294
|
+
/**
|
|
4295
|
+
* Convenience alias for selecting specific columns from a relation.
|
|
4296
|
+
*/
|
|
4297
|
+
includePick(relationName, cols) {
|
|
4298
|
+
return this.selectRelationColumns(relationName, ...cols);
|
|
4299
|
+
}
|
|
4300
|
+
/**
|
|
4301
|
+
* Selects columns for the root table and relations from a single config object.
|
|
4302
|
+
*/
|
|
4303
|
+
selectColumnsDeep(config) {
|
|
4304
|
+
let qb = this;
|
|
4305
|
+
if (config.root?.length) {
|
|
4306
|
+
qb = qb.selectColumns(...config.root);
|
|
4307
|
+
}
|
|
4308
|
+
for (const key of Object.keys(config)) {
|
|
4309
|
+
if (key === "root") continue;
|
|
4310
|
+
const relName = key;
|
|
4311
|
+
const cols = config[relName];
|
|
4312
|
+
if (!cols || !cols.length) continue;
|
|
4313
|
+
qb = qb.selectRelationColumns(relName, ...cols);
|
|
4314
|
+
}
|
|
4315
|
+
return qb;
|
|
4316
|
+
}
|
|
4188
4317
|
getLazyRelations() {
|
|
4189
4318
|
return Array.from(this.lazyRelations);
|
|
4190
4319
|
}
|