metal-orm 1.0.17 → 1.0.19

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 (39) hide show
  1. package/README.md +4 -3
  2. package/dist/decorators/index.cjs +192 -46
  3. package/dist/decorators/index.cjs.map +1 -1
  4. package/dist/decorators/index.d.cts +1 -1
  5. package/dist/decorators/index.d.ts +1 -1
  6. package/dist/decorators/index.js +192 -46
  7. package/dist/decorators/index.js.map +1 -1
  8. package/dist/index.cjs +245 -66
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +16 -29
  11. package/dist/index.d.ts +16 -29
  12. package/dist/index.js +243 -66
  13. package/dist/index.js.map +1 -1
  14. package/dist/{select-BPCn6MOH.d.cts → select-BuMpVcVt.d.cts} +83 -11
  15. package/dist/{select-BPCn6MOH.d.ts → select-BuMpVcVt.d.ts} +83 -11
  16. package/package.json +61 -54
  17. package/src/codegen/naming-strategy.ts +15 -10
  18. package/src/core/ast/builders.ts +23 -3
  19. package/src/core/ast/expression-builders.ts +14 -1
  20. package/src/core/ast/expression-nodes.ts +11 -9
  21. package/src/core/ast/join-node.ts +5 -3
  22. package/src/core/ast/join.ts +16 -16
  23. package/src/core/ast/query.ts +44 -29
  24. package/src/core/ddl/dialects/mssql-schema-dialect.ts +18 -0
  25. package/src/core/ddl/dialects/mysql-schema-dialect.ts +11 -0
  26. package/src/core/ddl/dialects/postgres-schema-dialect.ts +9 -0
  27. package/src/core/ddl/dialects/sqlite-schema-dialect.ts +9 -0
  28. package/src/core/dialect/base/sql-dialect.ts +58 -46
  29. package/src/core/dialect/mssql/index.ts +53 -28
  30. package/src/core/dialect/sqlite/index.ts +22 -13
  31. package/src/query-builder/column-selector.ts +9 -7
  32. package/src/query-builder/query-ast-service.ts +59 -38
  33. package/src/query-builder/relation-conditions.ts +38 -34
  34. package/src/query-builder/relation-manager.ts +8 -3
  35. package/src/query-builder/relation-service.ts +59 -46
  36. package/src/query-builder/select-query-state.ts +19 -7
  37. package/src/query-builder/select.ts +215 -135
  38. package/src/schema/column.ts +75 -39
  39. package/src/schema/types.ts +1 -0
@@ -1,4 +1,4 @@
1
- import { $ as TableHooks, a1 as ColumnType, h as ColumnDef, aS as EntityOrTableTargetResolver, a8 as CascadeMode, i as TableDef, aT as EntityConstructor, V as SelectQueryBuilder } from '../select-BPCn6MOH.cjs';
1
+ import { a2 as TableHooks, a4 as ColumnType, h as ColumnDef, aV as EntityOrTableTargetResolver, ab as CascadeMode, i as TableDef, aW as EntityConstructor, Z as SelectQueryBuilder } from '../select-BuMpVcVt.cjs';
2
2
 
3
3
  interface EntityOptions {
4
4
  tableName?: string;
@@ -1,4 +1,4 @@
1
- import { $ as TableHooks, a1 as ColumnType, h as ColumnDef, aS as EntityOrTableTargetResolver, a8 as CascadeMode, i as TableDef, aT as EntityConstructor, V as SelectQueryBuilder } from '../select-BPCn6MOH.js';
1
+ import { a2 as TableHooks, a4 as ColumnType, h as ColumnDef, aV as EntityOrTableTargetResolver, ab as CascadeMode, i as TableDef, aW as EntityConstructor, Z as SelectQueryBuilder } from '../select-BuMpVcVt.js';
2
2
 
3
3
  interface EntityOptions {
4
4
  tableName?: string;
@@ -390,6 +390,26 @@ var avg = buildAggregate("AVG");
390
390
  var min = buildAggregate("MIN");
391
391
  var max = buildAggregate("MAX");
392
392
 
393
+ // src/core/ast/builders.ts
394
+ var buildColumnNode = (table, column) => {
395
+ if (column.type === "Column") {
396
+ return column;
397
+ }
398
+ const def = column;
399
+ const baseTable = def.table ? table.alias && def.table === table.name ? table.alias : def.table : table.alias || table.name;
400
+ return {
401
+ type: "Column",
402
+ table: baseTable,
403
+ name: def.name
404
+ };
405
+ };
406
+ var derivedTable = (query, alias, columnAliases) => ({
407
+ type: "DerivedTable",
408
+ query,
409
+ alias,
410
+ columnAliases
411
+ });
412
+
393
413
  // src/core/functions/standard-strategy.ts
394
414
  var StandardFunctionStrategy = class _StandardFunctionStrategy {
395
415
  constructor() {
@@ -1079,7 +1099,7 @@ var SqlDialectBase = class extends Dialect {
1079
1099
  return this.returningStrategy.compileReturning(returning, ctx);
1080
1100
  }
1081
1101
  compileInsertColumnList(columns) {
1082
- return columns.map((column) => `${this.quoteIdentifier(column.table)}.${this.quoteIdentifier(column.name)}`).join(", ");
1102
+ return columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
1083
1103
  }
1084
1104
  compileInsertValues(values, ctx) {
1085
1105
  return values.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
@@ -1105,7 +1125,7 @@ var SqlDialectBase = class extends Dialect {
1105
1125
  compileUpdateAssignments(assignments, ctx) {
1106
1126
  return assignments.map((assignment) => {
1107
1127
  const col = assignment.column;
1108
- const target = `${this.quoteIdentifier(col.table)}.${this.quoteIdentifier(col.name)}`;
1128
+ const target = this.quoteIdentifier(col.name);
1109
1129
  const value = this.compileOperand(assignment.value, ctx);
1110
1130
  return `${target} = ${value}`;
1111
1131
  }).join(", ");
@@ -1137,12 +1157,29 @@ var SqlDialectBase = class extends Dialect {
1137
1157
  if (tableSource.type === "FunctionTable") {
1138
1158
  return this.compileFunctionTable(tableSource, ctx);
1139
1159
  }
1160
+ if (tableSource.type === "DerivedTable") {
1161
+ return this.compileDerivedTable(tableSource, ctx);
1162
+ }
1140
1163
  return this.compileTableSource(tableSource);
1141
1164
  }
1142
1165
  compileFunctionTable(fn, ctx) {
1143
1166
  return FunctionTableFormatter.format(fn, ctx, this);
1144
1167
  }
1168
+ compileDerivedTable(table, ctx) {
1169
+ if (!table.alias) {
1170
+ throw new Error("Derived tables must have an alias.");
1171
+ }
1172
+ const subquery = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
1173
+ const columns = table.columnAliases?.length ? ` (${table.columnAliases.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
1174
+ return `(${subquery}) AS ${this.quoteIdentifier(table.alias)}${columns}`;
1175
+ }
1145
1176
  compileTableSource(table) {
1177
+ if (table.type === "FunctionTable") {
1178
+ return this.compileFunctionTable(table);
1179
+ }
1180
+ if (table.type === "DerivedTable") {
1181
+ return this.compileDerivedTable(table);
1182
+ }
1146
1183
  const base = this.compileTableName(table);
1147
1184
  return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
1148
1185
  }
@@ -1531,6 +1568,12 @@ var SqliteDialect = class extends SqlDialectBase {
1531
1568
  const columns = this.formatReturningColumns(returning);
1532
1569
  return ` RETURNING ${columns}`;
1533
1570
  }
1571
+ formatReturningColumns(returning) {
1572
+ return returning.map((column) => {
1573
+ const alias = column.alias ? ` AS ${this.quoteIdentifier(column.alias)}` : "";
1574
+ return `${this.quoteIdentifier(column.name)}${alias}`;
1575
+ }).join(", ");
1576
+ }
1534
1577
  supportsReturning() {
1535
1578
  return true;
1536
1579
  }
@@ -1697,6 +1740,9 @@ var SqlServerDialect = class extends Dialect {
1697
1740
  return `UPDATE ${table} SET ${assignments}${whereClause};`;
1698
1741
  }
1699
1742
  compileDeleteAst(ast, ctx) {
1743
+ if (ast.from.type !== "Table") {
1744
+ throw new Error("DELETE only supports base tables in the MSSQL dialect.");
1745
+ }
1700
1746
  const table = this.quoteIdentifier(ast.from.name);
1701
1747
  const whereClause = this.compileWhere(ast.where, ctx);
1702
1748
  return `DELETE FROM ${table}${whereClause};`;
@@ -1720,9 +1766,9 @@ var SqlServerDialect = class extends Dialect {
1720
1766
  return expr;
1721
1767
  }).join(", ");
1722
1768
  const distinct = ast.distinct ? "DISTINCT " : "";
1723
- const from = `${this.quoteIdentifier(ast.from.name)}`;
1769
+ const from = this.compileTableSource(ast.from, ctx);
1724
1770
  const joins = ast.joins.map((j) => {
1725
- const table = this.quoteIdentifier(j.table.name);
1771
+ const table = this.compileTableSource(j.table, ctx);
1726
1772
  const cond = this.compileExpression(j.condition, ctx);
1727
1773
  return `${j.kind} JOIN ${table} ON ${cond}`;
1728
1774
  }).join(" ");
@@ -1752,6 +1798,21 @@ var SqlServerDialect = class extends Dialect {
1752
1798
  }
1753
1799
  return pagination;
1754
1800
  }
1801
+ compileTableSource(table, ctx) {
1802
+ if (table.type === "FunctionTable") {
1803
+ return FunctionTableFormatter.format(table, ctx, this);
1804
+ }
1805
+ if (table.type === "DerivedTable") {
1806
+ return this.compileDerivedTable(table, ctx);
1807
+ }
1808
+ const base = table.schema ? `${this.quoteIdentifier(table.schema)}.${this.quoteIdentifier(table.name)}` : this.quoteIdentifier(table.name);
1809
+ return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
1810
+ }
1811
+ compileDerivedTable(table, ctx) {
1812
+ const sub = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
1813
+ const cols = table.columnAliases?.length ? ` (${table.columnAliases.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
1814
+ return `(${sub}) AS ${this.quoteIdentifier(table.alias)}${cols}`;
1815
+ }
1755
1816
  compileCtes(ast, ctx) {
1756
1817
  if (!ast.ctes || ast.ctes.length === 0) return "";
1757
1818
  const defs = ast.ctes.map((cte) => {
@@ -1880,6 +1941,17 @@ var SelectQueryState = class _SelectQueryState {
1880
1941
  joins: [...this.ast.joins ?? [], join]
1881
1942
  });
1882
1943
  }
1944
+ /**
1945
+ * Replaces the FROM clause.
1946
+ * @param from - Table source for the FROM clause
1947
+ * @returns New SelectQueryState with updated FROM
1948
+ */
1949
+ withFrom(from) {
1950
+ return this.clone({
1951
+ ...this.ast,
1952
+ from
1953
+ });
1954
+ }
1883
1955
  /**
1884
1956
  * Adds a WHERE clause to the query
1885
1957
  * @param predicate - WHERE predicate expression
@@ -2372,19 +2444,6 @@ var buildDefaultHydrationPlan = (table) => ({
2372
2444
  relations: []
2373
2445
  });
2374
2446
 
2375
- // src/core/ast/builders.ts
2376
- var buildColumnNode = (table, column) => {
2377
- if (column.type === "Column") {
2378
- return column;
2379
- }
2380
- const def = column;
2381
- return {
2382
- type: "Column",
2383
- table: def.table || table.name,
2384
- name: def.name
2385
- };
2386
- };
2387
-
2388
2447
  // src/query-builder/raw-column-parser.ts
2389
2448
  var parseRawColumn = (col, tableName, ctes) => {
2390
2449
  if (col.includes("(")) {
@@ -2424,6 +2483,8 @@ var QueryAstService = class {
2424
2483
  const existingAliases = new Set(
2425
2484
  this.state.ast.columns.map((c) => c.alias || c.name)
2426
2485
  );
2486
+ const from = this.state.ast.from;
2487
+ const rootTableName = from.type === "Table" && from.alias ? from.alias : this.table.name;
2427
2488
  const newCols = Object.entries(columns).reduce((acc, [alias, val]) => {
2428
2489
  if (existingAliases.has(alias)) return acc;
2429
2490
  if (isExpressionSelectionNode(val)) {
@@ -2431,9 +2492,10 @@ var QueryAstService = class {
2431
2492
  return acc;
2432
2493
  }
2433
2494
  const colDef = val;
2495
+ const resolvedTable = colDef.table && colDef.table === this.table.name && from.type === "Table" && from.alias ? from.alias : colDef.table || rootTableName;
2434
2496
  acc.push({
2435
2497
  type: "Column",
2436
- table: colDef.table || this.table.name,
2498
+ table: resolvedTable,
2437
2499
  name: colDef.name,
2438
2500
  alias
2439
2501
  });
@@ -2448,7 +2510,9 @@ var QueryAstService = class {
2448
2510
  * @returns Column selection result with updated state and added columns
2449
2511
  */
2450
2512
  selectRaw(cols) {
2451
- const newCols = cols.map((col) => parseRawColumn(col, this.table.name, this.state.ast.ctes));
2513
+ const from = this.state.ast.from;
2514
+ const defaultTable = from.type === "Table" && from.alias ? from.alias : this.table.name;
2515
+ const newCols = cols.map((col) => parseRawColumn(col, defaultTable, this.state.ast.ctes));
2452
2516
  const nextState = this.state.withColumns(newCols);
2453
2517
  return { state: nextState, addedColumns: newCols };
2454
2518
  }
@@ -2484,6 +2548,14 @@ var QueryAstService = class {
2484
2548
  };
2485
2549
  return this.state.withSetOperation(op);
2486
2550
  }
2551
+ /**
2552
+ * Replaces the FROM clause for the current query.
2553
+ * @param from - Table source to use in the FROM clause
2554
+ * @returns Updated query state with new FROM
2555
+ */
2556
+ withFrom(from) {
2557
+ return this.state.withFrom(from);
2558
+ }
2487
2559
  /**
2488
2560
  * Selects a subquery as a column
2489
2561
  * @param alias - Alias for the subquery
@@ -2517,7 +2589,9 @@ var QueryAstService = class {
2517
2589
  * @returns Updated query state with GROUP BY clause
2518
2590
  */
2519
2591
  withGroupBy(col) {
2520
- const node = buildColumnNode(this.table, col);
2592
+ const from = this.state.ast.from;
2593
+ const tableRef = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
2594
+ const node = buildColumnNode(tableRef, col);
2521
2595
  return this.state.withGroupBy([node]);
2522
2596
  }
2523
2597
  /**
@@ -2536,7 +2610,9 @@ var QueryAstService = class {
2536
2610
  * @returns Updated query state with ORDER BY clause
2537
2611
  */
2538
2612
  withOrderBy(col, direction) {
2539
- const node = buildColumnNode(this.table, col);
2613
+ const from = this.state.ast.from;
2614
+ const tableRef = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
2615
+ const node = buildColumnNode(tableRef, col);
2540
2616
  return this.state.withOrderBy([{ type: "OrderBy", column: node, direction }]);
2541
2617
  }
2542
2618
  /**
@@ -2640,7 +2716,8 @@ var RelationProjectionHelper = class {
2640
2716
  var assertNever = (value) => {
2641
2717
  throw new Error(`Unhandled relation type: ${JSON.stringify(value)}`);
2642
2718
  };
2643
- var baseRelationCondition = (root, relation) => {
2719
+ var baseRelationCondition = (root, relation, rootAlias) => {
2720
+ const rootTable = rootAlias || root.name;
2644
2721
  const defaultLocalKey = relation.type === RelationKinds.HasMany || relation.type === RelationKinds.HasOne ? findPrimaryKey(root) : findPrimaryKey(relation.target);
2645
2722
  const localKey = relation.localKey || defaultLocalKey;
2646
2723
  switch (relation.type) {
@@ -2648,12 +2725,12 @@ var baseRelationCondition = (root, relation) => {
2648
2725
  case RelationKinds.HasOne:
2649
2726
  return eq(
2650
2727
  { type: "Column", table: relation.target.name, name: relation.foreignKey },
2651
- { type: "Column", table: root.name, name: localKey }
2728
+ { type: "Column", table: rootTable, name: localKey }
2652
2729
  );
2653
2730
  case RelationKinds.BelongsTo:
2654
2731
  return eq(
2655
2732
  { type: "Column", table: relation.target.name, name: localKey },
2656
- { type: "Column", table: root.name, name: relation.foreignKey }
2733
+ { type: "Column", table: rootTable, name: relation.foreignKey }
2657
2734
  );
2658
2735
  case RelationKinds.BelongsToMany:
2659
2736
  throw new Error("BelongsToMany relations do not support the standard join condition builder");
@@ -2661,12 +2738,13 @@ var baseRelationCondition = (root, relation) => {
2661
2738
  return assertNever(relation);
2662
2739
  }
2663
2740
  };
2664
- var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra) => {
2741
+ var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra, rootAlias) => {
2665
2742
  const rootKey = relation.localKey || findPrimaryKey(root);
2666
2743
  const targetKey = relation.targetKey || findPrimaryKey(relation.target);
2744
+ const rootTable = rootAlias || root.name;
2667
2745
  const pivotCondition = eq(
2668
2746
  { type: "Column", table: relation.pivotTable.name, name: relation.pivotForeignKeyToRoot },
2669
- { type: "Column", table: root.name, name: rootKey }
2747
+ { type: "Column", table: rootTable, name: rootKey }
2670
2748
  );
2671
2749
  const pivotJoin = createJoinNode(joinKind, relation.pivotTable.name, pivotCondition);
2672
2750
  let targetCondition = eq(
@@ -2684,12 +2762,12 @@ var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra) =>
2684
2762
  );
2685
2763
  return [pivotJoin, targetJoin];
2686
2764
  };
2687
- var buildRelationJoinCondition = (root, relation, extra) => {
2688
- const base = baseRelationCondition(root, relation);
2765
+ var buildRelationJoinCondition = (root, relation, extra, rootAlias) => {
2766
+ const base = baseRelationCondition(root, relation, rootAlias);
2689
2767
  return extra ? and(base, extra) : base;
2690
2768
  };
2691
- var buildRelationCorrelation = (root, relation) => {
2692
- return baseRelationCondition(root, relation);
2769
+ var buildRelationCorrelation = (root, relation, rootAlias) => {
2770
+ return baseRelationCondition(root, relation, rootAlias);
2693
2771
  };
2694
2772
 
2695
2773
  // src/core/ast/join-metadata.ts
@@ -2733,7 +2811,7 @@ var RelationService = class {
2733
2811
  match(relationName, predicate) {
2734
2812
  const joined = this.joinRelation(relationName, JOIN_KINDS.INNER, predicate);
2735
2813
  const pk = findPrimaryKey(this.table);
2736
- const distinctCols = [{ type: "Column", table: this.table.name, name: pk }];
2814
+ const distinctCols = [{ type: "Column", table: this.rootTableName(), name: pk }];
2737
2815
  const existingDistinct = joined.state.ast.distinct ? joined.state.ast.distinct : [];
2738
2816
  const nextState = this.astService(joined.state).withDistinct([...existingDistinct, ...distinctCols]);
2739
2817
  return { state: nextState, hydration: joined.hydration };
@@ -2820,9 +2898,13 @@ var RelationService = class {
2820
2898
  * @param ast - Query AST to modify
2821
2899
  * @returns Modified query AST with relation correlation
2822
2900
  */
2823
- applyRelationCorrelation(relationName, ast) {
2901
+ applyRelationCorrelation(relationName, ast, additionalCorrelation) {
2824
2902
  const relation = this.getRelation(relationName);
2825
- const correlation = buildRelationCorrelation(this.table, relation);
2903
+ const rootAlias = this.state.ast.from.type === "Table" ? this.state.ast.from.alias : void 0;
2904
+ let correlation = buildRelationCorrelation(this.table, relation, rootAlias);
2905
+ if (additionalCorrelation) {
2906
+ correlation = and(correlation, additionalCorrelation);
2907
+ }
2826
2908
  const whereInSubquery = ast.where ? and(correlation, ast.where) : correlation;
2827
2909
  return {
2828
2910
  ...ast,
@@ -2839,17 +2921,19 @@ var RelationService = class {
2839
2921
  */
2840
2922
  withJoin(state, relationName, joinKind, extraCondition) {
2841
2923
  const relation = this.getRelation(relationName);
2924
+ const rootAlias = state.ast.from.type === "Table" ? state.ast.from.alias : void 0;
2842
2925
  if (relation.type === RelationKinds.BelongsToMany) {
2843
2926
  const joins = buildBelongsToManyJoins(
2844
2927
  this.table,
2845
2928
  relationName,
2846
2929
  relation,
2847
2930
  joinKind,
2848
- extraCondition
2931
+ extraCondition,
2932
+ rootAlias
2849
2933
  );
2850
2934
  return joins.reduce((current, join) => this.astService(current).withJoin(join), state);
2851
2935
  }
2852
- const condition = buildRelationJoinCondition(this.table, relation, extraCondition);
2936
+ const condition = buildRelationJoinCondition(this.table, relation, extraCondition, rootAlias);
2853
2937
  const joinNode = createJoinNode(joinKind, relation.target.name, condition, relationName);
2854
2938
  return this.astService(state).withJoin(joinNode);
2855
2939
  }
@@ -2888,6 +2972,11 @@ var RelationService = class {
2888
2972
  astService(state = this.state) {
2889
2973
  return this.createQueryAstService(this.table, state);
2890
2974
  }
2975
+ rootTableName() {
2976
+ const from = this.state.ast.from;
2977
+ if (from.type === "Table" && from.alias) return from.alias;
2978
+ return this.table.name;
2979
+ }
2891
2980
  };
2892
2981
 
2893
2982
  // src/query-builder/select-query-builder-deps.ts
@@ -2962,7 +3051,9 @@ var ColumnSelector = class {
2962
3051
  * @returns Updated query context with DISTINCT clause
2963
3052
  */
2964
3053
  distinct(context, columns) {
2965
- const nodes = columns.map((col) => buildColumnNode(this.env.table, col));
3054
+ const from = context.state.ast.from;
3055
+ const tableRef = from.type === "Table" && from.alias ? { ...this.env.table, alias: from.alias } : this.env.table;
3056
+ const nodes = columns.map((col) => buildColumnNode(tableRef, col));
2966
3057
  const astService = this.env.deps.createQueryAstService(this.env.table, context.state);
2967
3058
  const nextState = astService.withDistinct(nodes);
2968
3059
  return { state: nextState, hydration: context.hydration };
@@ -3019,8 +3110,8 @@ var RelationManager = class {
3019
3110
  * @param ast - Query AST to modify
3020
3111
  * @returns Modified query AST with relation correlation
3021
3112
  */
3022
- applyRelationCorrelation(context, relationName, ast) {
3023
- return this.createService(context).applyRelationCorrelation(relationName, ast);
3113
+ applyRelationCorrelation(context, relationName, ast, additionalCorrelation) {
3114
+ return this.createService(context).applyRelationCorrelation(relationName, ast, additionalCorrelation);
3024
3115
  }
3025
3116
  /**
3026
3117
  * Creates a relation service instance
@@ -4067,9 +4158,30 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4067
4158
  clone(context = this.context, lazyRelations = new Set(this.lazyRelations)) {
4068
4159
  return new _SelectQueryBuilder(this.env.table, context.state, context.hydration, this.env.deps, lazyRelations);
4069
4160
  }
4161
+ /**
4162
+ * Applies an alias to the root FROM table.
4163
+ * @param alias - Alias to apply
4164
+ */
4165
+ as(alias) {
4166
+ const from = this.context.state.ast.from;
4167
+ if (from.type !== "Table") {
4168
+ throw new Error("Cannot alias non-table FROM sources");
4169
+ }
4170
+ const nextFrom = { ...from, alias };
4171
+ const nextContext = this.applyAst(this.context, (service) => service.withFrom(nextFrom));
4172
+ return this.clone(nextContext);
4173
+ }
4070
4174
  resolveQueryNode(query) {
4071
4175
  return typeof query.getAST === "function" ? query.getAST() : query;
4072
4176
  }
4177
+ applyCorrelation(ast, correlation) {
4178
+ if (!correlation) return ast;
4179
+ const combinedWhere = ast.where ? and(correlation, ast.where) : correlation;
4180
+ return {
4181
+ ...ast,
4182
+ where: combinedWhere
4183
+ };
4184
+ }
4073
4185
  createChildBuilder(table) {
4074
4186
  return new _SelectQueryBuilder(table, void 0, void 0, this.env.deps);
4075
4187
  }
@@ -4161,6 +4273,19 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4161
4273
  const nextContext = this.applyAst(this.context, (service) => service.withCte(name, subAst, columns, true));
4162
4274
  return this.clone(nextContext);
4163
4275
  }
4276
+ /**
4277
+ * Replaces the FROM clause with a derived table (subquery with alias)
4278
+ * @param subquery - Subquery to use as the FROM source
4279
+ * @param alias - Alias for the derived table
4280
+ * @param columnAliases - Optional column alias list
4281
+ * @returns New query builder instance with updated FROM
4282
+ */
4283
+ fromSubquery(subquery, alias, columnAliases) {
4284
+ const subAst = this.resolveQueryNode(subquery);
4285
+ const fromNode = derivedTable(subAst, alias, columnAliases);
4286
+ const nextContext = this.applyAst(this.context, (service) => service.withFrom(fromNode));
4287
+ return this.clone(nextContext);
4288
+ }
4164
4289
  /**
4165
4290
 
4166
4291
  * Selects a subquery as a column
@@ -4176,6 +4301,21 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4176
4301
  const query = this.resolveQueryNode(sub);
4177
4302
  return this.clone(this.columnSelector.selectSubquery(this.context, alias, query));
4178
4303
  }
4304
+ /**
4305
+ * Adds a JOIN against a derived table (subquery with alias)
4306
+ * @param subquery - Subquery to join
4307
+ * @param alias - Alias for the derived table
4308
+ * @param condition - Join condition expression
4309
+ * @param joinKind - Join kind (defaults to INNER)
4310
+ * @param columnAliases - Optional column alias list for the derived table
4311
+ * @returns New query builder instance with the derived-table join
4312
+ */
4313
+ joinSubquery(subquery, alias, condition, joinKind = JOIN_KINDS.INNER, columnAliases) {
4314
+ const subAst = this.resolveQueryNode(subquery);
4315
+ const joinNode = createJoinNode(joinKind, derivedTable(subAst, alias, columnAliases), condition);
4316
+ const nextContext = this.applyAst(this.context, (service) => service.withJoin(joinNode));
4317
+ return this.clone(nextContext);
4318
+ }
4179
4319
  /**
4180
4320
 
4181
4321
  * Adds an INNER JOIN to the query
@@ -4475,9 +4615,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4475
4615
  * @returns New query builder instance with the WHERE EXISTS condition
4476
4616
 
4477
4617
  */
4478
- whereExists(subquery) {
4618
+ whereExists(subquery, correlate) {
4479
4619
  const subAst = this.resolveQueryNode(subquery);
4480
- return this.where(exists(subAst));
4620
+ const correlated = this.applyCorrelation(subAst, correlate);
4621
+ return this.where(exists(correlated));
4481
4622
  }
4482
4623
  /**
4483
4624
 
@@ -4488,9 +4629,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4488
4629
  * @returns New query builder instance with the WHERE NOT EXISTS condition
4489
4630
 
4490
4631
  */
4491
- whereNotExists(subquery) {
4632
+ whereNotExists(subquery, correlate) {
4492
4633
  const subAst = this.resolveQueryNode(subquery);
4493
- return this.where(notExists(subAst));
4634
+ const correlated = this.applyCorrelation(subAst, correlate);
4635
+ return this.where(notExists(correlated));
4494
4636
  }
4495
4637
  /**
4496
4638
 
@@ -4503,17 +4645,19 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4503
4645
  * @returns New query builder instance with the relationship existence check
4504
4646
 
4505
4647
  */
4506
- whereHas(relationName, callback) {
4648
+ whereHas(relationName, callbackOrOptions, maybeOptions) {
4507
4649
  const relation = this.env.table.relations[relationName];
4508
4650
  if (!relation) {
4509
4651
  throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
4510
4652
  }
4653
+ const callback = typeof callbackOrOptions === "function" ? callbackOrOptions : void 0;
4654
+ const options = typeof callbackOrOptions === "function" ? maybeOptions : callbackOrOptions;
4511
4655
  let subQb = this.createChildBuilder(relation.target);
4512
4656
  if (callback) {
4513
4657
  subQb = callback(subQb);
4514
4658
  }
4515
4659
  const subAst = subQb.getAST();
4516
- const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst);
4660
+ const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst, options?.correlate);
4517
4661
  return this.where(exists(finalSubAst));
4518
4662
  }
4519
4663
  /**
@@ -4527,17 +4671,19 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4527
4671
  * @returns New query builder instance with the relationship non-existence check
4528
4672
 
4529
4673
  */
4530
- whereHasNot(relationName, callback) {
4674
+ whereHasNot(relationName, callbackOrOptions, maybeOptions) {
4531
4675
  const relation = this.env.table.relations[relationName];
4532
4676
  if (!relation) {
4533
4677
  throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
4534
4678
  }
4679
+ const callback = typeof callbackOrOptions === "function" ? callbackOrOptions : void 0;
4680
+ const options = typeof callbackOrOptions === "function" ? maybeOptions : callbackOrOptions;
4535
4681
  let subQb = this.createChildBuilder(relation.target);
4536
4682
  if (callback) {
4537
4683
  subQb = callback(subQb);
4538
4684
  }
4539
4685
  const subAst = subQb.getAST();
4540
- const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst);
4686
+ const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst, options?.correlate);
4541
4687
  return this.where(notExists(finalSubAst));
4542
4688
  }
4543
4689
  /**