metal-orm 1.0.43 → 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 (84) hide show
  1. package/README.md +173 -30
  2. package/dist/index.cjs +896 -476
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +1146 -275
  5. package/dist/index.d.ts +1146 -275
  6. package/dist/index.js +896 -474
  7. package/dist/index.js.map +1 -1
  8. package/package.json +1 -1
  9. package/src/core/ast/adapters.ts +8 -2
  10. package/src/core/ast/builders.ts +105 -81
  11. package/src/core/ast/expression-builders.ts +430 -390
  12. package/src/core/ast/expression-visitor.ts +47 -8
  13. package/src/core/ast/helpers.ts +23 -0
  14. package/src/core/ast/join-node.ts +17 -1
  15. package/src/core/ddl/dialects/base-schema-dialect.ts +7 -1
  16. package/src/core/ddl/dialects/index.ts +1 -0
  17. package/src/core/ddl/dialects/mssql-schema-dialect.ts +1 -0
  18. package/src/core/ddl/dialects/mysql-schema-dialect.ts +1 -0
  19. package/src/core/ddl/dialects/postgres-schema-dialect.ts +1 -0
  20. package/src/core/ddl/dialects/sqlite-schema-dialect.ts +1 -0
  21. package/src/core/ddl/introspect/catalogs/index.ts +1 -0
  22. package/src/core/ddl/introspect/catalogs/postgres.ts +2 -0
  23. package/src/core/ddl/introspect/context.ts +6 -0
  24. package/src/core/ddl/introspect/functions/postgres.ts +13 -0
  25. package/src/core/ddl/introspect/mssql.ts +11 -0
  26. package/src/core/ddl/introspect/mysql.ts +2 -0
  27. package/src/core/ddl/introspect/postgres.ts +14 -0
  28. package/src/core/ddl/introspect/registry.ts +14 -0
  29. package/src/core/ddl/introspect/run-select.ts +13 -0
  30. package/src/core/ddl/introspect/sqlite.ts +22 -0
  31. package/src/core/ddl/introspect/utils.ts +18 -0
  32. package/src/core/ddl/naming-strategy.ts +6 -0
  33. package/src/core/ddl/schema-dialect.ts +19 -6
  34. package/src/core/ddl/schema-diff.ts +22 -0
  35. package/src/core/ddl/schema-generator.ts +22 -0
  36. package/src/core/ddl/schema-plan-executor.ts +6 -0
  37. package/src/core/ddl/schema-types.ts +6 -0
  38. package/src/core/dialect/abstract.ts +2 -2
  39. package/src/core/execution/pooling/pool.ts +12 -7
  40. package/src/core/functions/datetime.ts +57 -33
  41. package/src/core/functions/numeric.ts +95 -30
  42. package/src/core/functions/standard-strategy.ts +35 -0
  43. package/src/core/functions/text.ts +83 -22
  44. package/src/core/functions/types.ts +23 -8
  45. package/src/decorators/bootstrap.ts +16 -4
  46. package/src/decorators/column.ts +17 -0
  47. package/src/decorators/decorator-metadata.ts +27 -0
  48. package/src/decorators/entity.ts +8 -0
  49. package/src/decorators/index.ts +3 -0
  50. package/src/decorators/relations.ts +32 -0
  51. package/src/orm/als.ts +34 -9
  52. package/src/orm/entity-context.ts +54 -0
  53. package/src/orm/entity-metadata.ts +122 -9
  54. package/src/orm/execute.ts +15 -0
  55. package/src/orm/lazy-batch.ts +68 -98
  56. package/src/orm/relations/has-many.ts +44 -0
  57. package/src/query/index.ts +74 -0
  58. package/src/query/target.ts +46 -0
  59. package/src/query-builder/delete-query-state.ts +30 -0
  60. package/src/query-builder/delete.ts +64 -19
  61. package/src/query-builder/hydration-manager.ts +46 -0
  62. package/src/query-builder/insert-query-state.ts +30 -0
  63. package/src/query-builder/insert.ts +46 -2
  64. package/src/query-builder/query-ast-service.ts +5 -0
  65. package/src/query-builder/query-resolution.ts +78 -0
  66. package/src/query-builder/raw-column-parser.ts +5 -0
  67. package/src/query-builder/relation-alias.ts +7 -0
  68. package/src/query-builder/relation-conditions.ts +61 -48
  69. package/src/query-builder/relation-service.ts +68 -63
  70. package/src/query-builder/relation-utils.ts +3 -0
  71. package/src/query-builder/select/cte-facet.ts +40 -0
  72. package/src/query-builder/select/from-facet.ts +80 -0
  73. package/src/query-builder/select/join-facet.ts +62 -0
  74. package/src/query-builder/select/predicate-facet.ts +103 -0
  75. package/src/query-builder/select/projection-facet.ts +69 -0
  76. package/src/query-builder/select/relation-facet.ts +81 -0
  77. package/src/query-builder/select/setop-facet.ts +36 -0
  78. package/src/query-builder/select-helpers.ts +13 -0
  79. package/src/query-builder/select-query-builder-deps.ts +19 -1
  80. package/src/query-builder/select-query-state.ts +2 -1
  81. package/src/query-builder/select.ts +795 -1163
  82. package/src/query-builder/update-query-state.ts +52 -0
  83. package/src/query-builder/update.ts +69 -19
  84. package/src/schema/table-guards.ts +31 -0
@@ -0,0 +1,103 @@
1
+ import { ColumnDef } from '../../schema/column.js';
2
+ import { ExpressionNode } from '../../core/ast/expression.js';
3
+ import { OrderingTerm } from '../../core/ast/query.js';
4
+ import { OrderDirection } from '../../core/sql/sql.js';
5
+ import { SelectQueryBuilderContext, SelectQueryBuilderEnvironment } from '../select-query-builder-deps.js';
6
+ import { QueryAstService } from '../query-ast-service.js';
7
+ import { SelectQueryState } from '../select-query-state.js';
8
+
9
+ /**
10
+ * Facet responsible for filtering and ordering operations
11
+ */
12
+ export class SelectPredicateFacet {
13
+ /**
14
+ * Creates a new SelectPredicateFacet instance
15
+ * @param env - Query builder environment
16
+ * @param createAstService - Function to create AST service
17
+ */
18
+ constructor(
19
+ private readonly env: SelectQueryBuilderEnvironment,
20
+ private readonly createAstService: (state: SelectQueryState) => QueryAstService
21
+ ) { }
22
+
23
+ /**
24
+ * Adds a WHERE condition to the query
25
+ * @param context - Current query context
26
+ * @param expr - WHERE expression
27
+ * @returns Updated query context with WHERE condition
28
+ */
29
+ where(context: SelectQueryBuilderContext, expr: ExpressionNode): SelectQueryBuilderContext {
30
+ const astService = this.createAstService(context.state);
31
+ const nextState = astService.withWhere(expr);
32
+ return { state: nextState, hydration: context.hydration };
33
+ }
34
+
35
+ /**
36
+ * Adds a GROUP BY clause to the query
37
+ * @param context - Current query context
38
+ * @param term - Column or ordering term to group by
39
+ * @returns Updated query context with GROUP BY clause
40
+ */
41
+ groupBy(context: SelectQueryBuilderContext, term: ColumnDef | OrderingTerm): SelectQueryBuilderContext {
42
+ const astService = this.createAstService(context.state);
43
+ const nextState = astService.withGroupBy(term);
44
+ return { state: nextState, hydration: context.hydration };
45
+ }
46
+
47
+ /**
48
+ * Adds a HAVING condition to the query
49
+ * @param context - Current query context
50
+ * @param expr - HAVING expression
51
+ * @returns Updated query context with HAVING condition
52
+ */
53
+ having(context: SelectQueryBuilderContext, expr: ExpressionNode): SelectQueryBuilderContext {
54
+ const astService = this.createAstService(context.state);
55
+ const nextState = astService.withHaving(expr);
56
+ return { state: nextState, hydration: context.hydration };
57
+ }
58
+
59
+ /**
60
+ * Adds an ORDER BY clause to the query
61
+ * @param context - Current query context
62
+ * @param term - Column or ordering term to order by
63
+ * @param direction - Order direction
64
+ * @param nulls - Nulls ordering
65
+ * @param collation - Collation
66
+ * @returns Updated query context with ORDER BY clause
67
+ */
68
+ orderBy(
69
+ context: SelectQueryBuilderContext,
70
+ term: ColumnDef | OrderingTerm,
71
+ direction: OrderDirection,
72
+ nulls?: 'FIRST' | 'LAST',
73
+ collation?: string
74
+ ): SelectQueryBuilderContext {
75
+ const astService = this.createAstService(context.state);
76
+ const nextState = astService.withOrderBy(term, direction, nulls, collation);
77
+ return { state: nextState, hydration: context.hydration };
78
+ }
79
+
80
+ /**
81
+ * Adds a LIMIT clause to the query
82
+ * @param context - Current query context
83
+ * @param n - Maximum number of rows
84
+ * @returns Updated query context with LIMIT clause
85
+ */
86
+ limit(context: SelectQueryBuilderContext, n: number): SelectQueryBuilderContext {
87
+ const astService = this.createAstService(context.state);
88
+ const nextState = astService.withLimit(n);
89
+ return { state: nextState, hydration: context.hydration };
90
+ }
91
+
92
+ /**
93
+ * Adds an OFFSET clause to the query
94
+ * @param context - Current query context
95
+ * @param n - Number of rows to skip
96
+ * @returns Updated query context with OFFSET clause
97
+ */
98
+ offset(context: SelectQueryBuilderContext, n: number): SelectQueryBuilderContext {
99
+ const astService = this.createAstService(context.state);
100
+ const nextState = astService.withOffset(n);
101
+ return { state: nextState, hydration: context.hydration };
102
+ }
103
+ }
@@ -0,0 +1,69 @@
1
+ import { ColumnDef } from '../../schema/column.js';
2
+ import { ColumnNode, FunctionNode, CaseExpressionNode, WindowFunctionNode } from '../../core/ast/expression.js';
3
+ import { SelectQueryBuilderContext } from '../select-query-builder-deps.js';
4
+ import { ColumnSelector } from '../column-selector.js';
5
+ import { SelectQueryNode } from '../../core/ast/query.js';
6
+
7
+ type ColumnSelectionValue = ColumnDef | FunctionNode | CaseExpressionNode | WindowFunctionNode;
8
+
9
+ /**
10
+ * Facet responsible for projection operations (SELECT, DISTINCT, etc.)
11
+ */
12
+ export class SelectProjectionFacet {
13
+ /**
14
+ * Creates a new SelectProjectionFacet instance
15
+ * @param columnSelector - Column selector dependency
16
+ */
17
+ constructor(private readonly columnSelector: ColumnSelector) { }
18
+
19
+ /**
20
+ * Selects columns for the query
21
+ * @param context - Current query context
22
+ * @param columns - Columns to select
23
+ * @returns Updated query context with selected columns
24
+ */
25
+ select(
26
+ context: SelectQueryBuilderContext,
27
+ columns: Record<string, ColumnSelectionValue>
28
+ ): SelectQueryBuilderContext {
29
+ return { ...context, state: this.columnSelector.select(context, columns).state };
30
+ }
31
+
32
+ /**
33
+ * Selects raw column expressions
34
+ * @param context - Current query context
35
+ * @param cols - Raw column expressions
36
+ * @returns Updated query context with raw column selections
37
+ */
38
+ selectRaw(context: SelectQueryBuilderContext, cols: string[]): SelectQueryBuilderContext {
39
+ return { ...context, state: this.columnSelector.selectRaw(context, cols).state };
40
+ }
41
+
42
+ /**
43
+ * Selects a subquery as a column
44
+ * @param context - Current query context
45
+ * @param alias - Alias for the subquery
46
+ * @param query - Subquery to select
47
+ * @returns Updated query context with subquery selection
48
+ */
49
+ selectSubquery(
50
+ context: SelectQueryBuilderContext,
51
+ alias: string,
52
+ query: SelectQueryNode
53
+ ): SelectQueryBuilderContext {
54
+ return { ...context, state: this.columnSelector.selectSubquery(context, alias, query).state };
55
+ }
56
+
57
+ /**
58
+ * Adds DISTINCT clause to the query
59
+ * @param context - Current query context
60
+ * @param cols - Columns to make distinct
61
+ * @returns Updated query context with DISTINCT clause
62
+ */
63
+ distinct(
64
+ context: SelectQueryBuilderContext,
65
+ cols: (ColumnDef | ColumnNode)[]
66
+ ): SelectQueryBuilderContext {
67
+ return { ...context, state: this.columnSelector.distinct(context, cols).state };
68
+ }
69
+ }
@@ -0,0 +1,81 @@
1
+ import { ExpressionNode } from '../../core/ast/expression.js';
2
+ import { JoinKind } from '../../core/sql/sql.js';
3
+ import { SelectQueryBuilderContext } from '../select-query-builder-deps.js';
4
+ import { RelationManager } from '../relation-manager.js';
5
+ import { RelationIncludeOptions } from '../relation-types.js';
6
+ import { SelectQueryNode } from '../../core/ast/query.js';
7
+
8
+ /**
9
+ * Facet responsible for relation operations (include, match, whereHas, etc.)
10
+ */
11
+ export class SelectRelationFacet {
12
+ /**
13
+ * Creates a new SelectRelationFacet instance
14
+ * @param relationManager - Relation manager dependency
15
+ */
16
+ constructor(private readonly relationManager: RelationManager) { }
17
+
18
+ /**
19
+ * Matches records based on a relationship
20
+ * @param context - Current query context
21
+ * @param relationName - Name of the relationship
22
+ * @param predicate - Optional predicate
23
+ * @returns Updated query context with relation match
24
+ */
25
+ match(
26
+ context: SelectQueryBuilderContext,
27
+ relationName: string,
28
+ predicate?: ExpressionNode
29
+ ): SelectQueryBuilderContext {
30
+ return this.relationManager.match(context, relationName, predicate);
31
+ }
32
+
33
+ /**
34
+ * Joins a related table
35
+ * @param context - Current query context
36
+ * @param relationName - Name of the relationship
37
+ * @param joinKind - Type of join
38
+ * @param extraCondition - Optional additional condition
39
+ * @returns Updated query context with relation join
40
+ */
41
+ joinRelation(
42
+ context: SelectQueryBuilderContext,
43
+ relationName: string,
44
+ joinKind: JoinKind,
45
+ extraCondition?: ExpressionNode
46
+ ): SelectQueryBuilderContext {
47
+ return this.relationManager.joinRelation(context, relationName, joinKind, extraCondition);
48
+ }
49
+
50
+ /**
51
+ * Includes related data in the query results
52
+ * @param context - Current query context
53
+ * @param relationName - Name of the relationship to include
54
+ * @param options - Optional include options
55
+ * @returns Updated query context with relation inclusion
56
+ */
57
+ include(
58
+ context: SelectQueryBuilderContext,
59
+ relationName: string,
60
+ options?: RelationIncludeOptions
61
+ ): SelectQueryBuilderContext {
62
+ return this.relationManager.include(context, relationName, options);
63
+ }
64
+
65
+ /**
66
+ * Applies correlation for relation-based subqueries
67
+ * @param context - Current query context
68
+ * @param relationName - Name of the relationship
69
+ * @param subAst - Subquery AST
70
+ * @param extraCorrelate - Optional additional correlation
71
+ * @returns Modified subquery AST with correlation
72
+ */
73
+ applyRelationCorrelation(
74
+ context: SelectQueryBuilderContext,
75
+ relationName: string,
76
+ subAst: SelectQueryNode,
77
+ extraCorrelate?: ExpressionNode
78
+ ): SelectQueryNode {
79
+ return this.relationManager.applyRelationCorrelation(context, relationName, subAst, extraCorrelate);
80
+ }
81
+ }
@@ -0,0 +1,36 @@
1
+ import { SelectQueryNode, SetOperationKind } from '../../core/ast/query.js';
2
+ import { SelectQueryBuilderContext, SelectQueryBuilderEnvironment } from '../select-query-builder-deps.js';
3
+ import { QueryAstService } from '../query-ast-service.js';
4
+ import { SelectQueryState } from '../select-query-state.js';
5
+
6
+ /**
7
+ * Facet responsible for set operations (UNION, INTERSECT, EXCEPT)
8
+ */
9
+ export class SelectSetOpFacet {
10
+ /**
11
+ * Creates a new SelectSetOpFacet instance
12
+ * @param env - Query builder environment
13
+ * @param createAstService - Function to create AST service
14
+ */
15
+ constructor(
16
+ private readonly env: SelectQueryBuilderEnvironment,
17
+ private readonly createAstService: (state: SelectQueryState) => QueryAstService
18
+ ) { }
19
+
20
+ /**
21
+ * Applies a set operation to the query
22
+ * @param context - Current query context
23
+ * @param operator - Set operation kind
24
+ * @param subAst - Subquery AST to combine
25
+ * @returns Updated query context with set operation
26
+ */
27
+ applySetOperation(
28
+ context: SelectQueryBuilderContext,
29
+ operator: SetOperationKind,
30
+ subAst: SelectQueryNode
31
+ ): SelectQueryBuilderContext {
32
+ const astService = this.createAstService(context.state);
33
+ const nextState = astService.withSetOperation(operator, subAst);
34
+ return { state: nextState, hydration: context.hydration };
35
+ }
36
+ }
@@ -4,6 +4,12 @@ import { getTableDefFromEntity } from '../decorators/bootstrap.js';
4
4
 
5
5
  /**
6
6
  * Build a typed selection map from a TableDef.
7
+ * @template TTable - The table definition type
8
+ * @template K - The column name keys
9
+ * @param table - The table definition to select columns from
10
+ * @param cols - Column names to include in the selection
11
+ * @returns A typed record mapping column names to their definitions
12
+ * @throws Error if a specified column is not found on the table
7
13
  */
8
14
  export function sel<
9
15
  TTable extends TableDef,
@@ -26,6 +32,13 @@ type Ctor<T> = { new(...args: unknown[]): T };
26
32
 
27
33
  /**
28
34
  * Build a typed selection map from an entity constructor.
35
+ * @template TEntity - The entity type
36
+ * @template K - The property name keys
37
+ * @param entity - The entity constructor to get table definition from
38
+ * @param props - Property names to include in the selection
39
+ * @returns A record mapping property names to their column definitions
40
+ * @throws Error if no table definition is registered for the entity
41
+ * @throws Error if a specified property is not found as a column
29
42
  */
30
43
  export function esel<TEntity extends object, K extends keyof TEntity & string>(
31
44
  entity: Ctor<TEntity>,
@@ -4,6 +4,8 @@ import { HydrationManager } from './hydration-manager.js';
4
4
  import { HydrationPlanner } from './hydration-planner.js';
5
5
  import { QueryAstService } from './query-ast-service.js';
6
6
  import { RelationService } from './relation-service.js';
7
+ import { ColumnSelector } from './column-selector.js';
8
+ import { RelationManager } from './relation-manager.js';
7
9
 
8
10
  /**
9
11
  * Context for query building operations
@@ -60,6 +62,18 @@ export interface SelectQueryBuilderDependencies {
60
62
  state: SelectQueryState,
61
63
  hydration: HydrationManager
62
64
  ) => RelationService;
65
+ /**
66
+ * Creates a new column selector
67
+ * @param env - Query builder environment
68
+ * @returns New column selector
69
+ */
70
+ createColumnSelector: (env: SelectQueryBuilderEnvironment) => ColumnSelector;
71
+ /**
72
+ * Creates a new relation manager
73
+ * @param env - Query builder environment
74
+ * @returns New relation manager
75
+ */
76
+ createRelationManager: (env: SelectQueryBuilderEnvironment) => RelationManager;
63
77
  }
64
78
 
65
79
  /**
@@ -99,13 +113,17 @@ export const resolveSelectQueryBuilderDependencies = (
99
113
  const createRelationService =
100
114
  overrides.createRelationService ??
101
115
  ((table, state, hydration) => new RelationService(table, state, hydration, createQueryAstService));
116
+ const createColumnSelector = overrides.createColumnSelector ?? (env => new ColumnSelector(env));
117
+ const createRelationManager = overrides.createRelationManager ?? (env => new RelationManager(env));
102
118
 
103
119
  return {
104
120
  createState: overrides.createState ?? (table => new SelectQueryState(table)),
105
121
  createHydration,
106
122
  createHydrationPlanner,
107
123
  createQueryAstService,
108
- createRelationService
124
+ createRelationService,
125
+ createColumnSelector,
126
+ createRelationManager
109
127
  };
110
128
  };
111
129
 
@@ -7,6 +7,7 @@ import {
7
7
  TableSourceNode,
8
8
  OrderingTerm
9
9
  } from '../core/ast/query.js';
10
+ import { createTableNode } from '../core/ast/builders.js';
10
11
  import {
11
12
  ColumnNode,
12
13
  ExpressionNode,
@@ -49,7 +50,7 @@ export class SelectQueryState {
49
50
  this.table = table;
50
51
  this.ast = ast ?? {
51
52
  type: 'SelectQuery',
52
- from: { type: 'Table', name: table.name },
53
+ from: createTableNode(table),
53
54
  columns: [],
54
55
  joins: []
55
56
  };