metal-orm 1.0.16 → 1.0.18

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 (64) hide show
  1. package/README.md +37 -40
  2. package/dist/decorators/index.cjs +344 -69
  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 +344 -69
  7. package/dist/decorators/index.js.map +1 -1
  8. package/dist/index.cjs +567 -181
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +66 -30
  11. package/dist/index.d.ts +66 -30
  12. package/dist/index.js +559 -181
  13. package/dist/index.js.map +1 -1
  14. package/dist/{select-BKZrMRCQ.d.cts → select-BuMpVcVt.d.cts} +265 -74
  15. package/dist/{select-BKZrMRCQ.d.ts → select-BuMpVcVt.d.ts} +265 -74
  16. package/package.json +5 -1
  17. package/src/codegen/naming-strategy.ts +15 -10
  18. package/src/core/ast/aggregate-functions.ts +50 -4
  19. package/src/core/ast/builders.ts +23 -3
  20. package/src/core/ast/expression-builders.ts +36 -16
  21. package/src/core/ast/expression-nodes.ts +17 -9
  22. package/src/core/ast/join-node.ts +5 -3
  23. package/src/core/ast/join.ts +16 -16
  24. package/src/core/ast/query.ts +44 -29
  25. package/src/core/ddl/dialects/mssql-schema-dialect.ts +18 -0
  26. package/src/core/ddl/dialects/mysql-schema-dialect.ts +11 -0
  27. package/src/core/ddl/dialects/postgres-schema-dialect.ts +9 -0
  28. package/src/core/ddl/dialects/sqlite-schema-dialect.ts +9 -0
  29. package/src/core/ddl/introspect/functions/postgres.ts +2 -6
  30. package/src/core/dialect/abstract.ts +12 -8
  31. package/src/core/dialect/base/sql-dialect.ts +58 -46
  32. package/src/core/dialect/mssql/functions.ts +24 -15
  33. package/src/core/dialect/mssql/index.ts +53 -28
  34. package/src/core/dialect/postgres/functions.ts +33 -24
  35. package/src/core/dialect/sqlite/functions.ts +19 -12
  36. package/src/core/dialect/sqlite/index.ts +22 -13
  37. package/src/core/functions/datetime.ts +2 -1
  38. package/src/core/functions/numeric.ts +2 -1
  39. package/src/core/functions/standard-strategy.ts +52 -12
  40. package/src/core/functions/text.ts +2 -1
  41. package/src/core/functions/types.ts +8 -8
  42. package/src/index.ts +5 -4
  43. package/src/orm/domain-event-bus.ts +43 -25
  44. package/src/orm/entity-meta.ts +40 -0
  45. package/src/orm/execution-context.ts +6 -0
  46. package/src/orm/hydration-context.ts +6 -4
  47. package/src/orm/orm-session.ts +35 -24
  48. package/src/orm/orm.ts +10 -10
  49. package/src/orm/query-logger.ts +15 -0
  50. package/src/orm/runtime-types.ts +60 -2
  51. package/src/orm/transaction-runner.ts +7 -0
  52. package/src/orm/unit-of-work.ts +1 -0
  53. package/src/query-builder/column-selector.ts +9 -7
  54. package/src/query-builder/insert-query-state.ts +13 -3
  55. package/src/query-builder/query-ast-service.ts +59 -38
  56. package/src/query-builder/relation-conditions.ts +38 -34
  57. package/src/query-builder/relation-manager.ts +8 -3
  58. package/src/query-builder/relation-service.ts +59 -46
  59. package/src/query-builder/select-helpers.ts +50 -0
  60. package/src/query-builder/select-query-state.ts +19 -7
  61. package/src/query-builder/select.ts +339 -167
  62. package/src/query-builder/update-query-state.ts +31 -9
  63. package/src/schema/column.ts +75 -39
  64. package/src/schema/types.ts +17 -6
@@ -70,17 +70,17 @@ export class RelationService {
70
70
  * @param predicate - Optional predicate expression
71
71
  * @returns Relation result with updated state and hydration
72
72
  */
73
- match(
74
- relationName: string,
75
- predicate?: ExpressionNode
76
- ): RelationResult {
77
- const joined = this.joinRelation(relationName, JOIN_KINDS.INNER, predicate);
78
- const pk = findPrimaryKey(this.table);
79
- const distinctCols: ColumnNode[] = [{ type: 'Column', table: this.table.name, name: pk }];
80
- const existingDistinct = joined.state.ast.distinct ? joined.state.ast.distinct : [];
81
- const nextState = this.astService(joined.state).withDistinct([...existingDistinct, ...distinctCols]);
82
- return { state: nextState, hydration: joined.hydration };
83
- }
73
+ match(
74
+ relationName: string,
75
+ predicate?: ExpressionNode
76
+ ): RelationResult {
77
+ const joined = this.joinRelation(relationName, JOIN_KINDS.INNER, predicate);
78
+ const pk = findPrimaryKey(this.table);
79
+ const distinctCols: ColumnNode[] = [{ type: 'Column', table: this.rootTableName(), name: pk }];
80
+ const existingDistinct = joined.state.ast.distinct ? joined.state.ast.distinct : [];
81
+ const nextState = this.astService(joined.state).withDistinct([...existingDistinct, ...distinctCols]);
82
+ return { state: nextState, hydration: joined.hydration };
83
+ }
84
84
 
85
85
  /**
86
86
  * Includes a relation in the query result
@@ -190,17 +190,22 @@ export class RelationService {
190
190
  * @param ast - Query AST to modify
191
191
  * @returns Modified query AST with relation correlation
192
192
  */
193
- applyRelationCorrelation(
194
- relationName: string,
195
- ast: SelectQueryNode
196
- ): SelectQueryNode {
197
- const relation = this.getRelation(relationName);
198
- const correlation = buildRelationCorrelation(this.table, relation);
199
- const whereInSubquery = ast.where
200
- ? and(correlation, ast.where)
201
- : correlation;
202
-
203
- return {
193
+ applyRelationCorrelation(
194
+ relationName: string,
195
+ ast: SelectQueryNode,
196
+ additionalCorrelation?: ExpressionNode
197
+ ): SelectQueryNode {
198
+ const relation = this.getRelation(relationName);
199
+ const rootAlias = this.state.ast.from.type === 'Table' ? this.state.ast.from.alias : undefined;
200
+ let correlation = buildRelationCorrelation(this.table, relation, rootAlias);
201
+ if (additionalCorrelation) {
202
+ correlation = and(correlation, additionalCorrelation);
203
+ }
204
+ const whereInSubquery = ast.where
205
+ ? and(correlation, ast.where)
206
+ : correlation;
207
+
208
+ return {
204
209
  ...ast,
205
210
  where: whereInSubquery
206
211
  };
@@ -214,26 +219,28 @@ export class RelationService {
214
219
  * @param extraCondition - Additional join condition
215
220
  * @returns Updated query state with join
216
221
  */
217
- private withJoin(
218
- state: SelectQueryState,
219
- relationName: string,
220
- joinKind: JoinKind,
221
- extraCondition?: ExpressionNode
222
- ): SelectQueryState {
223
- const relation = this.getRelation(relationName);
224
- if (relation.type === RelationKinds.BelongsToMany) {
225
- const joins = buildBelongsToManyJoins(
226
- this.table,
227
- relationName,
228
- relation as BelongsToManyRelation,
229
- joinKind,
230
- extraCondition
231
- );
232
- return joins.reduce((current, join) => this.astService(current).withJoin(join), state);
233
- }
234
-
235
- const condition = buildRelationJoinCondition(this.table, relation, extraCondition);
236
- const joinNode = createJoinNode(joinKind, relation.target.name, condition, relationName);
222
+ private withJoin(
223
+ state: SelectQueryState,
224
+ relationName: string,
225
+ joinKind: JoinKind,
226
+ extraCondition?: ExpressionNode
227
+ ): SelectQueryState {
228
+ const relation = this.getRelation(relationName);
229
+ const rootAlias = state.ast.from.type === 'Table' ? state.ast.from.alias : undefined;
230
+ if (relation.type === RelationKinds.BelongsToMany) {
231
+ const joins = buildBelongsToManyJoins(
232
+ this.table,
233
+ relationName,
234
+ relation as BelongsToManyRelation,
235
+ joinKind,
236
+ extraCondition,
237
+ rootAlias
238
+ );
239
+ return joins.reduce((current, join) => this.astService(current).withJoin(join), state);
240
+ }
241
+
242
+ const condition = buildRelationJoinCondition(this.table, relation, extraCondition, rootAlias);
243
+ const joinNode = createJoinNode(joinKind, relation.target.name, condition, relationName);
237
244
 
238
245
  return this.astService(state).withJoin(joinNode);
239
246
  }
@@ -277,9 +284,15 @@ export class RelationService {
277
284
  * @param state - Current query state
278
285
  * @returns QueryAstService instance
279
286
  */
280
- private astService(state: SelectQueryState = this.state): QueryAstService {
281
- return this.createQueryAstService(this.table, state);
282
- }
283
- }
287
+ private astService(state: SelectQueryState = this.state): QueryAstService {
288
+ return this.createQueryAstService(this.table, state);
289
+ }
290
+
291
+ private rootTableName(): string {
292
+ const from = this.state.ast.from;
293
+ if (from.type === 'Table' && from.alias) return from.alias;
294
+ return this.table.name;
295
+ }
296
+ }
284
297
 
285
298
  export type { RelationResult } from './relation-projection-helper.js';
@@ -0,0 +1,50 @@
1
+ import type { TableDef } from '../schema/table.js';
2
+ import type { ColumnDef } from '../schema/column.js';
3
+ import { getTableDefFromEntity } from '../decorators/bootstrap.js';
4
+
5
+ /**
6
+ * Build a typed selection map from a TableDef.
7
+ */
8
+ export function sel<
9
+ TTable extends TableDef,
10
+ K extends keyof TTable['columns'] & string
11
+ >(table: TTable, ...cols: K[]): Record<K, TTable['columns'][K]> {
12
+ const selection = {} as Record<K, TTable['columns'][K]>;
13
+
14
+ for (const col of cols) {
15
+ const def = table.columns[col] as TTable['columns'][K];
16
+ if (!def) {
17
+ throw new Error(`Column '${col}' not found on table '${table.name}'`);
18
+ }
19
+ selection[col] = def;
20
+ }
21
+
22
+ return selection;
23
+ }
24
+
25
+ type Ctor<T> = { new (...args: any[]): T };
26
+
27
+ /**
28
+ * Build a typed selection map from an entity constructor.
29
+ */
30
+ export function esel<TEntity, K extends keyof TEntity & string>(
31
+ entity: Ctor<TEntity>,
32
+ ...props: K[]
33
+ ): Record<K, ColumnDef> {
34
+ const table = getTableDefFromEntity(entity) as TableDef | undefined;
35
+ if (!table) {
36
+ throw new Error(`No table definition registered for entity '${entity.name}'`);
37
+ }
38
+
39
+ const selection = {} as Record<K, ColumnDef>;
40
+
41
+ for (const prop of props) {
42
+ const col = table.columns[prop];
43
+ if (!col) {
44
+ throw new Error(`No column '${prop}' found for entity '${entity.name}'`);
45
+ }
46
+ selection[prop] = col;
47
+ }
48
+
49
+ return selection;
50
+ }
@@ -1,5 +1,5 @@
1
1
  import { TableDef } from '../schema/table.js';
2
- import { SelectQueryNode, CommonTableExpressionNode, OrderByNode, SetOperationNode } from '../core/ast/query.js';
2
+ import { SelectQueryNode, CommonTableExpressionNode, OrderByNode, SetOperationNode, TableSourceNode } from '../core/ast/query.js';
3
3
  import {
4
4
  ColumnNode,
5
5
  ExpressionNode,
@@ -74,12 +74,24 @@ export class SelectQueryState {
74
74
  * @param join - Join node to add
75
75
  * @returns New SelectQueryState with added join
76
76
  */
77
- withJoin(join: JoinNode): SelectQueryState {
78
- return this.clone({
79
- ...this.ast,
80
- joins: [...(this.ast.joins ?? []), join]
81
- });
82
- }
77
+ withJoin(join: JoinNode): SelectQueryState {
78
+ return this.clone({
79
+ ...this.ast,
80
+ joins: [...(this.ast.joins ?? []), join]
81
+ });
82
+ }
83
+
84
+ /**
85
+ * Replaces the FROM clause.
86
+ * @param from - Table source for the FROM clause
87
+ * @returns New SelectQueryState with updated FROM
88
+ */
89
+ withFrom(from: TableSourceNode): SelectQueryState {
90
+ return this.clone({
91
+ ...this.ast,
92
+ from
93
+ });
94
+ }
83
95
 
84
96
  /**
85
97
  * Adds a WHERE clause to the query