metal-orm 1.0.7 → 1.0.9

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 (153) hide show
  1. package/README.md +133 -121
  2. package/dist/decorators/index.cjs +2564 -0
  3. package/dist/decorators/index.cjs.map +1 -0
  4. package/dist/decorators/index.d.cts +53 -0
  5. package/dist/decorators/index.d.ts +53 -0
  6. package/dist/decorators/index.js +2530 -0
  7. package/dist/decorators/index.js.map +1 -0
  8. package/dist/index.cjs +4227 -0
  9. package/dist/index.cjs.map +1 -0
  10. package/dist/index.d.cts +701 -0
  11. package/dist/index.d.ts +701 -0
  12. package/dist/index.js +4131 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/select-654m4qy8.d.cts +1522 -0
  15. package/dist/select-654m4qy8.d.ts +1522 -0
  16. package/package.json +27 -20
  17. package/src/codegen/typescript.ts +405 -393
  18. package/src/core/ast/aggregate-functions.ts +30 -0
  19. package/src/core/ast/builders.ts +43 -0
  20. package/src/core/ast/expression-builders.ts +310 -0
  21. package/src/core/ast/expression-nodes.ts +211 -0
  22. package/src/core/ast/expression-visitor.ts +99 -0
  23. package/src/core/ast/expression.ts +5 -0
  24. package/src/{utils → core/ast}/join-node.ts +20 -20
  25. package/src/{ast → core/ast}/join.ts +18 -18
  26. package/src/{ast → core/ast}/query.ts +113 -113
  27. package/src/core/ast/window-functions.ts +140 -0
  28. package/src/{dialect → core/dialect}/abstract.ts +94 -94
  29. package/src/{dialect → core/dialect}/mssql/index.ts +31 -31
  30. package/src/{dialect → core/dialect}/mysql/index.ts +31 -31
  31. package/src/{dialect → core/dialect}/postgres/index.ts +45 -45
  32. package/src/{dialect → core/dialect}/sqlite/index.ts +45 -45
  33. package/src/{constants → core/sql}/sql-operator-config.ts +39 -39
  34. package/src/decorators/bootstrap.ts +126 -0
  35. package/src/decorators/column.ts +78 -0
  36. package/src/decorators/entity.ts +36 -0
  37. package/src/decorators/index.ts +4 -0
  38. package/src/decorators/relations.ts +107 -0
  39. package/src/global.d.ts +1 -0
  40. package/src/index.ts +22 -22
  41. package/src/orm/db-executor.ts +11 -0
  42. package/src/orm/domain-event-bus.ts +52 -0
  43. package/src/{runtime → orm}/entity-meta.ts +52 -52
  44. package/src/orm/entity-metadata.ts +140 -0
  45. package/src/{runtime → orm}/entity.ts +252 -252
  46. package/src/{runtime → orm}/execute.ts +36 -36
  47. package/src/{runtime → orm}/hydration.ts +103 -103
  48. package/src/orm/identity-map.ts +37 -0
  49. package/src/{runtime → orm}/lazy-batch.ts +205 -205
  50. package/src/orm/orm-context.ts +154 -0
  51. package/src/orm/relation-change-processor.ts +140 -0
  52. package/src/{runtime → orm}/relations/belongs-to.ts +92 -92
  53. package/src/{runtime → orm}/relations/has-many.ts +111 -111
  54. package/src/{runtime → orm}/relations/many-to-many.ts +149 -149
  55. package/src/orm/runtime-types.ts +39 -0
  56. package/src/orm/transaction-runner.ts +17 -0
  57. package/src/orm/unit-of-work.ts +232 -0
  58. package/src/{builder/operations → query-builder}/column-selector.ts +78 -78
  59. package/src/{builder → query-builder}/delete-query-state.ts +38 -42
  60. package/src/{builder → query-builder}/delete.ts +46 -57
  61. package/src/{builder → query-builder}/hydration-manager.ts +87 -87
  62. package/src/{builder → query-builder}/hydration-planner.ts +182 -182
  63. package/src/{builder → query-builder}/insert-query-state.ts +51 -62
  64. package/src/{builder → query-builder}/insert.ts +48 -59
  65. package/src/{builder → query-builder}/query-ast-service.ts +208 -226
  66. package/src/{utils → query-builder}/raw-column-parser.ts +32 -32
  67. package/src/{builder → query-builder}/relation-conditions.ts +112 -112
  68. package/src/{builder/operations → query-builder}/relation-manager.ts +82 -82
  69. package/src/{builder → query-builder}/relation-projection-helper.ts +101 -101
  70. package/src/{builder → query-builder}/relation-service.ts +284 -284
  71. package/src/{builder → query-builder}/relation-types.ts +21 -21
  72. package/src/{builder → query-builder}/relation-utils.ts +12 -12
  73. package/src/{builder → query-builder}/select-query-builder-deps.ts +112 -94
  74. package/src/{builder → query-builder}/select-query-state.ts +179 -179
  75. package/src/{builder → query-builder}/select.ts +78 -69
  76. package/src/{builder → query-builder}/update-query-state.ts +55 -59
  77. package/src/{builder → query-builder}/update.ts +50 -61
  78. package/src/schema/column.ts +25 -25
  79. package/src/schema/relation.ts +116 -116
  80. package/src/schema/table.ts +34 -34
  81. package/src/schema/types.ts +76 -76
  82. package/.github/workflows/publish-metal-orm.yml +0 -38
  83. package/ROADMAP.md +0 -125
  84. package/docs/CHANGES.md +0 -104
  85. package/docs/advanced-features.md +0 -176
  86. package/docs/api-reference.md +0 -31
  87. package/docs/dml-operations.md +0 -156
  88. package/docs/getting-started.md +0 -171
  89. package/docs/hydration.md +0 -115
  90. package/docs/index.md +0 -36
  91. package/docs/multi-dialect-support.md +0 -59
  92. package/docs/query-builder.md +0 -135
  93. package/docs/runtime.md +0 -105
  94. package/docs/schema-definition.md +0 -112
  95. package/metadata.json +0 -5
  96. package/playground/api/playground-api.ts +0 -94
  97. package/playground/index.html +0 -15
  98. package/playground/src/App.css +0 -1
  99. package/playground/src/App.tsx +0 -114
  100. package/playground/src/components/CodeDisplay.tsx +0 -43
  101. package/playground/src/components/QueryExecutor.tsx +0 -189
  102. package/playground/src/components/ResultsTable.tsx +0 -67
  103. package/playground/src/components/ResultsTabs.tsx +0 -105
  104. package/playground/src/components/ScenarioList.tsx +0 -56
  105. package/playground/src/components/logo.svg +0 -45
  106. package/playground/src/data/scenarios.ts +0 -2
  107. package/playground/src/main.tsx +0 -9
  108. package/playground/src/services/PlaygroundApiService.ts +0 -60
  109. package/postcss.config.cjs +0 -5
  110. package/sql_sql-ansi-cheatsheet-2025.md +0 -264
  111. package/src/ast/expression.ts +0 -658
  112. package/src/builder/operations/cte-manager.ts +0 -34
  113. package/src/builder/operations/filter-manager.ts +0 -68
  114. package/src/builder/operations/join-manager.ts +0 -36
  115. package/src/builder/operations/pagination-manager.ts +0 -36
  116. package/src/playground/features/playground/api/types.ts +0 -16
  117. package/src/playground/features/playground/clients/MockClient.ts +0 -17
  118. package/src/playground/features/playground/clients/SqliteClient.ts +0 -57
  119. package/src/playground/features/playground/common/IDatabaseClient.ts +0 -10
  120. package/src/playground/features/playground/data/scenarios/aggregation.ts +0 -36
  121. package/src/playground/features/playground/data/scenarios/basics.ts +0 -25
  122. package/src/playground/features/playground/data/scenarios/edge_cases.ts +0 -57
  123. package/src/playground/features/playground/data/scenarios/filtering.ts +0 -94
  124. package/src/playground/features/playground/data/scenarios/hydration.ts +0 -27
  125. package/src/playground/features/playground/data/scenarios/index.ts +0 -29
  126. package/src/playground/features/playground/data/scenarios/ordering.ts +0 -25
  127. package/src/playground/features/playground/data/scenarios/pagination.ts +0 -16
  128. package/src/playground/features/playground/data/scenarios/relationships.ts +0 -75
  129. package/src/playground/features/playground/data/scenarios/types.ts +0 -70
  130. package/src/playground/features/playground/data/schema.ts +0 -91
  131. package/src/playground/features/playground/data/seed.ts +0 -104
  132. package/src/playground/features/playground/services/QueryExecutionService.ts +0 -121
  133. package/src/runtime/orm-context.ts +0 -539
  134. package/tests/belongs-to-many.test.ts +0 -57
  135. package/tests/between.test.ts +0 -43
  136. package/tests/case-expression.test.ts +0 -58
  137. package/tests/complex-exists.test.ts +0 -230
  138. package/tests/cte.test.ts +0 -118
  139. package/tests/dml.test.ts +0 -206
  140. package/tests/exists.test.ts +0 -127
  141. package/tests/like.test.ts +0 -33
  142. package/tests/orm-runtime.test.ts +0 -254
  143. package/tests/postgres.test.ts +0 -30
  144. package/tests/right-join.test.ts +0 -89
  145. package/tests/subquery-having.test.ts +0 -193
  146. package/tests/window-function.test.ts +0 -151
  147. package/tsconfig.json +0 -30
  148. package/tsup.config.ts +0 -10
  149. package/vite.config.ts +0 -22
  150. package/vitest.config.ts +0 -14
  151. /package/src/{constants → core/sql}/sql.ts +0 -0
  152. /package/src/{runtime → orm}/als.ts +0 -0
  153. /package/src/{utils → query-builder}/relation-alias.ts +0 -0
@@ -1,69 +1,69 @@
1
- import { TableDef } from './table';
2
-
3
- /**
4
- * Types of relationships supported between tables
5
- */
6
- export const RelationKinds = {
7
- /** One-to-many relationship */
8
- HasMany: 'HAS_MANY',
9
- /** Many-to-one relationship */
10
- BelongsTo: 'BELONGS_TO',
11
- /** Many-to-many relationship with pivot metadata */
12
- BelongsToMany: 'BELONGS_TO_MANY'
13
- } as const;
14
-
15
- /**
16
- * Type representing the supported relationship kinds
17
- */
18
- export type RelationType = (typeof RelationKinds)[keyof typeof RelationKinds];
19
-
20
- export type CascadeMode = 'none' | 'all' | 'persist' | 'remove' | 'link';
21
-
22
- /**
23
- * One-to-many relationship definition
24
- */
25
- export interface HasManyRelation<TTarget extends TableDef = TableDef> {
26
- type: typeof RelationKinds.HasMany;
27
- target: TTarget;
28
- foreignKey: string;
29
- localKey?: string;
30
- cascade?: CascadeMode;
31
- }
32
-
33
- /**
34
- * Many-to-one relationship definition
35
- */
36
- export interface BelongsToRelation<TTarget extends TableDef = TableDef> {
37
- type: typeof RelationKinds.BelongsTo;
38
- target: TTarget;
39
- foreignKey: string;
40
- localKey?: string;
41
- cascade?: CascadeMode;
42
- }
43
-
44
- /**
45
- * Many-to-many relationship definition with rich pivot metadata
46
- */
47
- export interface BelongsToManyRelation<TTarget extends TableDef = TableDef> {
48
- type: typeof RelationKinds.BelongsToMany;
49
- target: TTarget;
50
- pivotTable: TableDef;
51
- pivotForeignKeyToRoot: string;
52
- pivotForeignKeyToTarget: string;
53
- localKey?: string;
54
- targetKey?: string;
55
- pivotPrimaryKey?: string;
56
- defaultPivotColumns?: string[];
57
- cascade?: CascadeMode;
58
- }
59
-
60
- /**
61
- * Union type representing any supported relationship definition
62
- */
63
- export type RelationDef =
64
- | HasManyRelation
65
- | BelongsToRelation
66
- | BelongsToManyRelation;
1
+ import { TableDef } from './table.js';
2
+
3
+ /**
4
+ * Types of relationships supported between tables
5
+ */
6
+ export const RelationKinds = {
7
+ /** One-to-many relationship */
8
+ HasMany: 'HAS_MANY',
9
+ /** Many-to-one relationship */
10
+ BelongsTo: 'BELONGS_TO',
11
+ /** Many-to-many relationship with pivot metadata */
12
+ BelongsToMany: 'BELONGS_TO_MANY'
13
+ } as const;
14
+
15
+ /**
16
+ * Type representing the supported relationship kinds
17
+ */
18
+ export type RelationType = (typeof RelationKinds)[keyof typeof RelationKinds];
19
+
20
+ export type CascadeMode = 'none' | 'all' | 'persist' | 'remove' | 'link';
21
+
22
+ /**
23
+ * One-to-many relationship definition
24
+ */
25
+ export interface HasManyRelation<TTarget extends TableDef = TableDef> {
26
+ type: typeof RelationKinds.HasMany;
27
+ target: TTarget;
28
+ foreignKey: string;
29
+ localKey?: string;
30
+ cascade?: CascadeMode;
31
+ }
32
+
33
+ /**
34
+ * Many-to-one relationship definition
35
+ */
36
+ export interface BelongsToRelation<TTarget extends TableDef = TableDef> {
37
+ type: typeof RelationKinds.BelongsTo;
38
+ target: TTarget;
39
+ foreignKey: string;
40
+ localKey?: string;
41
+ cascade?: CascadeMode;
42
+ }
43
+
44
+ /**
45
+ * Many-to-many relationship definition with rich pivot metadata
46
+ */
47
+ export interface BelongsToManyRelation<TTarget extends TableDef = TableDef> {
48
+ type: typeof RelationKinds.BelongsToMany;
49
+ target: TTarget;
50
+ pivotTable: TableDef;
51
+ pivotForeignKeyToRoot: string;
52
+ pivotForeignKeyToTarget: string;
53
+ localKey?: string;
54
+ targetKey?: string;
55
+ pivotPrimaryKey?: string;
56
+ defaultPivotColumns?: string[];
57
+ cascade?: CascadeMode;
58
+ }
59
+
60
+ /**
61
+ * Union type representing any supported relationship definition
62
+ */
63
+ export type RelationDef =
64
+ | HasManyRelation
65
+ | BelongsToRelation
66
+ | BelongsToManyRelation;
67
67
 
68
68
  /**
69
69
  * Creates a one-to-many relationship definition
@@ -77,18 +77,18 @@ export type RelationDef =
77
77
  * hasMany(usersTable, 'user_id')
78
78
  * ```
79
79
  */
80
- export const hasMany = <TTarget extends TableDef>(
81
- target: TTarget,
82
- foreignKey: string,
83
- localKey?: string,
84
- cascade?: CascadeMode
85
- ): HasManyRelation<TTarget> => ({
86
- type: RelationKinds.HasMany,
87
- target,
88
- foreignKey,
89
- localKey,
90
- cascade
91
- });
80
+ export const hasMany = <TTarget extends TableDef>(
81
+ target: TTarget,
82
+ foreignKey: string,
83
+ localKey?: string,
84
+ cascade?: CascadeMode
85
+ ): HasManyRelation<TTarget> => ({
86
+ type: RelationKinds.HasMany,
87
+ target,
88
+ foreignKey,
89
+ localKey,
90
+ cascade
91
+ });
92
92
 
93
93
  /**
94
94
  * Creates a many-to-one relationship definition
@@ -102,18 +102,18 @@ export const hasMany = <TTarget extends TableDef>(
102
102
  * belongsTo(usersTable, 'user_id')
103
103
  * ```
104
104
  */
105
- export const belongsTo = <TTarget extends TableDef>(
106
- target: TTarget,
107
- foreignKey: string,
108
- localKey?: string,
109
- cascade?: CascadeMode
110
- ): BelongsToRelation<TTarget> => ({
111
- type: RelationKinds.BelongsTo,
112
- target,
113
- foreignKey,
114
- localKey,
115
- cascade
116
- });
105
+ export const belongsTo = <TTarget extends TableDef>(
106
+ target: TTarget,
107
+ foreignKey: string,
108
+ localKey?: string,
109
+ cascade?: CascadeMode
110
+ ): BelongsToRelation<TTarget> => ({
111
+ type: RelationKinds.BelongsTo,
112
+ target,
113
+ foreignKey,
114
+ localKey,
115
+ cascade
116
+ });
117
117
 
118
118
  /**
119
119
  * Creates a many-to-many relationship definition with pivot metadata
@@ -122,29 +122,29 @@ export const belongsTo = <TTarget extends TableDef>(
122
122
  * @param options - Pivot metadata configuration
123
123
  * @returns BelongsToManyRelation definition
124
124
  */
125
- export const belongsToMany = <
126
- TTarget extends TableDef
127
- >(
128
- target: TTarget,
129
- pivotTable: TableDef,
130
- options: {
131
- pivotForeignKeyToRoot: string;
132
- pivotForeignKeyToTarget: string;
133
- localKey?: string;
134
- targetKey?: string;
135
- pivotPrimaryKey?: string;
136
- defaultPivotColumns?: string[];
137
- cascade?: CascadeMode;
138
- }
139
- ): BelongsToManyRelation<TTarget> => ({
140
- type: RelationKinds.BelongsToMany,
141
- target,
142
- pivotTable,
143
- pivotForeignKeyToRoot: options.pivotForeignKeyToRoot,
144
- pivotForeignKeyToTarget: options.pivotForeignKeyToTarget,
145
- localKey: options.localKey,
146
- targetKey: options.targetKey,
147
- pivotPrimaryKey: options.pivotPrimaryKey,
148
- defaultPivotColumns: options.defaultPivotColumns,
149
- cascade: options.cascade
150
- });
125
+ export const belongsToMany = <
126
+ TTarget extends TableDef
127
+ >(
128
+ target: TTarget,
129
+ pivotTable: TableDef,
130
+ options: {
131
+ pivotForeignKeyToRoot: string;
132
+ pivotForeignKeyToTarget: string;
133
+ localKey?: string;
134
+ targetKey?: string;
135
+ pivotPrimaryKey?: string;
136
+ defaultPivotColumns?: string[];
137
+ cascade?: CascadeMode;
138
+ }
139
+ ): BelongsToManyRelation<TTarget> => ({
140
+ type: RelationKinds.BelongsToMany,
141
+ target,
142
+ pivotTable,
143
+ pivotForeignKeyToRoot: options.pivotForeignKeyToRoot,
144
+ pivotForeignKeyToTarget: options.pivotForeignKeyToTarget,
145
+ localKey: options.localKey,
146
+ targetKey: options.targetKey,
147
+ pivotPrimaryKey: options.pivotPrimaryKey,
148
+ defaultPivotColumns: options.defaultPivotColumns,
149
+ cascade: options.cascade
150
+ });
@@ -1,29 +1,29 @@
1
- import { ColumnDef } from './column';
2
- import { RelationDef } from './relation';
3
-
4
- export interface TableHooks {
5
- beforeInsert?(ctx: unknown, entity: any): Promise<void> | void;
6
- afterInsert?(ctx: unknown, entity: any): Promise<void> | void;
7
- beforeUpdate?(ctx: unknown, entity: any): Promise<void> | void;
8
- afterUpdate?(ctx: unknown, entity: any): Promise<void> | void;
9
- beforeDelete?(ctx: unknown, entity: any): Promise<void> | void;
10
- afterDelete?(ctx: unknown, entity: any): Promise<void> | void;
11
- }
12
-
13
- /**
14
- * Definition of a database table with its columns and relationships
15
- * @typeParam T - Type of the columns record
16
- */
17
- export interface TableDef<T extends Record<string, ColumnDef> = Record<string, ColumnDef>> {
18
- /** Name of the table */
19
- name: string;
20
- /** Record of column definitions keyed by column name */
21
- columns: T;
22
- /** Record of relationship definitions keyed by relation name */
23
- relations: Record<string, RelationDef>;
24
- /** Optional lifecycle hooks */
25
- hooks?: TableHooks;
26
- }
1
+ import { ColumnDef } from './column.js';
2
+ import { RelationDef } from './relation.js';
3
+
4
+ export interface TableHooks {
5
+ beforeInsert?(ctx: unknown, entity: any): Promise<void> | void;
6
+ afterInsert?(ctx: unknown, entity: any): Promise<void> | void;
7
+ beforeUpdate?(ctx: unknown, entity: any): Promise<void> | void;
8
+ afterUpdate?(ctx: unknown, entity: any): Promise<void> | void;
9
+ beforeDelete?(ctx: unknown, entity: any): Promise<void> | void;
10
+ afterDelete?(ctx: unknown, entity: any): Promise<void> | void;
11
+ }
12
+
13
+ /**
14
+ * Definition of a database table with its columns and relationships
15
+ * @typeParam T - Type of the columns record
16
+ */
17
+ export interface TableDef<T extends Record<string, ColumnDef> = Record<string, ColumnDef>> {
18
+ /** Name of the table */
19
+ name: string;
20
+ /** Record of column definitions keyed by column name */
21
+ columns: T;
22
+ /** Record of relationship definitions keyed by relation name */
23
+ relations: Record<string, RelationDef>;
24
+ /** Optional lifecycle hooks */
25
+ hooks?: TableHooks;
26
+ }
27
27
 
28
28
  /**
29
29
  * Creates a table definition with columns and relationships
@@ -42,17 +42,17 @@ export interface TableDef<T extends Record<string, ColumnDef> = Record<string, C
42
42
  * });
43
43
  * ```
44
44
  */
45
- export const defineTable = <T extends Record<string, ColumnDef>>(
46
- name: string,
47
- columns: T,
48
- relations: Record<string, RelationDef> = {},
49
- hooks?: TableHooks
50
- ): TableDef<T> => {
45
+ export const defineTable = <T extends Record<string, ColumnDef>>(
46
+ name: string,
47
+ columns: T,
48
+ relations: Record<string, RelationDef> = {},
49
+ hooks?: TableHooks
50
+ ): TableDef<T> => {
51
51
  // Runtime mutability to assign names to column definitions for convenience
52
52
  const colsWithNames = Object.entries(columns).reduce((acc, [key, def]) => {
53
53
  (acc as any)[key] = { ...def, name: key, table: name };
54
54
  return acc;
55
55
  }, {} as T);
56
56
 
57
- return { name, columns: colsWithNames, relations, hooks };
58
- };
57
+ return { name, columns: colsWithNames, relations, hooks };
58
+ };
@@ -1,76 +1,76 @@
1
- import { ColumnDef } from './column';
2
- import { TableDef } from './table';
3
- import {
4
- RelationDef,
5
- HasManyRelation,
6
- BelongsToRelation,
7
- BelongsToManyRelation
8
- } from './relation';
9
-
10
- /**
11
- * Maps a ColumnDef to its TypeScript type representation
12
- */
13
- export type ColumnToTs<T extends ColumnDef> =
14
- T['type'] extends 'INT' | 'INTEGER' | 'int' | 'integer' ? number :
15
- T['type'] extends 'BOOLEAN' | 'boolean' ? boolean :
16
- T['type'] extends 'JSON' | 'json' ? unknown :
17
- string;
18
-
19
- /**
20
- * Infers a row shape from a table definition
21
- */
22
- export type InferRow<TTable extends TableDef> = {
23
- [K in keyof TTable['columns']]: ColumnToTs<TTable['columns'][K]>;
24
- };
25
-
26
- type RelationResult<T extends RelationDef> =
27
- T extends HasManyRelation<infer TTarget> ? InferRow<TTarget>[] :
28
- T extends BelongsToRelation<infer TTarget> ? InferRow<TTarget> | null :
29
- T extends BelongsToManyRelation<infer TTarget> ? (InferRow<TTarget> & { _pivot?: any })[] :
30
- never;
31
-
32
- /**
33
- * Maps relation names to the expected row results
34
- */
35
- export type RelationMap<TTable extends TableDef> = {
36
- [K in keyof TTable['relations']]: RelationResult<TTable['relations'][K]>;
37
- };
38
-
39
- export interface HasManyCollection<TChild> {
40
- load(): Promise<TChild[]>;
41
- getItems(): TChild[];
42
- add(data: Partial<TChild>): TChild;
43
- attach(entity: TChild): void;
44
- remove(entity: TChild): void;
45
- clear(): void;
46
- }
47
-
48
- export interface BelongsToReference<TParent> {
49
- load(): Promise<TParent | null>;
50
- get(): TParent | null;
51
- set(data: Partial<TParent> | TParent | null): TParent | null;
52
- }
53
-
54
- export interface ManyToManyCollection<TTarget> {
55
- load(): Promise<TTarget[]>;
56
- getItems(): TTarget[];
57
- attach(target: TTarget | number | string): void;
58
- detach(target: TTarget | number | string): void;
59
- syncByIds(ids: (number | string)[]): Promise<void>;
60
- }
61
-
62
- export type Entity<
63
- TTable extends TableDef,
64
- TRow = InferRow<TTable>
65
- > = TRow & {
66
- [K in keyof RelationMap<TTable>]:
67
- TTable['relations'][K] extends HasManyRelation<infer TTarget>
68
- ? HasManyCollection<Entity<TTarget>>
69
- : TTable['relations'][K] extends BelongsToManyRelation<infer TTarget>
70
- ? ManyToManyCollection<Entity<TTarget>>
71
- : TTable['relations'][K] extends BelongsToRelation<infer TTarget>
72
- ? BelongsToReference<Entity<TTarget>>
73
- : never;
74
- } & {
75
- $load<K extends keyof RelationMap<TTable>>(relation: K): Promise<RelationMap<TTable>[K]>;
76
- };
1
+ import { ColumnDef } from './column.js';
2
+ import { TableDef } from './table.js';
3
+ import {
4
+ RelationDef,
5
+ HasManyRelation,
6
+ BelongsToRelation,
7
+ BelongsToManyRelation
8
+ } from './relation.js';
9
+
10
+ /**
11
+ * Maps a ColumnDef to its TypeScript type representation
12
+ */
13
+ export type ColumnToTs<T extends ColumnDef> =
14
+ T['type'] extends 'INT' | 'INTEGER' | 'int' | 'integer' ? number :
15
+ T['type'] extends 'BOOLEAN' | 'boolean' ? boolean :
16
+ T['type'] extends 'JSON' | 'json' ? unknown :
17
+ string;
18
+
19
+ /**
20
+ * Infers a row shape from a table definition
21
+ */
22
+ export type InferRow<TTable extends TableDef> = {
23
+ [K in keyof TTable['columns']]: ColumnToTs<TTable['columns'][K]>;
24
+ };
25
+
26
+ type RelationResult<T extends RelationDef> =
27
+ T extends HasManyRelation<infer TTarget> ? InferRow<TTarget>[] :
28
+ T extends BelongsToRelation<infer TTarget> ? InferRow<TTarget> | null :
29
+ T extends BelongsToManyRelation<infer TTarget> ? (InferRow<TTarget> & { _pivot?: any })[] :
30
+ never;
31
+
32
+ /**
33
+ * Maps relation names to the expected row results
34
+ */
35
+ export type RelationMap<TTable extends TableDef> = {
36
+ [K in keyof TTable['relations']]: RelationResult<TTable['relations'][K]>;
37
+ };
38
+
39
+ export interface HasManyCollection<TChild> {
40
+ load(): Promise<TChild[]>;
41
+ getItems(): TChild[];
42
+ add(data: Partial<TChild>): TChild;
43
+ attach(entity: TChild): void;
44
+ remove(entity: TChild): void;
45
+ clear(): void;
46
+ }
47
+
48
+ export interface BelongsToReference<TParent> {
49
+ load(): Promise<TParent | null>;
50
+ get(): TParent | null;
51
+ set(data: Partial<TParent> | TParent | null): TParent | null;
52
+ }
53
+
54
+ export interface ManyToManyCollection<TTarget> {
55
+ load(): Promise<TTarget[]>;
56
+ getItems(): TTarget[];
57
+ attach(target: TTarget | number | string): void;
58
+ detach(target: TTarget | number | string): void;
59
+ syncByIds(ids: (number | string)[]): Promise<void>;
60
+ }
61
+
62
+ export type Entity<
63
+ TTable extends TableDef,
64
+ TRow = InferRow<TTable>
65
+ > = TRow & {
66
+ [K in keyof RelationMap<TTable>]:
67
+ TTable['relations'][K] extends HasManyRelation<infer TTarget>
68
+ ? HasManyCollection<Entity<TTarget>>
69
+ : TTable['relations'][K] extends BelongsToManyRelation<infer TTarget>
70
+ ? ManyToManyCollection<Entity<TTarget>>
71
+ : TTable['relations'][K] extends BelongsToRelation<infer TTarget>
72
+ ? BelongsToReference<Entity<TTarget>>
73
+ : never;
74
+ } & {
75
+ $load<K extends keyof RelationMap<TTable>>(relation: K): Promise<RelationMap<TTable>[K]>;
76
+ };
@@ -1,38 +0,0 @@
1
- name: Publish metal-orm to npm
2
-
3
- on:
4
- push:
5
- branches:
6
- - main
7
-
8
- permissions:
9
- contents: read
10
- id-token: write # OIDC for Trusted Publishing
11
- packages: write
12
-
13
- jobs:
14
- publish:
15
- runs-on: ubuntu-latest
16
-
17
- steps:
18
- - name: Checkout
19
- uses: actions/checkout@v4
20
-
21
- - name: Setup Node
22
- uses: actions/setup-node@v4
23
- with:
24
- node-version: '20'
25
- registry-url: 'https://registry.npmjs.org'
26
-
27
- - name: Install deps
28
- run: npm ci
29
-
30
- - name: Test
31
- run: npm test
32
- continue-on-error: true # ou remove se quiser quebrar se falhar
33
-
34
- - name: Build
35
- run: npm run build
36
-
37
- - name: Publish (Trusted Publishing)
38
- run: npm publish --provenance --access public
package/ROADMAP.md DELETED
@@ -1,125 +0,0 @@
1
- # Metal ORM Roadmap
2
-
3
- ## Current ORM Capabilities
4
-
5
- The current implementation supports:
6
-
7
- - Basic SELECT with projections and aliases
8
- - INNER/LEFT JOINs with manual conditions
9
- - Smart relationship joins via `joinRelation()`
10
- - Eager loading with `include()` for 1:1 and 1:N relationships
11
- - Basic WHERE clauses with operators (eq, gt, like, in, null checks)
12
- - GROUP BY, ORDER BY, LIMIT, OFFSET
13
- - Aggregation functions (COUNT, SUM, AVG)
14
- - JSON path extraction (dialect-specific)
15
- - Hydration of nested objects from flat SQL results
16
- - EXISTS and NOT EXISTS subqueries
17
- - Scalar correlated subqueries in SELECT and WHERE
18
- - CASE expressions (simple and searched)
19
- - HAVING clause for post-aggregation filtering
20
-
21
- ## Identified Absences
22
-
23
- ### 1. CTE (Common Table Expressions) ✅
24
-
25
- **Completed:** Full CTE support has been implemented
26
-
27
- - Features: Simple CTEs, Recursive CTEs, Multiple CTEs, CTE with column aliases
28
- - **Implementation:** CTE AST node and dialect compilation for SQLite, MySQL, and MSSQL
29
- - Recursive CTEs properly handle the `WITH RECURSIVE` keyword (SQLite/MySQL only, MSSQL uses plain `WITH`)
30
- - Mixed recursive and non-recursive CTEs are supported
31
-
32
- ### 2. Window Functions ✅
33
-
34
- **Completed:** Comprehensive window function support has been implemented
35
-
36
- - Features: `ROW_NUMBER()`, `RANK()`, `DENSE_RANK()`, `LAG()`, `LEAD()`, `NTILE()`, `FIRST_VALUE()`, `LAST_VALUE()`
37
- - **Implementation:** Window function AST nodes with `PARTITION BY` and `ORDER BY` support
38
- - All three dialects (SQLite, MySQL, MSSQL) support window functions
39
-
40
- ### 3. RIGHT JOIN Support
41
-
42
- **Missing:** Only INNER, LEFT, and CROSS joins are defined
43
-
44
- - **Required Addition:** RIGHT JOIN support in join.ts and dialect compilation
45
-
46
- ### 4. Complex Aggregation Functions
47
-
48
- **Missing:** Limited aggregation functions
49
-
50
- - Queries: `5-top-platform-contributor-per-project`, `5-mega-user-engagement-analytics`
51
- - **Required Addition:** MIN, MAX, AVG functions, and GROUP_CONCAT
52
-
53
- ### 5. Parameterized Queries
54
-
55
- **Missing:** No parameter binding support
56
-
57
- - Queries: `1-1-parameterized-user-by-twitter`
58
- - **Required Addition:** Parameter placeholder support and binding mechanism
59
-
60
- ### 6. Advanced JSON Operations
61
-
62
- **Missing:** Limited JSON functionality
63
-
64
- - Queries: `1-1-profile-json-as-subquery-column`, `5-mega-user-engagement-analytics`
65
- - **Required Addition:** JSON_OBJECT, JSON_ARRAYAGG functions
66
-
67
- ### 7. Recursive CTEs ✅
68
-
69
- **Completed:** See Section 1 (CTE) above
70
-
71
- - Recursive CTEs are fully supported as part of the CTE implementation
72
-
73
- ### 8. Complex Ordering
74
-
75
- **Missing:** Limited ORDER BY expressions
76
-
77
- - Queries: `1-1-order-by-subquery-profile-field`, `5-mega-user-engagement-analytics`
78
- - **Required Addition:** ORDER BY with expressions and NULLS FIRST/LAST
79
-
80
- ### 9. DISTINCT ON (PostgreSQL-style)
81
-
82
- **Missing:** No DISTINCT ON support
83
-
84
- - **Required Addition:** Dialect-specific DISTINCT ON compilation
85
-
86
- ### 10. Subquery Aliasing
87
-
88
- **Missing:** No support for subqueries as derived tables
89
-
90
- - **Required Addition:** Derived table AST node
91
-
92
- ### 11. Advanced EXISTS Patterns
93
-
94
- **Missing:** EXISTS with complex correlated subqueries
95
-
96
- - Queries: `1-1-boolean-flag-from-subquery-on-profile`
97
- - **Required Addition:** Complex correlation support
98
-
99
- ## Priority Implementation Order
100
-
101
- ### Completed ✅
102
-
103
- - ~~CTE support~~ (Completed)
104
- - ~~Window functions~~ (Completed)
105
- - ~~Recursive CTEs~~ (Completed)
106
-
107
- ### High Priority:
108
-
109
- - Parameterized queries
110
- - RIGHT JOIN
111
- - Complex aggregation functions (MIN, MAX, GROUP_CONCAT)
112
-
113
- ### Medium Priority:
114
-
115
- - Advanced JSON operations
116
- - Complex ordering (expressions, NULLS FIRST/LAST)
117
-
118
- ### Lower Priority:
119
-
120
- - Subquery Aliasing (Derived tables)
121
- - Advanced EXISTS Patterns
122
-
123
- ## Implementation Notes
124
-
125
- The current ORM is well-architected with a clear AST structure and dialect abstraction, making it relatively straightforward to add these missing features by extending the existing patterns.