metal-orm 1.0.39 → 1.0.41

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 (52) hide show
  1. package/dist/index.cjs +1466 -189
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +723 -51
  4. package/dist/index.d.ts +723 -51
  5. package/dist/index.js +1457 -189
  6. package/dist/index.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/codegen/typescript.ts +66 -5
  9. package/src/core/ast/aggregate-functions.ts +15 -15
  10. package/src/core/ast/expression-builders.ts +378 -316
  11. package/src/core/ast/expression-nodes.ts +210 -186
  12. package/src/core/ast/expression-visitor.ts +40 -30
  13. package/src/core/ast/query.ts +164 -132
  14. package/src/core/ast/window-functions.ts +86 -86
  15. package/src/core/dialect/abstract.ts +509 -479
  16. package/src/core/dialect/base/groupby-compiler.ts +6 -6
  17. package/src/core/dialect/base/join-compiler.ts +9 -12
  18. package/src/core/dialect/base/orderby-compiler.ts +20 -6
  19. package/src/core/dialect/base/sql-dialect.ts +237 -138
  20. package/src/core/dialect/mssql/index.ts +164 -185
  21. package/src/core/dialect/sqlite/index.ts +39 -34
  22. package/src/core/execution/db-executor.ts +46 -6
  23. package/src/core/execution/executors/mssql-executor.ts +39 -22
  24. package/src/core/execution/executors/mysql-executor.ts +23 -6
  25. package/src/core/execution/executors/sqlite-executor.ts +29 -3
  26. package/src/core/execution/pooling/pool-types.ts +30 -0
  27. package/src/core/execution/pooling/pool.ts +268 -0
  28. package/src/core/functions/standard-strategy.ts +46 -37
  29. package/src/decorators/bootstrap.ts +7 -7
  30. package/src/index.ts +6 -0
  31. package/src/orm/domain-event-bus.ts +49 -0
  32. package/src/orm/entity-metadata.ts +9 -9
  33. package/src/orm/entity.ts +58 -0
  34. package/src/orm/orm-session.ts +465 -270
  35. package/src/orm/orm.ts +61 -11
  36. package/src/orm/pooled-executor-factory.ts +131 -0
  37. package/src/orm/query-logger.ts +6 -12
  38. package/src/orm/relation-change-processor.ts +75 -0
  39. package/src/orm/relations/many-to-many.ts +4 -2
  40. package/src/orm/save-graph.ts +303 -0
  41. package/src/orm/transaction-runner.ts +3 -3
  42. package/src/orm/unit-of-work.ts +128 -0
  43. package/src/query-builder/delete-query-state.ts +67 -38
  44. package/src/query-builder/delete.ts +37 -1
  45. package/src/query-builder/hydration-manager.ts +93 -79
  46. package/src/query-builder/insert-query-state.ts +131 -61
  47. package/src/query-builder/insert.ts +27 -1
  48. package/src/query-builder/query-ast-service.ts +207 -170
  49. package/src/query-builder/select-query-state.ts +169 -162
  50. package/src/query-builder/select.ts +15 -23
  51. package/src/query-builder/update-query-state.ts +114 -77
  52. package/src/query-builder/update.ts +38 -1
@@ -1,52 +1,61 @@
1
- import { TableDef } from '../schema/table.js';
2
- import { ColumnDef } from '../schema/column.js';
3
- import { SelectQueryNode, CommonTableExpressionNode, SetOperationKind, SetOperationNode, TableSourceNode } from '../core/ast/query.js';
4
- import { buildColumnNode } from '../core/ast/builders.js';
5
- import {
6
- ColumnNode,
7
- ExpressionNode,
8
- FunctionNode,
9
- CaseExpressionNode,
10
- WindowFunctionNode,
11
- ScalarSubqueryNode,
12
- and,
13
- isExpressionSelectionNode
14
- } from '../core/ast/expression.js';
15
- import { JoinNode } from '../core/ast/join.js';
16
- import { SelectQueryState, ProjectionNode } from './select-query-state.js';
17
- import { OrderDirection } from '../core/sql/sql.js';
18
- import { parseRawColumn } from './raw-column-parser.js';
19
-
20
- /**
21
- * Result of column selection operation
22
- */
23
- export interface ColumnSelectionResult {
24
- /**
25
- * Updated query state
26
- */
27
- state: SelectQueryState;
28
- /**
29
- * Columns that were added
30
- */
31
- addedColumns: ProjectionNode[];
32
- }
33
-
34
- /**
35
- * Service for manipulating query AST (Abstract Syntax Tree)
36
- */
37
- export class QueryAstService {
38
- /**
39
- * Creates a new QueryAstService instance
40
- * @param table - Table definition
41
- * @param state - Current query state
42
- */
43
- constructor(private readonly table: TableDef, private readonly state: SelectQueryState) {}
44
-
45
- /**
46
- * Selects columns for the query
47
- * @param columns - Columns to select (key: alias, value: column definition or expression)
48
- * @returns Column selection result with updated state and added columns
49
- */
1
+ import { TableDef } from '../schema/table.js';
2
+ import { ColumnDef } from '../schema/column.js';
3
+ import {
4
+ SelectQueryNode,
5
+ CommonTableExpressionNode,
6
+ SetOperationKind,
7
+ SetOperationNode,
8
+ TableSourceNode,
9
+ OrderingTerm
10
+ } from '../core/ast/query.js';
11
+ import { buildColumnNode } from '../core/ast/builders.js';
12
+ import {
13
+ AliasRefNode,
14
+ ColumnNode,
15
+ ExpressionNode,
16
+ FunctionNode,
17
+ CaseExpressionNode,
18
+ WindowFunctionNode,
19
+ ScalarSubqueryNode,
20
+ and,
21
+ isExpressionSelectionNode,
22
+ isOperandNode
23
+ } from '../core/ast/expression.js';
24
+ import { JoinNode } from '../core/ast/join.js';
25
+ import { SelectQueryState, ProjectionNode } from './select-query-state.js';
26
+ import { OrderDirection } from '../core/sql/sql.js';
27
+ import { parseRawColumn } from './raw-column-parser.js';
28
+
29
+ /**
30
+ * Result of column selection operation
31
+ */
32
+ export interface ColumnSelectionResult {
33
+ /**
34
+ * Updated query state
35
+ */
36
+ state: SelectQueryState;
37
+ /**
38
+ * Columns that were added
39
+ */
40
+ addedColumns: ProjectionNode[];
41
+ }
42
+
43
+ /**
44
+ * Service for manipulating query AST (Abstract Syntax Tree)
45
+ */
46
+ export class QueryAstService {
47
+ /**
48
+ * Creates a new QueryAstService instance
49
+ * @param table - Table definition
50
+ * @param state - Current query state
51
+ */
52
+ constructor(private readonly table: TableDef, private readonly state: SelectQueryState) {}
53
+
54
+ /**
55
+ * Selects columns for the query
56
+ * @param columns - Columns to select (key: alias, value: column definition or expression)
57
+ * @returns Column selection result with updated state and added columns
58
+ */
50
59
  select(
51
60
  columns: Record<string, ColumnDef | FunctionNode | CaseExpressionNode | WindowFunctionNode>
52
61
  ): ColumnSelectionResult {
@@ -77,16 +86,16 @@ export class QueryAstService {
77
86
  } as ColumnNode);
78
87
  return acc;
79
88
  }, []);
80
-
81
- const nextState = this.state.withColumns(newCols);
82
- return { state: nextState, addedColumns: newCols };
83
- }
84
-
85
- /**
86
- * Selects raw column expressions (best-effort parser for simple references/functions)
87
- * @param cols - Raw column expressions
88
- * @returns Column selection result with updated state and added columns
89
- */
89
+
90
+ const nextState = this.state.withColumns(newCols);
91
+ return { state: nextState, addedColumns: newCols };
92
+ }
93
+
94
+ /**
95
+ * Selects raw column expressions (best-effort parser for simple references/functions)
96
+ * @param cols - Raw column expressions
97
+ * @returns Column selection result with updated state and added columns
98
+ */
90
99
  selectRaw(cols: string[]): ColumnSelectionResult {
91
100
  const from = this.state.ast.from;
92
101
  const defaultTable = from.type === 'Table' && from.alias ? from.alias : this.table.name;
@@ -94,15 +103,15 @@ export class QueryAstService {
94
103
  const nextState = this.state.withColumns(newCols);
95
104
  return { state: nextState, addedColumns: newCols };
96
105
  }
97
-
98
- /**
99
- * Adds a Common Table Expression (CTE) to the query
100
- * @param name - Name of the CTE
101
- * @param query - Query for the CTE
102
- * @param columns - Optional column names for the CTE
103
- * @param recursive - Whether the CTE is recursive
104
- * @returns Updated query state with CTE
105
- */
106
+
107
+ /**
108
+ * Adds a Common Table Expression (CTE) to the query
109
+ * @param name - Name of the CTE
110
+ * @param query - Query for the CTE
111
+ * @param columns - Optional column names for the CTE
112
+ * @param recursive - Whether the CTE is recursive
113
+ * @returns Updated query state with CTE
114
+ */
106
115
  withCte(name: string, query: SelectQueryNode, columns?: string[], recursive = false): SelectQueryState {
107
116
  const cte: CommonTableExpressionNode = {
108
117
  type: 'CommonTableExpression',
@@ -138,107 +147,135 @@ export class QueryAstService {
138
147
  withFrom(from: TableSourceNode): SelectQueryState {
139
148
  return this.state.withFrom(from);
140
149
  }
141
-
142
- /**
143
- * Selects a subquery as a column
144
- * @param alias - Alias for the subquery
145
- * @param query - Subquery to select
146
- * @returns Updated query state with subquery selection
147
- */
148
- selectSubquery(alias: string, query: SelectQueryNode): SelectQueryState {
149
- const node: ScalarSubqueryNode = { type: 'ScalarSubquery', query, alias };
150
- return this.state.withColumns([node]);
151
- }
152
-
153
- /**
154
- * Adds a JOIN clause to the query
155
- * @param join - Join node to add
156
- * @returns Updated query state with JOIN
157
- */
158
- withJoin(join: JoinNode): SelectQueryState {
159
- return this.state.withJoin(join);
160
- }
161
-
162
- /**
163
- * Adds a WHERE clause to the query
164
- * @param expr - Expression for the WHERE clause
165
- * @returns Updated query state with WHERE clause
166
- */
167
- withWhere(expr: ExpressionNode): SelectQueryState {
168
- const combined = this.combineExpressions(this.state.ast.where, expr);
169
- return this.state.withWhere(combined);
170
- }
171
-
172
- /**
173
- * Adds a GROUP BY clause to the query
174
- * @param col - Column to group by
175
- * @returns Updated query state with GROUP BY clause
176
- */
177
- withGroupBy(col: ColumnDef | ColumnNode): SelectQueryState {
178
- const from = this.state.ast.from;
179
- const tableRef = from.type === 'Table' && from.alias ? { ...this.table, alias: from.alias } : this.table;
180
- const node = buildColumnNode(tableRef, col);
181
- return this.state.withGroupBy([node]);
182
- }
183
-
184
- /**
185
- * Adds a HAVING clause to the query
186
- * @param expr - Expression for the HAVING clause
187
- * @returns Updated query state with HAVING clause
188
- */
189
- withHaving(expr: ExpressionNode): SelectQueryState {
190
- const combined = this.combineExpressions(this.state.ast.having, expr);
191
- return this.state.withHaving(combined);
192
- }
193
-
194
- /**
195
- * Adds an ORDER BY clause to the query
196
- * @param col - Column to order by
197
- * @param direction - Order direction (ASC/DESC)
198
- * @returns Updated query state with ORDER BY clause
199
- */
200
- withOrderBy(col: ColumnDef | ColumnNode, direction: OrderDirection): SelectQueryState {
150
+
151
+ /**
152
+ * Selects a subquery as a column
153
+ * @param alias - Alias for the subquery
154
+ * @param query - Subquery to select
155
+ * @returns Updated query state with subquery selection
156
+ */
157
+ selectSubquery(alias: string, query: SelectQueryNode): SelectQueryState {
158
+ const node: ScalarSubqueryNode = { type: 'ScalarSubquery', query, alias };
159
+ return this.state.withColumns([node]);
160
+ }
161
+
162
+ /**
163
+ * Adds a JOIN clause to the query
164
+ * @param join - Join node to add
165
+ * @returns Updated query state with JOIN
166
+ */
167
+ withJoin(join: JoinNode): SelectQueryState {
168
+ return this.state.withJoin(join);
169
+ }
170
+
171
+ /**
172
+ * Adds a WHERE clause to the query
173
+ * @param expr - Expression for the WHERE clause
174
+ * @returns Updated query state with WHERE clause
175
+ */
176
+ withWhere(expr: ExpressionNode): SelectQueryState {
177
+ const combined = this.combineExpressions(this.state.ast.where, expr);
178
+ return this.state.withWhere(combined);
179
+ }
180
+
181
+ /**
182
+ * Adds a GROUP BY clause to the query
183
+ * @param col - Column to group by
184
+ * @returns Updated query state with GROUP BY clause
185
+ */
186
+ withGroupBy(col: ColumnDef | OrderingTerm): SelectQueryState {
187
+ const term = this.normalizeOrderingTerm(col);
188
+ return this.state.withGroupBy([term]);
189
+ }
190
+
191
+ /**
192
+ * Adds a HAVING clause to the query
193
+ * @param expr - Expression for the HAVING clause
194
+ * @returns Updated query state with HAVING clause
195
+ */
196
+ withHaving(expr: ExpressionNode): SelectQueryState {
197
+ const combined = this.combineExpressions(this.state.ast.having, expr);
198
+ return this.state.withHaving(combined);
199
+ }
200
+
201
+ /**
202
+ * Adds an ORDER BY clause to the query
203
+ * @param col - Column to order by
204
+ * @param direction - Order direction (ASC/DESC)
205
+ * @returns Updated query state with ORDER BY clause
206
+ */
207
+ withOrderBy(
208
+ term: ColumnDef | OrderingTerm,
209
+ direction: OrderDirection,
210
+ nulls?: 'FIRST' | 'LAST',
211
+ collation?: string
212
+ ): SelectQueryState {
213
+ const normalized = this.normalizeOrderingTerm(term);
214
+ return this.state.withOrderBy([{ type: 'OrderBy', term: normalized, direction, nulls, collation }]);
215
+ }
216
+
217
+ /**
218
+ * Adds a DISTINCT clause to the query
219
+ * @param cols - Columns to make distinct
220
+ * @returns Updated query state with DISTINCT clause
221
+ */
222
+ withDistinct(cols: ColumnNode[]): SelectQueryState {
223
+ return this.state.withDistinct(cols);
224
+ }
225
+
226
+ /**
227
+ * Adds a LIMIT clause to the query
228
+ * @param limit - Maximum number of rows to return
229
+ * @returns Updated query state with LIMIT clause
230
+ */
231
+ withLimit(limit: number): SelectQueryState {
232
+ return this.state.withLimit(limit);
233
+ }
234
+
235
+ /**
236
+ * Adds an OFFSET clause to the query
237
+ * @param offset - Number of rows to skip
238
+ * @returns Updated query state with OFFSET clause
239
+ */
240
+ withOffset(offset: number): SelectQueryState {
241
+ return this.state.withOffset(offset);
242
+ }
243
+
244
+ /**
245
+ * Combines expressions with AND operator
246
+ * @param existing - Existing expression
247
+ * @param next - New expression to combine
248
+ * @returns Combined expression
249
+ */
250
+ private combineExpressions(existing: ExpressionNode | undefined, next: ExpressionNode): ExpressionNode {
251
+ return existing ? and(existing, next) : next;
252
+ }
253
+
254
+ private normalizeOrderingTerm(term: ColumnDef | OrderingTerm): OrderingTerm {
201
255
  const from = this.state.ast.from;
202
256
  const tableRef = from.type === 'Table' && from.alias ? { ...this.table, alias: from.alias } : this.table;
203
- const node = buildColumnNode(tableRef, col);
204
- return this.state.withOrderBy([{ type: 'OrderBy', column: node, direction }]);
205
- }
206
-
207
- /**
208
- * Adds a DISTINCT clause to the query
209
- * @param cols - Columns to make distinct
210
- * @returns Updated query state with DISTINCT clause
211
- */
212
- withDistinct(cols: ColumnNode[]): SelectQueryState {
213
- return this.state.withDistinct(cols);
214
- }
215
-
216
- /**
217
- * Adds a LIMIT clause to the query
218
- * @param limit - Maximum number of rows to return
219
- * @returns Updated query state with LIMIT clause
220
- */
221
- withLimit(limit: number): SelectQueryState {
222
- return this.state.withLimit(limit);
223
- }
224
-
225
- /**
226
- * Adds an OFFSET clause to the query
227
- * @param offset - Number of rows to skip
228
- * @returns Updated query state with OFFSET clause
229
- */
230
- withOffset(offset: number): SelectQueryState {
231
- return this.state.withOffset(offset);
232
- }
233
-
234
- /**
235
- * Combines expressions with AND operator
236
- * @param existing - Existing expression
237
- * @param next - New expression to combine
238
- * @returns Combined expression
239
- */
240
- private combineExpressions(existing: ExpressionNode | undefined, next: ExpressionNode): ExpressionNode {
241
- return existing ? and(existing, next) : next;
242
- }
243
-
244
- }
257
+ const termType = (term as any)?.type;
258
+ if (termType === 'Column') {
259
+ return term as ColumnNode;
260
+ }
261
+ if (termType === 'AliasRef') {
262
+ return term as AliasRefNode;
263
+ }
264
+ if (isOperandNode(term)) {
265
+ return term as OrderingTerm;
266
+ }
267
+ if (
268
+ termType === 'BinaryExpression' ||
269
+ termType === 'LogicalExpression' ||
270
+ termType === 'NullExpression' ||
271
+ termType === 'InExpression' ||
272
+ termType === 'ExistsExpression' ||
273
+ termType === 'BetweenExpression' ||
274
+ termType === 'ArithmeticExpression'
275
+ ) {
276
+ return term as ExpressionNode;
277
+ }
278
+ return buildColumnNode(tableRef, term as ColumnDef);
279
+ }
280
+
281
+ }