metal-orm 1.0.42 → 1.0.44

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 (122) hide show
  1. package/README.md +195 -37
  2. package/dist/index.cjs +1014 -538
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +1267 -371
  5. package/dist/index.d.ts +1267 -371
  6. package/dist/index.js +1012 -536
  7. package/dist/index.js.map +1 -1
  8. package/package.json +8 -2
  9. package/scripts/run-eslint.mjs +34 -0
  10. package/src/codegen/typescript.ts +32 -15
  11. package/src/core/ast/adapters.ts +8 -2
  12. package/src/core/ast/builders.ts +105 -76
  13. package/src/core/ast/expression-builders.ts +430 -392
  14. package/src/core/ast/expression-nodes.ts +14 -5
  15. package/src/core/ast/expression-visitor.ts +56 -14
  16. package/src/core/ast/helpers.ts +23 -0
  17. package/src/core/ast/join-node.ts +18 -2
  18. package/src/core/ast/query.ts +6 -6
  19. package/src/core/ast/window-functions.ts +10 -2
  20. package/src/core/ddl/dialects/base-schema-dialect.ts +37 -4
  21. package/src/core/ddl/dialects/index.ts +1 -0
  22. package/src/core/ddl/dialects/mssql-schema-dialect.ts +5 -0
  23. package/src/core/ddl/dialects/mysql-schema-dialect.ts +3 -0
  24. package/src/core/ddl/dialects/postgres-schema-dialect.ts +14 -1
  25. package/src/core/ddl/dialects/render-reference.test.ts +69 -0
  26. package/src/core/ddl/dialects/sqlite-schema-dialect.ts +10 -0
  27. package/src/core/ddl/introspect/catalogs/index.ts +1 -0
  28. package/src/core/ddl/introspect/catalogs/postgres.ts +2 -0
  29. package/src/core/ddl/introspect/context.ts +6 -0
  30. package/src/core/ddl/introspect/functions/postgres.ts +13 -0
  31. package/src/core/ddl/introspect/mssql.ts +53 -8
  32. package/src/core/ddl/introspect/mysql.ts +32 -6
  33. package/src/core/ddl/introspect/postgres.ts +102 -34
  34. package/src/core/ddl/introspect/registry.ts +14 -0
  35. package/src/core/ddl/introspect/run-select.ts +19 -4
  36. package/src/core/ddl/introspect/sqlite.ts +78 -11
  37. package/src/core/ddl/introspect/types.ts +0 -1
  38. package/src/core/ddl/introspect/utils.ts +21 -3
  39. package/src/core/ddl/naming-strategy.ts +6 -0
  40. package/src/core/ddl/schema-dialect.ts +20 -6
  41. package/src/core/ddl/schema-diff.ts +22 -0
  42. package/src/core/ddl/schema-generator.ts +26 -12
  43. package/src/core/ddl/schema-plan-executor.ts +6 -0
  44. package/src/core/ddl/schema-types.ts +6 -0
  45. package/src/core/ddl/sql-writing.ts +4 -4
  46. package/src/core/dialect/abstract.ts +19 -7
  47. package/src/core/dialect/base/function-table-formatter.ts +3 -2
  48. package/src/core/dialect/base/join-compiler.ts +5 -3
  49. package/src/core/dialect/base/returning-strategy.ts +1 -0
  50. package/src/core/dialect/base/sql-dialect.ts +3 -3
  51. package/src/core/dialect/mssql/functions.ts +24 -25
  52. package/src/core/dialect/mssql/index.ts +1 -4
  53. package/src/core/dialect/mysql/functions.ts +0 -1
  54. package/src/core/dialect/postgres/functions.ts +33 -34
  55. package/src/core/dialect/postgres/index.ts +1 -0
  56. package/src/core/dialect/sqlite/functions.ts +18 -19
  57. package/src/core/dialect/sqlite/index.ts +2 -0
  58. package/src/core/execution/db-executor.ts +1 -1
  59. package/src/core/execution/executors/mysql-executor.ts +2 -2
  60. package/src/core/execution/executors/postgres-executor.ts +1 -1
  61. package/src/core/execution/pooling/pool.ts +12 -5
  62. package/src/core/functions/datetime.ts +58 -34
  63. package/src/core/functions/numeric.ts +96 -31
  64. package/src/core/functions/standard-strategy.ts +35 -0
  65. package/src/core/functions/text.ts +84 -23
  66. package/src/core/functions/types.ts +23 -8
  67. package/src/decorators/bootstrap.ts +42 -11
  68. package/src/decorators/column.ts +20 -11
  69. package/src/decorators/decorator-metadata.ts +30 -9
  70. package/src/decorators/entity.ts +29 -5
  71. package/src/decorators/index.ts +3 -0
  72. package/src/decorators/relations.ts +34 -11
  73. package/src/orm/als.ts +34 -9
  74. package/src/orm/entity-context.ts +62 -8
  75. package/src/orm/entity-meta.ts +8 -8
  76. package/src/orm/entity-metadata.ts +131 -16
  77. package/src/orm/entity.ts +28 -29
  78. package/src/orm/execute.ts +19 -4
  79. package/src/orm/hydration.ts +42 -39
  80. package/src/orm/identity-map.ts +1 -1
  81. package/src/orm/lazy-batch.ts +74 -104
  82. package/src/orm/orm-session.ts +24 -23
  83. package/src/orm/orm.ts +2 -5
  84. package/src/orm/relation-change-processor.ts +12 -11
  85. package/src/orm/relations/belongs-to.ts +11 -11
  86. package/src/orm/relations/has-many.ts +54 -10
  87. package/src/orm/relations/has-one.ts +8 -7
  88. package/src/orm/relations/many-to-many.ts +13 -13
  89. package/src/orm/runtime-types.ts +4 -4
  90. package/src/orm/save-graph.ts +31 -25
  91. package/src/orm/unit-of-work.ts +17 -17
  92. package/src/query/index.ts +74 -0
  93. package/src/query/target.ts +46 -0
  94. package/src/query-builder/delete-query-state.ts +30 -0
  95. package/src/query-builder/delete.ts +64 -18
  96. package/src/query-builder/hydration-manager.ts +52 -5
  97. package/src/query-builder/insert-query-state.ts +30 -0
  98. package/src/query-builder/insert.ts +58 -10
  99. package/src/query-builder/query-ast-service.ts +7 -2
  100. package/src/query-builder/query-resolution.ts +78 -0
  101. package/src/query-builder/raw-column-parser.ts +7 -1
  102. package/src/query-builder/relation-alias.ts +7 -0
  103. package/src/query-builder/relation-conditions.ts +61 -48
  104. package/src/query-builder/relation-service.ts +68 -63
  105. package/src/query-builder/relation-utils.ts +3 -0
  106. package/src/query-builder/select/cte-facet.ts +40 -0
  107. package/src/query-builder/select/from-facet.ts +80 -0
  108. package/src/query-builder/select/join-facet.ts +62 -0
  109. package/src/query-builder/select/predicate-facet.ts +103 -0
  110. package/src/query-builder/select/projection-facet.ts +69 -0
  111. package/src/query-builder/select/relation-facet.ts +81 -0
  112. package/src/query-builder/select/setop-facet.ts +36 -0
  113. package/src/query-builder/select-helpers.ts +15 -2
  114. package/src/query-builder/select-query-builder-deps.ts +19 -1
  115. package/src/query-builder/select-query-state.ts +2 -1
  116. package/src/query-builder/select.ts +795 -1163
  117. package/src/query-builder/update-query-state.ts +52 -0
  118. package/src/query-builder/update.ts +69 -18
  119. package/src/schema/column.ts +26 -26
  120. package/src/schema/table-guards.ts +31 -0
  121. package/src/schema/table.ts +47 -18
  122. package/src/schema/types.ts +22 -22
package/dist/index.js CHANGED
@@ -32,7 +32,8 @@ var init_schema_plan_executor = __esm({
32
32
  // src/schema/table.ts
33
33
  var defineTable = (name, columns, relations = {}, hooks, options = {}) => {
34
34
  const colsWithNames = Object.entries(columns).reduce((acc, [key, def]) => {
35
- acc[key] = { ...def, name: key, table: name };
35
+ const colDef = { ...def, name: key, table: name };
36
+ acc[key] = colDef;
36
37
  return acc;
37
38
  }, {});
38
39
  return {
@@ -56,17 +57,20 @@ var withColumnProps = (table) => {
56
57
  if (cached) return cached;
57
58
  const proxy = new Proxy(table, {
58
59
  get(target, prop, receiver) {
59
- if (prop === "$") return target.columns;
60
+ const t = target;
61
+ if (prop === "$") return t.columns;
60
62
  if (Reflect.has(target, prop)) return Reflect.get(target, prop, receiver);
61
- if (typeof prop === "string" && prop in target.columns) return target.columns[prop];
63
+ if (typeof prop === "string" && prop in t.columns) return t.columns[prop];
62
64
  return void 0;
63
65
  },
64
66
  has(target, prop) {
65
- return prop === "$" || Reflect.has(target, prop) || typeof prop === "string" && prop in target.columns;
67
+ const t = target;
68
+ return prop === "$" || Reflect.has(target, prop) || typeof prop === "string" && prop in t.columns;
66
69
  },
67
70
  ownKeys(target) {
71
+ const t = target;
68
72
  const base = Reflect.ownKeys(target);
69
- const cols = Object.keys(target.columns);
73
+ const cols = Object.keys(t.columns);
70
74
  for (const k of cols) {
71
75
  if (!base.includes(k)) base.push(k);
72
76
  }
@@ -98,6 +102,14 @@ var withColumnProps = (table) => {
98
102
  return proxy;
99
103
  };
100
104
  var tableRef = (table) => withColumnProps(table);
105
+ function getColumn(table, key) {
106
+ const col2 = table.columns[key];
107
+ if (!col2) {
108
+ const tableName = table.name || "<unknown>";
109
+ throw new Error(`Column '${key}' does not exist on table '${tableName}'`);
110
+ }
111
+ return col2;
112
+ }
101
113
 
102
114
  // src/schema/column.ts
103
115
  var col = {
@@ -302,46 +314,59 @@ var operandTypes = /* @__PURE__ */ new Set([
302
314
  "CaseExpression",
303
315
  "WindowFunction"
304
316
  ]);
305
- var isOperandNode = (node) => node && operandTypes.has(node.type);
306
- var isFunctionNode = (node) => node?.type === "Function";
307
- var isCaseExpressionNode = (node) => node?.type === "CaseExpression";
308
- var isWindowFunctionNode = (node) => node?.type === "WindowFunction";
317
+ var hasTypeProperty = (value) => typeof value === "object" && value !== null && "type" in value;
318
+ var isOperandNode = (node) => {
319
+ if (!hasTypeProperty(node)) return false;
320
+ return operandTypes.has(node.type);
321
+ };
322
+ var isFunctionNode = (node) => isOperandNode(node) && node.type === "Function";
323
+ var isCaseExpressionNode = (node) => isOperandNode(node) && node.type === "CaseExpression";
324
+ var isWindowFunctionNode = (node) => isOperandNode(node) && node.type === "WindowFunction";
309
325
  var isExpressionSelectionNode = (node) => isFunctionNode(node) || isCaseExpressionNode(node) || isWindowFunctionNode(node);
310
326
 
311
327
  // src/core/ast/expression-builders.ts
312
- var valueToOperand = (value) => {
313
- if (isOperandNode(value)) {
314
- return value;
315
- }
316
- return {
317
- type: "Literal",
318
- value
319
- };
320
- };
321
- var toNode = (col2) => {
322
- if (isOperandNode(col2)) return col2;
323
- const def = col2;
324
- return { type: "Column", table: def.table || "unknown", name: def.name };
325
- };
328
+ var isLiteralValue = (value) => value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
326
329
  var toLiteralNode = (value) => ({
327
330
  type: "Literal",
328
331
  value
329
332
  });
330
- var isLiteralValue = (value) => value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
331
- var isValueOperandInput = (value) => isOperandNode(value) || isLiteralValue(value);
332
- var toOperand = (val) => {
333
- if (isLiteralValue(val)) {
334
- return valueToOperand(val);
333
+ var columnRefToNode = (col2) => {
334
+ if (!col2.table) {
335
+ throw new Error(
336
+ `Column "${col2.name}" requires a table reference. Use columnOperand with a fully qualified ColumnRef or ColumnNode.`
337
+ );
335
338
  }
336
- return toNode(val);
339
+ return { type: "Column", table: col2.table, name: col2.name };
337
340
  };
341
+ var toOperandNode = (value) => {
342
+ if (isOperandNode(value)) {
343
+ return value;
344
+ }
345
+ if (isLiteralValue(value)) {
346
+ return toLiteralNode(value);
347
+ }
348
+ return columnRefToNode(value);
349
+ };
350
+ var valueToOperand = (value) => {
351
+ if (isOperandNode(value)) {
352
+ return value;
353
+ }
354
+ return toLiteralNode(value);
355
+ };
356
+ var toOperand = (val) => toOperandNode(val);
357
+ var isValueOperandInput = (value) => isOperandNode(value) || isLiteralValue(value);
338
358
  var hasQueryAst = (value) => typeof value.getAST === "function";
339
359
  var resolveSelectQueryNode = (query) => hasQueryAst(query) ? query.getAST() : query;
340
360
  var toScalarSubqueryNode = (query) => ({
341
361
  type: "ScalarSubquery",
342
362
  query: resolveSelectQueryNode(query)
343
363
  });
344
- var columnOperand = (col2) => toNode(col2);
364
+ var columnOperand = (col2) => {
365
+ if (isOperandNode(col2) && col2.type === "Column") {
366
+ return col2;
367
+ }
368
+ return columnRefToNode(col2);
369
+ };
345
370
  var outerRef = (col2) => ({
346
371
  ...columnOperand(col2),
347
372
  scope: "outer"
@@ -354,7 +379,7 @@ var correlateBy = (table, column) => outerRef({ name: column, table });
354
379
  var createBinaryExpression = (operator, left2, right2, escape) => {
355
380
  const node = {
356
381
  type: "BinaryExpression",
357
- left: toNode(left2),
382
+ left: toOperandNode(left2),
358
383
  operator,
359
384
  right: toOperand(right2)
360
385
  };
@@ -383,17 +408,17 @@ var or = (...operands) => ({
383
408
  });
384
409
  var isNull = (left2) => ({
385
410
  type: "NullExpression",
386
- left: toNode(left2),
411
+ left: toOperandNode(left2),
387
412
  operator: "IS NULL"
388
413
  });
389
414
  var isNotNull = (left2) => ({
390
415
  type: "NullExpression",
391
- left: toNode(left2),
416
+ left: toOperandNode(left2),
392
417
  operator: "IS NOT NULL"
393
418
  });
394
419
  var createInExpression = (operator, left2, right2) => ({
395
420
  type: "InExpression",
396
- left: toNode(left2),
421
+ left: toOperandNode(left2),
397
422
  operator,
398
423
  right: right2
399
424
  });
@@ -403,7 +428,7 @@ var inSubquery = (left2, subquery) => createInExpression("IN", left2, toScalarSu
403
428
  var notInSubquery = (left2, subquery) => createInExpression("NOT IN", left2, toScalarSubqueryNode(subquery));
404
429
  var createBetweenExpression = (operator, left2, lower2, upper2) => ({
405
430
  type: "BetweenExpression",
406
- left: toNode(left2),
431
+ left: toOperandNode(left2),
407
432
  operator,
408
433
  lower: toOperand(lower2),
409
434
  upper: toOperand(upper2)
@@ -585,24 +610,54 @@ var groupConcat = (col2, options) => ({
585
610
  });
586
611
 
587
612
  // src/core/ast/expression-visitor.ts
588
- var expressionDispatchers = /* @__PURE__ */ new Map();
589
- var operandDispatchers = /* @__PURE__ */ new Map();
613
+ var DispatcherRegistry = class _DispatcherRegistry {
614
+ constructor(dispatchers = /* @__PURE__ */ new Map()) {
615
+ this.dispatchers = dispatchers;
616
+ }
617
+ /**
618
+ * Registers a new dispatcher and returns a new registry instance
619
+ */
620
+ register(type, dispatcher) {
621
+ const newMap = new Map(this.dispatchers);
622
+ newMap.set(type, dispatcher);
623
+ return new _DispatcherRegistry(newMap);
624
+ }
625
+ /**
626
+ * Gets a dispatcher for the given type
627
+ */
628
+ get(type) {
629
+ return this.dispatchers.get(type);
630
+ }
631
+ /**
632
+ * Returns a new empty registry
633
+ */
634
+ clear() {
635
+ return new _DispatcherRegistry();
636
+ }
637
+ };
638
+ var expressionRegistry = new DispatcherRegistry();
639
+ var operandRegistry = new DispatcherRegistry();
590
640
  var registerExpressionDispatcher = (type, dispatcher) => {
591
- expressionDispatchers.set(type, dispatcher);
641
+ expressionRegistry = expressionRegistry.register(type, dispatcher);
592
642
  };
593
643
  var registerOperandDispatcher = (type, dispatcher) => {
594
- operandDispatchers.set(type, dispatcher);
644
+ operandRegistry = operandRegistry.register(type, dispatcher);
595
645
  };
596
- var clearExpressionDispatchers = () => expressionDispatchers.clear();
597
- var clearOperandDispatchers = () => operandDispatchers.clear();
646
+ var clearExpressionDispatchers = () => {
647
+ expressionRegistry = expressionRegistry.clear();
648
+ };
649
+ var clearOperandDispatchers = () => {
650
+ operandRegistry = operandRegistry.clear();
651
+ };
652
+ var getNodeType = (node) => typeof node === "object" && node !== null && typeof node.type === "string" ? node.type : void 0;
598
653
  var unsupportedExpression = (node) => {
599
- throw new Error(`Unsupported expression type "${node?.type ?? "unknown"}"`);
654
+ throw new Error(`Unsupported expression type "${getNodeType(node) ?? "unknown"}"`);
600
655
  };
601
656
  var unsupportedOperand = (node) => {
602
- throw new Error(`Unsupported operand type "${node?.type ?? "unknown"}"`);
657
+ throw new Error(`Unsupported operand type "${getNodeType(node) ?? "unknown"}"`);
603
658
  };
604
659
  var visitExpression = (node, visitor) => {
605
- const dynamic = expressionDispatchers.get(node?.type);
660
+ const dynamic = expressionRegistry.get(node.type);
606
661
  if (dynamic) return dynamic(node, visitor);
607
662
  switch (node.type) {
608
663
  case "BinaryExpression":
@@ -633,7 +688,7 @@ var visitExpression = (node, visitor) => {
633
688
  return unsupportedExpression(node);
634
689
  };
635
690
  var visitOperand = (node, visitor) => {
636
- const dynamic = operandDispatchers.get(node?.type);
691
+ const dynamic = operandRegistry.get(node.type);
637
692
  if (dynamic) return dynamic(node, visitor);
638
693
  switch (node.type) {
639
694
  case "Column":
@@ -668,24 +723,35 @@ var visitOperand = (node, visitor) => {
668
723
  };
669
724
 
670
725
  // src/core/ast/adapters.ts
726
+ var hasAlias = (obj) => typeof obj === "object" && obj !== null && "alias" in obj;
671
727
  var toColumnRef = (col2) => ({
672
728
  name: col2.name,
673
729
  table: col2.table,
674
- alias: col2.alias
730
+ alias: hasAlias(col2) ? col2.alias : void 0
675
731
  });
676
732
  var toTableRef = (table) => ({
677
733
  name: table.name,
678
734
  schema: table.schema,
679
- alias: table.alias
735
+ alias: hasAlias(table) ? table.alias : void 0
680
736
  });
681
737
 
682
738
  // src/core/ast/builders.ts
739
+ var isColumnNode = (col2) => "type" in col2 && col2.type === "Column";
740
+ var resolveTableName = (def, table) => {
741
+ if (!def.table) {
742
+ return table.alias || table.name;
743
+ }
744
+ if (table.alias && def.table === table.name) {
745
+ return table.alias;
746
+ }
747
+ return def.table;
748
+ };
683
749
  var buildColumnNode = (table, column) => {
684
- if (column.type === "Column") {
750
+ if (isColumnNode(column)) {
685
751
  return column;
686
752
  }
687
753
  const def = column;
688
- const baseTable = def.table ? table.alias && def.table === table.name ? table.alias : def.table : table.alias || table.name;
754
+ const baseTable = resolveTableName(def, table);
689
755
  return {
690
756
  type: "Column",
691
757
  table: baseTable,
@@ -699,7 +765,8 @@ var buildColumnNodes = (table, names) => names.map((name) => ({
699
765
  }));
700
766
  var createTableNode = (table) => ({
701
767
  type: "Table",
702
- name: table.name
768
+ name: table.name,
769
+ schema: table.schema
703
770
  });
704
771
  var fnTable = (name, args = [], alias, opts) => ({
705
772
  type: "FunctionTable",
@@ -720,6 +787,9 @@ var derivedTable = (query, alias, columnAliases) => ({
720
787
 
721
788
  // src/core/functions/standard-strategy.ts
722
789
  var StandardFunctionStrategy = class _StandardFunctionStrategy {
790
+ /**
791
+ * Creates a new StandardFunctionStrategy and registers standard functions.
792
+ */
723
793
  constructor() {
724
794
  this.renderers = /* @__PURE__ */ new Map();
725
795
  this.registerStandard();
@@ -758,12 +828,25 @@ var StandardFunctionStrategy = class _StandardFunctionStrategy {
758
828
  this.add("DATE_TRUNC", ({ compiledArgs }) => `DATE_TRUNC(${compiledArgs[0]}, ${compiledArgs[1]})`);
759
829
  this.add("GROUP_CONCAT", (ctx) => this.renderGroupConcat(ctx));
760
830
  }
831
+ /**
832
+ * Registers a renderer for a function name.
833
+ * @param name - The function name.
834
+ * @param renderer - The renderer function.
835
+ */
761
836
  add(name, renderer) {
762
837
  this.renderers.set(name, renderer);
763
838
  }
839
+ /**
840
+ * @inheritDoc
841
+ */
764
842
  getRenderer(name) {
765
843
  return this.renderers.get(name);
766
844
  }
845
+ /**
846
+ * Renders the GROUP_CONCAT function with optional ORDER BY and SEPARATOR.
847
+ * @param ctx - The function render context.
848
+ * @returns The rendered SQL string.
849
+ */
767
850
  renderGroupConcat(ctx) {
768
851
  const arg = ctx.compiledArgs[0];
769
852
  const orderClause = this.buildOrderByExpression(ctx);
@@ -771,6 +854,11 @@ var StandardFunctionStrategy = class _StandardFunctionStrategy {
771
854
  const separatorClause = this.formatGroupConcatSeparator(ctx);
772
855
  return `GROUP_CONCAT(${arg}${orderSegment}${separatorClause})`;
773
856
  }
857
+ /**
858
+ * Builds the ORDER BY clause for functions like GROUP_CONCAT.
859
+ * @param ctx - The function render context.
860
+ * @returns The ORDER BY SQL clause or empty string.
861
+ */
774
862
  buildOrderByExpression(ctx) {
775
863
  const orderBy = ctx.node.orderBy;
776
864
  if (!orderBy || orderBy.length === 0) {
@@ -786,16 +874,27 @@ var StandardFunctionStrategy = class _StandardFunctionStrategy {
786
874
  });
787
875
  return `ORDER BY ${parts.join(", ")}`;
788
876
  }
877
+ /**
878
+ * Formats the SEPARATOR clause for GROUP_CONCAT.
879
+ * @param ctx - The function render context.
880
+ * @returns The SEPARATOR SQL clause or empty string.
881
+ */
789
882
  formatGroupConcatSeparator(ctx) {
790
883
  if (!ctx.node.separator) {
791
884
  return "";
792
885
  }
793
886
  return ` SEPARATOR ${ctx.compileOperand(ctx.node.separator)}`;
794
887
  }
888
+ /**
889
+ * Gets the separator operand for GROUP_CONCAT, defaulting to comma.
890
+ * @param ctx - The function render context.
891
+ * @returns The separator operand.
892
+ */
795
893
  getGroupConcatSeparatorOperand(ctx) {
796
894
  return ctx.node.separator ?? _StandardFunctionStrategy.DEFAULT_GROUP_CONCAT_SEPARATOR;
797
895
  }
798
896
  static {
897
+ /** Default separator for GROUP_CONCAT, a comma. */
799
898
  this.DEFAULT_GROUP_CONCAT_SEPARATOR = {
800
899
  type: "Literal",
801
900
  value: ","
@@ -860,7 +959,8 @@ var Dialect = class _Dialect {
860
959
  if (!where) return "";
861
960
  return ` WHERE ${this.compileExpression(where, ctx)}`;
862
961
  }
863
- compileReturning(returning, ctx) {
962
+ compileReturning(returning, _ctx) {
963
+ void _ctx;
864
964
  if (!returning || returning.length === 0) return "";
865
965
  throw new Error("RETURNING is not supported by this dialect.");
866
966
  }
@@ -908,14 +1008,16 @@ var Dialect = class _Dialect {
908
1008
  * @param index - Parameter index
909
1009
  * @returns Formatted placeholder string
910
1010
  */
911
- formatPlaceholder(index) {
1011
+ formatPlaceholder(_index) {
1012
+ void _index;
912
1013
  return "?";
913
1014
  }
914
1015
  /**
915
1016
  * Whether the current dialect supports a given set operation.
916
1017
  * Override in concrete dialects to restrict support.
917
1018
  */
918
- supportsSetOperation(kind) {
1019
+ supportsSetOperation(_kind) {
1020
+ void _kind;
919
1021
  return true;
920
1022
  }
921
1023
  /**
@@ -1108,15 +1210,22 @@ var Dialect = class _Dialect {
1108
1210
  }
1109
1211
  registerDefaultOperandCompilers() {
1110
1212
  this.registerOperandCompiler("Literal", (literal, ctx) => ctx.addParameter(literal.value));
1111
- this.registerOperandCompiler("AliasRef", (alias, _ctx) => this.quoteIdentifier(alias.name));
1213
+ this.registerOperandCompiler("AliasRef", (alias, _ctx) => {
1214
+ void _ctx;
1215
+ return this.quoteIdentifier(alias.name);
1216
+ });
1112
1217
  this.registerOperandCompiler("Column", (column, _ctx) => {
1218
+ void _ctx;
1113
1219
  return `${this.quoteIdentifier(column.table)}.${this.quoteIdentifier(column.name)}`;
1114
1220
  });
1115
1221
  this.registerOperandCompiler(
1116
1222
  "Function",
1117
1223
  (fnNode, ctx) => this.compileFunctionOperand(fnNode, ctx)
1118
1224
  );
1119
- this.registerOperandCompiler("JsonPath", (path, _ctx) => this.compileJsonPath(path));
1225
+ this.registerOperandCompiler("JsonPath", (path, _ctx) => {
1226
+ void _ctx;
1227
+ return this.compileJsonPath(path);
1228
+ });
1120
1229
  this.registerOperandCompiler("ScalarSubquery", (node, ctx) => {
1121
1230
  const sql = this.compileSelectAst(node.query, ctx).trim().replace(/;$/, "");
1122
1231
  return `(${sql})`;
@@ -1160,7 +1269,8 @@ var Dialect = class _Dialect {
1160
1269
  });
1161
1270
  }
1162
1271
  // Default fallback, should be overridden by dialects if supported
1163
- compileJsonPath(node) {
1272
+ compileJsonPath(_node) {
1273
+ void _node;
1164
1274
  throw new Error("JSON Path not supported by this dialect");
1165
1275
  }
1166
1276
  /**
@@ -1326,6 +1436,7 @@ var NoReturningStrategy = class {
1326
1436
  * @throws Error indicating RETURNING is not supported.
1327
1437
  */
1328
1438
  compileReturning(returning, _ctx) {
1439
+ void _ctx;
1329
1440
  if (!returning || returning.length === 0) return "";
1330
1441
  throw new Error("RETURNING is not supported by this dialect.");
1331
1442
  }
@@ -1727,6 +1838,7 @@ var PostgresDialect = class extends SqlDialectBase {
1727
1838
  return `${col2}->>'${node.path}'`;
1728
1839
  }
1729
1840
  compileReturning(returning, ctx) {
1841
+ void ctx;
1730
1842
  if (!returning || returning.length === 0) return "";
1731
1843
  const columns = this.formatReturningColumns(returning);
1732
1844
  return ` RETURNING ${columns}`;
@@ -1977,9 +2089,11 @@ var SqliteDialect = class extends SqlDialectBase {
1977
2089
  return `json_extract(${col2}, '${node.path}')`;
1978
2090
  }
1979
2091
  compileQualifiedColumn(column, _table) {
2092
+ void _table;
1980
2093
  return this.quoteIdentifier(column.name);
1981
2094
  }
1982
2095
  compileReturning(returning, ctx) {
2096
+ void ctx;
1983
2097
  if (!returning || returning.length === 0) return "";
1984
2098
  const columns = this.formatReturningColumns(returning);
1985
2099
  return ` RETURNING ${columns}`;
@@ -2301,7 +2415,7 @@ var SelectQueryState = class _SelectQueryState {
2301
2415
  this.table = table;
2302
2416
  this.ast = ast ?? {
2303
2417
  type: "SelectQuery",
2304
- from: { type: "Table", name: table.name },
2418
+ from: createTableNode(table),
2305
2419
  columns: [],
2306
2420
  joins: []
2307
2421
  };
@@ -2452,10 +2566,18 @@ var SelectQueryState = class _SelectQueryState {
2452
2566
  var createJoinNode = (kind, tableName, condition, relationName) => ({
2453
2567
  type: "Join",
2454
2568
  kind,
2455
- table: typeof tableName === "string" ? { type: "Table", name: tableName } : tableName,
2569
+ table: typeof tableName === "string" ? parseQualifiedTableRef(tableName) : tableName,
2456
2570
  condition,
2457
2571
  meta: relationName ? { relationName } : void 0
2458
2572
  });
2573
+ var parseQualifiedTableRef = (ref) => {
2574
+ const parts = ref.split(".");
2575
+ if (parts.length === 2) {
2576
+ const [schema, name] = parts;
2577
+ return { type: "Table", schema, name };
2578
+ }
2579
+ return { type: "Table", name: ref };
2580
+ };
2459
2581
 
2460
2582
  // src/query-builder/hydration-manager.ts
2461
2583
  var HydrationManager = class _HydrationManager {
@@ -2542,6 +2664,11 @@ var HydrationManager = class _HydrationManager {
2542
2664
  const hasPagination = ast.limit !== void 0 || ast.offset !== void 0;
2543
2665
  return hasPagination && this.hasMultiplyingRelations(plan);
2544
2666
  }
2667
+ /**
2668
+ * Checks if the hydration plan contains relations that multiply rows
2669
+ * @param plan - Hydration plan to check
2670
+ * @returns True if plan has HasMany or BelongsToMany relations
2671
+ */
2545
2672
  hasMultiplyingRelations(plan) {
2546
2673
  return plan.relations.some(
2547
2674
  (rel) => rel.type === RelationKinds.HasMany || rel.type === RelationKinds.BelongsToMany
@@ -2619,6 +2746,12 @@ var HydrationManager = class _HydrationManager {
2619
2746
  ctes: [...ast.ctes ?? [], baseCte, pageCte]
2620
2747
  };
2621
2748
  }
2749
+ /**
2750
+ * Generates a unique CTE name by appending a suffix if needed
2751
+ * @param existing - Existing CTE nodes
2752
+ * @param baseName - Base name for the CTE
2753
+ * @returns Unique CTE name
2754
+ */
2622
2755
  nextCteName(existing, baseName) {
2623
2756
  const names = new Set((existing ?? []).map((cte) => cte.name));
2624
2757
  let candidate = baseName;
@@ -2629,15 +2762,26 @@ var HydrationManager = class _HydrationManager {
2629
2762
  }
2630
2763
  return candidate;
2631
2764
  }
2765
+ /**
2766
+ * Extracts projection names from column nodes
2767
+ * @param columns - Projection nodes
2768
+ * @returns Array of names or undefined if any column lacks name/alias
2769
+ */
2632
2770
  getProjectionNames(columns) {
2633
2771
  const names = [];
2634
2772
  for (const col2 of columns) {
2635
- const alias = col2.alias ?? col2.name;
2773
+ const node = col2;
2774
+ const alias = node.alias ?? node.name;
2636
2775
  if (!alias) return void 0;
2637
2776
  names.push(alias);
2638
2777
  }
2639
2778
  return names;
2640
2779
  }
2780
+ /**
2781
+ * Builds a map of column keys to their aliases from projection nodes
2782
+ * @param columns - Projection nodes
2783
+ * @returns Map of 'table.name' to alias
2784
+ */
2641
2785
  buildProjectionAliasMap(columns) {
2642
2786
  const map = /* @__PURE__ */ new Map();
2643
2787
  for (const col2 of columns) {
@@ -2648,6 +2792,15 @@ var HydrationManager = class _HydrationManager {
2648
2792
  }
2649
2793
  return map;
2650
2794
  }
2795
+ /**
2796
+ * Maps order by nodes to use base CTE alias
2797
+ * @param orderBy - Original order by nodes
2798
+ * @param plan - Hydration plan
2799
+ * @param projectionAliases - Map of column aliases
2800
+ * @param baseAlias - Base CTE alias
2801
+ * @param availableColumns - Set of available column names
2802
+ * @returns Mapped order by nodes, null if cannot map
2803
+ */
2651
2804
  mapOrderBy(orderBy, plan, projectionAliases, baseAlias, availableColumns) {
2652
2805
  if (!orderBy || orderBy.length === 0) {
2653
2806
  return void 0;
@@ -2660,6 +2813,15 @@ var HydrationManager = class _HydrationManager {
2660
2813
  }
2661
2814
  return mapped;
2662
2815
  }
2816
+ /**
2817
+ * Maps a single ordering term to use base CTE alias
2818
+ * @param term - Ordering term to map
2819
+ * @param plan - Hydration plan
2820
+ * @param projectionAliases - Map of column aliases
2821
+ * @param baseAlias - Base CTE alias
2822
+ * @param availableColumns - Set of available column names
2823
+ * @returns Mapped term or null if cannot map
2824
+ */
2663
2825
  mapOrderingTerm(term, plan, projectionAliases, baseAlias, availableColumns) {
2664
2826
  if (term.type === "Column") {
2665
2827
  const col2 = term;
@@ -2675,6 +2837,13 @@ var HydrationManager = class _HydrationManager {
2675
2837
  }
2676
2838
  return null;
2677
2839
  }
2840
+ /**
2841
+ * Builds column nodes for paging CTE
2842
+ * @param primaryKey - Primary key name
2843
+ * @param orderBy - Order by nodes
2844
+ * @param tableAlias - Table alias for columns
2845
+ * @returns Array of column nodes for paging
2846
+ */
2678
2847
  buildPagingColumns(primaryKey, orderBy, tableAlias) {
2679
2848
  const columns = [{ type: "Column", table: tableAlias, name: primaryKey, alias: primaryKey }];
2680
2849
  if (!orderBy) return columns;
@@ -2849,7 +3018,8 @@ var buildDefaultHydrationPlan = (table) => ({
2849
3018
  // src/query-builder/raw-column-parser.ts
2850
3019
  var parseRawColumn = (col2, tableName, ctes) => {
2851
3020
  if (col2.includes("(")) {
2852
- const [fn4, rest] = col2.split("(");
3021
+ const [_fn, rest] = col2.split("(");
3022
+ void _fn;
2853
3023
  const colName = rest.replace(")", "");
2854
3024
  const [table, name] = colName.includes(".") ? colName.split(".") : [tableName, colName];
2855
3025
  return { type: "Column", table, name, alias: col2 };
@@ -3046,10 +3216,15 @@ var QueryAstService = class {
3046
3216
  combineExpressions(existing, next) {
3047
3217
  return existing ? and(existing, next) : next;
3048
3218
  }
3219
+ /**
3220
+ * Normalizes an ordering term to a standard OrderingTerm
3221
+ * @param term - Column definition or ordering term to normalize
3222
+ * @returns Normalized ordering term
3223
+ */
3049
3224
  normalizeOrderingTerm(term) {
3050
3225
  const from = this.state.ast.from;
3051
3226
  const tableRef2 = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
3052
- const termType = term?.type;
3227
+ const termType = term.type;
3053
3228
  if (termType === "Column") {
3054
3229
  return term;
3055
3230
  }
@@ -3162,7 +3337,11 @@ var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra, ro
3162
3337
  { type: "Column", table: relation.pivotTable.name, name: relation.pivotForeignKeyToRoot },
3163
3338
  { type: "Column", table: rootTable, name: rootKey }
3164
3339
  );
3165
- const pivotJoin = createJoinNode(joinKind, relation.pivotTable.name, pivotCondition);
3340
+ const pivotJoin = createJoinNode(
3341
+ joinKind,
3342
+ { type: "Table", name: relation.pivotTable.name, schema: relation.pivotTable.schema },
3343
+ pivotCondition
3344
+ );
3166
3345
  let targetCondition = eq(
3167
3346
  { type: "Column", table: relation.target.name, name: targetKey },
3168
3347
  { type: "Column", table: relation.pivotTable.name, name: relation.pivotForeignKeyToTarget }
@@ -3172,7 +3351,7 @@ var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra, ro
3172
3351
  }
3173
3352
  const targetJoin = createJoinNode(
3174
3353
  joinKind,
3175
- relation.target.name,
3354
+ { type: "Table", name: relation.target.name, schema: relation.target.schema },
3176
3355
  targetCondition,
3177
3356
  relationName
3178
3357
  );
@@ -3350,7 +3529,12 @@ var RelationService = class {
3350
3529
  return joins.reduce((current, join) => this.astService(current).withJoin(join), state);
3351
3530
  }
3352
3531
  const condition = buildRelationJoinCondition(this.table, relation, extraCondition, rootAlias);
3353
- const joinNode = createJoinNode(joinKind, relation.target.name, condition, relationName);
3532
+ const joinNode = createJoinNode(
3533
+ joinKind,
3534
+ { type: "Table", name: relation.target.name, schema: relation.target.schema },
3535
+ condition,
3536
+ relationName
3537
+ );
3354
3538
  return this.astService(state).withJoin(joinNode);
3355
3539
  }
3356
3540
  /**
@@ -3395,25 +3579,6 @@ var RelationService = class {
3395
3579
  }
3396
3580
  };
3397
3581
 
3398
- // src/query-builder/select-query-builder-deps.ts
3399
- var defaultCreateQueryAstService = (table, state) => new QueryAstService(table, state);
3400
- var defaultCreateHydrationPlanner = (table) => new HydrationPlanner(table);
3401
- var defaultCreateHydration = (table, plannerFactory) => new HydrationManager(table, plannerFactory(table));
3402
- var resolveSelectQueryBuilderDependencies = (overrides = {}) => {
3403
- const createQueryAstService = overrides.createQueryAstService ?? defaultCreateQueryAstService;
3404
- const createHydrationPlanner = overrides.createHydrationPlanner ?? defaultCreateHydrationPlanner;
3405
- const createHydration = overrides.createHydration ?? ((table) => defaultCreateHydration(table, createHydrationPlanner));
3406
- const createRelationService = overrides.createRelationService ?? ((table, state, hydration) => new RelationService(table, state, hydration, createQueryAstService));
3407
- return {
3408
- createState: overrides.createState ?? ((table) => new SelectQueryState(table)),
3409
- createHydration,
3410
- createHydrationPlanner,
3411
- createQueryAstService,
3412
- createRelationService
3413
- };
3414
- };
3415
- var defaultSelectQueryBuilderDependencies = resolveSelectQueryBuilderDependencies();
3416
-
3417
3582
  // src/query-builder/column-selector.ts
3418
3583
  var ColumnSelector = class {
3419
3584
  /**
@@ -3539,6 +3704,29 @@ var RelationManager = class {
3539
3704
  }
3540
3705
  };
3541
3706
 
3707
+ // src/query-builder/select-query-builder-deps.ts
3708
+ var defaultCreateQueryAstService = (table, state) => new QueryAstService(table, state);
3709
+ var defaultCreateHydrationPlanner = (table) => new HydrationPlanner(table);
3710
+ var defaultCreateHydration = (table, plannerFactory) => new HydrationManager(table, plannerFactory(table));
3711
+ var resolveSelectQueryBuilderDependencies = (overrides = {}) => {
3712
+ const createQueryAstService = overrides.createQueryAstService ?? defaultCreateQueryAstService;
3713
+ const createHydrationPlanner = overrides.createHydrationPlanner ?? defaultCreateHydrationPlanner;
3714
+ const createHydration = overrides.createHydration ?? ((table) => defaultCreateHydration(table, createHydrationPlanner));
3715
+ const createRelationService = overrides.createRelationService ?? ((table, state, hydration) => new RelationService(table, state, hydration, createQueryAstService));
3716
+ const createColumnSelector = overrides.createColumnSelector ?? ((env) => new ColumnSelector(env));
3717
+ const createRelationManager = overrides.createRelationManager ?? ((env) => new RelationManager(env));
3718
+ return {
3719
+ createState: overrides.createState ?? ((table) => new SelectQueryState(table)),
3720
+ createHydration,
3721
+ createHydrationPlanner,
3722
+ createQueryAstService,
3723
+ createRelationService,
3724
+ createColumnSelector,
3725
+ createRelationManager
3726
+ };
3727
+ };
3728
+ var defaultSelectQueryBuilderDependencies = resolveSelectQueryBuilderDependencies();
3729
+
3542
3730
  // src/orm/hydration.ts
3543
3731
  var hydrateRows = (rows, plan) => {
3544
3732
  if (!plan || !rows.length) return rows;
@@ -3664,6 +3852,18 @@ var hideInternal = (obj, keys) => {
3664
3852
  }
3665
3853
  };
3666
3854
  var DefaultHasManyCollection = class {
3855
+ /**
3856
+ * Creates a new DefaultHasManyCollection instance.
3857
+ * @param ctx - The entity context
3858
+ * @param meta - The entity metadata
3859
+ * @param root - The root entity
3860
+ * @param relationName - The relation name
3861
+ * @param relation - The relation definition
3862
+ * @param rootTable - The root table definition
3863
+ * @param loader - The loader function for lazy loading
3864
+ * @param createEntity - Function to create entities from rows
3865
+ * @param localKey - The local key for the relation
3866
+ */
3667
3867
  constructor(ctx, meta, root, relationName, relation, rootTable, loader, createEntity, localKey) {
3668
3868
  this.ctx = ctx;
3669
3869
  this.meta = meta;
@@ -3681,6 +3881,10 @@ var DefaultHasManyCollection = class {
3681
3881
  hideInternal(this, ["ctx", "meta", "root", "relationName", "relation", "rootTable", "loader", "createEntity", "localKey"]);
3682
3882
  this.hydrateFromCache();
3683
3883
  }
3884
+ /**
3885
+ * Loads the related entities if not already loaded.
3886
+ * @returns Promise resolving to the array of child entities
3887
+ */
3684
3888
  async load() {
3685
3889
  if (this.loaded) return this.items;
3686
3890
  const map = await this.loader();
@@ -3690,9 +3894,18 @@ var DefaultHasManyCollection = class {
3690
3894
  this.loaded = true;
3691
3895
  return this.items;
3692
3896
  }
3897
+ /**
3898
+ * Gets the current items in the collection.
3899
+ * @returns Array of child entities
3900
+ */
3693
3901
  getItems() {
3694
3902
  return this.items;
3695
3903
  }
3904
+ /**
3905
+ * Adds a new child entity to the collection.
3906
+ * @param data - Partial data for the new entity
3907
+ * @returns The created entity
3908
+ */
3696
3909
  add(data) {
3697
3910
  const keyValue = this.root[this.localKey];
3698
3911
  const childRow = {
@@ -3712,6 +3925,10 @@ var DefaultHasManyCollection = class {
3712
3925
  );
3713
3926
  return entity;
3714
3927
  }
3928
+ /**
3929
+ * Attaches an existing entity to the collection.
3930
+ * @param entity - The entity to attach
3931
+ */
3715
3932
  attach(entity) {
3716
3933
  const keyValue = this.root[this.localKey];
3717
3934
  entity[this.relation.foreignKey] = keyValue;
@@ -3726,6 +3943,10 @@ var DefaultHasManyCollection = class {
3726
3943
  { kind: "attach", entity }
3727
3944
  );
3728
3945
  }
3946
+ /**
3947
+ * Removes an entity from the collection.
3948
+ * @param entity - The entity to remove
3949
+ */
3729
3950
  remove(entity) {
3730
3951
  this.items = this.items.filter((item) => item !== entity);
3731
3952
  this.removed.add(entity);
@@ -3738,6 +3959,9 @@ var DefaultHasManyCollection = class {
3738
3959
  { kind: "remove", entity }
3739
3960
  );
3740
3961
  }
3962
+ /**
3963
+ * Clears all entities from the collection.
3964
+ */
3741
3965
  clear() {
3742
3966
  for (const entity of [...this.items]) {
3743
3967
  this.remove(entity);
@@ -3754,6 +3978,10 @@ var DefaultHasManyCollection = class {
3754
3978
  this.items = rows.map((row) => this.createEntity(row));
3755
3979
  this.loaded = true;
3756
3980
  }
3981
+ /**
3982
+ * Returns the items for JSON serialization.
3983
+ * @returns Array of child entities
3984
+ */
3757
3985
  toJSON() {
3758
3986
  return this.items;
3759
3987
  }
@@ -4049,7 +4277,6 @@ var DefaultManyToManyCollection = class {
4049
4277
  }
4050
4278
  async syncByIds(ids) {
4051
4279
  await this.load();
4052
- const targetKey = this.relation.targetKey || findPrimaryKey(this.relation.target);
4053
4280
  const normalized = new Set(ids.map((id) => toKey5(id)));
4054
4281
  const currentIds = new Set(this.items.map((item) => toKey5(this.extractId(item))));
4055
4282
  for (const id of normalized) {
@@ -4130,112 +4357,92 @@ var executeQuery = async (ctx, qb) => {
4130
4357
  return rowsFromResults(results);
4131
4358
  };
4132
4359
  var toKey6 = (value) => value === null || value === void 0 ? "" : String(value);
4133
- var loadHasManyRelation = async (ctx, rootTable, _relationName, relation) => {
4134
- const localKey = relation.localKey || findPrimaryKey(rootTable);
4135
- const roots = ctx.getEntitiesForTable(rootTable);
4136
- const keys = /* @__PURE__ */ new Set();
4360
+ var collectKeysFromRoots = (roots, key) => {
4361
+ const collected = /* @__PURE__ */ new Set();
4137
4362
  for (const tracked of roots) {
4138
- const value = tracked.entity[localKey];
4363
+ const value = tracked.entity[key];
4139
4364
  if (value !== null && value !== void 0) {
4140
- keys.add(value);
4365
+ collected.add(value);
4141
4366
  }
4142
4367
  }
4143
- if (!keys.size) {
4144
- return /* @__PURE__ */ new Map();
4145
- }
4146
- const selectMap = selectAllColumns(relation.target);
4147
- const fb = new SelectQueryBuilder(relation.target).select(selectMap);
4148
- const fkColumn = relation.target.columns[relation.foreignKey];
4149
- if (!fkColumn) return /* @__PURE__ */ new Map();
4150
- fb.where(inList(fkColumn, Array.from(keys)));
4151
- const rows = await executeQuery(ctx, fb);
4368
+ return collected;
4369
+ };
4370
+ var buildInListValues = (keys) => Array.from(keys);
4371
+ var fetchRowsForKeys = async (ctx, table, column, keys) => {
4372
+ const qb = new SelectQueryBuilder(table).select(selectAllColumns(table));
4373
+ qb.where(inList(column, buildInListValues(keys)));
4374
+ return executeQuery(ctx, qb);
4375
+ };
4376
+ var groupRowsByMany = (rows, keyColumn) => {
4152
4377
  const grouped = /* @__PURE__ */ new Map();
4153
4378
  for (const row of rows) {
4154
- const fkValue = row[relation.foreignKey];
4155
- if (fkValue === null || fkValue === void 0) continue;
4156
- const key = toKey6(fkValue);
4379
+ const value = row[keyColumn];
4380
+ if (value === null || value === void 0) continue;
4381
+ const key = toKey6(value);
4157
4382
  const bucket = grouped.get(key) ?? [];
4158
4383
  bucket.push(row);
4159
4384
  grouped.set(key, bucket);
4160
4385
  }
4161
4386
  return grouped;
4162
4387
  };
4163
- var loadHasOneRelation = async (ctx, rootTable, _relationName, relation) => {
4164
- const localKey = relation.localKey || findPrimaryKey(rootTable);
4165
- const roots = ctx.getEntitiesForTable(rootTable);
4166
- const keys = /* @__PURE__ */ new Set();
4167
- for (const tracked of roots) {
4168
- const value = tracked.entity[localKey];
4169
- if (value !== null && value !== void 0) {
4170
- keys.add(value);
4388
+ var groupRowsByUnique = (rows, keyColumn) => {
4389
+ const lookup = /* @__PURE__ */ new Map();
4390
+ for (const row of rows) {
4391
+ const value = row[keyColumn];
4392
+ if (value === null || value === void 0) continue;
4393
+ const key = toKey6(value);
4394
+ if (!lookup.has(key)) {
4395
+ lookup.set(key, row);
4171
4396
  }
4172
4397
  }
4398
+ return lookup;
4399
+ };
4400
+ var loadHasManyRelation = async (ctx, rootTable, _relationName, relation) => {
4401
+ const localKey = relation.localKey || findPrimaryKey(rootTable);
4402
+ const roots = ctx.getEntitiesForTable(rootTable);
4403
+ const keys = collectKeysFromRoots(roots, localKey);
4173
4404
  if (!keys.size) {
4174
4405
  return /* @__PURE__ */ new Map();
4175
4406
  }
4176
- const selectMap = selectAllColumns(relation.target);
4177
- const qb = new SelectQueryBuilder(relation.target).select(selectMap);
4178
4407
  const fkColumn = relation.target.columns[relation.foreignKey];
4179
4408
  if (!fkColumn) return /* @__PURE__ */ new Map();
4180
- qb.where(inList(fkColumn, Array.from(keys)));
4181
- const rows = await executeQuery(ctx, qb);
4182
- const lookup = /* @__PURE__ */ new Map();
4183
- for (const row of rows) {
4184
- const fkValue = row[relation.foreignKey];
4185
- if (fkValue === null || fkValue === void 0) continue;
4186
- const key = toKey6(fkValue);
4187
- if (!lookup.has(key)) {
4188
- lookup.set(key, row);
4189
- }
4409
+ const rows = await fetchRowsForKeys(ctx, relation.target, fkColumn, keys);
4410
+ return groupRowsByMany(rows, relation.foreignKey);
4411
+ };
4412
+ var loadHasOneRelation = async (ctx, rootTable, _relationName, relation) => {
4413
+ const localKey = relation.localKey || findPrimaryKey(rootTable);
4414
+ const roots = ctx.getEntitiesForTable(rootTable);
4415
+ const keys = collectKeysFromRoots(roots, localKey);
4416
+ if (!keys.size) {
4417
+ return /* @__PURE__ */ new Map();
4190
4418
  }
4191
- return lookup;
4419
+ const fkColumn = relation.target.columns[relation.foreignKey];
4420
+ if (!fkColumn) return /* @__PURE__ */ new Map();
4421
+ const rows = await fetchRowsForKeys(ctx, relation.target, fkColumn, keys);
4422
+ return groupRowsByUnique(rows, relation.foreignKey);
4192
4423
  };
4193
4424
  var loadBelongsToRelation = async (ctx, rootTable, _relationName, relation) => {
4194
4425
  const roots = ctx.getEntitiesForTable(rootTable);
4195
- const foreignKeys = /* @__PURE__ */ new Set();
4196
- for (const tracked of roots) {
4197
- const value = tracked.entity[relation.foreignKey];
4198
- if (value !== null && value !== void 0) {
4199
- foreignKeys.add(value);
4200
- }
4201
- }
4426
+ const foreignKeys = collectKeysFromRoots(roots, relation.foreignKey);
4202
4427
  if (!foreignKeys.size) {
4203
4428
  return /* @__PURE__ */ new Map();
4204
4429
  }
4205
- const selectMap = selectAllColumns(relation.target);
4206
- const qb = new SelectQueryBuilder(relation.target).select(selectMap);
4207
4430
  const targetKey = relation.localKey || findPrimaryKey(relation.target);
4208
4431
  const pkColumn = relation.target.columns[targetKey];
4209
4432
  if (!pkColumn) return /* @__PURE__ */ new Map();
4210
- qb.where(inList(pkColumn, Array.from(foreignKeys)));
4211
- const rows = await executeQuery(ctx, qb);
4212
- const map = /* @__PURE__ */ new Map();
4213
- for (const row of rows) {
4214
- const keyValue = row[targetKey];
4215
- if (keyValue === null || keyValue === void 0) continue;
4216
- map.set(toKey6(keyValue), row);
4217
- }
4218
- return map;
4433
+ const rows = await fetchRowsForKeys(ctx, relation.target, pkColumn, foreignKeys);
4434
+ return groupRowsByUnique(rows, targetKey);
4219
4435
  };
4220
4436
  var loadBelongsToManyRelation = async (ctx, rootTable, _relationName, relation) => {
4221
4437
  const rootKey = relation.localKey || findPrimaryKey(rootTable);
4222
4438
  const roots = ctx.getEntitiesForTable(rootTable);
4223
- const rootIds = /* @__PURE__ */ new Set();
4224
- for (const tracked of roots) {
4225
- const value = tracked.entity[rootKey];
4226
- if (value !== null && value !== void 0) {
4227
- rootIds.add(value);
4228
- }
4229
- }
4439
+ const rootIds = collectKeysFromRoots(roots, rootKey);
4230
4440
  if (!rootIds.size) {
4231
4441
  return /* @__PURE__ */ new Map();
4232
4442
  }
4233
- const pivotSelect = selectAllColumns(relation.pivotTable);
4234
- const pivotQb = new SelectQueryBuilder(relation.pivotTable).select(pivotSelect);
4235
- const pivotFkCol = relation.pivotTable.columns[relation.pivotForeignKeyToRoot];
4236
- if (!pivotFkCol) return /* @__PURE__ */ new Map();
4237
- pivotQb.where(inList(pivotFkCol, Array.from(rootIds)));
4238
- const pivotRows = await executeQuery(ctx, pivotQb);
4443
+ const pivotColumn = relation.pivotTable.columns[relation.pivotForeignKeyToRoot];
4444
+ if (!pivotColumn) return /* @__PURE__ */ new Map();
4445
+ const pivotRows = await fetchRowsForKeys(ctx, relation.pivotTable, pivotColumn, rootIds);
4239
4446
  const rootLookup = /* @__PURE__ */ new Map();
4240
4447
  const targetIds = /* @__PURE__ */ new Set();
4241
4448
  for (const pivot of pivotRows) {
@@ -4255,19 +4462,11 @@ var loadBelongsToManyRelation = async (ctx, rootTable, _relationName, relation)
4255
4462
  if (!targetIds.size) {
4256
4463
  return /* @__PURE__ */ new Map();
4257
4464
  }
4258
- const targetSelect = selectAllColumns(relation.target);
4259
4465
  const targetKey = relation.targetKey || findPrimaryKey(relation.target);
4260
4466
  const targetPkColumn = relation.target.columns[targetKey];
4261
4467
  if (!targetPkColumn) return /* @__PURE__ */ new Map();
4262
- const targetQb = new SelectQueryBuilder(relation.target).select(targetSelect);
4263
- targetQb.where(inList(targetPkColumn, Array.from(targetIds)));
4264
- const targetRows = await executeQuery(ctx, targetQb);
4265
- const targetMap = /* @__PURE__ */ new Map();
4266
- for (const row of targetRows) {
4267
- const pkValue = row[targetKey];
4268
- if (pkValue === null || pkValue === void 0) continue;
4269
- targetMap.set(toKey6(pkValue), row);
4270
- }
4468
+ const targetRows = await fetchRowsForKeys(ctx, relation.target, targetPkColumn, targetIds);
4469
+ const targetMap = groupRowsByUnique(targetRows, targetKey);
4271
4470
  const result = /* @__PURE__ */ new Map();
4272
4471
  for (const [rootId, entries] of rootLookup.entries()) {
4273
4472
  const bucket = [];
@@ -4320,7 +4519,6 @@ var createEntityProxy = (ctx, table, row, lazyRelations = []) => {
4320
4519
  enumerable: false,
4321
4520
  writable: false
4322
4521
  });
4323
- let proxy;
4324
4522
  const handler = {
4325
4523
  get(targetObj, prop, receiver) {
4326
4524
  if (prop === ENTITY_META) {
@@ -4328,7 +4526,7 @@ var createEntityProxy = (ctx, table, row, lazyRelations = []) => {
4328
4526
  }
4329
4527
  if (prop === "$load") {
4330
4528
  return async (relationName) => {
4331
- const wrapper = getRelationWrapper(meta, relationName, proxy);
4529
+ const wrapper = getRelationWrapper(meta, relationName, receiver);
4332
4530
  if (wrapper && typeof wrapper.load === "function") {
4333
4531
  return wrapper.load();
4334
4532
  }
@@ -4336,19 +4534,19 @@ var createEntityProxy = (ctx, table, row, lazyRelations = []) => {
4336
4534
  };
4337
4535
  }
4338
4536
  if (typeof prop === "string" && table.relations[prop]) {
4339
- return getRelationWrapper(meta, prop, proxy);
4537
+ return getRelationWrapper(meta, prop, receiver);
4340
4538
  }
4341
4539
  return Reflect.get(targetObj, prop, receiver);
4342
4540
  },
4343
4541
  set(targetObj, prop, value, receiver) {
4344
4542
  const result = Reflect.set(targetObj, prop, value, receiver);
4345
4543
  if (typeof prop === "string" && table.columns[prop]) {
4346
- ctx.markDirty(proxy);
4544
+ ctx.markDirty(receiver);
4347
4545
  }
4348
4546
  return result;
4349
4547
  }
4350
4548
  };
4351
- proxy = new Proxy(target, handler);
4549
+ const proxy = new Proxy(target, handler);
4352
4550
  populateHydrationCache(proxy, row, meta);
4353
4551
  return proxy;
4354
4552
  };
@@ -4545,21 +4743,21 @@ async function executeHydratedWithContexts(_execCtx, hydCtx, qb) {
4545
4743
  return executeWithEntityContext(entityCtx, qb);
4546
4744
  }
4547
4745
 
4746
+ // src/query-builder/query-resolution.ts
4747
+ function resolveSelectQuery(query) {
4748
+ const candidate = query;
4749
+ return typeof candidate.getAST === "function" && candidate.getAST ? candidate.getAST() : query;
4750
+ }
4751
+
4548
4752
  // src/query-builder/select.ts
4549
4753
  var SelectQueryBuilder = class _SelectQueryBuilder {
4550
4754
  /**
4551
-
4552
- * Creates a new SelectQueryBuilder instance
4553
-
4554
- * @param table - Table definition to query
4555
-
4556
- * @param state - Optional initial query state
4557
-
4558
- * @param hydration - Optional hydration manager
4559
-
4560
- * @param dependencies - Optional query builder dependencies
4561
-
4562
- */
4755
+ * Creates a new SelectQueryBuilder instance
4756
+ * @param table - Table definition to query
4757
+ * @param state - Optional initial query state
4758
+ * @param hydration - Optional hydration manager
4759
+ * @param dependencies - Optional query builder dependencies
4760
+ */
4563
4761
  constructor(table, state, hydration, dependencies, lazyRelations) {
4564
4762
  const deps = resolveSelectQueryBuilderDependencies(dependencies);
4565
4763
  this.env = { table, deps };
@@ -4570,9 +4768,15 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4570
4768
  hydration: initialHydration
4571
4769
  };
4572
4770
  this.lazyRelations = new Set(lazyRelations ?? []);
4573
- this.columnSelector = new ColumnSelector(this.env);
4574
- this.relationManager = new RelationManager(this.env);
4771
+ this.columnSelector = deps.createColumnSelector(this.env);
4772
+ this.relationManager = deps.createRelationManager(this.env);
4575
4773
  }
4774
+ /**
4775
+ * Creates a new SelectQueryBuilder instance with updated context and lazy relations
4776
+ * @param context - Updated query context
4777
+ * @param lazyRelations - Updated lazy relations set
4778
+ * @returns New SelectQueryBuilder instance
4779
+ */
4576
4780
  clone(context = this.context, lazyRelations = new Set(this.lazyRelations)) {
4577
4781
  return new _SelectQueryBuilder(this.env.table, context.state, context.hydration, this.env.deps, lazyRelations);
4578
4782
  }
@@ -4589,9 +4793,12 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4589
4793
  const nextContext = this.applyAst(this.context, (service) => service.withFrom(nextFrom));
4590
4794
  return this.clone(nextContext);
4591
4795
  }
4592
- resolveQueryNode(query) {
4593
- return typeof query.getAST === "function" ? query.getAST() : query;
4594
- }
4796
+ /**
4797
+ * Applies correlation expression to the query AST
4798
+ * @param ast - Query AST to modify
4799
+ * @param correlation - Correlation expression
4800
+ * @returns Modified AST with correlation applied
4801
+ */
4595
4802
  applyCorrelation(ast, correlation) {
4596
4803
  if (!correlation) return ast;
4597
4804
  const combinedWhere = ast.where ? and(correlation, ast.where) : correlation;
@@ -4600,39 +4807,53 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4600
4807
  where: combinedWhere
4601
4808
  };
4602
4809
  }
4810
+ /**
4811
+ * Creates a new child query builder for a related table
4812
+ * @param table - Table definition for the child builder
4813
+ * @returns New SelectQueryBuilder instance for the child table
4814
+ */
4603
4815
  createChildBuilder(table) {
4604
4816
  return new _SelectQueryBuilder(table, void 0, void 0, this.env.deps);
4605
4817
  }
4818
+ /**
4819
+ * Applies an AST mutation using the query AST service
4820
+ * @param context - Current query context
4821
+ * @param mutator - Function that mutates the AST
4822
+ * @returns Updated query context
4823
+ */
4606
4824
  applyAst(context, mutator) {
4607
4825
  const astService = this.env.deps.createQueryAstService(this.env.table, context.state);
4608
4826
  const nextState = mutator(astService);
4609
4827
  return { state: nextState, hydration: context.hydration };
4610
4828
  }
4829
+ /**
4830
+ * Applies a join to the query context
4831
+ * @param context - Current query context
4832
+ * @param table - Table to join
4833
+ * @param condition - Join condition
4834
+ * @param kind - Join kind
4835
+ * @returns Updated query context with join applied
4836
+ */
4611
4837
  applyJoin(context, table, condition, kind) {
4612
- const joinNode = createJoinNode(kind, table.name, condition);
4838
+ const joinNode = createJoinNode(kind, { type: "Table", name: table.name, schema: table.schema }, condition);
4613
4839
  return this.applyAst(context, (service) => service.withJoin(joinNode));
4614
4840
  }
4841
+ /**
4842
+ * Applies a set operation to the query
4843
+ * @param operator - Set operation kind
4844
+ * @param query - Query to combine with
4845
+ * @returns Updated query context with set operation
4846
+ */
4615
4847
  applySetOperation(operator, query) {
4616
- const subAst = this.resolveQueryNode(query);
4848
+ const subAst = resolveSelectQuery(query);
4617
4849
  return this.applyAst(this.context, (service) => service.withSetOperation(operator, subAst));
4618
4850
  }
4619
- /**
4620
-
4621
- * Selects specific columns for the query
4622
-
4623
- * @param columns - Record of column definitions, function nodes, case expressions, or window functions
4624
-
4625
- * @returns New query builder instance with selected columns
4626
-
4627
- */
4628
- select(columns) {
4629
- return this.clone(this.columnSelector.select(this.context, columns));
4630
- }
4631
- /**
4632
- * Selects columns from the root table by name (typed).
4633
- * @param cols - Column names on the root table
4634
- */
4635
- selectColumns(...cols) {
4851
+ select(...args) {
4852
+ if (args.length === 1 && typeof args[0] === "object" && args[0] !== null && typeof args[0] !== "string") {
4853
+ const columns = args[0];
4854
+ return this.clone(this.columnSelector.select(this.context, columns));
4855
+ }
4856
+ const cols = args;
4636
4857
  const selection = {};
4637
4858
  for (const key of cols) {
4638
4859
  const col2 = this.env.table.columns[key];
@@ -4641,53 +4862,37 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4641
4862
  }
4642
4863
  selection[key] = col2;
4643
4864
  }
4644
- return this.select(selection);
4865
+ return this.clone(this.columnSelector.select(this.context, selection));
4645
4866
  }
4646
4867
  /**
4647
-
4648
- * Selects raw column expressions
4649
-
4650
- * @param cols - Column expressions as strings
4651
-
4652
- * @returns New query builder instance with raw column selections
4653
-
4654
- */
4868
+ * Selects raw column expressions
4869
+ * @param cols - Column expressions as strings
4870
+ * @returns New query builder instance with raw column selections
4871
+ */
4655
4872
  selectRaw(...cols) {
4656
4873
  return this.clone(this.columnSelector.selectRaw(this.context, cols));
4657
4874
  }
4658
4875
  /**
4659
-
4660
- * Adds a Common Table Expression (CTE) to the query
4661
-
4662
- * @param name - Name of the CTE
4663
-
4664
- * @param query - Query builder or query node for the CTE
4665
-
4666
- * @param columns - Optional column names for the CTE
4667
-
4668
- * @returns New query builder instance with the CTE
4669
-
4670
- */
4876
+ * Adds a Common Table Expression (CTE) to the query
4877
+ * @param name - Name of the CTE
4878
+ * @param query - Query builder or query node for the CTE
4879
+ * @param columns - Optional column names for the CTE
4880
+ * @returns New query builder instance with the CTE
4881
+ */
4671
4882
  with(name, query, columns) {
4672
- const subAst = this.resolveQueryNode(query);
4883
+ const subAst = resolveSelectQuery(query);
4673
4884
  const nextContext = this.applyAst(this.context, (service) => service.withCte(name, subAst, columns, false));
4674
4885
  return this.clone(nextContext);
4675
4886
  }
4676
4887
  /**
4677
-
4678
- * Adds a recursive Common Table Expression (CTE) to the query
4679
-
4680
- * @param name - Name of the CTE
4681
-
4682
- * @param query - Query builder or query node for the CTE
4683
-
4684
- * @param columns - Optional column names for the CTE
4685
-
4686
- * @returns New query builder instance with the recursive CTE
4687
-
4688
- */
4888
+ * Adds a recursive Common Table Expression (CTE) to the query
4889
+ * @param name - Name of the CTE
4890
+ * @param query - Query builder or query node for the CTE
4891
+ * @param columns - Optional column names for the CTE
4892
+ * @returns New query builder instance with the recursive CTE
4893
+ */
4689
4894
  withRecursive(name, query, columns) {
4690
- const subAst = this.resolveQueryNode(query);
4895
+ const subAst = resolveSelectQuery(query);
4691
4896
  const nextContext = this.applyAst(this.context, (service) => service.withCte(name, subAst, columns, true));
4692
4897
  return this.clone(nextContext);
4693
4898
  }
@@ -4699,24 +4904,31 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4699
4904
  * @returns New query builder instance with updated FROM
4700
4905
  */
4701
4906
  fromSubquery(subquery, alias, columnAliases) {
4702
- const subAst = this.resolveQueryNode(subquery);
4907
+ const subAst = resolveSelectQuery(subquery);
4703
4908
  const fromNode = derivedTable(subAst, alias, columnAliases);
4704
4909
  const nextContext = this.applyAst(this.context, (service) => service.withFrom(fromNode));
4705
4910
  return this.clone(nextContext);
4706
4911
  }
4707
4912
  /**
4708
-
4709
- * Selects a subquery as a column
4710
-
4711
- * @param alias - Alias for the subquery column
4712
-
4713
- * @param sub - Query builder or query node for the subquery
4714
-
4715
- * @returns New query builder instance with the subquery selection
4716
-
4717
- */
4913
+ * Replaces the FROM clause with a function table expression.
4914
+ * @param name - Function name
4915
+ * @param args - Optional function arguments
4916
+ * @param alias - Optional alias for the function table
4917
+ * @param options - Optional function-table metadata (lateral, ordinality, column aliases, schema)
4918
+ */
4919
+ fromFunctionTable(name, args = [], alias, options) {
4920
+ const functionTable = fnTable(name, args, alias, options);
4921
+ const nextContext = this.applyAst(this.context, (service) => service.withFrom(functionTable));
4922
+ return this.clone(nextContext);
4923
+ }
4924
+ /**
4925
+ * Selects a subquery as a column
4926
+ * @param alias - Alias for the subquery column
4927
+ * @param sub - Query builder or query node for the subquery
4928
+ * @returns New query builder instance with the subquery selection
4929
+ */
4718
4930
  selectSubquery(alias, sub2) {
4719
- const query = this.resolveQueryNode(sub2);
4931
+ const query = resolveSelectQuery(sub2);
4720
4932
  return this.clone(this.columnSelector.selectSubquery(this.context, alias, query));
4721
4933
  }
4722
4934
  /**
@@ -4729,103 +4941,92 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4729
4941
  * @returns New query builder instance with the derived-table join
4730
4942
  */
4731
4943
  joinSubquery(subquery, alias, condition, joinKind = JOIN_KINDS.INNER, columnAliases) {
4732
- const subAst = this.resolveQueryNode(subquery);
4944
+ const subAst = resolveSelectQuery(subquery);
4733
4945
  const joinNode = createJoinNode(joinKind, derivedTable(subAst, alias, columnAliases), condition);
4734
4946
  const nextContext = this.applyAst(this.context, (service) => service.withJoin(joinNode));
4735
4947
  return this.clone(nextContext);
4736
4948
  }
4737
4949
  /**
4738
-
4739
- * Adds an INNER JOIN to the query
4740
-
4741
- * @param table - Table to join
4742
-
4743
- * @param condition - Join condition expression
4744
-
4745
- * @returns New query builder instance with the INNER JOIN
4746
-
4747
- */
4950
+ * Adds a join against a function table (e.g., `generate_series`) using `fnTable` internally.
4951
+ * @param name - Function name
4952
+ * @param args - Optional arguments passed to the function
4953
+ * @param alias - Alias for the function table so columns can be referenced
4954
+ * @param condition - Join condition expression
4955
+ * @param joinKind - Kind of join (defaults to INNER)
4956
+ * @param options - Optional metadata (lateral, ordinality, column aliases, schema)
4957
+ */
4958
+ joinFunctionTable(name, args = [], alias, condition, joinKind = JOIN_KINDS.INNER, options) {
4959
+ const functionTable = fnTable(name, args, alias, options);
4960
+ const joinNode = createJoinNode(joinKind, functionTable, condition);
4961
+ const nextContext = this.applyAst(this.context, (service) => service.withJoin(joinNode));
4962
+ return this.clone(nextContext);
4963
+ }
4964
+ /**
4965
+ * Adds an INNER JOIN to the query
4966
+ * @param table - Table to join
4967
+ * @param condition - Join condition expression
4968
+ * @returns New query builder instance with the INNER JOIN
4969
+ */
4748
4970
  innerJoin(table, condition) {
4749
4971
  const nextContext = this.applyJoin(this.context, table, condition, JOIN_KINDS.INNER);
4750
4972
  return this.clone(nextContext);
4751
4973
  }
4752
4974
  /**
4753
-
4754
- * Adds a LEFT JOIN to the query
4755
-
4756
- * @param table - Table to join
4757
-
4758
- * @param condition - Join condition expression
4759
-
4760
- * @returns New query builder instance with the LEFT JOIN
4761
-
4762
- */
4975
+ * Adds a LEFT JOIN to the query
4976
+ * @param table - Table to join
4977
+ * @param condition - Join condition expression
4978
+ * @returns New query builder instance with the LEFT JOIN
4979
+ */
4763
4980
  leftJoin(table, condition) {
4764
4981
  const nextContext = this.applyJoin(this.context, table, condition, JOIN_KINDS.LEFT);
4765
4982
  return this.clone(nextContext);
4766
4983
  }
4767
4984
  /**
4768
-
4769
- * Adds a RIGHT JOIN to the query
4770
-
4771
- * @param table - Table to join
4772
-
4773
- * @param condition - Join condition expression
4774
-
4775
- * @returns New query builder instance with the RIGHT JOIN
4776
-
4777
- */
4985
+ * Adds a RIGHT JOIN to the query
4986
+ * @param table - Table to join
4987
+ * @param condition - Join condition expression
4988
+ * @returns New query builder instance with the RIGHT JOIN
4989
+ */
4778
4990
  rightJoin(table, condition) {
4779
4991
  const nextContext = this.applyJoin(this.context, table, condition, JOIN_KINDS.RIGHT);
4780
4992
  return this.clone(nextContext);
4781
4993
  }
4782
4994
  /**
4783
-
4784
- * Matches records based on a relationship
4785
-
4786
- * @param relationName - Name of the relationship to match
4787
-
4788
- * @param predicate - Optional predicate expression
4789
-
4790
- * @returns New query builder instance with the relationship match
4791
-
4792
- */
4995
+ * Matches records based on a relationship
4996
+ * @param relationName - Name of the relationship to match
4997
+ * @param predicate - Optional predicate expression
4998
+ * @returns New query builder instance with the relationship match
4999
+ */
4793
5000
  match(relationName, predicate) {
4794
5001
  const nextContext = this.relationManager.match(this.context, relationName, predicate);
4795
5002
  return this.clone(nextContext);
4796
5003
  }
4797
5004
  /**
4798
-
4799
- * Joins a related table
4800
-
4801
- * @param relationName - Name of the relationship to join
4802
-
4803
- * @param joinKind - Type of join (defaults to INNER)
4804
-
4805
- * @param extraCondition - Optional additional join condition
4806
-
4807
- * @returns New query builder instance with the relationship join
4808
-
4809
- */
5005
+ * Joins a related table
5006
+ * @param relationName - Name of the relationship to join
5007
+ * @param joinKind - Type of join (defaults to INNER)
5008
+ * @param extraCondition - Optional additional join condition
5009
+ * @returns New query builder instance with the relationship join
5010
+ */
4810
5011
  joinRelation(relationName, joinKind = JOIN_KINDS.INNER, extraCondition) {
4811
5012
  const nextContext = this.relationManager.joinRelation(this.context, relationName, joinKind, extraCondition);
4812
5013
  return this.clone(nextContext);
4813
5014
  }
4814
5015
  /**
4815
-
4816
- * Includes related data in the query results
4817
-
4818
- * @param relationName - Name of the relationship to include
4819
-
4820
- * @param options - Optional include options
4821
-
4822
- * @returns New query builder instance with the relationship inclusion
4823
-
4824
- */
5016
+ * Includes related data in the query results
5017
+ * @param relationName - Name of the relationship to include
5018
+ * @param options - Optional include options
5019
+ * @returns New query builder instance with the relationship inclusion
5020
+ */
4825
5021
  include(relationName, options) {
4826
5022
  const nextContext = this.relationManager.include(this.context, relationName, options);
4827
5023
  return this.clone(nextContext);
4828
5024
  }
5025
+ /**
5026
+ * Includes a relation lazily in the query results
5027
+ * @param relationName - Name of the relation to include lazily
5028
+ * @returns New query builder instance with lazy relation inclusion
5029
+ */
4829
5030
  includeLazy(relationName) {
4830
5031
  const nextLazy = new Set(this.lazyRelations);
4831
5032
  nextLazy.add(relationName);
@@ -4856,43 +5057,57 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4856
5057
  return this.selectRelationColumns(relationName, ...cols);
4857
5058
  }
4858
5059
  /**
4859
- * Selects columns for the root table and relations from a single config object.
5060
+ * Selects columns for the root table and relations from an array of entries
5061
+ * @param config - Configuration array for deep column selection
5062
+ * @returns New query builder instance with deep column selections
4860
5063
  */
4861
5064
  selectColumnsDeep(config) {
4862
- let qb = this;
4863
- if (config.root?.length) {
4864
- qb = qb.selectColumns(...config.root);
4865
- }
4866
- for (const key of Object.keys(config)) {
4867
- if (key === "root") continue;
4868
- const relName = key;
4869
- const cols = config[relName];
4870
- if (!cols || !cols.length) continue;
4871
- qb = qb.selectRelationColumns(relName, ...cols);
5065
+ let currBuilder = this;
5066
+ for (const entry of config) {
5067
+ if (entry.type === "root") {
5068
+ currBuilder = currBuilder.select(...entry.columns);
5069
+ } else {
5070
+ currBuilder = currBuilder.selectRelationColumns(entry.relationName, ...entry.columns);
5071
+ }
4872
5072
  }
4873
- return qb;
5073
+ return currBuilder;
4874
5074
  }
5075
+ /**
5076
+ * Gets the list of lazy relations
5077
+ * @returns Array of lazy relation names
5078
+ */
4875
5079
  getLazyRelations() {
4876
5080
  return Array.from(this.lazyRelations);
4877
5081
  }
5082
+ /**
5083
+ * Gets the table definition for this query builder
5084
+ * @returns Table definition
5085
+ */
4878
5086
  getTable() {
4879
5087
  return this.env.table;
4880
5088
  }
5089
+ /**
5090
+ * Executes the query and returns hydrated results
5091
+ * @param ctx - ORM session context
5092
+ * @returns Promise of entity instances
5093
+ */
4881
5094
  async execute(ctx) {
4882
5095
  return executeHydrated(ctx, this);
4883
5096
  }
5097
+ /**
5098
+ * Executes the query with provided execution and hydration contexts
5099
+ * @param execCtx - Execution context
5100
+ * @param hydCtx - Hydration context
5101
+ * @returns Promise of entity instances
5102
+ */
4884
5103
  async executeWithContexts(execCtx, hydCtx) {
4885
5104
  return executeHydratedWithContexts(execCtx, hydCtx, this);
4886
5105
  }
4887
5106
  /**
4888
-
4889
- * Adds a WHERE condition to the query
4890
-
4891
- * @param expr - Expression for the WHERE clause
4892
-
4893
- * @returns New query builder instance with the WHERE condition
4894
-
4895
- */
5107
+ * Adds a WHERE condition to the query
5108
+ * @param expr - Expression for the WHERE clause
5109
+ * @returns New query builder instance with the WHERE condition
5110
+ */
4896
5111
  where(expr) {
4897
5112
  const nextContext = this.applyAst(this.context, (service) => service.withWhere(expr));
4898
5113
  return this.clone(nextContext);
@@ -4907,14 +5122,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4907
5122
  return this.clone(nextContext);
4908
5123
  }
4909
5124
  /**
4910
-
4911
- * Adds a HAVING condition to the query
4912
-
4913
- * @param expr - Expression for the HAVING clause
4914
-
4915
- * @returns New query builder instance with the HAVING condition
4916
-
4917
- */
5125
+ * Adds a HAVING condition to the query
5126
+ * @param expr - Expression for the HAVING clause
5127
+ * @returns New query builder instance with the HAVING condition
5128
+ */
4918
5129
  having(expr) {
4919
5130
  const nextContext = this.applyAst(this.context, (service) => service.withHaving(expr));
4920
5131
  return this.clone(nextContext);
@@ -4935,130 +5146,89 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4935
5146
  return this.clone(nextContext);
4936
5147
  }
4937
5148
  /**
4938
-
4939
- * Adds a DISTINCT clause to the query
4940
-
4941
- * @param cols - Columns to make distinct
4942
-
4943
- * @returns New query builder instance with the DISTINCT clause
4944
-
4945
- */
5149
+ * Adds a DISTINCT clause to the query
5150
+ * @param cols - Columns to make distinct
5151
+ * @returns New query builder instance with the DISTINCT clause
5152
+ */
4946
5153
  distinct(...cols) {
4947
5154
  return this.clone(this.columnSelector.distinct(this.context, cols));
4948
5155
  }
4949
5156
  /**
4950
-
4951
- * Adds a LIMIT clause to the query
4952
-
4953
- * @param n - Maximum number of rows to return
4954
-
4955
- * @returns New query builder instance with the LIMIT clause
4956
-
4957
- */
5157
+ * Adds a LIMIT clause to the query
5158
+ * @param n - Maximum number of rows to return
5159
+ * @returns New query builder instance with the LIMIT clause
5160
+ */
4958
5161
  limit(n) {
4959
5162
  const nextContext = this.applyAst(this.context, (service) => service.withLimit(n));
4960
5163
  return this.clone(nextContext);
4961
5164
  }
4962
5165
  /**
4963
-
4964
- * Adds an OFFSET clause to the query
4965
-
4966
- * @param n - Number of rows to skip
4967
-
4968
- * @returns New query builder instance with the OFFSET clause
4969
-
4970
- */
5166
+ * Adds an OFFSET clause to the query
5167
+ * @param n - Number of rows to skip
5168
+ * @returns New query builder instance with the OFFSET clause
5169
+ */
4971
5170
  offset(n) {
4972
5171
  const nextContext = this.applyAst(this.context, (service) => service.withOffset(n));
4973
5172
  return this.clone(nextContext);
4974
5173
  }
4975
5174
  /**
4976
-
4977
- * Combines this query with another using UNION
4978
-
4979
- * @param query - Query to union with
4980
-
4981
- * @returns New query builder instance with the set operation
4982
-
4983
- */
5175
+ * Combines this query with another using UNION
5176
+ * @param query - Query to union with
5177
+ * @returns New query builder instance with the set operation
5178
+ */
4984
5179
  union(query) {
4985
5180
  return this.clone(this.applySetOperation("UNION", query));
4986
5181
  }
4987
5182
  /**
4988
-
4989
- * Combines this query with another using UNION ALL
4990
-
4991
- * @param query - Query to union with
4992
-
4993
- * @returns New query builder instance with the set operation
4994
-
4995
- */
5183
+ * Combines this query with another using UNION ALL
5184
+ * @param query - Query to union with
5185
+ * @returns New query builder instance with the set operation
5186
+ */
4996
5187
  unionAll(query) {
4997
5188
  return this.clone(this.applySetOperation("UNION ALL", query));
4998
5189
  }
4999
5190
  /**
5000
-
5001
- * Combines this query with another using INTERSECT
5002
-
5003
- * @param query - Query to intersect with
5004
-
5005
- * @returns New query builder instance with the set operation
5006
-
5007
- */
5191
+ * Combines this query with another using INTERSECT
5192
+ * @param query - Query to intersect with
5193
+ * @returns New query builder instance with the set operation
5194
+ */
5008
5195
  intersect(query) {
5009
5196
  return this.clone(this.applySetOperation("INTERSECT", query));
5010
5197
  }
5011
5198
  /**
5012
-
5013
- * Combines this query with another using EXCEPT
5014
-
5015
- * @param query - Query to subtract
5016
-
5017
- * @returns New query builder instance with the set operation
5018
-
5019
- */
5199
+ * Combines this query with another using EXCEPT
5200
+ * @param query - Query to subtract
5201
+ * @returns New query builder instance with the set operation
5202
+ */
5020
5203
  except(query) {
5021
5204
  return this.clone(this.applySetOperation("EXCEPT", query));
5022
5205
  }
5023
5206
  /**
5024
-
5025
- * Adds a WHERE EXISTS condition to the query
5026
-
5027
- * @param subquery - Subquery to check for existence
5028
-
5029
- * @returns New query builder instance with the WHERE EXISTS condition
5030
-
5031
- */
5207
+ * Adds a WHERE EXISTS condition to the query
5208
+ * @param subquery - Subquery to check for existence
5209
+ * @returns New query builder instance with the WHERE EXISTS condition
5210
+ */
5032
5211
  whereExists(subquery, correlate) {
5033
- const subAst = this.resolveQueryNode(subquery);
5212
+ const subAst = resolveSelectQuery(subquery);
5034
5213
  const correlated = this.applyCorrelation(subAst, correlate);
5035
5214
  return this.where(exists(correlated));
5036
5215
  }
5037
5216
  /**
5038
-
5039
- * Adds a WHERE NOT EXISTS condition to the query
5040
-
5041
- * @param subquery - Subquery to check for non-existence
5042
-
5043
- * @returns New query builder instance with the WHERE NOT EXISTS condition
5044
-
5045
- */
5217
+ * Adds a WHERE NOT EXISTS condition to the query
5218
+ * @param subquery - Subquery to check for non-existence
5219
+ * @returns New query builder instance with the WHERE NOT EXISTS condition
5220
+ */
5046
5221
  whereNotExists(subquery, correlate) {
5047
- const subAst = this.resolveQueryNode(subquery);
5222
+ const subAst = resolveSelectQuery(subquery);
5048
5223
  const correlated = this.applyCorrelation(subAst, correlate);
5049
5224
  return this.where(notExists(correlated));
5050
5225
  }
5051
5226
  /**
5052
-
5053
- * Adds a WHERE EXISTS condition based on a relationship
5054
-
5055
- * @param relationName - Name of the relationship to check
5056
-
5057
- * @param callback - Optional callback to modify the relationship query
5058
-
5059
- * @returns New query builder instance with the relationship existence check
5060
-
5061
- */
5227
+ * Adds a WHERE EXISTS condition based on a relationship
5228
+ * @param relationName - Name of the relationship to check
5229
+ * @param callback - Optional callback to modify the relationship query
5230
+ * @returns New query builder instance with the relationship existence check
5231
+ */
5062
5232
  whereHas(relationName, callbackOrOptions, maybeOptions) {
5063
5233
  const relation = this.env.table.relations[relationName];
5064
5234
  if (!relation) {
@@ -5075,16 +5245,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
5075
5245
  return this.where(exists(finalSubAst));
5076
5246
  }
5077
5247
  /**
5078
-
5079
- * Adds a WHERE NOT EXISTS condition based on a relationship
5080
-
5081
- * @param relationName - Name of the relationship to check
5082
-
5083
- * @param callback - Optional callback to modify the relationship query
5084
-
5085
- * @returns New query builder instance with the relationship non-existence check
5086
-
5087
- */
5248
+ * Adds a WHERE NOT EXISTS condition based on a relationship
5249
+ * @param relationName - Name of the relationship to check
5250
+ * @param callback - Optional callback to modify the relationship query
5251
+ * @returns New query builder instance with the relationship non-existence check
5252
+ */
5088
5253
  whereHasNot(relationName, callbackOrOptions, maybeOptions) {
5089
5254
  const relation = this.env.table.relations[relationName];
5090
5255
  if (!relation) {
@@ -5101,53 +5266,61 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
5101
5266
  return this.where(notExists(finalSubAst));
5102
5267
  }
5103
5268
  /**
5104
-
5105
- * Compiles the query to SQL for a specific dialect
5106
-
5107
- * @param dialect - Database dialect to compile for
5108
-
5109
- * @returns Compiled query with SQL and parameters
5110
-
5111
- */
5269
+ * Compiles the query to SQL for a specific dialect
5270
+ * @param dialect - Database dialect to compile for
5271
+ * @returns Compiled query with SQL and parameters
5272
+ */
5112
5273
  compile(dialect) {
5113
5274
  const resolved = resolveDialectInput(dialect);
5114
- return resolved.compileSelect(this.context.state.ast);
5275
+ return resolved.compileSelect(this.getAST());
5115
5276
  }
5116
5277
  /**
5117
-
5118
- * Converts the query to SQL string for a specific dialect
5119
-
5120
- * @param dialect - Database dialect to generate SQL for
5121
-
5122
- * @returns SQL string representation of the query
5123
-
5124
- */
5278
+ * Converts the query to SQL string for a specific dialect
5279
+ * @param dialect - Database dialect to generate SQL for
5280
+ * @returns SQL string representation of the query
5281
+ */
5125
5282
  toSql(dialect) {
5126
5283
  return this.compile(dialect).sql;
5127
5284
  }
5128
5285
  /**
5129
-
5130
- * Gets the hydration plan for the query
5131
-
5132
- * @returns Hydration plan or undefined if none exists
5133
-
5134
- */
5286
+ * Gets the hydration plan for the query
5287
+ * @returns Hydration plan or undefined if none exists
5288
+ */
5135
5289
  getHydrationPlan() {
5136
5290
  return this.context.hydration.getPlan();
5137
5291
  }
5138
5292
  /**
5139
-
5140
- * Gets the Abstract Syntax Tree (AST) representation of the query
5141
-
5142
- * @returns Query AST with hydration applied
5143
-
5144
- */
5293
+ * Gets the Abstract Syntax Tree (AST) representation of the query
5294
+ * @returns Query AST with hydration applied
5295
+ */
5145
5296
  getAST() {
5146
5297
  return this.context.hydration.applyToAst(this.context.state.ast);
5147
5298
  }
5148
5299
  };
5149
- var createColumn = (table, name) => ({ type: "Column", table, name });
5150
- var createLiteral = (val) => ({ type: "Literal", value: val });
5300
+
5301
+ // src/schema/table-guards.ts
5302
+ var isColumnsRecord = (columns) => {
5303
+ return typeof columns === "object" && columns !== null;
5304
+ };
5305
+ var isRelationsRecord = (relations) => {
5306
+ return typeof relations === "object" && relations !== null;
5307
+ };
5308
+ var isTableDef = (value) => {
5309
+ if (typeof value !== "object" || value === null) {
5310
+ return false;
5311
+ }
5312
+ const candidate = value;
5313
+ if (typeof candidate.name !== "string") {
5314
+ return false;
5315
+ }
5316
+ if (!isColumnsRecord(candidate.columns)) {
5317
+ return false;
5318
+ }
5319
+ if (!isRelationsRecord(candidate.relations)) {
5320
+ return false;
5321
+ }
5322
+ return true;
5323
+ };
5151
5324
 
5152
5325
  // src/orm/entity-metadata.ts
5153
5326
  var metadataMap = /* @__PURE__ */ new Map();
@@ -5191,23 +5364,20 @@ var buildTableDef = (meta) => {
5191
5364
  if (meta.table) {
5192
5365
  return meta.table;
5193
5366
  }
5194
- const columns = Object.entries(meta.columns).reduce((acc, [key, def]) => {
5195
- acc[key] = {
5367
+ const columns = {};
5368
+ for (const [key, def] of Object.entries(meta.columns)) {
5369
+ columns[key] = {
5196
5370
  ...def,
5197
5371
  name: key,
5198
5372
  table: meta.tableName
5199
5373
  };
5200
- return acc;
5201
- }, {});
5374
+ }
5202
5375
  const table = defineTable(meta.tableName, columns, {}, meta.hooks);
5203
5376
  meta.table = table;
5204
5377
  return table;
5205
5378
  };
5206
5379
 
5207
5380
  // src/decorators/bootstrap.ts
5208
- var isTableDef = (value) => {
5209
- return typeof value === "object" && value !== null && "columns" in value;
5210
- };
5211
5381
  var unwrapTarget = (target) => {
5212
5382
  if (typeof target === "function" && target.prototype === void 0) {
5213
5383
  return target();
@@ -5305,6 +5475,13 @@ var selectFromEntity = (ctor) => {
5305
5475
  }
5306
5476
  return new SelectQueryBuilder(table);
5307
5477
  };
5478
+ var entityRef = (ctor) => {
5479
+ const table = getTableDefFromEntity(ctor);
5480
+ if (!table) {
5481
+ throw new Error(`Entity '${ctor.name}' is not registered with decorators or has not been bootstrapped`);
5482
+ }
5483
+ return tableRef(table);
5484
+ };
5308
5485
 
5309
5486
  // src/query-builder/select-helpers.ts
5310
5487
  function sel(table, ...cols) {
@@ -5336,6 +5513,11 @@ function esel(entity, ...props) {
5336
5513
 
5337
5514
  // src/query-builder/insert-query-state.ts
5338
5515
  var InsertQueryState = class _InsertQueryState {
5516
+ /**
5517
+ * Creates a new InsertQueryState instance
5518
+ * @param table - The table definition for the INSERT query
5519
+ * @param ast - Optional initial AST node, defaults to a basic INSERT query
5520
+ */
5339
5521
  constructor(table, ast) {
5340
5522
  this.table = table;
5341
5523
  this.ast = ast ?? {
@@ -5366,6 +5548,13 @@ var InsertQueryState = class _InsertQueryState {
5366
5548
  if (!names.length) return [];
5367
5549
  return buildColumnNodes(this.table, names);
5368
5550
  }
5551
+ /**
5552
+ * Adds VALUES clause to the INSERT query
5553
+ * @param rows - Array of row objects to insert
5554
+ * @returns A new InsertQueryState with the VALUES clause added
5555
+ * @throws Error if mixing VALUES with SELECT source
5556
+ * @throws Error if invalid values are provided
5557
+ */
5369
5558
  withValues(rows) {
5370
5559
  if (!rows.length) return this;
5371
5560
  if (this.ast.source.type === "InsertSelect") {
@@ -5392,6 +5581,11 @@ var InsertQueryState = class _InsertQueryState {
5392
5581
  }
5393
5582
  });
5394
5583
  }
5584
+ /**
5585
+ * Sets the columns for the INSERT query
5586
+ * @param columns - Column nodes to insert into
5587
+ * @returns A new InsertQueryState with the specified columns
5588
+ */
5395
5589
  withColumns(columns) {
5396
5590
  if (!columns.length) return this;
5397
5591
  return this.clone({
@@ -5399,6 +5593,14 @@ var InsertQueryState = class _InsertQueryState {
5399
5593
  columns: [...columns]
5400
5594
  });
5401
5595
  }
5596
+ /**
5597
+ * Adds SELECT source to the INSERT query
5598
+ * @param query - The SELECT query to use as source
5599
+ * @param columns - Target columns for the INSERT
5600
+ * @returns A new InsertQueryState with the SELECT source
5601
+ * @throws Error if mixing SELECT with VALUES source
5602
+ * @throws Error if no destination columns specified
5603
+ */
5402
5604
  withSelect(query, columns) {
5403
5605
  const targetColumns = columns.length ? columns : this.ast.columns.length ? this.ast.columns : this.getTableColumns();
5404
5606
  if (!targetColumns.length) {
@@ -5416,6 +5618,11 @@ var InsertQueryState = class _InsertQueryState {
5416
5618
  }
5417
5619
  });
5418
5620
  }
5621
+ /**
5622
+ * Adds a RETURNING clause to the INSERT query
5623
+ * @param columns - Columns to return after insertion
5624
+ * @returns A new InsertQueryState with the RETURNING clause added
5625
+ */
5419
5626
  withReturning(columns) {
5420
5627
  return this.clone({
5421
5628
  ...this.ast,
@@ -5426,6 +5633,11 @@ var InsertQueryState = class _InsertQueryState {
5426
5633
 
5427
5634
  // src/query-builder/insert.ts
5428
5635
  var InsertQueryBuilder = class _InsertQueryBuilder {
5636
+ /**
5637
+ * Creates a new InsertQueryBuilder instance
5638
+ * @param table - The table definition for the INSERT query
5639
+ * @param state - Optional initial query state, defaults to a new InsertQueryState
5640
+ */
5429
5641
  constructor(table, state) {
5430
5642
  this.table = table;
5431
5643
  this.state = state ?? new InsertQueryState(table);
@@ -5433,20 +5645,42 @@ var InsertQueryBuilder = class _InsertQueryBuilder {
5433
5645
  clone(state) {
5434
5646
  return new _InsertQueryBuilder(this.table, state);
5435
5647
  }
5648
+ /**
5649
+ * Adds VALUES to the INSERT query
5650
+ * @param rowOrRows - Single row object or array of row objects to insert
5651
+ * @returns A new InsertQueryBuilder with the VALUES clause added
5652
+ */
5436
5653
  values(rowOrRows) {
5437
5654
  const rows = Array.isArray(rowOrRows) ? rowOrRows : [rowOrRows];
5438
5655
  if (!rows.length) return this;
5439
5656
  return this.clone(this.state.withValues(rows));
5440
5657
  }
5658
+ /**
5659
+ * Specifies the columns for the INSERT query
5660
+ * @param columns - Column definitions or nodes to insert into
5661
+ * @returns A new InsertQueryBuilder with the specified columns
5662
+ */
5441
5663
  columns(...columns) {
5442
5664
  if (!columns.length) return this;
5443
5665
  return this.clone(this.state.withColumns(this.resolveColumnNodes(columns)));
5444
5666
  }
5667
+ /**
5668
+ * Sets the source of the INSERT query to a SELECT query
5669
+ * @template TSource - The source table type
5670
+ * @param query - The SELECT query or query builder to use as source
5671
+ * @param columns - Optional target columns for the INSERT
5672
+ * @returns A new InsertQueryBuilder with the SELECT source
5673
+ */
5445
5674
  fromSelect(query, columns = []) {
5446
5675
  const ast = this.resolveSelectQuery(query);
5447
5676
  const nodes = columns.length ? this.resolveColumnNodes(columns) : [];
5448
5677
  return this.clone(this.state.withSelect(ast, nodes));
5449
5678
  }
5679
+ /**
5680
+ * Adds a RETURNING clause to the INSERT query
5681
+ * @param columns - Columns to return after insertion
5682
+ * @returns A new InsertQueryBuilder with the RETURNING clause added
5683
+ */
5450
5684
  returning(...columns) {
5451
5685
  if (!columns.length) return this;
5452
5686
  const nodes = columns.map((column) => buildColumnNode(this.table, column));
@@ -5457,18 +5691,29 @@ var InsertQueryBuilder = class _InsertQueryBuilder {
5457
5691
  return columns.map((column) => buildColumnNode(this.table, column));
5458
5692
  }
5459
5693
  resolveSelectQuery(query) {
5460
- return typeof query.getAST === "function" ? query.getAST() : query;
5694
+ const candidate = query;
5695
+ return typeof candidate.getAST === "function" && candidate.getAST ? candidate.getAST() : query;
5461
5696
  }
5462
5697
  compile(arg) {
5463
- if (typeof arg.compileInsert === "function") {
5464
- return arg.compileInsert(this.state.ast);
5698
+ const candidate = arg;
5699
+ if (typeof candidate.compileInsert === "function") {
5700
+ return candidate.compileInsert(this.state.ast);
5465
5701
  }
5466
5702
  const dialect = resolveDialectInput(arg);
5467
5703
  return dialect.compileInsert(this.state.ast);
5468
5704
  }
5705
+ /**
5706
+ * Returns the SQL string for the INSERT query
5707
+ * @param arg - The compiler or dialect to generate SQL for
5708
+ * @returns The SQL string representation of the query
5709
+ */
5469
5710
  toSql(arg) {
5470
5711
  return this.compile(arg).sql;
5471
5712
  }
5713
+ /**
5714
+ * Returns the Abstract Syntax Tree (AST) representation of the query
5715
+ * @returns The AST node for the INSERT query
5716
+ */
5472
5717
  getAST() {
5473
5718
  return this.state.ast;
5474
5719
  }
@@ -5487,6 +5732,11 @@ var isUpdateValue = (value) => {
5487
5732
  }
5488
5733
  };
5489
5734
  var UpdateQueryState = class _UpdateQueryState {
5735
+ /**
5736
+ * Creates a new UpdateQueryState instance
5737
+ * @param table - Table definition for the update
5738
+ * @param ast - Optional existing AST
5739
+ */
5490
5740
  constructor(table, ast) {
5491
5741
  this.table = table;
5492
5742
  this.ast = ast ?? {
@@ -5496,9 +5746,19 @@ var UpdateQueryState = class _UpdateQueryState {
5496
5746
  joins: []
5497
5747
  };
5498
5748
  }
5749
+ /**
5750
+ * Creates a new UpdateQueryState with updated AST
5751
+ * @param nextAst - Updated AST
5752
+ * @returns New UpdateQueryState instance
5753
+ */
5499
5754
  clone(nextAst) {
5500
5755
  return new _UpdateQueryState(this.table, nextAst);
5501
5756
  }
5757
+ /**
5758
+ * Sets the columns to update with their new values
5759
+ * @param values - Record of column names to values
5760
+ * @returns New UpdateQueryState with SET clause
5761
+ */
5502
5762
  withSet(values) {
5503
5763
  const assignments = Object.entries(values).map(([column, rawValue]) => {
5504
5764
  if (!isUpdateValue(rawValue)) {
@@ -5520,30 +5780,55 @@ var UpdateQueryState = class _UpdateQueryState {
5520
5780
  set: assignments
5521
5781
  });
5522
5782
  }
5783
+ /**
5784
+ * Adds a WHERE condition to the update query
5785
+ * @param expr - WHERE expression
5786
+ * @returns New UpdateQueryState with WHERE clause
5787
+ */
5523
5788
  withWhere(expr) {
5524
5789
  return this.clone({
5525
5790
  ...this.ast,
5526
5791
  where: expr
5527
5792
  });
5528
5793
  }
5794
+ /**
5795
+ * Adds a RETURNING clause to the update query
5796
+ * @param columns - Columns to return
5797
+ * @returns New UpdateQueryState with RETURNING clause
5798
+ */
5529
5799
  withReturning(columns) {
5530
5800
  return this.clone({
5531
5801
  ...this.ast,
5532
5802
  returning: [...columns]
5533
5803
  });
5534
5804
  }
5805
+ /**
5806
+ * Sets the FROM clause for the update query
5807
+ * @param from - Table source for FROM
5808
+ * @returns New UpdateQueryState with FROM clause
5809
+ */
5535
5810
  withFrom(from) {
5536
5811
  return this.clone({
5537
5812
  ...this.ast,
5538
5813
  from
5539
5814
  });
5540
5815
  }
5816
+ /**
5817
+ * Adds a JOIN to the update query
5818
+ * @param join - Join node to add
5819
+ * @returns New UpdateQueryState with JOIN
5820
+ */
5541
5821
  withJoin(join) {
5542
5822
  return this.clone({
5543
5823
  ...this.ast,
5544
5824
  joins: [...this.ast.joins ?? [], join]
5545
5825
  });
5546
5826
  }
5827
+ /**
5828
+ * Applies an alias to the table being updated
5829
+ * @param alias - Alias for the table
5830
+ * @returns New UpdateQueryState with table alias
5831
+ */
5547
5832
  withTableAlias(alias) {
5548
5833
  return this.clone({
5549
5834
  ...this.ast,
@@ -5557,6 +5842,11 @@ var UpdateQueryState = class _UpdateQueryState {
5557
5842
 
5558
5843
  // src/query-builder/update.ts
5559
5844
  var UpdateQueryBuilder = class _UpdateQueryBuilder {
5845
+ /**
5846
+ * Creates a new UpdateQueryBuilder instance
5847
+ * @param table - The table definition for the UPDATE query
5848
+ * @param state - Optional initial query state, defaults to a new UpdateQueryState
5849
+ */
5560
5850
  constructor(table, state) {
5561
5851
  this.table = table;
5562
5852
  this.state = state ?? new UpdateQueryState(table);
@@ -5564,24 +5854,57 @@ var UpdateQueryBuilder = class _UpdateQueryBuilder {
5564
5854
  clone(state) {
5565
5855
  return new _UpdateQueryBuilder(this.table, state);
5566
5856
  }
5857
+ /**
5858
+ * Sets an alias for the table in the UPDATE query
5859
+ * @param alias - The alias to assign to the table
5860
+ * @returns A new UpdateQueryBuilder with the table alias set
5861
+ */
5567
5862
  as(alias) {
5568
5863
  return this.clone(this.state.withTableAlias(alias));
5569
5864
  }
5865
+ /**
5866
+ * Adds a FROM clause to the UPDATE query
5867
+ * @param source - The table source to use in the FROM clause
5868
+ * @returns A new UpdateQueryBuilder with the FROM clause added
5869
+ */
5570
5870
  from(source) {
5571
5871
  const tableSource = this.resolveTableSource(source);
5572
5872
  return this.clone(this.state.withFrom(tableSource));
5573
5873
  }
5874
+ /**
5875
+ * Adds a JOIN clause to the UPDATE query
5876
+ * @param table - The table to join with
5877
+ * @param condition - The join condition expression
5878
+ * @param kind - The type of join (defaults to INNER)
5879
+ * @param relationName - Optional name for the relation
5880
+ * @returns A new UpdateQueryBuilder with the JOIN clause added
5881
+ */
5574
5882
  join(table, condition, kind = JOIN_KINDS.INNER, relationName) {
5575
5883
  const joinTarget = this.resolveJoinTarget(table);
5576
5884
  const joinNode = createJoinNode(kind, joinTarget, condition, relationName);
5577
5885
  return this.clone(this.state.withJoin(joinNode));
5578
5886
  }
5887
+ /**
5888
+ * Adds a SET clause to the UPDATE query
5889
+ * @param values - The column-value pairs to update
5890
+ * @returns A new UpdateQueryBuilder with the SET clause added
5891
+ */
5579
5892
  set(values) {
5580
5893
  return this.clone(this.state.withSet(values));
5581
5894
  }
5895
+ /**
5896
+ * Adds a WHERE clause to the UPDATE query
5897
+ * @param expr - The expression to use as the WHERE condition
5898
+ * @returns A new UpdateQueryBuilder with the WHERE clause added
5899
+ */
5582
5900
  where(expr) {
5583
5901
  return this.clone(this.state.withWhere(expr));
5584
5902
  }
5903
+ /**
5904
+ * Adds a RETURNING clause to the UPDATE query
5905
+ * @param columns - Columns to return after update
5906
+ * @returns A new UpdateQueryBuilder with the RETURNING clause added
5907
+ */
5585
5908
  returning(...columns) {
5586
5909
  if (!columns.length) return this;
5587
5910
  const nodes = columns.map((column) => buildColumnNode(this.table, column));
@@ -5597,16 +5920,36 @@ var UpdateQueryBuilder = class _UpdateQueryBuilder {
5597
5920
  if (typeof table === "string") return table;
5598
5921
  return this.resolveTableSource(table);
5599
5922
  }
5600
- compile(arg) {
5601
- if (typeof arg.compileUpdate === "function") {
5602
- return arg.compileUpdate(this.state.ast);
5603
- }
5604
- const dialect = resolveDialectInput(arg);
5605
- return dialect.compileUpdate(this.state.ast);
5923
+ /**
5924
+ * Compiles the UPDATE query for the specified dialect
5925
+ * @param dialect - The SQL dialect to compile for
5926
+ * @returns The compiled query with SQL and parameters
5927
+ */
5928
+ compile(dialect) {
5929
+ const resolved = resolveDialectInput(dialect);
5930
+ return resolved.compileUpdate(this.state.ast);
5606
5931
  }
5607
- toSql(arg) {
5608
- return this.compile(arg).sql;
5932
+ /**
5933
+ * Returns the SQL string for the UPDATE query
5934
+ * @param dialect - The SQL dialect to generate SQL for
5935
+ * @returns The SQL string representation of the query
5936
+ */
5937
+ toSql(dialect) {
5938
+ return this.compile(dialect).sql;
5609
5939
  }
5940
+ /**
5941
+ * Executes the UPDATE query using the provided session
5942
+ * @param session - The ORM session to execute the query with
5943
+ * @returns A promise that resolves to the query results
5944
+ */
5945
+ async execute(session) {
5946
+ const compiled = this.compile(session.dialect);
5947
+ return session.executor.executeSql(compiled.sql, compiled.params);
5948
+ }
5949
+ /**
5950
+ * Returns the Abstract Syntax Tree (AST) representation of the query
5951
+ * @returns The AST node for the UPDATE query
5952
+ */
5610
5953
  getAST() {
5611
5954
  return this.state.ast;
5612
5955
  }
@@ -5615,6 +5958,11 @@ var isTableSourceNode = (source) => typeof source.type === "string";
5615
5958
 
5616
5959
  // src/query-builder/delete-query-state.ts
5617
5960
  var DeleteQueryState = class _DeleteQueryState {
5961
+ /**
5962
+ * Creates a new DeleteQueryState instance
5963
+ * @param table - The table definition for the DELETE query
5964
+ * @param ast - Optional initial AST node, defaults to a basic DELETE query
5965
+ */
5618
5966
  constructor(table, ast) {
5619
5967
  this.table = table;
5620
5968
  this.ast = ast ?? {
@@ -5626,30 +5974,55 @@ var DeleteQueryState = class _DeleteQueryState {
5626
5974
  clone(nextAst) {
5627
5975
  return new _DeleteQueryState(this.table, nextAst);
5628
5976
  }
5977
+ /**
5978
+ * Adds a WHERE clause to the DELETE query
5979
+ * @param expr - The expression to use as the WHERE condition
5980
+ * @returns A new DeleteQueryState with the WHERE clause added
5981
+ */
5629
5982
  withWhere(expr) {
5630
5983
  return this.clone({
5631
5984
  ...this.ast,
5632
5985
  where: expr
5633
5986
  });
5634
5987
  }
5988
+ /**
5989
+ * Adds a RETURNING clause to the DELETE query
5990
+ * @param columns - The columns to return after deletion
5991
+ * @returns A new DeleteQueryState with the RETURNING clause added
5992
+ */
5635
5993
  withReturning(columns) {
5636
5994
  return this.clone({
5637
5995
  ...this.ast,
5638
5996
  returning: [...columns]
5639
5997
  });
5640
5998
  }
5999
+ /**
6000
+ * Adds a USING clause to the DELETE query
6001
+ * @param source - The table source to use in the USING clause
6002
+ * @returns A new DeleteQueryState with the USING clause added
6003
+ */
5641
6004
  withUsing(source) {
5642
6005
  return this.clone({
5643
6006
  ...this.ast,
5644
6007
  using: source
5645
6008
  });
5646
6009
  }
6010
+ /**
6011
+ * Adds a JOIN clause to the DELETE query
6012
+ * @param join - The join node to add
6013
+ * @returns A new DeleteQueryState with the JOIN clause added
6014
+ */
5647
6015
  withJoin(join) {
5648
6016
  return this.clone({
5649
6017
  ...this.ast,
5650
6018
  joins: [...this.ast.joins ?? [], join]
5651
6019
  });
5652
6020
  }
6021
+ /**
6022
+ * Sets an alias for the table in the DELETE query
6023
+ * @param alias - The alias to assign to the table
6024
+ * @returns A new DeleteQueryState with the table alias set
6025
+ */
5653
6026
  withTableAlias(alias) {
5654
6027
  return this.clone({
5655
6028
  ...this.ast,
@@ -5663,6 +6036,11 @@ var DeleteQueryState = class _DeleteQueryState {
5663
6036
 
5664
6037
  // src/query-builder/delete.ts
5665
6038
  var DeleteQueryBuilder = class _DeleteQueryBuilder {
6039
+ /**
6040
+ * Creates a new DeleteQueryBuilder instance
6041
+ * @param table - The table definition for the DELETE query
6042
+ * @param state - Optional initial query state, defaults to a new DeleteQueryState
6043
+ */
5666
6044
  constructor(table, state) {
5667
6045
  this.table = table;
5668
6046
  this.state = state ?? new DeleteQueryState(table);
@@ -5670,20 +6048,48 @@ var DeleteQueryBuilder = class _DeleteQueryBuilder {
5670
6048
  clone(state) {
5671
6049
  return new _DeleteQueryBuilder(this.table, state);
5672
6050
  }
6051
+ /**
6052
+ * Adds a WHERE clause to the DELETE query
6053
+ * @param expr - The expression to use as the WHERE condition
6054
+ * @returns A new DeleteQueryBuilder with the WHERE clause added
6055
+ */
5673
6056
  where(expr) {
5674
6057
  return this.clone(this.state.withWhere(expr));
5675
6058
  }
6059
+ /**
6060
+ * Sets an alias for the table in the DELETE query
6061
+ * @param alias - The alias to assign to the table
6062
+ * @returns A new DeleteQueryBuilder with the table alias set
6063
+ */
5676
6064
  as(alias) {
5677
6065
  return this.clone(this.state.withTableAlias(alias));
5678
6066
  }
6067
+ /**
6068
+ * Adds a USING clause to the DELETE query
6069
+ * @param source - The table source to use in the USING clause
6070
+ * @returns A new DeleteQueryBuilder with the USING clause added
6071
+ */
5679
6072
  using(source) {
5680
6073
  return this.clone(this.state.withUsing(this.resolveTableSource(source)));
5681
6074
  }
6075
+ /**
6076
+ * Adds a JOIN clause to the DELETE query
6077
+ * @param table - The table to join with
6078
+ * @param condition - The join condition expression
6079
+ * @param kind - The type of join (defaults to INNER)
6080
+ * @param relationName - Optional name for the relation
6081
+ * @returns A new DeleteQueryBuilder with the JOIN clause added
6082
+ */
5682
6083
  join(table, condition, kind = JOIN_KINDS.INNER, relationName) {
5683
6084
  const target = this.resolveJoinTarget(table);
5684
6085
  const joinNode = createJoinNode(kind, target, condition, relationName);
5685
6086
  return this.clone(this.state.withJoin(joinNode));
5686
6087
  }
6088
+ /**
6089
+ * Adds a RETURNING clause to the DELETE query
6090
+ * @param columns - The columns to return after deletion
6091
+ * @returns A new DeleteQueryBuilder with the RETURNING clause added
6092
+ */
5687
6093
  returning(...columns) {
5688
6094
  if (!columns.length) return this;
5689
6095
  const nodes = columns.map((column) => buildColumnNode(this.table, column));
@@ -5699,16 +6105,36 @@ var DeleteQueryBuilder = class _DeleteQueryBuilder {
5699
6105
  if (typeof table === "string") return table;
5700
6106
  return this.resolveTableSource(table);
5701
6107
  }
5702
- compile(arg) {
5703
- if (typeof arg.compileDelete === "function") {
5704
- return arg.compileDelete(this.state.ast);
5705
- }
5706
- const dialect = resolveDialectInput(arg);
5707
- return dialect.compileDelete(this.state.ast);
6108
+ /**
6109
+ * Compiles the DELETE query for the specified dialect
6110
+ * @param dialect - The SQL dialect to compile for
6111
+ * @returns The compiled query with SQL and parameters
6112
+ */
6113
+ compile(dialect) {
6114
+ const resolved = resolveDialectInput(dialect);
6115
+ return resolved.compileDelete(this.state.ast);
5708
6116
  }
5709
- toSql(arg) {
5710
- return this.compile(arg).sql;
6117
+ /**
6118
+ * Returns the SQL string for the DELETE query
6119
+ * @param dialect - The SQL dialect to generate SQL for
6120
+ * @returns The SQL string representation of the query
6121
+ */
6122
+ toSql(dialect) {
6123
+ return this.compile(dialect).sql;
6124
+ }
6125
+ /**
6126
+ * Executes the DELETE query using the provided session
6127
+ * @param session - The ORM session to execute the query with
6128
+ * @returns A promise that resolves to the query results
6129
+ */
6130
+ async execute(session) {
6131
+ const compiled = this.compile(session.dialect);
6132
+ return session.executor.executeSql(compiled.sql, compiled.params);
5711
6133
  }
6134
+ /**
6135
+ * Returns the Abstract Syntax Tree (AST) representation of the query
6136
+ * @returns The AST node for the DELETE query
6137
+ */
5712
6138
  getAST() {
5713
6139
  return this.state.ast;
5714
6140
  }
@@ -5751,7 +6177,7 @@ var generateCreateTableSql = (table, dialect) => {
5751
6177
  const pk = resolvePrimaryKey(table);
5752
6178
  const inlinePkColumns = /* @__PURE__ */ new Set();
5753
6179
  const columnLines = Object.values(table.columns).map((col2) => {
5754
- const includePk = dialect.preferInlinePkAutoincrement?.(col2, table, pk) && pk.includes(col2.name);
6180
+ const includePk = dialect.preferInlinePkAutoincrement(col2, table, pk) && pk.includes(col2.name);
5755
6181
  if (includePk) {
5756
6182
  inlinePkColumns.add(col2.name);
5757
6183
  }
@@ -6143,6 +6569,13 @@ async function runSelectNode(ast, ctx) {
6143
6569
 
6144
6570
  // src/core/ddl/introspect/postgres.ts
6145
6571
  var postgresIntrospector = {
6572
+ /**
6573
+ * Introspects the PostgreSQL database schema by querying information_schema and pg_catalog.
6574
+ * Builds tables with columns, primary keys, foreign keys, and indexes.
6575
+ * @param ctx - The introspection context with database executor.
6576
+ * @param options - Options for schema selection and table filtering.
6577
+ * @returns A promise resolving to the complete database schema.
6578
+ */
6146
6579
  async introspect(ctx, options) {
6147
6580
  const schema = options.schema || "public";
6148
6581
  const tables = [];
@@ -6256,7 +6689,7 @@ var postgresIntrospector = {
6256
6689
  ],
6257
6690
  where: and(
6258
6691
  eq({ table: "ns", name: "nspname" }, schema),
6259
- eq({ table: "i", name: "indisprimary" }, { type: "Literal", value: false })
6692
+ eq({ table: "i", name: "indisprimary" }, false)
6260
6693
  )
6261
6694
  };
6262
6695
  const indexQueryRows = await runSelectNode(indexQuery, ctx);
@@ -6420,8 +6853,22 @@ var mysqlIntrospector = {
6420
6853
  };
6421
6854
 
6422
6855
  // src/core/ddl/introspect/sqlite.ts
6856
+ var toReferentialAction = (value) => {
6857
+ if (!value) return void 0;
6858
+ const normalized = value.toUpperCase();
6859
+ if (normalized === "NO ACTION" || normalized === "RESTRICT" || normalized === "CASCADE" || normalized === "SET NULL" || normalized === "SET DEFAULT") {
6860
+ return normalized;
6861
+ }
6862
+ return void 0;
6863
+ };
6423
6864
  var escapeSingleQuotes = (name) => name.replace(/'/g, "''");
6424
6865
  var sqliteIntrospector = {
6866
+ /**
6867
+ * Introspects the SQLite database schema by querying sqlite_master and various PRAGMAs.
6868
+ * @param ctx - The database execution context containing the DbExecutor.
6869
+ * @param options - Options controlling which tables and schemas to include.
6870
+ * @returns A promise that resolves to the introspected DatabaseSchema.
6871
+ */
6425
6872
  async introspect(ctx, options) {
6426
6873
  const tables = [];
6427
6874
  const tableRows = await queryRows(
@@ -6453,8 +6900,8 @@ var sqliteIntrospector = {
6453
6900
  col2.references = {
6454
6901
  table: fk.table,
6455
6902
  column: fk.to,
6456
- onDelete: fk.on_delete?.toUpperCase(),
6457
- onUpdate: fk.on_update?.toUpperCase()
6903
+ onDelete: toReferentialAction(fk.on_delete),
6904
+ onUpdate: toReferentialAction(fk.on_update)
6458
6905
  };
6459
6906
  }
6460
6907
  });
@@ -6477,6 +6924,12 @@ var sqliteIntrospector = {
6477
6924
 
6478
6925
  // src/core/ddl/introspect/mssql.ts
6479
6926
  var mssqlIntrospector = {
6927
+ /**
6928
+ * Introspects the MSSQL database schema.
6929
+ * @param ctx - The introspection context containing the database executor.
6930
+ * @param options - Options for introspection, such as schema filter.
6931
+ * @returns A promise that resolves to the introspected database schema.
6932
+ */
6480
6933
  async introspect(ctx, options) {
6481
6934
  const schema = options.schema;
6482
6935
  const filterSchema = schema ? "sch.name = @p1" : "1=1";
@@ -6759,10 +7212,21 @@ var dateTrunc = (part, date) => fn3("DATE_TRUNC", [part, date]);
6759
7212
  // src/orm/als.ts
6760
7213
  var AsyncLocalStorage = class {
6761
7214
  /**
6762
- * Executes a callback with the specified store value
6763
- * @param store - Value to store during callback execution
6764
- * @param callback - Function to execute with the store value
6765
- * @returns Result of the callback function
7215
+ * Executes a callback function within a context containing the specified store value.
7216
+ * The store value is only available during the callback's execution and is automatically
7217
+ * cleared afterward.
7218
+ *
7219
+ * @param store - The context value to make available during callback execution
7220
+ * @param callback - Function to execute with the store value available
7221
+ * @returns Result of the callback function execution
7222
+ *
7223
+ * @example
7224
+ * ```
7225
+ * const als = new AsyncLocalStorage<number>();
7226
+ * als.run(42, () => {
7227
+ * console.log(als.getStore()); // Outputs: 42
7228
+ * });
7229
+ * ```
6766
7230
  */
6767
7231
  run(store, callback) {
6768
7232
  this.store = store;
@@ -6773,8 +7237,20 @@ var AsyncLocalStorage = class {
6773
7237
  }
6774
7238
  }
6775
7239
  /**
6776
- * Gets the currently stored value
6777
- * @returns Current store value or undefined if none exists
7240
+ * Retrieves the current store value from the async context.
7241
+ * Returns undefined if called outside of a `run()` callback execution.
7242
+ *
7243
+ * @returns Current store value or undefined if no context exists
7244
+ *
7245
+ * @example
7246
+ * ```
7247
+ * const als = new AsyncLocalStorage<string>();
7248
+ * console.log(als.getStore()); // Outputs: undefined
7249
+ *
7250
+ * als.run('hello', () => {
7251
+ * console.log(als.getStore()); // Outputs: 'hello'
7252
+ * });
7253
+ * ```
6778
7254
  */
6779
7255
  getStore() {
6780
7256
  return this.store;
@@ -6864,11 +7340,7 @@ var TypeScriptGenerator = class {
6864
7340
  const lines = [];
6865
7341
  const hydration = ast.meta?.hydration;
6866
7342
  const hydratedRelations = new Set(hydration?.relations?.map((r) => r.name) ?? []);
6867
- const selections = ast.columns.filter((col2) => !(hydration && isRelationAlias(col2.alias))).map((col2) => {
6868
- const key = col2.alias || col2.name;
6869
- const operand = col2;
6870
- return `${key}: ${this.printOperand(operand)}`;
6871
- });
7343
+ const selections = ast.columns.filter((col2) => !(hydration && isRelationAlias(col2.alias))).map((col2, index) => `${this.getSelectionKey(col2, index)}: ${this.printOperand(col2)}`);
6872
7344
  lines.push(`db.select({`);
6873
7345
  selections.forEach((sel2, index) => {
6874
7346
  lines.push(` ${sel2}${index < selections.length - 1 ? "," : ""}`);
@@ -6956,7 +7428,7 @@ var TypeScriptGenerator = class {
6956
7428
  * Prints an ordering term (operand/expression/alias) to TypeScript code.
6957
7429
  */
6958
7430
  printOrderingTerm(term) {
6959
- if (!term || !term.type) {
7431
+ if (!term || !("type" in term)) {
6960
7432
  throw new Error("Unsupported ordering term");
6961
7433
  }
6962
7434
  switch (term.type) {
@@ -6975,6 +7447,18 @@ var TypeScriptGenerator = class {
6975
7447
  return this.printExpression(term);
6976
7448
  }
6977
7449
  }
7450
+ getSelectionKey(selection, index) {
7451
+ if (selection.alias) {
7452
+ return selection.alias;
7453
+ }
7454
+ if (this.isNamedSelection(selection)) {
7455
+ return selection.name;
7456
+ }
7457
+ return `selection${index + 1}`;
7458
+ }
7459
+ isNamedSelection(selection) {
7460
+ return "name" in selection;
7461
+ }
6978
7462
  visitBinaryExpression(binary) {
6979
7463
  return this.printBinaryExpression(binary);
6980
7464
  }
@@ -7758,6 +8242,7 @@ var RelationChangeProcessor = class {
7758
8242
  * @param _entry - The relation change entry (reserved for future use)
7759
8243
  */
7760
8244
  async handleBelongsToChange(_entry) {
8245
+ void _entry;
7761
8246
  }
7762
8247
  /**
7763
8248
  * Handles changes for belongs-to-many relations.
@@ -7871,7 +8356,7 @@ var RelationChangeProcessor = class {
7871
8356
  const key = findPrimaryKey(table);
7872
8357
  const value = entity[key];
7873
8358
  if (value === void 0 || value === null) return null;
7874
- return value;
8359
+ return value ?? null;
7875
8360
  }
7876
8361
  };
7877
8362
 
@@ -8463,8 +8948,6 @@ var Orm = class {
8463
8948
  const session = new OrmSession({ orm: this, executor });
8464
8949
  try {
8465
8950
  return await session.transaction(() => fn4(session));
8466
- } catch (err) {
8467
- throw err;
8468
8951
  } finally {
8469
8952
  await session.dispose();
8470
8953
  }
@@ -8495,9 +8978,6 @@ var getOrCreateMetadataBag = (context) => {
8495
8978
  var readMetadataBag = (context) => {
8496
8979
  return context.metadata?.[METADATA_KEY];
8497
8980
  };
8498
- var registerInitializer = (context, initializer) => {
8499
- context.addInitializer?.(initializer);
8500
- };
8501
8981
 
8502
8982
  // src/decorators/entity.ts
8503
8983
  var toSnakeCase = (value) => {
@@ -8527,14 +9007,24 @@ function Entity(options = {}) {
8527
9007
  if (bag) {
8528
9008
  const meta = ensureEntityMetadata(ctor);
8529
9009
  for (const entry of bag.columns) {
8530
- if (!meta.columns[entry.propertyName]) {
8531
- addColumnMetadata(ctor, entry.propertyName, { ...entry.column });
9010
+ if (meta.columns[entry.propertyName]) {
9011
+ throw new Error(
9012
+ `Column '${entry.propertyName}' is already defined on entity '${ctor.name}'.`
9013
+ );
8532
9014
  }
9015
+ addColumnMetadata(ctor, entry.propertyName, { ...entry.column });
8533
9016
  }
8534
9017
  for (const entry of bag.relations) {
8535
- if (!meta.relations[entry.propertyName]) {
8536
- addRelationMetadata(ctor, entry.propertyName, entry.relation);
9018
+ if (meta.relations[entry.propertyName]) {
9019
+ throw new Error(
9020
+ `Relation '${entry.propertyName}' is already defined on entity '${ctor.name}'.`
9021
+ );
8537
9022
  }
9023
+ const relationCopy = entry.relation.kind === RelationKinds.BelongsToMany ? {
9024
+ ...entry.relation,
9025
+ defaultPivotColumns: entry.relation.defaultPivotColumns ? [...entry.relation.defaultPivotColumns] : void 0
9026
+ } : { ...entry.relation };
9027
+ addRelationMetadata(ctor, entry.propertyName, relationCopy);
8538
9028
  }
8539
9029
  }
8540
9030
  }
@@ -8597,13 +9087,6 @@ var registerColumnFromContext = (context, column) => {
8597
9087
  if (!bag.columns.some((entry) => entry.propertyName === propertyName)) {
8598
9088
  bag.columns.push({ propertyName, column: { ...column } });
8599
9089
  }
8600
- registerInitializer(context, function() {
8601
- const ctor = resolveConstructor(this);
8602
- if (!ctor) {
8603
- return;
8604
- }
8605
- registerColumn(ctor, propertyName, column);
8606
- });
8607
9090
  };
8608
9091
  function Column(definition) {
8609
9092
  const normalized = normalizeColumnInput(definition);
@@ -8659,13 +9142,6 @@ var createFieldDecorator = (metadataFactory) => {
8659
9142
  if (!bag.relations.some((entry) => entry.propertyName === propertyName2)) {
8660
9143
  bag.relations.push({ propertyName: propertyName2, relation: relationMetadata });
8661
9144
  }
8662
- registerInitializer(ctx, function() {
8663
- const ctor2 = resolveConstructor2(this);
8664
- if (!ctor2) {
8665
- return;
8666
- }
8667
- registerRelation(ctor2, propertyName2, relationMetadata);
8668
- });
8669
9145
  return;
8670
9146
  }
8671
9147
  const propertyName = normalizePropertyName2(propertyKeyOrContext);
@@ -9302,11 +9778,9 @@ export {
9302
9778
  cos,
9303
9779
  cot,
9304
9780
  count,
9305
- createColumn,
9306
9781
  createEntityFromRow,
9307
9782
  createEntityProxy,
9308
9783
  createExecutorFromQueryRunner,
9309
- createLiteral,
9310
9784
  createMssqlExecutor,
9311
9785
  createMysqlExecutor,
9312
9786
  createPooledExecutorFactory,
@@ -9330,6 +9804,7 @@ export {
9330
9804
  diffSchema,
9331
9805
  div,
9332
9806
  endOfMonth,
9807
+ entityRef,
9333
9808
  eq,
9334
9809
  esel,
9335
9810
  executeHydrated,
@@ -9342,6 +9817,7 @@ export {
9342
9817
  fromUnixTime,
9343
9818
  generateCreateTableSql,
9344
9819
  generateSchemaSql,
9820
+ getColumn,
9345
9821
  getSchemaIntrospector,
9346
9822
  getTableDefFromEntity,
9347
9823
  groupConcat,