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.cjs CHANGED
@@ -99,11 +99,9 @@ __export(index_exports, {
99
99
  cos: () => cos,
100
100
  cot: () => cot,
101
101
  count: () => count,
102
- createColumn: () => createColumn,
103
102
  createEntityFromRow: () => createEntityFromRow,
104
103
  createEntityProxy: () => createEntityProxy,
105
104
  createExecutorFromQueryRunner: () => createExecutorFromQueryRunner,
106
- createLiteral: () => createLiteral,
107
105
  createMssqlExecutor: () => createMssqlExecutor,
108
106
  createMysqlExecutor: () => createMysqlExecutor,
109
107
  createPooledExecutorFactory: () => createPooledExecutorFactory,
@@ -127,6 +125,7 @@ __export(index_exports, {
127
125
  diffSchema: () => diffSchema,
128
126
  div: () => div,
129
127
  endOfMonth: () => endOfMonth,
128
+ entityRef: () => entityRef,
130
129
  eq: () => eq,
131
130
  esel: () => esel,
132
131
  executeHydrated: () => executeHydrated,
@@ -139,6 +138,7 @@ __export(index_exports, {
139
138
  fromUnixTime: () => fromUnixTime,
140
139
  generateCreateTableSql: () => generateCreateTableSql,
141
140
  generateSchemaSql: () => generateSchemaSql,
141
+ getColumn: () => getColumn,
142
142
  getSchemaIntrospector: () => getSchemaIntrospector,
143
143
  getTableDefFromEntity: () => getTableDefFromEntity,
144
144
  groupConcat: () => groupConcat,
@@ -247,7 +247,8 @@ module.exports = __toCommonJS(index_exports);
247
247
  // src/schema/table.ts
248
248
  var defineTable = (name, columns, relations = {}, hooks, options = {}) => {
249
249
  const colsWithNames = Object.entries(columns).reduce((acc, [key, def]) => {
250
- acc[key] = { ...def, name: key, table: name };
250
+ const colDef = { ...def, name: key, table: name };
251
+ acc[key] = colDef;
251
252
  return acc;
252
253
  }, {});
253
254
  return {
@@ -271,17 +272,20 @@ var withColumnProps = (table) => {
271
272
  if (cached) return cached;
272
273
  const proxy = new Proxy(table, {
273
274
  get(target, prop, receiver) {
274
- if (prop === "$") return target.columns;
275
+ const t = target;
276
+ if (prop === "$") return t.columns;
275
277
  if (Reflect.has(target, prop)) return Reflect.get(target, prop, receiver);
276
- if (typeof prop === "string" && prop in target.columns) return target.columns[prop];
278
+ if (typeof prop === "string" && prop in t.columns) return t.columns[prop];
277
279
  return void 0;
278
280
  },
279
281
  has(target, prop) {
280
- return prop === "$" || Reflect.has(target, prop) || typeof prop === "string" && prop in target.columns;
282
+ const t = target;
283
+ return prop === "$" || Reflect.has(target, prop) || typeof prop === "string" && prop in t.columns;
281
284
  },
282
285
  ownKeys(target) {
286
+ const t = target;
283
287
  const base = Reflect.ownKeys(target);
284
- const cols = Object.keys(target.columns);
288
+ const cols = Object.keys(t.columns);
285
289
  for (const k of cols) {
286
290
  if (!base.includes(k)) base.push(k);
287
291
  }
@@ -313,6 +317,14 @@ var withColumnProps = (table) => {
313
317
  return proxy;
314
318
  };
315
319
  var tableRef = (table) => withColumnProps(table);
320
+ function getColumn(table, key) {
321
+ const col2 = table.columns[key];
322
+ if (!col2) {
323
+ const tableName = table.name || "<unknown>";
324
+ throw new Error(`Column '${key}' does not exist on table '${tableName}'`);
325
+ }
326
+ return col2;
327
+ }
316
328
 
317
329
  // src/schema/column.ts
318
330
  var col = {
@@ -517,46 +529,59 @@ var operandTypes = /* @__PURE__ */ new Set([
517
529
  "CaseExpression",
518
530
  "WindowFunction"
519
531
  ]);
520
- var isOperandNode = (node) => node && operandTypes.has(node.type);
521
- var isFunctionNode = (node) => node?.type === "Function";
522
- var isCaseExpressionNode = (node) => node?.type === "CaseExpression";
523
- var isWindowFunctionNode = (node) => node?.type === "WindowFunction";
532
+ var hasTypeProperty = (value) => typeof value === "object" && value !== null && "type" in value;
533
+ var isOperandNode = (node) => {
534
+ if (!hasTypeProperty(node)) return false;
535
+ return operandTypes.has(node.type);
536
+ };
537
+ var isFunctionNode = (node) => isOperandNode(node) && node.type === "Function";
538
+ var isCaseExpressionNode = (node) => isOperandNode(node) && node.type === "CaseExpression";
539
+ var isWindowFunctionNode = (node) => isOperandNode(node) && node.type === "WindowFunction";
524
540
  var isExpressionSelectionNode = (node) => isFunctionNode(node) || isCaseExpressionNode(node) || isWindowFunctionNode(node);
525
541
 
526
542
  // src/core/ast/expression-builders.ts
527
- var valueToOperand = (value) => {
528
- if (isOperandNode(value)) {
529
- return value;
530
- }
531
- return {
532
- type: "Literal",
533
- value
534
- };
535
- };
536
- var toNode = (col2) => {
537
- if (isOperandNode(col2)) return col2;
538
- const def = col2;
539
- return { type: "Column", table: def.table || "unknown", name: def.name };
540
- };
543
+ var isLiteralValue = (value) => value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
541
544
  var toLiteralNode = (value) => ({
542
545
  type: "Literal",
543
546
  value
544
547
  });
545
- var isLiteralValue = (value) => value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
546
- var isValueOperandInput = (value) => isOperandNode(value) || isLiteralValue(value);
547
- var toOperand = (val) => {
548
- if (isLiteralValue(val)) {
549
- return valueToOperand(val);
548
+ var columnRefToNode = (col2) => {
549
+ if (!col2.table) {
550
+ throw new Error(
551
+ `Column "${col2.name}" requires a table reference. Use columnOperand with a fully qualified ColumnRef or ColumnNode.`
552
+ );
550
553
  }
551
- return toNode(val);
554
+ return { type: "Column", table: col2.table, name: col2.name };
552
555
  };
556
+ var toOperandNode = (value) => {
557
+ if (isOperandNode(value)) {
558
+ return value;
559
+ }
560
+ if (isLiteralValue(value)) {
561
+ return toLiteralNode(value);
562
+ }
563
+ return columnRefToNode(value);
564
+ };
565
+ var valueToOperand = (value) => {
566
+ if (isOperandNode(value)) {
567
+ return value;
568
+ }
569
+ return toLiteralNode(value);
570
+ };
571
+ var toOperand = (val) => toOperandNode(val);
572
+ var isValueOperandInput = (value) => isOperandNode(value) || isLiteralValue(value);
553
573
  var hasQueryAst = (value) => typeof value.getAST === "function";
554
574
  var resolveSelectQueryNode = (query) => hasQueryAst(query) ? query.getAST() : query;
555
575
  var toScalarSubqueryNode = (query) => ({
556
576
  type: "ScalarSubquery",
557
577
  query: resolveSelectQueryNode(query)
558
578
  });
559
- var columnOperand = (col2) => toNode(col2);
579
+ var columnOperand = (col2) => {
580
+ if (isOperandNode(col2) && col2.type === "Column") {
581
+ return col2;
582
+ }
583
+ return columnRefToNode(col2);
584
+ };
560
585
  var outerRef = (col2) => ({
561
586
  ...columnOperand(col2),
562
587
  scope: "outer"
@@ -569,7 +594,7 @@ var correlateBy = (table, column) => outerRef({ name: column, table });
569
594
  var createBinaryExpression = (operator, left2, right2, escape) => {
570
595
  const node = {
571
596
  type: "BinaryExpression",
572
- left: toNode(left2),
597
+ left: toOperandNode(left2),
573
598
  operator,
574
599
  right: toOperand(right2)
575
600
  };
@@ -598,17 +623,17 @@ var or = (...operands) => ({
598
623
  });
599
624
  var isNull = (left2) => ({
600
625
  type: "NullExpression",
601
- left: toNode(left2),
626
+ left: toOperandNode(left2),
602
627
  operator: "IS NULL"
603
628
  });
604
629
  var isNotNull = (left2) => ({
605
630
  type: "NullExpression",
606
- left: toNode(left2),
631
+ left: toOperandNode(left2),
607
632
  operator: "IS NOT NULL"
608
633
  });
609
634
  var createInExpression = (operator, left2, right2) => ({
610
635
  type: "InExpression",
611
- left: toNode(left2),
636
+ left: toOperandNode(left2),
612
637
  operator,
613
638
  right: right2
614
639
  });
@@ -618,7 +643,7 @@ var inSubquery = (left2, subquery) => createInExpression("IN", left2, toScalarSu
618
643
  var notInSubquery = (left2, subquery) => createInExpression("NOT IN", left2, toScalarSubqueryNode(subquery));
619
644
  var createBetweenExpression = (operator, left2, lower2, upper2) => ({
620
645
  type: "BetweenExpression",
621
- left: toNode(left2),
646
+ left: toOperandNode(left2),
622
647
  operator,
623
648
  lower: toOperand(lower2),
624
649
  upper: toOperand(upper2)
@@ -800,24 +825,54 @@ var groupConcat = (col2, options) => ({
800
825
  });
801
826
 
802
827
  // src/core/ast/expression-visitor.ts
803
- var expressionDispatchers = /* @__PURE__ */ new Map();
804
- var operandDispatchers = /* @__PURE__ */ new Map();
828
+ var DispatcherRegistry = class _DispatcherRegistry {
829
+ constructor(dispatchers = /* @__PURE__ */ new Map()) {
830
+ this.dispatchers = dispatchers;
831
+ }
832
+ /**
833
+ * Registers a new dispatcher and returns a new registry instance
834
+ */
835
+ register(type, dispatcher) {
836
+ const newMap = new Map(this.dispatchers);
837
+ newMap.set(type, dispatcher);
838
+ return new _DispatcherRegistry(newMap);
839
+ }
840
+ /**
841
+ * Gets a dispatcher for the given type
842
+ */
843
+ get(type) {
844
+ return this.dispatchers.get(type);
845
+ }
846
+ /**
847
+ * Returns a new empty registry
848
+ */
849
+ clear() {
850
+ return new _DispatcherRegistry();
851
+ }
852
+ };
853
+ var expressionRegistry = new DispatcherRegistry();
854
+ var operandRegistry = new DispatcherRegistry();
805
855
  var registerExpressionDispatcher = (type, dispatcher) => {
806
- expressionDispatchers.set(type, dispatcher);
856
+ expressionRegistry = expressionRegistry.register(type, dispatcher);
807
857
  };
808
858
  var registerOperandDispatcher = (type, dispatcher) => {
809
- operandDispatchers.set(type, dispatcher);
859
+ operandRegistry = operandRegistry.register(type, dispatcher);
810
860
  };
811
- var clearExpressionDispatchers = () => expressionDispatchers.clear();
812
- var clearOperandDispatchers = () => operandDispatchers.clear();
861
+ var clearExpressionDispatchers = () => {
862
+ expressionRegistry = expressionRegistry.clear();
863
+ };
864
+ var clearOperandDispatchers = () => {
865
+ operandRegistry = operandRegistry.clear();
866
+ };
867
+ var getNodeType = (node) => typeof node === "object" && node !== null && typeof node.type === "string" ? node.type : void 0;
813
868
  var unsupportedExpression = (node) => {
814
- throw new Error(`Unsupported expression type "${node?.type ?? "unknown"}"`);
869
+ throw new Error(`Unsupported expression type "${getNodeType(node) ?? "unknown"}"`);
815
870
  };
816
871
  var unsupportedOperand = (node) => {
817
- throw new Error(`Unsupported operand type "${node?.type ?? "unknown"}"`);
872
+ throw new Error(`Unsupported operand type "${getNodeType(node) ?? "unknown"}"`);
818
873
  };
819
874
  var visitExpression = (node, visitor) => {
820
- const dynamic = expressionDispatchers.get(node?.type);
875
+ const dynamic = expressionRegistry.get(node.type);
821
876
  if (dynamic) return dynamic(node, visitor);
822
877
  switch (node.type) {
823
878
  case "BinaryExpression":
@@ -848,7 +903,7 @@ var visitExpression = (node, visitor) => {
848
903
  return unsupportedExpression(node);
849
904
  };
850
905
  var visitOperand = (node, visitor) => {
851
- const dynamic = operandDispatchers.get(node?.type);
906
+ const dynamic = operandRegistry.get(node.type);
852
907
  if (dynamic) return dynamic(node, visitor);
853
908
  switch (node.type) {
854
909
  case "Column":
@@ -883,24 +938,35 @@ var visitOperand = (node, visitor) => {
883
938
  };
884
939
 
885
940
  // src/core/ast/adapters.ts
941
+ var hasAlias = (obj) => typeof obj === "object" && obj !== null && "alias" in obj;
886
942
  var toColumnRef = (col2) => ({
887
943
  name: col2.name,
888
944
  table: col2.table,
889
- alias: col2.alias
945
+ alias: hasAlias(col2) ? col2.alias : void 0
890
946
  });
891
947
  var toTableRef = (table) => ({
892
948
  name: table.name,
893
949
  schema: table.schema,
894
- alias: table.alias
950
+ alias: hasAlias(table) ? table.alias : void 0
895
951
  });
896
952
 
897
953
  // src/core/ast/builders.ts
954
+ var isColumnNode = (col2) => "type" in col2 && col2.type === "Column";
955
+ var resolveTableName = (def, table) => {
956
+ if (!def.table) {
957
+ return table.alias || table.name;
958
+ }
959
+ if (table.alias && def.table === table.name) {
960
+ return table.alias;
961
+ }
962
+ return def.table;
963
+ };
898
964
  var buildColumnNode = (table, column) => {
899
- if (column.type === "Column") {
965
+ if (isColumnNode(column)) {
900
966
  return column;
901
967
  }
902
968
  const def = column;
903
- const baseTable = def.table ? table.alias && def.table === table.name ? table.alias : def.table : table.alias || table.name;
969
+ const baseTable = resolveTableName(def, table);
904
970
  return {
905
971
  type: "Column",
906
972
  table: baseTable,
@@ -914,7 +980,8 @@ var buildColumnNodes = (table, names) => names.map((name) => ({
914
980
  }));
915
981
  var createTableNode = (table) => ({
916
982
  type: "Table",
917
- name: table.name
983
+ name: table.name,
984
+ schema: table.schema
918
985
  });
919
986
  var fnTable = (name, args = [], alias, opts) => ({
920
987
  type: "FunctionTable",
@@ -935,6 +1002,9 @@ var derivedTable = (query, alias, columnAliases) => ({
935
1002
 
936
1003
  // src/core/functions/standard-strategy.ts
937
1004
  var StandardFunctionStrategy = class _StandardFunctionStrategy {
1005
+ /**
1006
+ * Creates a new StandardFunctionStrategy and registers standard functions.
1007
+ */
938
1008
  constructor() {
939
1009
  this.renderers = /* @__PURE__ */ new Map();
940
1010
  this.registerStandard();
@@ -973,12 +1043,25 @@ var StandardFunctionStrategy = class _StandardFunctionStrategy {
973
1043
  this.add("DATE_TRUNC", ({ compiledArgs }) => `DATE_TRUNC(${compiledArgs[0]}, ${compiledArgs[1]})`);
974
1044
  this.add("GROUP_CONCAT", (ctx) => this.renderGroupConcat(ctx));
975
1045
  }
1046
+ /**
1047
+ * Registers a renderer for a function name.
1048
+ * @param name - The function name.
1049
+ * @param renderer - The renderer function.
1050
+ */
976
1051
  add(name, renderer) {
977
1052
  this.renderers.set(name, renderer);
978
1053
  }
1054
+ /**
1055
+ * @inheritDoc
1056
+ */
979
1057
  getRenderer(name) {
980
1058
  return this.renderers.get(name);
981
1059
  }
1060
+ /**
1061
+ * Renders the GROUP_CONCAT function with optional ORDER BY and SEPARATOR.
1062
+ * @param ctx - The function render context.
1063
+ * @returns The rendered SQL string.
1064
+ */
982
1065
  renderGroupConcat(ctx) {
983
1066
  const arg = ctx.compiledArgs[0];
984
1067
  const orderClause = this.buildOrderByExpression(ctx);
@@ -986,6 +1069,11 @@ var StandardFunctionStrategy = class _StandardFunctionStrategy {
986
1069
  const separatorClause = this.formatGroupConcatSeparator(ctx);
987
1070
  return `GROUP_CONCAT(${arg}${orderSegment}${separatorClause})`;
988
1071
  }
1072
+ /**
1073
+ * Builds the ORDER BY clause for functions like GROUP_CONCAT.
1074
+ * @param ctx - The function render context.
1075
+ * @returns The ORDER BY SQL clause or empty string.
1076
+ */
989
1077
  buildOrderByExpression(ctx) {
990
1078
  const orderBy = ctx.node.orderBy;
991
1079
  if (!orderBy || orderBy.length === 0) {
@@ -1001,16 +1089,27 @@ var StandardFunctionStrategy = class _StandardFunctionStrategy {
1001
1089
  });
1002
1090
  return `ORDER BY ${parts.join(", ")}`;
1003
1091
  }
1092
+ /**
1093
+ * Formats the SEPARATOR clause for GROUP_CONCAT.
1094
+ * @param ctx - The function render context.
1095
+ * @returns The SEPARATOR SQL clause or empty string.
1096
+ */
1004
1097
  formatGroupConcatSeparator(ctx) {
1005
1098
  if (!ctx.node.separator) {
1006
1099
  return "";
1007
1100
  }
1008
1101
  return ` SEPARATOR ${ctx.compileOperand(ctx.node.separator)}`;
1009
1102
  }
1103
+ /**
1104
+ * Gets the separator operand for GROUP_CONCAT, defaulting to comma.
1105
+ * @param ctx - The function render context.
1106
+ * @returns The separator operand.
1107
+ */
1010
1108
  getGroupConcatSeparatorOperand(ctx) {
1011
1109
  return ctx.node.separator ?? _StandardFunctionStrategy.DEFAULT_GROUP_CONCAT_SEPARATOR;
1012
1110
  }
1013
1111
  static {
1112
+ /** Default separator for GROUP_CONCAT, a comma. */
1014
1113
  this.DEFAULT_GROUP_CONCAT_SEPARATOR = {
1015
1114
  type: "Literal",
1016
1115
  value: ","
@@ -1075,7 +1174,8 @@ var Dialect = class _Dialect {
1075
1174
  if (!where) return "";
1076
1175
  return ` WHERE ${this.compileExpression(where, ctx)}`;
1077
1176
  }
1078
- compileReturning(returning, ctx) {
1177
+ compileReturning(returning, _ctx) {
1178
+ void _ctx;
1079
1179
  if (!returning || returning.length === 0) return "";
1080
1180
  throw new Error("RETURNING is not supported by this dialect.");
1081
1181
  }
@@ -1123,14 +1223,16 @@ var Dialect = class _Dialect {
1123
1223
  * @param index - Parameter index
1124
1224
  * @returns Formatted placeholder string
1125
1225
  */
1126
- formatPlaceholder(index) {
1226
+ formatPlaceholder(_index) {
1227
+ void _index;
1127
1228
  return "?";
1128
1229
  }
1129
1230
  /**
1130
1231
  * Whether the current dialect supports a given set operation.
1131
1232
  * Override in concrete dialects to restrict support.
1132
1233
  */
1133
- supportsSetOperation(kind) {
1234
+ supportsSetOperation(_kind) {
1235
+ void _kind;
1134
1236
  return true;
1135
1237
  }
1136
1238
  /**
@@ -1323,15 +1425,22 @@ var Dialect = class _Dialect {
1323
1425
  }
1324
1426
  registerDefaultOperandCompilers() {
1325
1427
  this.registerOperandCompiler("Literal", (literal, ctx) => ctx.addParameter(literal.value));
1326
- this.registerOperandCompiler("AliasRef", (alias, _ctx) => this.quoteIdentifier(alias.name));
1428
+ this.registerOperandCompiler("AliasRef", (alias, _ctx) => {
1429
+ void _ctx;
1430
+ return this.quoteIdentifier(alias.name);
1431
+ });
1327
1432
  this.registerOperandCompiler("Column", (column, _ctx) => {
1433
+ void _ctx;
1328
1434
  return `${this.quoteIdentifier(column.table)}.${this.quoteIdentifier(column.name)}`;
1329
1435
  });
1330
1436
  this.registerOperandCompiler(
1331
1437
  "Function",
1332
1438
  (fnNode, ctx) => this.compileFunctionOperand(fnNode, ctx)
1333
1439
  );
1334
- this.registerOperandCompiler("JsonPath", (path, _ctx) => this.compileJsonPath(path));
1440
+ this.registerOperandCompiler("JsonPath", (path, _ctx) => {
1441
+ void _ctx;
1442
+ return this.compileJsonPath(path);
1443
+ });
1335
1444
  this.registerOperandCompiler("ScalarSubquery", (node, ctx) => {
1336
1445
  const sql = this.compileSelectAst(node.query, ctx).trim().replace(/;$/, "");
1337
1446
  return `(${sql})`;
@@ -1375,7 +1484,8 @@ var Dialect = class _Dialect {
1375
1484
  });
1376
1485
  }
1377
1486
  // Default fallback, should be overridden by dialects if supported
1378
- compileJsonPath(node) {
1487
+ compileJsonPath(_node) {
1488
+ void _node;
1379
1489
  throw new Error("JSON Path not supported by this dialect");
1380
1490
  }
1381
1491
  /**
@@ -1541,6 +1651,7 @@ var NoReturningStrategy = class {
1541
1651
  * @throws Error indicating RETURNING is not supported.
1542
1652
  */
1543
1653
  compileReturning(returning, _ctx) {
1654
+ void _ctx;
1544
1655
  if (!returning || returning.length === 0) return "";
1545
1656
  throw new Error("RETURNING is not supported by this dialect.");
1546
1657
  }
@@ -1942,6 +2053,7 @@ var PostgresDialect = class extends SqlDialectBase {
1942
2053
  return `${col2}->>'${node.path}'`;
1943
2054
  }
1944
2055
  compileReturning(returning, ctx) {
2056
+ void ctx;
1945
2057
  if (!returning || returning.length === 0) return "";
1946
2058
  const columns = this.formatReturningColumns(returning);
1947
2059
  return ` RETURNING ${columns}`;
@@ -2192,9 +2304,11 @@ var SqliteDialect = class extends SqlDialectBase {
2192
2304
  return `json_extract(${col2}, '${node.path}')`;
2193
2305
  }
2194
2306
  compileQualifiedColumn(column, _table) {
2307
+ void _table;
2195
2308
  return this.quoteIdentifier(column.name);
2196
2309
  }
2197
2310
  compileReturning(returning, ctx) {
2311
+ void ctx;
2198
2312
  if (!returning || returning.length === 0) return "";
2199
2313
  const columns = this.formatReturningColumns(returning);
2200
2314
  return ` RETURNING ${columns}`;
@@ -2516,7 +2630,7 @@ var SelectQueryState = class _SelectQueryState {
2516
2630
  this.table = table;
2517
2631
  this.ast = ast ?? {
2518
2632
  type: "SelectQuery",
2519
- from: { type: "Table", name: table.name },
2633
+ from: createTableNode(table),
2520
2634
  columns: [],
2521
2635
  joins: []
2522
2636
  };
@@ -2667,10 +2781,18 @@ var SelectQueryState = class _SelectQueryState {
2667
2781
  var createJoinNode = (kind, tableName, condition, relationName) => ({
2668
2782
  type: "Join",
2669
2783
  kind,
2670
- table: typeof tableName === "string" ? { type: "Table", name: tableName } : tableName,
2784
+ table: typeof tableName === "string" ? parseQualifiedTableRef(tableName) : tableName,
2671
2785
  condition,
2672
2786
  meta: relationName ? { relationName } : void 0
2673
2787
  });
2788
+ var parseQualifiedTableRef = (ref) => {
2789
+ const parts = ref.split(".");
2790
+ if (parts.length === 2) {
2791
+ const [schema, name] = parts;
2792
+ return { type: "Table", schema, name };
2793
+ }
2794
+ return { type: "Table", name: ref };
2795
+ };
2674
2796
 
2675
2797
  // src/query-builder/hydration-manager.ts
2676
2798
  var HydrationManager = class _HydrationManager {
@@ -2757,6 +2879,11 @@ var HydrationManager = class _HydrationManager {
2757
2879
  const hasPagination = ast.limit !== void 0 || ast.offset !== void 0;
2758
2880
  return hasPagination && this.hasMultiplyingRelations(plan);
2759
2881
  }
2882
+ /**
2883
+ * Checks if the hydration plan contains relations that multiply rows
2884
+ * @param plan - Hydration plan to check
2885
+ * @returns True if plan has HasMany or BelongsToMany relations
2886
+ */
2760
2887
  hasMultiplyingRelations(plan) {
2761
2888
  return plan.relations.some(
2762
2889
  (rel) => rel.type === RelationKinds.HasMany || rel.type === RelationKinds.BelongsToMany
@@ -2834,6 +2961,12 @@ var HydrationManager = class _HydrationManager {
2834
2961
  ctes: [...ast.ctes ?? [], baseCte, pageCte]
2835
2962
  };
2836
2963
  }
2964
+ /**
2965
+ * Generates a unique CTE name by appending a suffix if needed
2966
+ * @param existing - Existing CTE nodes
2967
+ * @param baseName - Base name for the CTE
2968
+ * @returns Unique CTE name
2969
+ */
2837
2970
  nextCteName(existing, baseName) {
2838
2971
  const names = new Set((existing ?? []).map((cte) => cte.name));
2839
2972
  let candidate = baseName;
@@ -2844,15 +2977,26 @@ var HydrationManager = class _HydrationManager {
2844
2977
  }
2845
2978
  return candidate;
2846
2979
  }
2980
+ /**
2981
+ * Extracts projection names from column nodes
2982
+ * @param columns - Projection nodes
2983
+ * @returns Array of names or undefined if any column lacks name/alias
2984
+ */
2847
2985
  getProjectionNames(columns) {
2848
2986
  const names = [];
2849
2987
  for (const col2 of columns) {
2850
- const alias = col2.alias ?? col2.name;
2988
+ const node = col2;
2989
+ const alias = node.alias ?? node.name;
2851
2990
  if (!alias) return void 0;
2852
2991
  names.push(alias);
2853
2992
  }
2854
2993
  return names;
2855
2994
  }
2995
+ /**
2996
+ * Builds a map of column keys to their aliases from projection nodes
2997
+ * @param columns - Projection nodes
2998
+ * @returns Map of 'table.name' to alias
2999
+ */
2856
3000
  buildProjectionAliasMap(columns) {
2857
3001
  const map = /* @__PURE__ */ new Map();
2858
3002
  for (const col2 of columns) {
@@ -2863,6 +3007,15 @@ var HydrationManager = class _HydrationManager {
2863
3007
  }
2864
3008
  return map;
2865
3009
  }
3010
+ /**
3011
+ * Maps order by nodes to use base CTE alias
3012
+ * @param orderBy - Original order by nodes
3013
+ * @param plan - Hydration plan
3014
+ * @param projectionAliases - Map of column aliases
3015
+ * @param baseAlias - Base CTE alias
3016
+ * @param availableColumns - Set of available column names
3017
+ * @returns Mapped order by nodes, null if cannot map
3018
+ */
2866
3019
  mapOrderBy(orderBy, plan, projectionAliases, baseAlias, availableColumns) {
2867
3020
  if (!orderBy || orderBy.length === 0) {
2868
3021
  return void 0;
@@ -2875,6 +3028,15 @@ var HydrationManager = class _HydrationManager {
2875
3028
  }
2876
3029
  return mapped;
2877
3030
  }
3031
+ /**
3032
+ * Maps a single ordering term to use base CTE alias
3033
+ * @param term - Ordering term to map
3034
+ * @param plan - Hydration plan
3035
+ * @param projectionAliases - Map of column aliases
3036
+ * @param baseAlias - Base CTE alias
3037
+ * @param availableColumns - Set of available column names
3038
+ * @returns Mapped term or null if cannot map
3039
+ */
2878
3040
  mapOrderingTerm(term, plan, projectionAliases, baseAlias, availableColumns) {
2879
3041
  if (term.type === "Column") {
2880
3042
  const col2 = term;
@@ -2890,6 +3052,13 @@ var HydrationManager = class _HydrationManager {
2890
3052
  }
2891
3053
  return null;
2892
3054
  }
3055
+ /**
3056
+ * Builds column nodes for paging CTE
3057
+ * @param primaryKey - Primary key name
3058
+ * @param orderBy - Order by nodes
3059
+ * @param tableAlias - Table alias for columns
3060
+ * @returns Array of column nodes for paging
3061
+ */
2893
3062
  buildPagingColumns(primaryKey, orderBy, tableAlias) {
2894
3063
  const columns = [{ type: "Column", table: tableAlias, name: primaryKey, alias: primaryKey }];
2895
3064
  if (!orderBy) return columns;
@@ -3064,7 +3233,8 @@ var buildDefaultHydrationPlan = (table) => ({
3064
3233
  // src/query-builder/raw-column-parser.ts
3065
3234
  var parseRawColumn = (col2, tableName, ctes) => {
3066
3235
  if (col2.includes("(")) {
3067
- const [fn4, rest] = col2.split("(");
3236
+ const [_fn, rest] = col2.split("(");
3237
+ void _fn;
3068
3238
  const colName = rest.replace(")", "");
3069
3239
  const [table, name] = colName.includes(".") ? colName.split(".") : [tableName, colName];
3070
3240
  return { type: "Column", table, name, alias: col2 };
@@ -3261,10 +3431,15 @@ var QueryAstService = class {
3261
3431
  combineExpressions(existing, next) {
3262
3432
  return existing ? and(existing, next) : next;
3263
3433
  }
3434
+ /**
3435
+ * Normalizes an ordering term to a standard OrderingTerm
3436
+ * @param term - Column definition or ordering term to normalize
3437
+ * @returns Normalized ordering term
3438
+ */
3264
3439
  normalizeOrderingTerm(term) {
3265
3440
  const from = this.state.ast.from;
3266
3441
  const tableRef2 = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
3267
- const termType = term?.type;
3442
+ const termType = term.type;
3268
3443
  if (termType === "Column") {
3269
3444
  return term;
3270
3445
  }
@@ -3377,7 +3552,11 @@ var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra, ro
3377
3552
  { type: "Column", table: relation.pivotTable.name, name: relation.pivotForeignKeyToRoot },
3378
3553
  { type: "Column", table: rootTable, name: rootKey }
3379
3554
  );
3380
- const pivotJoin = createJoinNode(joinKind, relation.pivotTable.name, pivotCondition);
3555
+ const pivotJoin = createJoinNode(
3556
+ joinKind,
3557
+ { type: "Table", name: relation.pivotTable.name, schema: relation.pivotTable.schema },
3558
+ pivotCondition
3559
+ );
3381
3560
  let targetCondition = eq(
3382
3561
  { type: "Column", table: relation.target.name, name: targetKey },
3383
3562
  { type: "Column", table: relation.pivotTable.name, name: relation.pivotForeignKeyToTarget }
@@ -3387,7 +3566,7 @@ var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra, ro
3387
3566
  }
3388
3567
  const targetJoin = createJoinNode(
3389
3568
  joinKind,
3390
- relation.target.name,
3569
+ { type: "Table", name: relation.target.name, schema: relation.target.schema },
3391
3570
  targetCondition,
3392
3571
  relationName
3393
3572
  );
@@ -3565,7 +3744,12 @@ var RelationService = class {
3565
3744
  return joins.reduce((current, join) => this.astService(current).withJoin(join), state);
3566
3745
  }
3567
3746
  const condition = buildRelationJoinCondition(this.table, relation, extraCondition, rootAlias);
3568
- const joinNode = createJoinNode(joinKind, relation.target.name, condition, relationName);
3747
+ const joinNode = createJoinNode(
3748
+ joinKind,
3749
+ { type: "Table", name: relation.target.name, schema: relation.target.schema },
3750
+ condition,
3751
+ relationName
3752
+ );
3569
3753
  return this.astService(state).withJoin(joinNode);
3570
3754
  }
3571
3755
  /**
@@ -3610,25 +3794,6 @@ var RelationService = class {
3610
3794
  }
3611
3795
  };
3612
3796
 
3613
- // src/query-builder/select-query-builder-deps.ts
3614
- var defaultCreateQueryAstService = (table, state) => new QueryAstService(table, state);
3615
- var defaultCreateHydrationPlanner = (table) => new HydrationPlanner(table);
3616
- var defaultCreateHydration = (table, plannerFactory) => new HydrationManager(table, plannerFactory(table));
3617
- var resolveSelectQueryBuilderDependencies = (overrides = {}) => {
3618
- const createQueryAstService = overrides.createQueryAstService ?? defaultCreateQueryAstService;
3619
- const createHydrationPlanner = overrides.createHydrationPlanner ?? defaultCreateHydrationPlanner;
3620
- const createHydration = overrides.createHydration ?? ((table) => defaultCreateHydration(table, createHydrationPlanner));
3621
- const createRelationService = overrides.createRelationService ?? ((table, state, hydration) => new RelationService(table, state, hydration, createQueryAstService));
3622
- return {
3623
- createState: overrides.createState ?? ((table) => new SelectQueryState(table)),
3624
- createHydration,
3625
- createHydrationPlanner,
3626
- createQueryAstService,
3627
- createRelationService
3628
- };
3629
- };
3630
- var defaultSelectQueryBuilderDependencies = resolveSelectQueryBuilderDependencies();
3631
-
3632
3797
  // src/query-builder/column-selector.ts
3633
3798
  var ColumnSelector = class {
3634
3799
  /**
@@ -3754,6 +3919,29 @@ var RelationManager = class {
3754
3919
  }
3755
3920
  };
3756
3921
 
3922
+ // src/query-builder/select-query-builder-deps.ts
3923
+ var defaultCreateQueryAstService = (table, state) => new QueryAstService(table, state);
3924
+ var defaultCreateHydrationPlanner = (table) => new HydrationPlanner(table);
3925
+ var defaultCreateHydration = (table, plannerFactory) => new HydrationManager(table, plannerFactory(table));
3926
+ var resolveSelectQueryBuilderDependencies = (overrides = {}) => {
3927
+ const createQueryAstService = overrides.createQueryAstService ?? defaultCreateQueryAstService;
3928
+ const createHydrationPlanner = overrides.createHydrationPlanner ?? defaultCreateHydrationPlanner;
3929
+ const createHydration = overrides.createHydration ?? ((table) => defaultCreateHydration(table, createHydrationPlanner));
3930
+ const createRelationService = overrides.createRelationService ?? ((table, state, hydration) => new RelationService(table, state, hydration, createQueryAstService));
3931
+ const createColumnSelector = overrides.createColumnSelector ?? ((env) => new ColumnSelector(env));
3932
+ const createRelationManager = overrides.createRelationManager ?? ((env) => new RelationManager(env));
3933
+ return {
3934
+ createState: overrides.createState ?? ((table) => new SelectQueryState(table)),
3935
+ createHydration,
3936
+ createHydrationPlanner,
3937
+ createQueryAstService,
3938
+ createRelationService,
3939
+ createColumnSelector,
3940
+ createRelationManager
3941
+ };
3942
+ };
3943
+ var defaultSelectQueryBuilderDependencies = resolveSelectQueryBuilderDependencies();
3944
+
3757
3945
  // src/orm/hydration.ts
3758
3946
  var hydrateRows = (rows, plan) => {
3759
3947
  if (!plan || !rows.length) return rows;
@@ -3879,6 +4067,18 @@ var hideInternal = (obj, keys) => {
3879
4067
  }
3880
4068
  };
3881
4069
  var DefaultHasManyCollection = class {
4070
+ /**
4071
+ * Creates a new DefaultHasManyCollection instance.
4072
+ * @param ctx - The entity context
4073
+ * @param meta - The entity metadata
4074
+ * @param root - The root entity
4075
+ * @param relationName - The relation name
4076
+ * @param relation - The relation definition
4077
+ * @param rootTable - The root table definition
4078
+ * @param loader - The loader function for lazy loading
4079
+ * @param createEntity - Function to create entities from rows
4080
+ * @param localKey - The local key for the relation
4081
+ */
3882
4082
  constructor(ctx, meta, root, relationName, relation, rootTable, loader, createEntity, localKey) {
3883
4083
  this.ctx = ctx;
3884
4084
  this.meta = meta;
@@ -3896,6 +4096,10 @@ var DefaultHasManyCollection = class {
3896
4096
  hideInternal(this, ["ctx", "meta", "root", "relationName", "relation", "rootTable", "loader", "createEntity", "localKey"]);
3897
4097
  this.hydrateFromCache();
3898
4098
  }
4099
+ /**
4100
+ * Loads the related entities if not already loaded.
4101
+ * @returns Promise resolving to the array of child entities
4102
+ */
3899
4103
  async load() {
3900
4104
  if (this.loaded) return this.items;
3901
4105
  const map = await this.loader();
@@ -3905,9 +4109,18 @@ var DefaultHasManyCollection = class {
3905
4109
  this.loaded = true;
3906
4110
  return this.items;
3907
4111
  }
4112
+ /**
4113
+ * Gets the current items in the collection.
4114
+ * @returns Array of child entities
4115
+ */
3908
4116
  getItems() {
3909
4117
  return this.items;
3910
4118
  }
4119
+ /**
4120
+ * Adds a new child entity to the collection.
4121
+ * @param data - Partial data for the new entity
4122
+ * @returns The created entity
4123
+ */
3911
4124
  add(data) {
3912
4125
  const keyValue = this.root[this.localKey];
3913
4126
  const childRow = {
@@ -3927,6 +4140,10 @@ var DefaultHasManyCollection = class {
3927
4140
  );
3928
4141
  return entity;
3929
4142
  }
4143
+ /**
4144
+ * Attaches an existing entity to the collection.
4145
+ * @param entity - The entity to attach
4146
+ */
3930
4147
  attach(entity) {
3931
4148
  const keyValue = this.root[this.localKey];
3932
4149
  entity[this.relation.foreignKey] = keyValue;
@@ -3941,6 +4158,10 @@ var DefaultHasManyCollection = class {
3941
4158
  { kind: "attach", entity }
3942
4159
  );
3943
4160
  }
4161
+ /**
4162
+ * Removes an entity from the collection.
4163
+ * @param entity - The entity to remove
4164
+ */
3944
4165
  remove(entity) {
3945
4166
  this.items = this.items.filter((item) => item !== entity);
3946
4167
  this.removed.add(entity);
@@ -3953,6 +4174,9 @@ var DefaultHasManyCollection = class {
3953
4174
  { kind: "remove", entity }
3954
4175
  );
3955
4176
  }
4177
+ /**
4178
+ * Clears all entities from the collection.
4179
+ */
3956
4180
  clear() {
3957
4181
  for (const entity of [...this.items]) {
3958
4182
  this.remove(entity);
@@ -3969,6 +4193,10 @@ var DefaultHasManyCollection = class {
3969
4193
  this.items = rows.map((row) => this.createEntity(row));
3970
4194
  this.loaded = true;
3971
4195
  }
4196
+ /**
4197
+ * Returns the items for JSON serialization.
4198
+ * @returns Array of child entities
4199
+ */
3972
4200
  toJSON() {
3973
4201
  return this.items;
3974
4202
  }
@@ -4264,7 +4492,6 @@ var DefaultManyToManyCollection = class {
4264
4492
  }
4265
4493
  async syncByIds(ids) {
4266
4494
  await this.load();
4267
- const targetKey = this.relation.targetKey || findPrimaryKey(this.relation.target);
4268
4495
  const normalized = new Set(ids.map((id) => toKey5(id)));
4269
4496
  const currentIds = new Set(this.items.map((item) => toKey5(this.extractId(item))));
4270
4497
  for (const id of normalized) {
@@ -4345,112 +4572,92 @@ var executeQuery = async (ctx, qb) => {
4345
4572
  return rowsFromResults(results);
4346
4573
  };
4347
4574
  var toKey6 = (value) => value === null || value === void 0 ? "" : String(value);
4348
- var loadHasManyRelation = async (ctx, rootTable, _relationName, relation) => {
4349
- const localKey = relation.localKey || findPrimaryKey(rootTable);
4350
- const roots = ctx.getEntitiesForTable(rootTable);
4351
- const keys = /* @__PURE__ */ new Set();
4575
+ var collectKeysFromRoots = (roots, key) => {
4576
+ const collected = /* @__PURE__ */ new Set();
4352
4577
  for (const tracked of roots) {
4353
- const value = tracked.entity[localKey];
4578
+ const value = tracked.entity[key];
4354
4579
  if (value !== null && value !== void 0) {
4355
- keys.add(value);
4580
+ collected.add(value);
4356
4581
  }
4357
4582
  }
4358
- if (!keys.size) {
4359
- return /* @__PURE__ */ new Map();
4360
- }
4361
- const selectMap = selectAllColumns(relation.target);
4362
- const fb = new SelectQueryBuilder(relation.target).select(selectMap);
4363
- const fkColumn = relation.target.columns[relation.foreignKey];
4364
- if (!fkColumn) return /* @__PURE__ */ new Map();
4365
- fb.where(inList(fkColumn, Array.from(keys)));
4366
- const rows = await executeQuery(ctx, fb);
4583
+ return collected;
4584
+ };
4585
+ var buildInListValues = (keys) => Array.from(keys);
4586
+ var fetchRowsForKeys = async (ctx, table, column, keys) => {
4587
+ const qb = new SelectQueryBuilder(table).select(selectAllColumns(table));
4588
+ qb.where(inList(column, buildInListValues(keys)));
4589
+ return executeQuery(ctx, qb);
4590
+ };
4591
+ var groupRowsByMany = (rows, keyColumn) => {
4367
4592
  const grouped = /* @__PURE__ */ new Map();
4368
4593
  for (const row of rows) {
4369
- const fkValue = row[relation.foreignKey];
4370
- if (fkValue === null || fkValue === void 0) continue;
4371
- const key = toKey6(fkValue);
4594
+ const value = row[keyColumn];
4595
+ if (value === null || value === void 0) continue;
4596
+ const key = toKey6(value);
4372
4597
  const bucket = grouped.get(key) ?? [];
4373
4598
  bucket.push(row);
4374
4599
  grouped.set(key, bucket);
4375
4600
  }
4376
4601
  return grouped;
4377
4602
  };
4378
- var loadHasOneRelation = async (ctx, rootTable, _relationName, relation) => {
4379
- const localKey = relation.localKey || findPrimaryKey(rootTable);
4380
- const roots = ctx.getEntitiesForTable(rootTable);
4381
- const keys = /* @__PURE__ */ new Set();
4382
- for (const tracked of roots) {
4383
- const value = tracked.entity[localKey];
4384
- if (value !== null && value !== void 0) {
4385
- keys.add(value);
4603
+ var groupRowsByUnique = (rows, keyColumn) => {
4604
+ const lookup = /* @__PURE__ */ new Map();
4605
+ for (const row of rows) {
4606
+ const value = row[keyColumn];
4607
+ if (value === null || value === void 0) continue;
4608
+ const key = toKey6(value);
4609
+ if (!lookup.has(key)) {
4610
+ lookup.set(key, row);
4386
4611
  }
4387
4612
  }
4613
+ return lookup;
4614
+ };
4615
+ var loadHasManyRelation = async (ctx, rootTable, _relationName, relation) => {
4616
+ const localKey = relation.localKey || findPrimaryKey(rootTable);
4617
+ const roots = ctx.getEntitiesForTable(rootTable);
4618
+ const keys = collectKeysFromRoots(roots, localKey);
4388
4619
  if (!keys.size) {
4389
4620
  return /* @__PURE__ */ new Map();
4390
4621
  }
4391
- const selectMap = selectAllColumns(relation.target);
4392
- const qb = new SelectQueryBuilder(relation.target).select(selectMap);
4393
4622
  const fkColumn = relation.target.columns[relation.foreignKey];
4394
4623
  if (!fkColumn) return /* @__PURE__ */ new Map();
4395
- qb.where(inList(fkColumn, Array.from(keys)));
4396
- const rows = await executeQuery(ctx, qb);
4397
- const lookup = /* @__PURE__ */ new Map();
4398
- for (const row of rows) {
4399
- const fkValue = row[relation.foreignKey];
4400
- if (fkValue === null || fkValue === void 0) continue;
4401
- const key = toKey6(fkValue);
4402
- if (!lookup.has(key)) {
4403
- lookup.set(key, row);
4404
- }
4624
+ const rows = await fetchRowsForKeys(ctx, relation.target, fkColumn, keys);
4625
+ return groupRowsByMany(rows, relation.foreignKey);
4626
+ };
4627
+ var loadHasOneRelation = async (ctx, rootTable, _relationName, relation) => {
4628
+ const localKey = relation.localKey || findPrimaryKey(rootTable);
4629
+ const roots = ctx.getEntitiesForTable(rootTable);
4630
+ const keys = collectKeysFromRoots(roots, localKey);
4631
+ if (!keys.size) {
4632
+ return /* @__PURE__ */ new Map();
4405
4633
  }
4406
- return lookup;
4634
+ const fkColumn = relation.target.columns[relation.foreignKey];
4635
+ if (!fkColumn) return /* @__PURE__ */ new Map();
4636
+ const rows = await fetchRowsForKeys(ctx, relation.target, fkColumn, keys);
4637
+ return groupRowsByUnique(rows, relation.foreignKey);
4407
4638
  };
4408
4639
  var loadBelongsToRelation = async (ctx, rootTable, _relationName, relation) => {
4409
4640
  const roots = ctx.getEntitiesForTable(rootTable);
4410
- const foreignKeys = /* @__PURE__ */ new Set();
4411
- for (const tracked of roots) {
4412
- const value = tracked.entity[relation.foreignKey];
4413
- if (value !== null && value !== void 0) {
4414
- foreignKeys.add(value);
4415
- }
4416
- }
4641
+ const foreignKeys = collectKeysFromRoots(roots, relation.foreignKey);
4417
4642
  if (!foreignKeys.size) {
4418
4643
  return /* @__PURE__ */ new Map();
4419
4644
  }
4420
- const selectMap = selectAllColumns(relation.target);
4421
- const qb = new SelectQueryBuilder(relation.target).select(selectMap);
4422
4645
  const targetKey = relation.localKey || findPrimaryKey(relation.target);
4423
4646
  const pkColumn = relation.target.columns[targetKey];
4424
4647
  if (!pkColumn) return /* @__PURE__ */ new Map();
4425
- qb.where(inList(pkColumn, Array.from(foreignKeys)));
4426
- const rows = await executeQuery(ctx, qb);
4427
- const map = /* @__PURE__ */ new Map();
4428
- for (const row of rows) {
4429
- const keyValue = row[targetKey];
4430
- if (keyValue === null || keyValue === void 0) continue;
4431
- map.set(toKey6(keyValue), row);
4432
- }
4433
- return map;
4648
+ const rows = await fetchRowsForKeys(ctx, relation.target, pkColumn, foreignKeys);
4649
+ return groupRowsByUnique(rows, targetKey);
4434
4650
  };
4435
4651
  var loadBelongsToManyRelation = async (ctx, rootTable, _relationName, relation) => {
4436
4652
  const rootKey = relation.localKey || findPrimaryKey(rootTable);
4437
4653
  const roots = ctx.getEntitiesForTable(rootTable);
4438
- const rootIds = /* @__PURE__ */ new Set();
4439
- for (const tracked of roots) {
4440
- const value = tracked.entity[rootKey];
4441
- if (value !== null && value !== void 0) {
4442
- rootIds.add(value);
4443
- }
4444
- }
4654
+ const rootIds = collectKeysFromRoots(roots, rootKey);
4445
4655
  if (!rootIds.size) {
4446
4656
  return /* @__PURE__ */ new Map();
4447
4657
  }
4448
- const pivotSelect = selectAllColumns(relation.pivotTable);
4449
- const pivotQb = new SelectQueryBuilder(relation.pivotTable).select(pivotSelect);
4450
- const pivotFkCol = relation.pivotTable.columns[relation.pivotForeignKeyToRoot];
4451
- if (!pivotFkCol) return /* @__PURE__ */ new Map();
4452
- pivotQb.where(inList(pivotFkCol, Array.from(rootIds)));
4453
- const pivotRows = await executeQuery(ctx, pivotQb);
4658
+ const pivotColumn = relation.pivotTable.columns[relation.pivotForeignKeyToRoot];
4659
+ if (!pivotColumn) return /* @__PURE__ */ new Map();
4660
+ const pivotRows = await fetchRowsForKeys(ctx, relation.pivotTable, pivotColumn, rootIds);
4454
4661
  const rootLookup = /* @__PURE__ */ new Map();
4455
4662
  const targetIds = /* @__PURE__ */ new Set();
4456
4663
  for (const pivot of pivotRows) {
@@ -4470,19 +4677,11 @@ var loadBelongsToManyRelation = async (ctx, rootTable, _relationName, relation)
4470
4677
  if (!targetIds.size) {
4471
4678
  return /* @__PURE__ */ new Map();
4472
4679
  }
4473
- const targetSelect = selectAllColumns(relation.target);
4474
4680
  const targetKey = relation.targetKey || findPrimaryKey(relation.target);
4475
4681
  const targetPkColumn = relation.target.columns[targetKey];
4476
4682
  if (!targetPkColumn) return /* @__PURE__ */ new Map();
4477
- const targetQb = new SelectQueryBuilder(relation.target).select(targetSelect);
4478
- targetQb.where(inList(targetPkColumn, Array.from(targetIds)));
4479
- const targetRows = await executeQuery(ctx, targetQb);
4480
- const targetMap = /* @__PURE__ */ new Map();
4481
- for (const row of targetRows) {
4482
- const pkValue = row[targetKey];
4483
- if (pkValue === null || pkValue === void 0) continue;
4484
- targetMap.set(toKey6(pkValue), row);
4485
- }
4683
+ const targetRows = await fetchRowsForKeys(ctx, relation.target, targetPkColumn, targetIds);
4684
+ const targetMap = groupRowsByUnique(targetRows, targetKey);
4486
4685
  const result = /* @__PURE__ */ new Map();
4487
4686
  for (const [rootId, entries] of rootLookup.entries()) {
4488
4687
  const bucket = [];
@@ -4535,7 +4734,6 @@ var createEntityProxy = (ctx, table, row, lazyRelations = []) => {
4535
4734
  enumerable: false,
4536
4735
  writable: false
4537
4736
  });
4538
- let proxy;
4539
4737
  const handler = {
4540
4738
  get(targetObj, prop, receiver) {
4541
4739
  if (prop === ENTITY_META) {
@@ -4543,7 +4741,7 @@ var createEntityProxy = (ctx, table, row, lazyRelations = []) => {
4543
4741
  }
4544
4742
  if (prop === "$load") {
4545
4743
  return async (relationName) => {
4546
- const wrapper = getRelationWrapper(meta, relationName, proxy);
4744
+ const wrapper = getRelationWrapper(meta, relationName, receiver);
4547
4745
  if (wrapper && typeof wrapper.load === "function") {
4548
4746
  return wrapper.load();
4549
4747
  }
@@ -4551,19 +4749,19 @@ var createEntityProxy = (ctx, table, row, lazyRelations = []) => {
4551
4749
  };
4552
4750
  }
4553
4751
  if (typeof prop === "string" && table.relations[prop]) {
4554
- return getRelationWrapper(meta, prop, proxy);
4752
+ return getRelationWrapper(meta, prop, receiver);
4555
4753
  }
4556
4754
  return Reflect.get(targetObj, prop, receiver);
4557
4755
  },
4558
4756
  set(targetObj, prop, value, receiver) {
4559
4757
  const result = Reflect.set(targetObj, prop, value, receiver);
4560
4758
  if (typeof prop === "string" && table.columns[prop]) {
4561
- ctx.markDirty(proxy);
4759
+ ctx.markDirty(receiver);
4562
4760
  }
4563
4761
  return result;
4564
4762
  }
4565
4763
  };
4566
- proxy = new Proxy(target, handler);
4764
+ const proxy = new Proxy(target, handler);
4567
4765
  populateHydrationCache(proxy, row, meta);
4568
4766
  return proxy;
4569
4767
  };
@@ -4760,21 +4958,21 @@ async function executeHydratedWithContexts(_execCtx, hydCtx, qb) {
4760
4958
  return executeWithEntityContext(entityCtx, qb);
4761
4959
  }
4762
4960
 
4961
+ // src/query-builder/query-resolution.ts
4962
+ function resolveSelectQuery(query) {
4963
+ const candidate = query;
4964
+ return typeof candidate.getAST === "function" && candidate.getAST ? candidate.getAST() : query;
4965
+ }
4966
+
4763
4967
  // src/query-builder/select.ts
4764
4968
  var SelectQueryBuilder = class _SelectQueryBuilder {
4765
4969
  /**
4766
-
4767
- * Creates a new SelectQueryBuilder instance
4768
-
4769
- * @param table - Table definition to query
4770
-
4771
- * @param state - Optional initial query state
4772
-
4773
- * @param hydration - Optional hydration manager
4774
-
4775
- * @param dependencies - Optional query builder dependencies
4776
-
4777
- */
4970
+ * Creates a new SelectQueryBuilder instance
4971
+ * @param table - Table definition to query
4972
+ * @param state - Optional initial query state
4973
+ * @param hydration - Optional hydration manager
4974
+ * @param dependencies - Optional query builder dependencies
4975
+ */
4778
4976
  constructor(table, state, hydration, dependencies, lazyRelations) {
4779
4977
  const deps = resolveSelectQueryBuilderDependencies(dependencies);
4780
4978
  this.env = { table, deps };
@@ -4785,9 +4983,15 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4785
4983
  hydration: initialHydration
4786
4984
  };
4787
4985
  this.lazyRelations = new Set(lazyRelations ?? []);
4788
- this.columnSelector = new ColumnSelector(this.env);
4789
- this.relationManager = new RelationManager(this.env);
4986
+ this.columnSelector = deps.createColumnSelector(this.env);
4987
+ this.relationManager = deps.createRelationManager(this.env);
4790
4988
  }
4989
+ /**
4990
+ * Creates a new SelectQueryBuilder instance with updated context and lazy relations
4991
+ * @param context - Updated query context
4992
+ * @param lazyRelations - Updated lazy relations set
4993
+ * @returns New SelectQueryBuilder instance
4994
+ */
4791
4995
  clone(context = this.context, lazyRelations = new Set(this.lazyRelations)) {
4792
4996
  return new _SelectQueryBuilder(this.env.table, context.state, context.hydration, this.env.deps, lazyRelations);
4793
4997
  }
@@ -4804,9 +5008,12 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4804
5008
  const nextContext = this.applyAst(this.context, (service) => service.withFrom(nextFrom));
4805
5009
  return this.clone(nextContext);
4806
5010
  }
4807
- resolveQueryNode(query) {
4808
- return typeof query.getAST === "function" ? query.getAST() : query;
4809
- }
5011
+ /**
5012
+ * Applies correlation expression to the query AST
5013
+ * @param ast - Query AST to modify
5014
+ * @param correlation - Correlation expression
5015
+ * @returns Modified AST with correlation applied
5016
+ */
4810
5017
  applyCorrelation(ast, correlation) {
4811
5018
  if (!correlation) return ast;
4812
5019
  const combinedWhere = ast.where ? and(correlation, ast.where) : correlation;
@@ -4815,39 +5022,53 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4815
5022
  where: combinedWhere
4816
5023
  };
4817
5024
  }
5025
+ /**
5026
+ * Creates a new child query builder for a related table
5027
+ * @param table - Table definition for the child builder
5028
+ * @returns New SelectQueryBuilder instance for the child table
5029
+ */
4818
5030
  createChildBuilder(table) {
4819
5031
  return new _SelectQueryBuilder(table, void 0, void 0, this.env.deps);
4820
5032
  }
5033
+ /**
5034
+ * Applies an AST mutation using the query AST service
5035
+ * @param context - Current query context
5036
+ * @param mutator - Function that mutates the AST
5037
+ * @returns Updated query context
5038
+ */
4821
5039
  applyAst(context, mutator) {
4822
5040
  const astService = this.env.deps.createQueryAstService(this.env.table, context.state);
4823
5041
  const nextState = mutator(astService);
4824
5042
  return { state: nextState, hydration: context.hydration };
4825
5043
  }
5044
+ /**
5045
+ * Applies a join to the query context
5046
+ * @param context - Current query context
5047
+ * @param table - Table to join
5048
+ * @param condition - Join condition
5049
+ * @param kind - Join kind
5050
+ * @returns Updated query context with join applied
5051
+ */
4826
5052
  applyJoin(context, table, condition, kind) {
4827
- const joinNode = createJoinNode(kind, table.name, condition);
5053
+ const joinNode = createJoinNode(kind, { type: "Table", name: table.name, schema: table.schema }, condition);
4828
5054
  return this.applyAst(context, (service) => service.withJoin(joinNode));
4829
5055
  }
5056
+ /**
5057
+ * Applies a set operation to the query
5058
+ * @param operator - Set operation kind
5059
+ * @param query - Query to combine with
5060
+ * @returns Updated query context with set operation
5061
+ */
4830
5062
  applySetOperation(operator, query) {
4831
- const subAst = this.resolveQueryNode(query);
5063
+ const subAst = resolveSelectQuery(query);
4832
5064
  return this.applyAst(this.context, (service) => service.withSetOperation(operator, subAst));
4833
5065
  }
4834
- /**
4835
-
4836
- * Selects specific columns for the query
4837
-
4838
- * @param columns - Record of column definitions, function nodes, case expressions, or window functions
4839
-
4840
- * @returns New query builder instance with selected columns
4841
-
4842
- */
4843
- select(columns) {
4844
- return this.clone(this.columnSelector.select(this.context, columns));
4845
- }
4846
- /**
4847
- * Selects columns from the root table by name (typed).
4848
- * @param cols - Column names on the root table
4849
- */
4850
- selectColumns(...cols) {
5066
+ select(...args) {
5067
+ if (args.length === 1 && typeof args[0] === "object" && args[0] !== null && typeof args[0] !== "string") {
5068
+ const columns = args[0];
5069
+ return this.clone(this.columnSelector.select(this.context, columns));
5070
+ }
5071
+ const cols = args;
4851
5072
  const selection = {};
4852
5073
  for (const key of cols) {
4853
5074
  const col2 = this.env.table.columns[key];
@@ -4856,53 +5077,37 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4856
5077
  }
4857
5078
  selection[key] = col2;
4858
5079
  }
4859
- return this.select(selection);
5080
+ return this.clone(this.columnSelector.select(this.context, selection));
4860
5081
  }
4861
5082
  /**
4862
-
4863
- * Selects raw column expressions
4864
-
4865
- * @param cols - Column expressions as strings
4866
-
4867
- * @returns New query builder instance with raw column selections
4868
-
4869
- */
5083
+ * Selects raw column expressions
5084
+ * @param cols - Column expressions as strings
5085
+ * @returns New query builder instance with raw column selections
5086
+ */
4870
5087
  selectRaw(...cols) {
4871
5088
  return this.clone(this.columnSelector.selectRaw(this.context, cols));
4872
5089
  }
4873
5090
  /**
4874
-
4875
- * Adds a Common Table Expression (CTE) to the query
4876
-
4877
- * @param name - Name of the CTE
4878
-
4879
- * @param query - Query builder or query node for the CTE
4880
-
4881
- * @param columns - Optional column names for the CTE
4882
-
4883
- * @returns New query builder instance with the CTE
4884
-
4885
- */
5091
+ * Adds a Common Table Expression (CTE) to the query
5092
+ * @param name - Name of the CTE
5093
+ * @param query - Query builder or query node for the CTE
5094
+ * @param columns - Optional column names for the CTE
5095
+ * @returns New query builder instance with the CTE
5096
+ */
4886
5097
  with(name, query, columns) {
4887
- const subAst = this.resolveQueryNode(query);
5098
+ const subAst = resolveSelectQuery(query);
4888
5099
  const nextContext = this.applyAst(this.context, (service) => service.withCte(name, subAst, columns, false));
4889
5100
  return this.clone(nextContext);
4890
5101
  }
4891
5102
  /**
4892
-
4893
- * Adds a recursive Common Table Expression (CTE) to the query
4894
-
4895
- * @param name - Name of the CTE
4896
-
4897
- * @param query - Query builder or query node for the CTE
4898
-
4899
- * @param columns - Optional column names for the CTE
4900
-
4901
- * @returns New query builder instance with the recursive CTE
4902
-
4903
- */
5103
+ * Adds a recursive Common Table Expression (CTE) to the query
5104
+ * @param name - Name of the CTE
5105
+ * @param query - Query builder or query node for the CTE
5106
+ * @param columns - Optional column names for the CTE
5107
+ * @returns New query builder instance with the recursive CTE
5108
+ */
4904
5109
  withRecursive(name, query, columns) {
4905
- const subAst = this.resolveQueryNode(query);
5110
+ const subAst = resolveSelectQuery(query);
4906
5111
  const nextContext = this.applyAst(this.context, (service) => service.withCte(name, subAst, columns, true));
4907
5112
  return this.clone(nextContext);
4908
5113
  }
@@ -4914,24 +5119,31 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4914
5119
  * @returns New query builder instance with updated FROM
4915
5120
  */
4916
5121
  fromSubquery(subquery, alias, columnAliases) {
4917
- const subAst = this.resolveQueryNode(subquery);
5122
+ const subAst = resolveSelectQuery(subquery);
4918
5123
  const fromNode = derivedTable(subAst, alias, columnAliases);
4919
5124
  const nextContext = this.applyAst(this.context, (service) => service.withFrom(fromNode));
4920
5125
  return this.clone(nextContext);
4921
5126
  }
4922
5127
  /**
4923
-
4924
- * Selects a subquery as a column
4925
-
4926
- * @param alias - Alias for the subquery column
4927
-
4928
- * @param sub - Query builder or query node for the subquery
4929
-
4930
- * @returns New query builder instance with the subquery selection
4931
-
4932
- */
5128
+ * Replaces the FROM clause with a function table expression.
5129
+ * @param name - Function name
5130
+ * @param args - Optional function arguments
5131
+ * @param alias - Optional alias for the function table
5132
+ * @param options - Optional function-table metadata (lateral, ordinality, column aliases, schema)
5133
+ */
5134
+ fromFunctionTable(name, args = [], alias, options) {
5135
+ const functionTable = fnTable(name, args, alias, options);
5136
+ const nextContext = this.applyAst(this.context, (service) => service.withFrom(functionTable));
5137
+ return this.clone(nextContext);
5138
+ }
5139
+ /**
5140
+ * Selects a subquery as a column
5141
+ * @param alias - Alias for the subquery column
5142
+ * @param sub - Query builder or query node for the subquery
5143
+ * @returns New query builder instance with the subquery selection
5144
+ */
4933
5145
  selectSubquery(alias, sub2) {
4934
- const query = this.resolveQueryNode(sub2);
5146
+ const query = resolveSelectQuery(sub2);
4935
5147
  return this.clone(this.columnSelector.selectSubquery(this.context, alias, query));
4936
5148
  }
4937
5149
  /**
@@ -4944,103 +5156,92 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4944
5156
  * @returns New query builder instance with the derived-table join
4945
5157
  */
4946
5158
  joinSubquery(subquery, alias, condition, joinKind = JOIN_KINDS.INNER, columnAliases) {
4947
- const subAst = this.resolveQueryNode(subquery);
5159
+ const subAst = resolveSelectQuery(subquery);
4948
5160
  const joinNode = createJoinNode(joinKind, derivedTable(subAst, alias, columnAliases), condition);
4949
5161
  const nextContext = this.applyAst(this.context, (service) => service.withJoin(joinNode));
4950
5162
  return this.clone(nextContext);
4951
5163
  }
4952
5164
  /**
4953
-
4954
- * Adds an INNER JOIN to the query
4955
-
4956
- * @param table - Table to join
4957
-
4958
- * @param condition - Join condition expression
4959
-
4960
- * @returns New query builder instance with the INNER JOIN
4961
-
4962
- */
5165
+ * Adds a join against a function table (e.g., `generate_series`) using `fnTable` internally.
5166
+ * @param name - Function name
5167
+ * @param args - Optional arguments passed to the function
5168
+ * @param alias - Alias for the function table so columns can be referenced
5169
+ * @param condition - Join condition expression
5170
+ * @param joinKind - Kind of join (defaults to INNER)
5171
+ * @param options - Optional metadata (lateral, ordinality, column aliases, schema)
5172
+ */
5173
+ joinFunctionTable(name, args = [], alias, condition, joinKind = JOIN_KINDS.INNER, options) {
5174
+ const functionTable = fnTable(name, args, alias, options);
5175
+ const joinNode = createJoinNode(joinKind, functionTable, condition);
5176
+ const nextContext = this.applyAst(this.context, (service) => service.withJoin(joinNode));
5177
+ return this.clone(nextContext);
5178
+ }
5179
+ /**
5180
+ * Adds an INNER JOIN to the query
5181
+ * @param table - Table to join
5182
+ * @param condition - Join condition expression
5183
+ * @returns New query builder instance with the INNER JOIN
5184
+ */
4963
5185
  innerJoin(table, condition) {
4964
5186
  const nextContext = this.applyJoin(this.context, table, condition, JOIN_KINDS.INNER);
4965
5187
  return this.clone(nextContext);
4966
5188
  }
4967
5189
  /**
4968
-
4969
- * Adds a LEFT JOIN to the query
4970
-
4971
- * @param table - Table to join
4972
-
4973
- * @param condition - Join condition expression
4974
-
4975
- * @returns New query builder instance with the LEFT JOIN
4976
-
4977
- */
5190
+ * Adds a LEFT JOIN to the query
5191
+ * @param table - Table to join
5192
+ * @param condition - Join condition expression
5193
+ * @returns New query builder instance with the LEFT JOIN
5194
+ */
4978
5195
  leftJoin(table, condition) {
4979
5196
  const nextContext = this.applyJoin(this.context, table, condition, JOIN_KINDS.LEFT);
4980
5197
  return this.clone(nextContext);
4981
5198
  }
4982
5199
  /**
4983
-
4984
- * Adds a RIGHT JOIN to the query
4985
-
4986
- * @param table - Table to join
4987
-
4988
- * @param condition - Join condition expression
4989
-
4990
- * @returns New query builder instance with the RIGHT JOIN
4991
-
4992
- */
5200
+ * Adds a RIGHT JOIN to the query
5201
+ * @param table - Table to join
5202
+ * @param condition - Join condition expression
5203
+ * @returns New query builder instance with the RIGHT JOIN
5204
+ */
4993
5205
  rightJoin(table, condition) {
4994
5206
  const nextContext = this.applyJoin(this.context, table, condition, JOIN_KINDS.RIGHT);
4995
5207
  return this.clone(nextContext);
4996
5208
  }
4997
5209
  /**
4998
-
4999
- * Matches records based on a relationship
5000
-
5001
- * @param relationName - Name of the relationship to match
5002
-
5003
- * @param predicate - Optional predicate expression
5004
-
5005
- * @returns New query builder instance with the relationship match
5006
-
5007
- */
5210
+ * Matches records based on a relationship
5211
+ * @param relationName - Name of the relationship to match
5212
+ * @param predicate - Optional predicate expression
5213
+ * @returns New query builder instance with the relationship match
5214
+ */
5008
5215
  match(relationName, predicate) {
5009
5216
  const nextContext = this.relationManager.match(this.context, relationName, predicate);
5010
5217
  return this.clone(nextContext);
5011
5218
  }
5012
5219
  /**
5013
-
5014
- * Joins a related table
5015
-
5016
- * @param relationName - Name of the relationship to join
5017
-
5018
- * @param joinKind - Type of join (defaults to INNER)
5019
-
5020
- * @param extraCondition - Optional additional join condition
5021
-
5022
- * @returns New query builder instance with the relationship join
5023
-
5024
- */
5220
+ * Joins a related table
5221
+ * @param relationName - Name of the relationship to join
5222
+ * @param joinKind - Type of join (defaults to INNER)
5223
+ * @param extraCondition - Optional additional join condition
5224
+ * @returns New query builder instance with the relationship join
5225
+ */
5025
5226
  joinRelation(relationName, joinKind = JOIN_KINDS.INNER, extraCondition) {
5026
5227
  const nextContext = this.relationManager.joinRelation(this.context, relationName, joinKind, extraCondition);
5027
5228
  return this.clone(nextContext);
5028
5229
  }
5029
5230
  /**
5030
-
5031
- * Includes related data in the query results
5032
-
5033
- * @param relationName - Name of the relationship to include
5034
-
5035
- * @param options - Optional include options
5036
-
5037
- * @returns New query builder instance with the relationship inclusion
5038
-
5039
- */
5231
+ * Includes related data in the query results
5232
+ * @param relationName - Name of the relationship to include
5233
+ * @param options - Optional include options
5234
+ * @returns New query builder instance with the relationship inclusion
5235
+ */
5040
5236
  include(relationName, options) {
5041
5237
  const nextContext = this.relationManager.include(this.context, relationName, options);
5042
5238
  return this.clone(nextContext);
5043
5239
  }
5240
+ /**
5241
+ * Includes a relation lazily in the query results
5242
+ * @param relationName - Name of the relation to include lazily
5243
+ * @returns New query builder instance with lazy relation inclusion
5244
+ */
5044
5245
  includeLazy(relationName) {
5045
5246
  const nextLazy = new Set(this.lazyRelations);
5046
5247
  nextLazy.add(relationName);
@@ -5071,43 +5272,57 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
5071
5272
  return this.selectRelationColumns(relationName, ...cols);
5072
5273
  }
5073
5274
  /**
5074
- * Selects columns for the root table and relations from a single config object.
5275
+ * Selects columns for the root table and relations from an array of entries
5276
+ * @param config - Configuration array for deep column selection
5277
+ * @returns New query builder instance with deep column selections
5075
5278
  */
5076
5279
  selectColumnsDeep(config) {
5077
- let qb = this;
5078
- if (config.root?.length) {
5079
- qb = qb.selectColumns(...config.root);
5080
- }
5081
- for (const key of Object.keys(config)) {
5082
- if (key === "root") continue;
5083
- const relName = key;
5084
- const cols = config[relName];
5085
- if (!cols || !cols.length) continue;
5086
- qb = qb.selectRelationColumns(relName, ...cols);
5280
+ let currBuilder = this;
5281
+ for (const entry of config) {
5282
+ if (entry.type === "root") {
5283
+ currBuilder = currBuilder.select(...entry.columns);
5284
+ } else {
5285
+ currBuilder = currBuilder.selectRelationColumns(entry.relationName, ...entry.columns);
5286
+ }
5087
5287
  }
5088
- return qb;
5288
+ return currBuilder;
5089
5289
  }
5290
+ /**
5291
+ * Gets the list of lazy relations
5292
+ * @returns Array of lazy relation names
5293
+ */
5090
5294
  getLazyRelations() {
5091
5295
  return Array.from(this.lazyRelations);
5092
5296
  }
5297
+ /**
5298
+ * Gets the table definition for this query builder
5299
+ * @returns Table definition
5300
+ */
5093
5301
  getTable() {
5094
5302
  return this.env.table;
5095
5303
  }
5304
+ /**
5305
+ * Executes the query and returns hydrated results
5306
+ * @param ctx - ORM session context
5307
+ * @returns Promise of entity instances
5308
+ */
5096
5309
  async execute(ctx) {
5097
5310
  return executeHydrated(ctx, this);
5098
5311
  }
5312
+ /**
5313
+ * Executes the query with provided execution and hydration contexts
5314
+ * @param execCtx - Execution context
5315
+ * @param hydCtx - Hydration context
5316
+ * @returns Promise of entity instances
5317
+ */
5099
5318
  async executeWithContexts(execCtx, hydCtx) {
5100
5319
  return executeHydratedWithContexts(execCtx, hydCtx, this);
5101
5320
  }
5102
5321
  /**
5103
-
5104
- * Adds a WHERE condition to the query
5105
-
5106
- * @param expr - Expression for the WHERE clause
5107
-
5108
- * @returns New query builder instance with the WHERE condition
5109
-
5110
- */
5322
+ * Adds a WHERE condition to the query
5323
+ * @param expr - Expression for the WHERE clause
5324
+ * @returns New query builder instance with the WHERE condition
5325
+ */
5111
5326
  where(expr) {
5112
5327
  const nextContext = this.applyAst(this.context, (service) => service.withWhere(expr));
5113
5328
  return this.clone(nextContext);
@@ -5122,14 +5337,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
5122
5337
  return this.clone(nextContext);
5123
5338
  }
5124
5339
  /**
5125
-
5126
- * Adds a HAVING condition to the query
5127
-
5128
- * @param expr - Expression for the HAVING clause
5129
-
5130
- * @returns New query builder instance with the HAVING condition
5131
-
5132
- */
5340
+ * Adds a HAVING condition to the query
5341
+ * @param expr - Expression for the HAVING clause
5342
+ * @returns New query builder instance with the HAVING condition
5343
+ */
5133
5344
  having(expr) {
5134
5345
  const nextContext = this.applyAst(this.context, (service) => service.withHaving(expr));
5135
5346
  return this.clone(nextContext);
@@ -5150,130 +5361,89 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
5150
5361
  return this.clone(nextContext);
5151
5362
  }
5152
5363
  /**
5153
-
5154
- * Adds a DISTINCT clause to the query
5155
-
5156
- * @param cols - Columns to make distinct
5157
-
5158
- * @returns New query builder instance with the DISTINCT clause
5159
-
5160
- */
5364
+ * Adds a DISTINCT clause to the query
5365
+ * @param cols - Columns to make distinct
5366
+ * @returns New query builder instance with the DISTINCT clause
5367
+ */
5161
5368
  distinct(...cols) {
5162
5369
  return this.clone(this.columnSelector.distinct(this.context, cols));
5163
5370
  }
5164
5371
  /**
5165
-
5166
- * Adds a LIMIT clause to the query
5167
-
5168
- * @param n - Maximum number of rows to return
5169
-
5170
- * @returns New query builder instance with the LIMIT clause
5171
-
5172
- */
5372
+ * Adds a LIMIT clause to the query
5373
+ * @param n - Maximum number of rows to return
5374
+ * @returns New query builder instance with the LIMIT clause
5375
+ */
5173
5376
  limit(n) {
5174
5377
  const nextContext = this.applyAst(this.context, (service) => service.withLimit(n));
5175
5378
  return this.clone(nextContext);
5176
5379
  }
5177
5380
  /**
5178
-
5179
- * Adds an OFFSET clause to the query
5180
-
5181
- * @param n - Number of rows to skip
5182
-
5183
- * @returns New query builder instance with the OFFSET clause
5184
-
5185
- */
5381
+ * Adds an OFFSET clause to the query
5382
+ * @param n - Number of rows to skip
5383
+ * @returns New query builder instance with the OFFSET clause
5384
+ */
5186
5385
  offset(n) {
5187
5386
  const nextContext = this.applyAst(this.context, (service) => service.withOffset(n));
5188
5387
  return this.clone(nextContext);
5189
5388
  }
5190
5389
  /**
5191
-
5192
- * Combines this query with another using UNION
5193
-
5194
- * @param query - Query to union with
5195
-
5196
- * @returns New query builder instance with the set operation
5197
-
5198
- */
5390
+ * Combines this query with another using UNION
5391
+ * @param query - Query to union with
5392
+ * @returns New query builder instance with the set operation
5393
+ */
5199
5394
  union(query) {
5200
5395
  return this.clone(this.applySetOperation("UNION", query));
5201
5396
  }
5202
5397
  /**
5203
-
5204
- * Combines this query with another using UNION ALL
5205
-
5206
- * @param query - Query to union with
5207
-
5208
- * @returns New query builder instance with the set operation
5209
-
5210
- */
5398
+ * Combines this query with another using UNION ALL
5399
+ * @param query - Query to union with
5400
+ * @returns New query builder instance with the set operation
5401
+ */
5211
5402
  unionAll(query) {
5212
5403
  return this.clone(this.applySetOperation("UNION ALL", query));
5213
5404
  }
5214
5405
  /**
5215
-
5216
- * Combines this query with another using INTERSECT
5217
-
5218
- * @param query - Query to intersect with
5219
-
5220
- * @returns New query builder instance with the set operation
5221
-
5222
- */
5406
+ * Combines this query with another using INTERSECT
5407
+ * @param query - Query to intersect with
5408
+ * @returns New query builder instance with the set operation
5409
+ */
5223
5410
  intersect(query) {
5224
5411
  return this.clone(this.applySetOperation("INTERSECT", query));
5225
5412
  }
5226
5413
  /**
5227
-
5228
- * Combines this query with another using EXCEPT
5229
-
5230
- * @param query - Query to subtract
5231
-
5232
- * @returns New query builder instance with the set operation
5233
-
5234
- */
5414
+ * Combines this query with another using EXCEPT
5415
+ * @param query - Query to subtract
5416
+ * @returns New query builder instance with the set operation
5417
+ */
5235
5418
  except(query) {
5236
5419
  return this.clone(this.applySetOperation("EXCEPT", query));
5237
5420
  }
5238
5421
  /**
5239
-
5240
- * Adds a WHERE EXISTS condition to the query
5241
-
5242
- * @param subquery - Subquery to check for existence
5243
-
5244
- * @returns New query builder instance with the WHERE EXISTS condition
5245
-
5246
- */
5422
+ * Adds a WHERE EXISTS condition to the query
5423
+ * @param subquery - Subquery to check for existence
5424
+ * @returns New query builder instance with the WHERE EXISTS condition
5425
+ */
5247
5426
  whereExists(subquery, correlate) {
5248
- const subAst = this.resolveQueryNode(subquery);
5427
+ const subAst = resolveSelectQuery(subquery);
5249
5428
  const correlated = this.applyCorrelation(subAst, correlate);
5250
5429
  return this.where(exists(correlated));
5251
5430
  }
5252
5431
  /**
5253
-
5254
- * Adds a WHERE NOT EXISTS condition to the query
5255
-
5256
- * @param subquery - Subquery to check for non-existence
5257
-
5258
- * @returns New query builder instance with the WHERE NOT EXISTS condition
5259
-
5260
- */
5432
+ * Adds a WHERE NOT EXISTS condition to the query
5433
+ * @param subquery - Subquery to check for non-existence
5434
+ * @returns New query builder instance with the WHERE NOT EXISTS condition
5435
+ */
5261
5436
  whereNotExists(subquery, correlate) {
5262
- const subAst = this.resolveQueryNode(subquery);
5437
+ const subAst = resolveSelectQuery(subquery);
5263
5438
  const correlated = this.applyCorrelation(subAst, correlate);
5264
5439
  return this.where(notExists(correlated));
5265
5440
  }
5266
5441
  /**
5267
-
5268
- * Adds a WHERE EXISTS condition based on a relationship
5269
-
5270
- * @param relationName - Name of the relationship to check
5271
-
5272
- * @param callback - Optional callback to modify the relationship query
5273
-
5274
- * @returns New query builder instance with the relationship existence check
5275
-
5276
- */
5442
+ * Adds a WHERE EXISTS condition based on a relationship
5443
+ * @param relationName - Name of the relationship to check
5444
+ * @param callback - Optional callback to modify the relationship query
5445
+ * @returns New query builder instance with the relationship existence check
5446
+ */
5277
5447
  whereHas(relationName, callbackOrOptions, maybeOptions) {
5278
5448
  const relation = this.env.table.relations[relationName];
5279
5449
  if (!relation) {
@@ -5290,16 +5460,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
5290
5460
  return this.where(exists(finalSubAst));
5291
5461
  }
5292
5462
  /**
5293
-
5294
- * Adds a WHERE NOT EXISTS condition based on a relationship
5295
-
5296
- * @param relationName - Name of the relationship to check
5297
-
5298
- * @param callback - Optional callback to modify the relationship query
5299
-
5300
- * @returns New query builder instance with the relationship non-existence check
5301
-
5302
- */
5463
+ * Adds a WHERE NOT EXISTS condition based on a relationship
5464
+ * @param relationName - Name of the relationship to check
5465
+ * @param callback - Optional callback to modify the relationship query
5466
+ * @returns New query builder instance with the relationship non-existence check
5467
+ */
5303
5468
  whereHasNot(relationName, callbackOrOptions, maybeOptions) {
5304
5469
  const relation = this.env.table.relations[relationName];
5305
5470
  if (!relation) {
@@ -5316,53 +5481,61 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
5316
5481
  return this.where(notExists(finalSubAst));
5317
5482
  }
5318
5483
  /**
5319
-
5320
- * Compiles the query to SQL for a specific dialect
5321
-
5322
- * @param dialect - Database dialect to compile for
5323
-
5324
- * @returns Compiled query with SQL and parameters
5325
-
5326
- */
5484
+ * Compiles the query to SQL for a specific dialect
5485
+ * @param dialect - Database dialect to compile for
5486
+ * @returns Compiled query with SQL and parameters
5487
+ */
5327
5488
  compile(dialect) {
5328
5489
  const resolved = resolveDialectInput(dialect);
5329
- return resolved.compileSelect(this.context.state.ast);
5490
+ return resolved.compileSelect(this.getAST());
5330
5491
  }
5331
5492
  /**
5332
-
5333
- * Converts the query to SQL string for a specific dialect
5334
-
5335
- * @param dialect - Database dialect to generate SQL for
5336
-
5337
- * @returns SQL string representation of the query
5338
-
5339
- */
5493
+ * Converts the query to SQL string for a specific dialect
5494
+ * @param dialect - Database dialect to generate SQL for
5495
+ * @returns SQL string representation of the query
5496
+ */
5340
5497
  toSql(dialect) {
5341
5498
  return this.compile(dialect).sql;
5342
5499
  }
5343
5500
  /**
5344
-
5345
- * Gets the hydration plan for the query
5346
-
5347
- * @returns Hydration plan or undefined if none exists
5348
-
5349
- */
5501
+ * Gets the hydration plan for the query
5502
+ * @returns Hydration plan or undefined if none exists
5503
+ */
5350
5504
  getHydrationPlan() {
5351
5505
  return this.context.hydration.getPlan();
5352
5506
  }
5353
5507
  /**
5354
-
5355
- * Gets the Abstract Syntax Tree (AST) representation of the query
5356
-
5357
- * @returns Query AST with hydration applied
5358
-
5359
- */
5508
+ * Gets the Abstract Syntax Tree (AST) representation of the query
5509
+ * @returns Query AST with hydration applied
5510
+ */
5360
5511
  getAST() {
5361
5512
  return this.context.hydration.applyToAst(this.context.state.ast);
5362
5513
  }
5363
5514
  };
5364
- var createColumn = (table, name) => ({ type: "Column", table, name });
5365
- var createLiteral = (val) => ({ type: "Literal", value: val });
5515
+
5516
+ // src/schema/table-guards.ts
5517
+ var isColumnsRecord = (columns) => {
5518
+ return typeof columns === "object" && columns !== null;
5519
+ };
5520
+ var isRelationsRecord = (relations) => {
5521
+ return typeof relations === "object" && relations !== null;
5522
+ };
5523
+ var isTableDef = (value) => {
5524
+ if (typeof value !== "object" || value === null) {
5525
+ return false;
5526
+ }
5527
+ const candidate = value;
5528
+ if (typeof candidate.name !== "string") {
5529
+ return false;
5530
+ }
5531
+ if (!isColumnsRecord(candidate.columns)) {
5532
+ return false;
5533
+ }
5534
+ if (!isRelationsRecord(candidate.relations)) {
5535
+ return false;
5536
+ }
5537
+ return true;
5538
+ };
5366
5539
 
5367
5540
  // src/orm/entity-metadata.ts
5368
5541
  var metadataMap = /* @__PURE__ */ new Map();
@@ -5406,23 +5579,20 @@ var buildTableDef = (meta) => {
5406
5579
  if (meta.table) {
5407
5580
  return meta.table;
5408
5581
  }
5409
- const columns = Object.entries(meta.columns).reduce((acc, [key, def]) => {
5410
- acc[key] = {
5582
+ const columns = {};
5583
+ for (const [key, def] of Object.entries(meta.columns)) {
5584
+ columns[key] = {
5411
5585
  ...def,
5412
5586
  name: key,
5413
5587
  table: meta.tableName
5414
5588
  };
5415
- return acc;
5416
- }, {});
5589
+ }
5417
5590
  const table = defineTable(meta.tableName, columns, {}, meta.hooks);
5418
5591
  meta.table = table;
5419
5592
  return table;
5420
5593
  };
5421
5594
 
5422
5595
  // src/decorators/bootstrap.ts
5423
- var isTableDef = (value) => {
5424
- return typeof value === "object" && value !== null && "columns" in value;
5425
- };
5426
5596
  var unwrapTarget = (target) => {
5427
5597
  if (typeof target === "function" && target.prototype === void 0) {
5428
5598
  return target();
@@ -5520,6 +5690,13 @@ var selectFromEntity = (ctor) => {
5520
5690
  }
5521
5691
  return new SelectQueryBuilder(table);
5522
5692
  };
5693
+ var entityRef = (ctor) => {
5694
+ const table = getTableDefFromEntity(ctor);
5695
+ if (!table) {
5696
+ throw new Error(`Entity '${ctor.name}' is not registered with decorators or has not been bootstrapped`);
5697
+ }
5698
+ return tableRef(table);
5699
+ };
5523
5700
 
5524
5701
  // src/query-builder/select-helpers.ts
5525
5702
  function sel(table, ...cols) {
@@ -5551,6 +5728,11 @@ function esel(entity, ...props) {
5551
5728
 
5552
5729
  // src/query-builder/insert-query-state.ts
5553
5730
  var InsertQueryState = class _InsertQueryState {
5731
+ /**
5732
+ * Creates a new InsertQueryState instance
5733
+ * @param table - The table definition for the INSERT query
5734
+ * @param ast - Optional initial AST node, defaults to a basic INSERT query
5735
+ */
5554
5736
  constructor(table, ast) {
5555
5737
  this.table = table;
5556
5738
  this.ast = ast ?? {
@@ -5581,6 +5763,13 @@ var InsertQueryState = class _InsertQueryState {
5581
5763
  if (!names.length) return [];
5582
5764
  return buildColumnNodes(this.table, names);
5583
5765
  }
5766
+ /**
5767
+ * Adds VALUES clause to the INSERT query
5768
+ * @param rows - Array of row objects to insert
5769
+ * @returns A new InsertQueryState with the VALUES clause added
5770
+ * @throws Error if mixing VALUES with SELECT source
5771
+ * @throws Error if invalid values are provided
5772
+ */
5584
5773
  withValues(rows) {
5585
5774
  if (!rows.length) return this;
5586
5775
  if (this.ast.source.type === "InsertSelect") {
@@ -5607,6 +5796,11 @@ var InsertQueryState = class _InsertQueryState {
5607
5796
  }
5608
5797
  });
5609
5798
  }
5799
+ /**
5800
+ * Sets the columns for the INSERT query
5801
+ * @param columns - Column nodes to insert into
5802
+ * @returns A new InsertQueryState with the specified columns
5803
+ */
5610
5804
  withColumns(columns) {
5611
5805
  if (!columns.length) return this;
5612
5806
  return this.clone({
@@ -5614,6 +5808,14 @@ var InsertQueryState = class _InsertQueryState {
5614
5808
  columns: [...columns]
5615
5809
  });
5616
5810
  }
5811
+ /**
5812
+ * Adds SELECT source to the INSERT query
5813
+ * @param query - The SELECT query to use as source
5814
+ * @param columns - Target columns for the INSERT
5815
+ * @returns A new InsertQueryState with the SELECT source
5816
+ * @throws Error if mixing SELECT with VALUES source
5817
+ * @throws Error if no destination columns specified
5818
+ */
5617
5819
  withSelect(query, columns) {
5618
5820
  const targetColumns = columns.length ? columns : this.ast.columns.length ? this.ast.columns : this.getTableColumns();
5619
5821
  if (!targetColumns.length) {
@@ -5631,6 +5833,11 @@ var InsertQueryState = class _InsertQueryState {
5631
5833
  }
5632
5834
  });
5633
5835
  }
5836
+ /**
5837
+ * Adds a RETURNING clause to the INSERT query
5838
+ * @param columns - Columns to return after insertion
5839
+ * @returns A new InsertQueryState with the RETURNING clause added
5840
+ */
5634
5841
  withReturning(columns) {
5635
5842
  return this.clone({
5636
5843
  ...this.ast,
@@ -5641,6 +5848,11 @@ var InsertQueryState = class _InsertQueryState {
5641
5848
 
5642
5849
  // src/query-builder/insert.ts
5643
5850
  var InsertQueryBuilder = class _InsertQueryBuilder {
5851
+ /**
5852
+ * Creates a new InsertQueryBuilder instance
5853
+ * @param table - The table definition for the INSERT query
5854
+ * @param state - Optional initial query state, defaults to a new InsertQueryState
5855
+ */
5644
5856
  constructor(table, state) {
5645
5857
  this.table = table;
5646
5858
  this.state = state ?? new InsertQueryState(table);
@@ -5648,20 +5860,42 @@ var InsertQueryBuilder = class _InsertQueryBuilder {
5648
5860
  clone(state) {
5649
5861
  return new _InsertQueryBuilder(this.table, state);
5650
5862
  }
5863
+ /**
5864
+ * Adds VALUES to the INSERT query
5865
+ * @param rowOrRows - Single row object or array of row objects to insert
5866
+ * @returns A new InsertQueryBuilder with the VALUES clause added
5867
+ */
5651
5868
  values(rowOrRows) {
5652
5869
  const rows = Array.isArray(rowOrRows) ? rowOrRows : [rowOrRows];
5653
5870
  if (!rows.length) return this;
5654
5871
  return this.clone(this.state.withValues(rows));
5655
5872
  }
5873
+ /**
5874
+ * Specifies the columns for the INSERT query
5875
+ * @param columns - Column definitions or nodes to insert into
5876
+ * @returns A new InsertQueryBuilder with the specified columns
5877
+ */
5656
5878
  columns(...columns) {
5657
5879
  if (!columns.length) return this;
5658
5880
  return this.clone(this.state.withColumns(this.resolveColumnNodes(columns)));
5659
5881
  }
5882
+ /**
5883
+ * Sets the source of the INSERT query to a SELECT query
5884
+ * @template TSource - The source table type
5885
+ * @param query - The SELECT query or query builder to use as source
5886
+ * @param columns - Optional target columns for the INSERT
5887
+ * @returns A new InsertQueryBuilder with the SELECT source
5888
+ */
5660
5889
  fromSelect(query, columns = []) {
5661
5890
  const ast = this.resolveSelectQuery(query);
5662
5891
  const nodes = columns.length ? this.resolveColumnNodes(columns) : [];
5663
5892
  return this.clone(this.state.withSelect(ast, nodes));
5664
5893
  }
5894
+ /**
5895
+ * Adds a RETURNING clause to the INSERT query
5896
+ * @param columns - Columns to return after insertion
5897
+ * @returns A new InsertQueryBuilder with the RETURNING clause added
5898
+ */
5665
5899
  returning(...columns) {
5666
5900
  if (!columns.length) return this;
5667
5901
  const nodes = columns.map((column) => buildColumnNode(this.table, column));
@@ -5672,18 +5906,29 @@ var InsertQueryBuilder = class _InsertQueryBuilder {
5672
5906
  return columns.map((column) => buildColumnNode(this.table, column));
5673
5907
  }
5674
5908
  resolveSelectQuery(query) {
5675
- return typeof query.getAST === "function" ? query.getAST() : query;
5909
+ const candidate = query;
5910
+ return typeof candidate.getAST === "function" && candidate.getAST ? candidate.getAST() : query;
5676
5911
  }
5677
5912
  compile(arg) {
5678
- if (typeof arg.compileInsert === "function") {
5679
- return arg.compileInsert(this.state.ast);
5913
+ const candidate = arg;
5914
+ if (typeof candidate.compileInsert === "function") {
5915
+ return candidate.compileInsert(this.state.ast);
5680
5916
  }
5681
5917
  const dialect = resolveDialectInput(arg);
5682
5918
  return dialect.compileInsert(this.state.ast);
5683
5919
  }
5920
+ /**
5921
+ * Returns the SQL string for the INSERT query
5922
+ * @param arg - The compiler or dialect to generate SQL for
5923
+ * @returns The SQL string representation of the query
5924
+ */
5684
5925
  toSql(arg) {
5685
5926
  return this.compile(arg).sql;
5686
5927
  }
5928
+ /**
5929
+ * Returns the Abstract Syntax Tree (AST) representation of the query
5930
+ * @returns The AST node for the INSERT query
5931
+ */
5687
5932
  getAST() {
5688
5933
  return this.state.ast;
5689
5934
  }
@@ -5702,6 +5947,11 @@ var isUpdateValue = (value) => {
5702
5947
  }
5703
5948
  };
5704
5949
  var UpdateQueryState = class _UpdateQueryState {
5950
+ /**
5951
+ * Creates a new UpdateQueryState instance
5952
+ * @param table - Table definition for the update
5953
+ * @param ast - Optional existing AST
5954
+ */
5705
5955
  constructor(table, ast) {
5706
5956
  this.table = table;
5707
5957
  this.ast = ast ?? {
@@ -5711,9 +5961,19 @@ var UpdateQueryState = class _UpdateQueryState {
5711
5961
  joins: []
5712
5962
  };
5713
5963
  }
5964
+ /**
5965
+ * Creates a new UpdateQueryState with updated AST
5966
+ * @param nextAst - Updated AST
5967
+ * @returns New UpdateQueryState instance
5968
+ */
5714
5969
  clone(nextAst) {
5715
5970
  return new _UpdateQueryState(this.table, nextAst);
5716
5971
  }
5972
+ /**
5973
+ * Sets the columns to update with their new values
5974
+ * @param values - Record of column names to values
5975
+ * @returns New UpdateQueryState with SET clause
5976
+ */
5717
5977
  withSet(values) {
5718
5978
  const assignments = Object.entries(values).map(([column, rawValue]) => {
5719
5979
  if (!isUpdateValue(rawValue)) {
@@ -5735,30 +5995,55 @@ var UpdateQueryState = class _UpdateQueryState {
5735
5995
  set: assignments
5736
5996
  });
5737
5997
  }
5998
+ /**
5999
+ * Adds a WHERE condition to the update query
6000
+ * @param expr - WHERE expression
6001
+ * @returns New UpdateQueryState with WHERE clause
6002
+ */
5738
6003
  withWhere(expr) {
5739
6004
  return this.clone({
5740
6005
  ...this.ast,
5741
6006
  where: expr
5742
6007
  });
5743
6008
  }
6009
+ /**
6010
+ * Adds a RETURNING clause to the update query
6011
+ * @param columns - Columns to return
6012
+ * @returns New UpdateQueryState with RETURNING clause
6013
+ */
5744
6014
  withReturning(columns) {
5745
6015
  return this.clone({
5746
6016
  ...this.ast,
5747
6017
  returning: [...columns]
5748
6018
  });
5749
6019
  }
6020
+ /**
6021
+ * Sets the FROM clause for the update query
6022
+ * @param from - Table source for FROM
6023
+ * @returns New UpdateQueryState with FROM clause
6024
+ */
5750
6025
  withFrom(from) {
5751
6026
  return this.clone({
5752
6027
  ...this.ast,
5753
6028
  from
5754
6029
  });
5755
6030
  }
6031
+ /**
6032
+ * Adds a JOIN to the update query
6033
+ * @param join - Join node to add
6034
+ * @returns New UpdateQueryState with JOIN
6035
+ */
5756
6036
  withJoin(join) {
5757
6037
  return this.clone({
5758
6038
  ...this.ast,
5759
6039
  joins: [...this.ast.joins ?? [], join]
5760
6040
  });
5761
6041
  }
6042
+ /**
6043
+ * Applies an alias to the table being updated
6044
+ * @param alias - Alias for the table
6045
+ * @returns New UpdateQueryState with table alias
6046
+ */
5762
6047
  withTableAlias(alias) {
5763
6048
  return this.clone({
5764
6049
  ...this.ast,
@@ -5772,6 +6057,11 @@ var UpdateQueryState = class _UpdateQueryState {
5772
6057
 
5773
6058
  // src/query-builder/update.ts
5774
6059
  var UpdateQueryBuilder = class _UpdateQueryBuilder {
6060
+ /**
6061
+ * Creates a new UpdateQueryBuilder instance
6062
+ * @param table - The table definition for the UPDATE query
6063
+ * @param state - Optional initial query state, defaults to a new UpdateQueryState
6064
+ */
5775
6065
  constructor(table, state) {
5776
6066
  this.table = table;
5777
6067
  this.state = state ?? new UpdateQueryState(table);
@@ -5779,24 +6069,57 @@ var UpdateQueryBuilder = class _UpdateQueryBuilder {
5779
6069
  clone(state) {
5780
6070
  return new _UpdateQueryBuilder(this.table, state);
5781
6071
  }
6072
+ /**
6073
+ * Sets an alias for the table in the UPDATE query
6074
+ * @param alias - The alias to assign to the table
6075
+ * @returns A new UpdateQueryBuilder with the table alias set
6076
+ */
5782
6077
  as(alias) {
5783
6078
  return this.clone(this.state.withTableAlias(alias));
5784
6079
  }
6080
+ /**
6081
+ * Adds a FROM clause to the UPDATE query
6082
+ * @param source - The table source to use in the FROM clause
6083
+ * @returns A new UpdateQueryBuilder with the FROM clause added
6084
+ */
5785
6085
  from(source) {
5786
6086
  const tableSource = this.resolveTableSource(source);
5787
6087
  return this.clone(this.state.withFrom(tableSource));
5788
6088
  }
6089
+ /**
6090
+ * Adds a JOIN clause to the UPDATE query
6091
+ * @param table - The table to join with
6092
+ * @param condition - The join condition expression
6093
+ * @param kind - The type of join (defaults to INNER)
6094
+ * @param relationName - Optional name for the relation
6095
+ * @returns A new UpdateQueryBuilder with the JOIN clause added
6096
+ */
5789
6097
  join(table, condition, kind = JOIN_KINDS.INNER, relationName) {
5790
6098
  const joinTarget = this.resolveJoinTarget(table);
5791
6099
  const joinNode = createJoinNode(kind, joinTarget, condition, relationName);
5792
6100
  return this.clone(this.state.withJoin(joinNode));
5793
6101
  }
6102
+ /**
6103
+ * Adds a SET clause to the UPDATE query
6104
+ * @param values - The column-value pairs to update
6105
+ * @returns A new UpdateQueryBuilder with the SET clause added
6106
+ */
5794
6107
  set(values) {
5795
6108
  return this.clone(this.state.withSet(values));
5796
6109
  }
6110
+ /**
6111
+ * Adds a WHERE clause to the UPDATE query
6112
+ * @param expr - The expression to use as the WHERE condition
6113
+ * @returns A new UpdateQueryBuilder with the WHERE clause added
6114
+ */
5797
6115
  where(expr) {
5798
6116
  return this.clone(this.state.withWhere(expr));
5799
6117
  }
6118
+ /**
6119
+ * Adds a RETURNING clause to the UPDATE query
6120
+ * @param columns - Columns to return after update
6121
+ * @returns A new UpdateQueryBuilder with the RETURNING clause added
6122
+ */
5800
6123
  returning(...columns) {
5801
6124
  if (!columns.length) return this;
5802
6125
  const nodes = columns.map((column) => buildColumnNode(this.table, column));
@@ -5812,16 +6135,36 @@ var UpdateQueryBuilder = class _UpdateQueryBuilder {
5812
6135
  if (typeof table === "string") return table;
5813
6136
  return this.resolveTableSource(table);
5814
6137
  }
5815
- compile(arg) {
5816
- if (typeof arg.compileUpdate === "function") {
5817
- return arg.compileUpdate(this.state.ast);
5818
- }
5819
- const dialect = resolveDialectInput(arg);
5820
- return dialect.compileUpdate(this.state.ast);
6138
+ /**
6139
+ * Compiles the UPDATE query for the specified dialect
6140
+ * @param dialect - The SQL dialect to compile for
6141
+ * @returns The compiled query with SQL and parameters
6142
+ */
6143
+ compile(dialect) {
6144
+ const resolved = resolveDialectInput(dialect);
6145
+ return resolved.compileUpdate(this.state.ast);
5821
6146
  }
5822
- toSql(arg) {
5823
- return this.compile(arg).sql;
6147
+ /**
6148
+ * Returns the SQL string for the UPDATE query
6149
+ * @param dialect - The SQL dialect to generate SQL for
6150
+ * @returns The SQL string representation of the query
6151
+ */
6152
+ toSql(dialect) {
6153
+ return this.compile(dialect).sql;
5824
6154
  }
6155
+ /**
6156
+ * Executes the UPDATE query using the provided session
6157
+ * @param session - The ORM session to execute the query with
6158
+ * @returns A promise that resolves to the query results
6159
+ */
6160
+ async execute(session) {
6161
+ const compiled = this.compile(session.dialect);
6162
+ return session.executor.executeSql(compiled.sql, compiled.params);
6163
+ }
6164
+ /**
6165
+ * Returns the Abstract Syntax Tree (AST) representation of the query
6166
+ * @returns The AST node for the UPDATE query
6167
+ */
5825
6168
  getAST() {
5826
6169
  return this.state.ast;
5827
6170
  }
@@ -5830,6 +6173,11 @@ var isTableSourceNode = (source) => typeof source.type === "string";
5830
6173
 
5831
6174
  // src/query-builder/delete-query-state.ts
5832
6175
  var DeleteQueryState = class _DeleteQueryState {
6176
+ /**
6177
+ * Creates a new DeleteQueryState instance
6178
+ * @param table - The table definition for the DELETE query
6179
+ * @param ast - Optional initial AST node, defaults to a basic DELETE query
6180
+ */
5833
6181
  constructor(table, ast) {
5834
6182
  this.table = table;
5835
6183
  this.ast = ast ?? {
@@ -5841,30 +6189,55 @@ var DeleteQueryState = class _DeleteQueryState {
5841
6189
  clone(nextAst) {
5842
6190
  return new _DeleteQueryState(this.table, nextAst);
5843
6191
  }
6192
+ /**
6193
+ * Adds a WHERE clause to the DELETE query
6194
+ * @param expr - The expression to use as the WHERE condition
6195
+ * @returns A new DeleteQueryState with the WHERE clause added
6196
+ */
5844
6197
  withWhere(expr) {
5845
6198
  return this.clone({
5846
6199
  ...this.ast,
5847
6200
  where: expr
5848
6201
  });
5849
6202
  }
6203
+ /**
6204
+ * Adds a RETURNING clause to the DELETE query
6205
+ * @param columns - The columns to return after deletion
6206
+ * @returns A new DeleteQueryState with the RETURNING clause added
6207
+ */
5850
6208
  withReturning(columns) {
5851
6209
  return this.clone({
5852
6210
  ...this.ast,
5853
6211
  returning: [...columns]
5854
6212
  });
5855
6213
  }
6214
+ /**
6215
+ * Adds a USING clause to the DELETE query
6216
+ * @param source - The table source to use in the USING clause
6217
+ * @returns A new DeleteQueryState with the USING clause added
6218
+ */
5856
6219
  withUsing(source) {
5857
6220
  return this.clone({
5858
6221
  ...this.ast,
5859
6222
  using: source
5860
6223
  });
5861
6224
  }
6225
+ /**
6226
+ * Adds a JOIN clause to the DELETE query
6227
+ * @param join - The join node to add
6228
+ * @returns A new DeleteQueryState with the JOIN clause added
6229
+ */
5862
6230
  withJoin(join) {
5863
6231
  return this.clone({
5864
6232
  ...this.ast,
5865
6233
  joins: [...this.ast.joins ?? [], join]
5866
6234
  });
5867
6235
  }
6236
+ /**
6237
+ * Sets an alias for the table in the DELETE query
6238
+ * @param alias - The alias to assign to the table
6239
+ * @returns A new DeleteQueryState with the table alias set
6240
+ */
5868
6241
  withTableAlias(alias) {
5869
6242
  return this.clone({
5870
6243
  ...this.ast,
@@ -5878,6 +6251,11 @@ var DeleteQueryState = class _DeleteQueryState {
5878
6251
 
5879
6252
  // src/query-builder/delete.ts
5880
6253
  var DeleteQueryBuilder = class _DeleteQueryBuilder {
6254
+ /**
6255
+ * Creates a new DeleteQueryBuilder instance
6256
+ * @param table - The table definition for the DELETE query
6257
+ * @param state - Optional initial query state, defaults to a new DeleteQueryState
6258
+ */
5881
6259
  constructor(table, state) {
5882
6260
  this.table = table;
5883
6261
  this.state = state ?? new DeleteQueryState(table);
@@ -5885,20 +6263,48 @@ var DeleteQueryBuilder = class _DeleteQueryBuilder {
5885
6263
  clone(state) {
5886
6264
  return new _DeleteQueryBuilder(this.table, state);
5887
6265
  }
6266
+ /**
6267
+ * Adds a WHERE clause to the DELETE query
6268
+ * @param expr - The expression to use as the WHERE condition
6269
+ * @returns A new DeleteQueryBuilder with the WHERE clause added
6270
+ */
5888
6271
  where(expr) {
5889
6272
  return this.clone(this.state.withWhere(expr));
5890
6273
  }
6274
+ /**
6275
+ * Sets an alias for the table in the DELETE query
6276
+ * @param alias - The alias to assign to the table
6277
+ * @returns A new DeleteQueryBuilder with the table alias set
6278
+ */
5891
6279
  as(alias) {
5892
6280
  return this.clone(this.state.withTableAlias(alias));
5893
6281
  }
6282
+ /**
6283
+ * Adds a USING clause to the DELETE query
6284
+ * @param source - The table source to use in the USING clause
6285
+ * @returns A new DeleteQueryBuilder with the USING clause added
6286
+ */
5894
6287
  using(source) {
5895
6288
  return this.clone(this.state.withUsing(this.resolveTableSource(source)));
5896
6289
  }
6290
+ /**
6291
+ * Adds a JOIN clause to the DELETE query
6292
+ * @param table - The table to join with
6293
+ * @param condition - The join condition expression
6294
+ * @param kind - The type of join (defaults to INNER)
6295
+ * @param relationName - Optional name for the relation
6296
+ * @returns A new DeleteQueryBuilder with the JOIN clause added
6297
+ */
5897
6298
  join(table, condition, kind = JOIN_KINDS.INNER, relationName) {
5898
6299
  const target = this.resolveJoinTarget(table);
5899
6300
  const joinNode = createJoinNode(kind, target, condition, relationName);
5900
6301
  return this.clone(this.state.withJoin(joinNode));
5901
6302
  }
6303
+ /**
6304
+ * Adds a RETURNING clause to the DELETE query
6305
+ * @param columns - The columns to return after deletion
6306
+ * @returns A new DeleteQueryBuilder with the RETURNING clause added
6307
+ */
5902
6308
  returning(...columns) {
5903
6309
  if (!columns.length) return this;
5904
6310
  const nodes = columns.map((column) => buildColumnNode(this.table, column));
@@ -5914,16 +6320,36 @@ var DeleteQueryBuilder = class _DeleteQueryBuilder {
5914
6320
  if (typeof table === "string") return table;
5915
6321
  return this.resolveTableSource(table);
5916
6322
  }
5917
- compile(arg) {
5918
- if (typeof arg.compileDelete === "function") {
5919
- return arg.compileDelete(this.state.ast);
5920
- }
5921
- const dialect = resolveDialectInput(arg);
5922
- return dialect.compileDelete(this.state.ast);
6323
+ /**
6324
+ * Compiles the DELETE query for the specified dialect
6325
+ * @param dialect - The SQL dialect to compile for
6326
+ * @returns The compiled query with SQL and parameters
6327
+ */
6328
+ compile(dialect) {
6329
+ const resolved = resolveDialectInput(dialect);
6330
+ return resolved.compileDelete(this.state.ast);
5923
6331
  }
5924
- toSql(arg) {
5925
- return this.compile(arg).sql;
6332
+ /**
6333
+ * Returns the SQL string for the DELETE query
6334
+ * @param dialect - The SQL dialect to generate SQL for
6335
+ * @returns The SQL string representation of the query
6336
+ */
6337
+ toSql(dialect) {
6338
+ return this.compile(dialect).sql;
6339
+ }
6340
+ /**
6341
+ * Executes the DELETE query using the provided session
6342
+ * @param session - The ORM session to execute the query with
6343
+ * @returns A promise that resolves to the query results
6344
+ */
6345
+ async execute(session) {
6346
+ const compiled = this.compile(session.dialect);
6347
+ return session.executor.executeSql(compiled.sql, compiled.params);
5926
6348
  }
6349
+ /**
6350
+ * Returns the Abstract Syntax Tree (AST) representation of the query
6351
+ * @returns The AST node for the DELETE query
6352
+ */
5927
6353
  getAST() {
5928
6354
  return this.state.ast;
5929
6355
  }
@@ -5966,7 +6392,7 @@ var generateCreateTableSql = (table, dialect) => {
5966
6392
  const pk = resolvePrimaryKey(table);
5967
6393
  const inlinePkColumns = /* @__PURE__ */ new Set();
5968
6394
  const columnLines = Object.values(table.columns).map((col2) => {
5969
- const includePk = dialect.preferInlinePkAutoincrement?.(col2, table, pk) && pk.includes(col2.name);
6395
+ const includePk = dialect.preferInlinePkAutoincrement(col2, table, pk) && pk.includes(col2.name);
5970
6396
  if (includePk) {
5971
6397
  inlinePkColumns.add(col2.name);
5972
6398
  }
@@ -6358,6 +6784,13 @@ async function runSelectNode(ast, ctx) {
6358
6784
 
6359
6785
  // src/core/ddl/introspect/postgres.ts
6360
6786
  var postgresIntrospector = {
6787
+ /**
6788
+ * Introspects the PostgreSQL database schema by querying information_schema and pg_catalog.
6789
+ * Builds tables with columns, primary keys, foreign keys, and indexes.
6790
+ * @param ctx - The introspection context with database executor.
6791
+ * @param options - Options for schema selection and table filtering.
6792
+ * @returns A promise resolving to the complete database schema.
6793
+ */
6361
6794
  async introspect(ctx, options) {
6362
6795
  const schema = options.schema || "public";
6363
6796
  const tables = [];
@@ -6471,7 +6904,7 @@ var postgresIntrospector = {
6471
6904
  ],
6472
6905
  where: and(
6473
6906
  eq({ table: "ns", name: "nspname" }, schema),
6474
- eq({ table: "i", name: "indisprimary" }, { type: "Literal", value: false })
6907
+ eq({ table: "i", name: "indisprimary" }, false)
6475
6908
  )
6476
6909
  };
6477
6910
  const indexQueryRows = await runSelectNode(indexQuery, ctx);
@@ -6635,8 +7068,22 @@ var mysqlIntrospector = {
6635
7068
  };
6636
7069
 
6637
7070
  // src/core/ddl/introspect/sqlite.ts
7071
+ var toReferentialAction = (value) => {
7072
+ if (!value) return void 0;
7073
+ const normalized = value.toUpperCase();
7074
+ if (normalized === "NO ACTION" || normalized === "RESTRICT" || normalized === "CASCADE" || normalized === "SET NULL" || normalized === "SET DEFAULT") {
7075
+ return normalized;
7076
+ }
7077
+ return void 0;
7078
+ };
6638
7079
  var escapeSingleQuotes = (name) => name.replace(/'/g, "''");
6639
7080
  var sqliteIntrospector = {
7081
+ /**
7082
+ * Introspects the SQLite database schema by querying sqlite_master and various PRAGMAs.
7083
+ * @param ctx - The database execution context containing the DbExecutor.
7084
+ * @param options - Options controlling which tables and schemas to include.
7085
+ * @returns A promise that resolves to the introspected DatabaseSchema.
7086
+ */
6640
7087
  async introspect(ctx, options) {
6641
7088
  const tables = [];
6642
7089
  const tableRows = await queryRows(
@@ -6668,8 +7115,8 @@ var sqliteIntrospector = {
6668
7115
  col2.references = {
6669
7116
  table: fk.table,
6670
7117
  column: fk.to,
6671
- onDelete: fk.on_delete?.toUpperCase(),
6672
- onUpdate: fk.on_update?.toUpperCase()
7118
+ onDelete: toReferentialAction(fk.on_delete),
7119
+ onUpdate: toReferentialAction(fk.on_update)
6673
7120
  };
6674
7121
  }
6675
7122
  });
@@ -6692,6 +7139,12 @@ var sqliteIntrospector = {
6692
7139
 
6693
7140
  // src/core/ddl/introspect/mssql.ts
6694
7141
  var mssqlIntrospector = {
7142
+ /**
7143
+ * Introspects the MSSQL database schema.
7144
+ * @param ctx - The introspection context containing the database executor.
7145
+ * @param options - Options for introspection, such as schema filter.
7146
+ * @returns A promise that resolves to the introspected database schema.
7147
+ */
6695
7148
  async introspect(ctx, options) {
6696
7149
  const schema = options.schema;
6697
7150
  const filterSchema = schema ? "sch.name = @p1" : "1=1";
@@ -6974,10 +7427,21 @@ var dateTrunc = (part, date) => fn3("DATE_TRUNC", [part, date]);
6974
7427
  // src/orm/als.ts
6975
7428
  var AsyncLocalStorage = class {
6976
7429
  /**
6977
- * Executes a callback with the specified store value
6978
- * @param store - Value to store during callback execution
6979
- * @param callback - Function to execute with the store value
6980
- * @returns Result of the callback function
7430
+ * Executes a callback function within a context containing the specified store value.
7431
+ * The store value is only available during the callback's execution and is automatically
7432
+ * cleared afterward.
7433
+ *
7434
+ * @param store - The context value to make available during callback execution
7435
+ * @param callback - Function to execute with the store value available
7436
+ * @returns Result of the callback function execution
7437
+ *
7438
+ * @example
7439
+ * ```
7440
+ * const als = new AsyncLocalStorage<number>();
7441
+ * als.run(42, () => {
7442
+ * console.log(als.getStore()); // Outputs: 42
7443
+ * });
7444
+ * ```
6981
7445
  */
6982
7446
  run(store, callback) {
6983
7447
  this.store = store;
@@ -6988,8 +7452,20 @@ var AsyncLocalStorage = class {
6988
7452
  }
6989
7453
  }
6990
7454
  /**
6991
- * Gets the currently stored value
6992
- * @returns Current store value or undefined if none exists
7455
+ * Retrieves the current store value from the async context.
7456
+ * Returns undefined if called outside of a `run()` callback execution.
7457
+ *
7458
+ * @returns Current store value or undefined if no context exists
7459
+ *
7460
+ * @example
7461
+ * ```
7462
+ * const als = new AsyncLocalStorage<string>();
7463
+ * console.log(als.getStore()); // Outputs: undefined
7464
+ *
7465
+ * als.run('hello', () => {
7466
+ * console.log(als.getStore()); // Outputs: 'hello'
7467
+ * });
7468
+ * ```
6993
7469
  */
6994
7470
  getStore() {
6995
7471
  return this.store;
@@ -7079,11 +7555,7 @@ var TypeScriptGenerator = class {
7079
7555
  const lines = [];
7080
7556
  const hydration = ast.meta?.hydration;
7081
7557
  const hydratedRelations = new Set(hydration?.relations?.map((r) => r.name) ?? []);
7082
- const selections = ast.columns.filter((col2) => !(hydration && isRelationAlias(col2.alias))).map((col2) => {
7083
- const key = col2.alias || col2.name;
7084
- const operand = col2;
7085
- return `${key}: ${this.printOperand(operand)}`;
7086
- });
7558
+ const selections = ast.columns.filter((col2) => !(hydration && isRelationAlias(col2.alias))).map((col2, index) => `${this.getSelectionKey(col2, index)}: ${this.printOperand(col2)}`);
7087
7559
  lines.push(`db.select({`);
7088
7560
  selections.forEach((sel2, index) => {
7089
7561
  lines.push(` ${sel2}${index < selections.length - 1 ? "," : ""}`);
@@ -7171,7 +7643,7 @@ var TypeScriptGenerator = class {
7171
7643
  * Prints an ordering term (operand/expression/alias) to TypeScript code.
7172
7644
  */
7173
7645
  printOrderingTerm(term) {
7174
- if (!term || !term.type) {
7646
+ if (!term || !("type" in term)) {
7175
7647
  throw new Error("Unsupported ordering term");
7176
7648
  }
7177
7649
  switch (term.type) {
@@ -7190,6 +7662,18 @@ var TypeScriptGenerator = class {
7190
7662
  return this.printExpression(term);
7191
7663
  }
7192
7664
  }
7665
+ getSelectionKey(selection, index) {
7666
+ if (selection.alias) {
7667
+ return selection.alias;
7668
+ }
7669
+ if (this.isNamedSelection(selection)) {
7670
+ return selection.name;
7671
+ }
7672
+ return `selection${index + 1}`;
7673
+ }
7674
+ isNamedSelection(selection) {
7675
+ return "name" in selection;
7676
+ }
7193
7677
  visitBinaryExpression(binary) {
7194
7678
  return this.printBinaryExpression(binary);
7195
7679
  }
@@ -7973,6 +8457,7 @@ var RelationChangeProcessor = class {
7973
8457
  * @param _entry - The relation change entry (reserved for future use)
7974
8458
  */
7975
8459
  async handleBelongsToChange(_entry) {
8460
+ void _entry;
7976
8461
  }
7977
8462
  /**
7978
8463
  * Handles changes for belongs-to-many relations.
@@ -8086,7 +8571,7 @@ var RelationChangeProcessor = class {
8086
8571
  const key = findPrimaryKey(table);
8087
8572
  const value = entity[key];
8088
8573
  if (value === void 0 || value === null) return null;
8089
- return value;
8574
+ return value ?? null;
8090
8575
  }
8091
8576
  };
8092
8577
 
@@ -8678,8 +9163,6 @@ var Orm = class {
8678
9163
  const session = new OrmSession({ orm: this, executor });
8679
9164
  try {
8680
9165
  return await session.transaction(() => fn4(session));
8681
- } catch (err) {
8682
- throw err;
8683
9166
  } finally {
8684
9167
  await session.dispose();
8685
9168
  }
@@ -8710,9 +9193,6 @@ var getOrCreateMetadataBag = (context) => {
8710
9193
  var readMetadataBag = (context) => {
8711
9194
  return context.metadata?.[METADATA_KEY];
8712
9195
  };
8713
- var registerInitializer = (context, initializer) => {
8714
- context.addInitializer?.(initializer);
8715
- };
8716
9196
 
8717
9197
  // src/decorators/entity.ts
8718
9198
  var toSnakeCase = (value) => {
@@ -8742,14 +9222,24 @@ function Entity(options = {}) {
8742
9222
  if (bag) {
8743
9223
  const meta = ensureEntityMetadata(ctor);
8744
9224
  for (const entry of bag.columns) {
8745
- if (!meta.columns[entry.propertyName]) {
8746
- addColumnMetadata(ctor, entry.propertyName, { ...entry.column });
9225
+ if (meta.columns[entry.propertyName]) {
9226
+ throw new Error(
9227
+ `Column '${entry.propertyName}' is already defined on entity '${ctor.name}'.`
9228
+ );
8747
9229
  }
9230
+ addColumnMetadata(ctor, entry.propertyName, { ...entry.column });
8748
9231
  }
8749
9232
  for (const entry of bag.relations) {
8750
- if (!meta.relations[entry.propertyName]) {
8751
- addRelationMetadata(ctor, entry.propertyName, entry.relation);
9233
+ if (meta.relations[entry.propertyName]) {
9234
+ throw new Error(
9235
+ `Relation '${entry.propertyName}' is already defined on entity '${ctor.name}'.`
9236
+ );
8752
9237
  }
9238
+ const relationCopy = entry.relation.kind === RelationKinds.BelongsToMany ? {
9239
+ ...entry.relation,
9240
+ defaultPivotColumns: entry.relation.defaultPivotColumns ? [...entry.relation.defaultPivotColumns] : void 0
9241
+ } : { ...entry.relation };
9242
+ addRelationMetadata(ctor, entry.propertyName, relationCopy);
8753
9243
  }
8754
9244
  }
8755
9245
  }
@@ -8812,13 +9302,6 @@ var registerColumnFromContext = (context, column) => {
8812
9302
  if (!bag.columns.some((entry) => entry.propertyName === propertyName)) {
8813
9303
  bag.columns.push({ propertyName, column: { ...column } });
8814
9304
  }
8815
- registerInitializer(context, function() {
8816
- const ctor = resolveConstructor(this);
8817
- if (!ctor) {
8818
- return;
8819
- }
8820
- registerColumn(ctor, propertyName, column);
8821
- });
8822
9305
  };
8823
9306
  function Column(definition) {
8824
9307
  const normalized = normalizeColumnInput(definition);
@@ -8874,13 +9357,6 @@ var createFieldDecorator = (metadataFactory) => {
8874
9357
  if (!bag.relations.some((entry) => entry.propertyName === propertyName2)) {
8875
9358
  bag.relations.push({ propertyName: propertyName2, relation: relationMetadata });
8876
9359
  }
8877
- registerInitializer(ctx, function() {
8878
- const ctor2 = resolveConstructor2(this);
8879
- if (!ctor2) {
8880
- return;
8881
- }
8882
- registerRelation(ctor2, propertyName2, relationMetadata);
8883
- });
8884
9360
  return;
8885
9361
  }
8886
9362
  const propertyName = normalizePropertyName2(propertyKeyOrContext);
@@ -9518,11 +9994,9 @@ function createPooledExecutorFactory(opts) {
9518
9994
  cos,
9519
9995
  cot,
9520
9996
  count,
9521
- createColumn,
9522
9997
  createEntityFromRow,
9523
9998
  createEntityProxy,
9524
9999
  createExecutorFromQueryRunner,
9525
- createLiteral,
9526
10000
  createMssqlExecutor,
9527
10001
  createMysqlExecutor,
9528
10002
  createPooledExecutorFactory,
@@ -9546,6 +10020,7 @@ function createPooledExecutorFactory(opts) {
9546
10020
  diffSchema,
9547
10021
  div,
9548
10022
  endOfMonth,
10023
+ entityRef,
9549
10024
  eq,
9550
10025
  esel,
9551
10026
  executeHydrated,
@@ -9558,6 +10033,7 @@ function createPooledExecutorFactory(opts) {
9558
10033
  fromUnixTime,
9559
10034
  generateCreateTableSql,
9560
10035
  generateSchemaSql,
10036
+ getColumn,
9561
10037
  getSchemaIntrospector,
9562
10038
  getTableDefFromEntity,
9563
10039
  groupConcat,