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.
Files changed (45) hide show
  1. package/README.md +33 -37
  2. package/dist/decorators/index.cjs +152 -23
  3. package/dist/decorators/index.cjs.map +1 -1
  4. package/dist/decorators/index.d.cts +1 -1
  5. package/dist/decorators/index.d.ts +1 -1
  6. package/dist/decorators/index.js +152 -23
  7. package/dist/decorators/index.js.map +1 -1
  8. package/dist/index.cjs +322 -115
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +53 -4
  11. package/dist/index.d.ts +53 -4
  12. package/dist/index.js +316 -115
  13. package/dist/index.js.map +1 -1
  14. package/dist/{select-BKZrMRCQ.d.cts → select-BPCn6MOH.d.cts} +183 -64
  15. package/dist/{select-BKZrMRCQ.d.ts → select-BPCn6MOH.d.ts} +183 -64
  16. package/package.json +2 -1
  17. package/src/core/ast/aggregate-functions.ts +50 -4
  18. package/src/core/ast/expression-builders.ts +22 -15
  19. package/src/core/ast/expression-nodes.ts +6 -0
  20. package/src/core/ddl/introspect/functions/postgres.ts +2 -6
  21. package/src/core/dialect/abstract.ts +12 -8
  22. package/src/core/dialect/mssql/functions.ts +24 -15
  23. package/src/core/dialect/postgres/functions.ts +33 -24
  24. package/src/core/dialect/sqlite/functions.ts +19 -12
  25. package/src/core/functions/datetime.ts +2 -1
  26. package/src/core/functions/numeric.ts +2 -1
  27. package/src/core/functions/standard-strategy.ts +52 -12
  28. package/src/core/functions/text.ts +2 -1
  29. package/src/core/functions/types.ts +8 -8
  30. package/src/index.ts +5 -4
  31. package/src/orm/domain-event-bus.ts +43 -25
  32. package/src/orm/entity-meta.ts +40 -0
  33. package/src/orm/execution-context.ts +6 -0
  34. package/src/orm/hydration-context.ts +6 -4
  35. package/src/orm/orm-session.ts +35 -24
  36. package/src/orm/orm.ts +10 -10
  37. package/src/orm/query-logger.ts +15 -0
  38. package/src/orm/runtime-types.ts +60 -2
  39. package/src/orm/transaction-runner.ts +7 -0
  40. package/src/orm/unit-of-work.ts +1 -0
  41. package/src/query-builder/insert-query-state.ts +13 -3
  42. package/src/query-builder/select-helpers.ts +50 -0
  43. package/src/query-builder/select.ts +122 -30
  44. package/src/query-builder/update-query-state.ts +31 -9
  45. package/src/schema/types.ts +16 -6
@@ -1,4 +1,4 @@
1
- import { $ as TableHooks, a1 as ColumnType, h as ColumnDef, aN as EntityOrTableTargetResolver, a8 as CascadeMode, i as TableDef, aO as EntityConstructor, V as SelectQueryBuilder } from '../select-BKZrMRCQ.cjs';
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, aN as EntityOrTableTargetResolver, a8 as CascadeMode, i as TableDef, aO as EntityConstructor, V as SelectQueryBuilder } from '../select-BKZrMRCQ.js';
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;
@@ -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 === null) return { type: "Literal", value: null };
312
- if (typeof val === "string" || typeof val === "number" || typeof val === "boolean") {
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({ node: fnNode, compiledArgs });
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
  }