metal-orm 1.1.10 → 1.1.16

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 (192) hide show
  1. package/README.md +758 -769
  2. package/dist/index.cjs +106 -43
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +5 -5
  5. package/dist/index.d.ts +5 -5
  6. package/dist/index.js +106 -43
  7. package/dist/index.js.map +1 -1
  8. package/package.json +100 -96
  9. package/scripts/generate-entities/render.mjs +21 -12
  10. package/scripts/generate-entities/schema.mjs +209 -195
  11. package/scripts/generate-entities/tree-detection.mjs +159 -153
  12. package/scripts/inflection/pt-br.mjs +468 -468
  13. package/scripts/run-eslint.mjs +33 -34
  14. package/scripts/show-sql-seed.sql +102 -0
  15. package/scripts/show-sql.mjs +321 -325
  16. package/src/bulk/bulk-delete-executor.ts +3 -5
  17. package/src/bulk/bulk-insert-executor.ts +7 -7
  18. package/src/bulk/bulk-update-executor.ts +2 -2
  19. package/src/bulk/bulk-upsert-executor.ts +5 -7
  20. package/src/codegen/naming-strategy.ts +54 -54
  21. package/src/codegen/typescript.ts +482 -482
  22. package/src/core/ast/adapters.ts +1 -1
  23. package/src/core/ast/builders.ts +123 -123
  24. package/src/core/ast/expression-builders.ts +745 -745
  25. package/src/core/ast/expression-nodes.ts +304 -304
  26. package/src/core/ast/expression-visitor.ts +212 -212
  27. package/src/core/ast/expression.ts +20 -20
  28. package/src/core/ast/helpers.ts +14 -14
  29. package/src/core/ast/join.ts +18 -18
  30. package/src/core/ast/query.ts +200 -200
  31. package/src/core/ddl/dialects/base-schema-dialect.ts +1 -1
  32. package/src/core/ddl/dialects/mssql-schema-dialect.ts +1 -1
  33. package/src/core/ddl/dialects/mysql-schema-dialect.ts +1 -1
  34. package/src/core/ddl/dialects/postgres-schema-dialect.ts +1 -1
  35. package/src/core/ddl/dialects/render-reference.test.ts +70 -70
  36. package/src/core/ddl/dialects/sqlite-schema-dialect.ts +1 -1
  37. package/src/core/ddl/introspect/catalogs/index.ts +5 -5
  38. package/src/core/ddl/introspect/catalogs/postgres.ts +146 -146
  39. package/src/core/ddl/introspect/context.ts +15 -15
  40. package/src/core/ddl/introspect/functions/postgres.ts +35 -35
  41. package/src/core/ddl/introspect/mysql.ts +113 -36
  42. package/src/core/ddl/introspect/registry.ts +40 -40
  43. package/src/core/ddl/introspect/run-select.ts +35 -35
  44. package/src/core/ddl/introspect/utils.ts +56 -56
  45. package/src/core/ddl/naming-strategy.ts +16 -16
  46. package/src/core/ddl/schema-dialect.ts +56 -56
  47. package/src/core/ddl/schema-diff.ts +234 -234
  48. package/src/core/ddl/schema-generator.ts +1 -1
  49. package/src/core/ddl/schema-introspect.ts +25 -25
  50. package/src/core/ddl/sql-writing.ts +171 -171
  51. package/src/core/dialect/abstract.ts +541 -541
  52. package/src/core/dialect/base/cte-compiler.ts +33 -33
  53. package/src/core/dialect/base/function-table-formatter.ts +103 -103
  54. package/src/core/dialect/base/groupby-compiler.ts +21 -21
  55. package/src/core/dialect/base/join-compiler.ts +25 -25
  56. package/src/core/dialect/base/orderby-compiler.ts +35 -35
  57. package/src/core/dialect/base/pagination-strategy.ts +32 -32
  58. package/src/core/dialect/base/returning-strategy.ts +57 -57
  59. package/src/core/dialect/base/sql-dialect.ts +294 -294
  60. package/src/core/dialect/dialect-factory.ts +91 -91
  61. package/src/core/dialect/mssql/functions.ts +120 -120
  62. package/src/core/dialect/mssql/index.ts +317 -317
  63. package/src/core/dialect/mysql/functions.ts +103 -103
  64. package/src/core/dialect/mysql/index.ts +105 -105
  65. package/src/core/dialect/postgres/functions.ts +108 -108
  66. package/src/core/dialect/postgres/index.ts +91 -91
  67. package/src/core/dialect/sqlite/functions.ts +129 -129
  68. package/src/core/dialect/sqlite/index.ts +67 -67
  69. package/src/core/driver/database-driver.ts +19 -19
  70. package/src/core/driver/mssql-driver.ts +23 -23
  71. package/src/core/driver/mysql-driver.ts +23 -23
  72. package/src/core/driver/postgres-driver.ts +23 -23
  73. package/src/core/driver/sqlite-driver.ts +23 -23
  74. package/src/core/execution/db-executor.ts +92 -92
  75. package/src/core/execution/executors/better-sqlite3-executor.ts +94 -94
  76. package/src/core/execution/executors/mssql-executor.ts +184 -184
  77. package/src/core/execution/executors/mysql-executor.ts +88 -88
  78. package/src/core/execution/executors/postgres-executor.ts +26 -26
  79. package/src/core/execution/executors/sqlite-executor.ts +42 -42
  80. package/src/core/execution/pooling/pool-types.ts +30 -30
  81. package/src/core/execution/pooling/pool.ts +275 -275
  82. package/src/core/functions/array.ts +35 -35
  83. package/src/core/functions/control-flow.ts +79 -79
  84. package/src/core/functions/datetime.ts +237 -237
  85. package/src/core/functions/json.ts +70 -70
  86. package/src/core/functions/numeric.ts +297 -297
  87. package/src/core/functions/text.ts +334 -334
  88. package/src/core/functions/types.ts +33 -33
  89. package/src/core/hydration/types.ts +51 -51
  90. package/src/core/sql/sql-operator-config.ts +39 -39
  91. package/src/core/sql/sql.ts +152 -152
  92. package/src/decorators/column-decorator.ts +87 -87
  93. package/src/decorators/decorator-metadata.ts +143 -143
  94. package/src/decorators/entity.ts +93 -93
  95. package/src/decorators/index.ts +39 -39
  96. package/src/decorators/relations.ts +231 -231
  97. package/src/decorators/transformers/built-in/string-transformers.ts +231 -231
  98. package/src/decorators/transformers/transformer-decorators.ts +134 -134
  99. package/src/decorators/transformers/transformer-executor.ts +171 -171
  100. package/src/decorators/transformers/transformer-metadata.ts +73 -73
  101. package/src/decorators/validators/built-in/br-cep-validator.ts +55 -55
  102. package/src/decorators/validators/built-in/br-cnpj-validator.ts +105 -105
  103. package/src/decorators/validators/built-in/br-cpf-validator.ts +103 -103
  104. package/src/decorators/validators/country-validator-registry.ts +64 -64
  105. package/src/decorators/validators/country-validators-decorators.ts +203 -203
  106. package/src/decorators/validators/country-validators.ts +105 -105
  107. package/src/decorators/validators/validator-metadata.ts +59 -59
  108. package/src/dto/dto-types.ts +226 -226
  109. package/src/dto/filter-types.ts +141 -141
  110. package/src/dto/index.ts +95 -95
  111. package/src/dto/openapi/generators/base.ts +29 -29
  112. package/src/dto/openapi/generators/column.ts +37 -37
  113. package/src/dto/openapi/generators/dto.ts +91 -91
  114. package/src/dto/openapi/generators/filter.ts +75 -75
  115. package/src/dto/openapi/generators/nested-dto.ts +618 -618
  116. package/src/dto/openapi/generators/pagination.ts +111 -111
  117. package/src/dto/openapi/generators/relation-filter.ts +228 -228
  118. package/src/dto/openapi/index.ts +12 -12
  119. package/src/dto/openapi/types.ts +101 -101
  120. package/src/dto/openapi/utilities.ts +95 -95
  121. package/src/dto/pagination-utils.ts +150 -150
  122. package/src/dto/transform.ts +197 -197
  123. package/src/index.ts +86 -86
  124. package/src/orm/als.ts +58 -58
  125. package/src/orm/domain-event-bus.ts +119 -119
  126. package/src/orm/entity-context.ts +86 -86
  127. package/src/orm/entity-materializer.ts +159 -159
  128. package/src/orm/entity-meta.ts +97 -97
  129. package/src/orm/entity-registry.ts +39 -39
  130. package/src/orm/entity-relation-cache.ts +39 -39
  131. package/src/orm/execute.ts +194 -194
  132. package/src/orm/execution-context.ts +18 -18
  133. package/src/orm/hydration-context.ts +26 -26
  134. package/src/orm/hydration.ts +112 -112
  135. package/src/orm/identity-map.ts +61 -61
  136. package/src/orm/interceptor-pipeline.ts +16 -16
  137. package/src/orm/lazy-batch/belongs-to-many.ts +119 -119
  138. package/src/orm/lazy-batch/belongs-to.ts +108 -108
  139. package/src/orm/lazy-batch/has-many.ts +69 -69
  140. package/src/orm/lazy-batch/has-one.ts +68 -68
  141. package/src/orm/lazy-batch/shared.ts +125 -125
  142. package/src/orm/orm-session.ts +620 -620
  143. package/src/orm/orm.ts +34 -34
  144. package/src/orm/pooled-executor-factory.ts +121 -121
  145. package/src/orm/query-logger.ts +40 -40
  146. package/src/orm/relation-change-processor.ts +420 -420
  147. package/src/orm/relations/belongs-to.ts +143 -143
  148. package/src/orm/relations/has-many.ts +204 -204
  149. package/src/orm/relations/has-one.ts +174 -174
  150. package/src/orm/relations/many-to-many.ts +288 -288
  151. package/src/orm/relations/morph-many.ts +156 -156
  152. package/src/orm/relations/morph-one.ts +151 -151
  153. package/src/orm/relations/morph-to.ts +162 -162
  154. package/src/orm/runtime-types.ts +92 -92
  155. package/src/orm/save-graph.ts +561 -561
  156. package/src/orm/transaction-runner.ts +24 -24
  157. package/src/orm/unit-of-work.ts +426 -426
  158. package/src/query/index.ts +69 -69
  159. package/src/query/target.ts +46 -46
  160. package/src/query-builder/column-selector.ts +81 -81
  161. package/src/query-builder/delete.ts +141 -141
  162. package/src/query-builder/insert-query-state.ts +149 -149
  163. package/src/query-builder/insert.ts +117 -117
  164. package/src/query-builder/query-ast-service.ts +287 -287
  165. package/src/query-builder/query-resolution.ts +78 -78
  166. package/src/query-builder/raw-column-parser.ts +38 -38
  167. package/src/query-builder/relation-filter-utils.ts +153 -153
  168. package/src/query-builder/relation-join-planner.ts +10 -10
  169. package/src/query-builder/relation-manager.ts +87 -87
  170. package/src/query-builder/relation-projection-helper.ts +102 -102
  171. package/src/query-builder/relation-types.ts +9 -9
  172. package/src/query-builder/relation-utils.ts +15 -15
  173. package/src/query-builder/select/cte-facet.ts +40 -40
  174. package/src/query-builder/select/from-facet.ts +80 -80
  175. package/src/query-builder/select/join-facet.ts +62 -62
  176. package/src/query-builder/select/predicate-facet.ts +104 -104
  177. package/src/query-builder/select/projection-facet.ts +70 -70
  178. package/src/query-builder/select/relation-facet.ts +81 -81
  179. package/src/query-builder/select/setop-facet.ts +36 -36
  180. package/src/query-builder/select-helpers.ts +1 -1
  181. package/src/query-builder/select-query-builder-deps.ts +130 -130
  182. package/src/query-builder/select-query-state.ts +207 -207
  183. package/src/query-builder/update.ts +151 -151
  184. package/src/schema/column-types.ts +322 -322
  185. package/src/schema/table-guards.ts +37 -37
  186. package/src/schema/table.ts +281 -281
  187. package/src/tree/index.ts +13 -13
  188. package/src/tree/nested-set-strategy.ts +545 -545
  189. package/src/tree/tree-decorator.ts +397 -397
  190. package/src/tree/tree-manager.ts +754 -754
  191. package/src/tree/tree-query.ts +427 -427
  192. package/src/tree/tree-types.ts +299 -299
@@ -1,159 +1,159 @@
1
- import { EntityConstructor } from './entity-metadata.js';
2
- import { rebuildRegistry } from './entity-registry.js';
3
- import { hasEntityMeta } from './entity-meta.js';
4
-
5
- /**
6
- * Strategy interface for materializing entity instances (Open/Closed Principle).
7
- */
8
- export interface EntityMaterializationStrategy {
9
- /**
10
- * Creates an instance of the entity class and populates it with data.
11
- * @param ctor - The entity constructor
12
- * @param data - The raw data to populate
13
- * @returns The materialized entity instance
14
- */
15
- materialize<T>(ctor: EntityConstructor<T>, data: Record<string, unknown>): T;
16
- }
17
-
18
- /**
19
- * Default strategy: Uses Object.create() to create instance without calling constructor.
20
- * Safe for classes with required constructor parameters.
21
- */
22
- export class PrototypeMaterializationStrategy implements EntityMaterializationStrategy {
23
- materialize<T>(ctor: EntityConstructor<T>, data: Record<string, unknown>): T {
24
- const instance = Object.create(ctor.prototype) as T;
25
- Object.assign(instance, data);
26
- return instance;
27
- }
28
- }
29
-
30
- /**
31
- * Alternative strategy: Calls default constructor then assigns properties.
32
- * Use when class constructor initializes important state.
33
- */
34
- export class ConstructorMaterializationStrategy implements EntityMaterializationStrategy {
35
- materialize<T>(ctor: EntityConstructor<T>, data: Record<string, unknown>): T {
36
- const instance = Reflect.construct(ctor, []) as T & Record<string, unknown>;
37
- Object.assign(instance, data);
38
- return instance;
39
- }
40
- }
41
-
42
- /**
43
- * Interface for materializing query results into real entity class instances.
44
- */
45
- export interface EntityMaterializer {
46
- /**
47
- * Materializes a single row into a real entity instance.
48
- * @param entityClass - The entity constructor
49
- * @param row - The raw data row
50
- * @returns The materialized entity instance
51
- */
52
- materialize<T>(entityClass: EntityConstructor<T>, row: Record<string, unknown>): T;
53
-
54
- /**
55
- * Materializes multiple rows into real entity instances.
56
- * @param entityClass - The entity constructor
57
- * @param rows - The raw data rows
58
- * @returns Array of materialized entity instances
59
- */
60
- materializeMany<T>(entityClass: EntityConstructor<T>, rows: Record<string, unknown>[]): T[];
61
- }
62
-
63
- /**
64
- * Default implementation of EntityMaterializer.
65
- * Converts query results into actual class instances with working methods.
66
- *
67
- * @example
68
- * const materializer = new DefaultEntityMaterializer();
69
- * const users = materializer.materializeMany(User, queryResults);
70
- * users[0] instanceof User; // true
71
- * users[0].getFullName(); // works!
72
- */
73
- export class DefaultEntityMaterializer implements EntityMaterializer {
74
- constructor(
75
- private readonly strategy: EntityMaterializationStrategy = new ConstructorMaterializationStrategy()
76
- ) { }
77
-
78
- materialize<T>(ctor: EntityConstructor<T>, row: Record<string, unknown>): T {
79
- if (hasEntityMeta(row)) {
80
- return this.materializeEntityProxy(ctor, row);
81
- }
82
-
83
- const instance = this.strategy.materialize(ctor, row);
84
- this.materializeRelations(instance as Record<string, unknown>);
85
- return instance;
86
- }
87
-
88
- materializeMany<T>(ctor: EntityConstructor<T>, rows: Record<string, unknown>[]): T[] {
89
- return rows.map(row => this.materialize(ctor, row));
90
- }
91
-
92
- /**
93
- * Recursively materializes nested relation data.
94
- */
95
- private materializeRelations(instance: Record<string, unknown>): void {
96
- // Rebuild registry to ensure we have latest metadata
97
- rebuildRegistry();
98
-
99
- for (const value of Object.values(instance)) {
100
- if (value === null || value === undefined) continue;
101
-
102
- // Handle has-one / belongs-to (single object)
103
- if (typeof value === 'object' && !Array.isArray(value)) {
104
- const nested = value as Record<string, unknown>;
105
- // Check if this looks like an entity (has common entity patterns)
106
- if (this.isEntityLike(nested)) {
107
- // For now, keep as-is since we don't have relation metadata here
108
- // Future: use relation metadata to get target constructor
109
- }
110
- }
111
-
112
- // Handle has-many / belongs-to-many (array)
113
- if (Array.isArray(value) && value.length > 0) {
114
- const first = value[0];
115
- if (typeof first === 'object' && first !== null && this.isEntityLike(first)) {
116
- // For now, keep array as-is
117
- // Future: materialize each item if we can resolve the target class
118
- }
119
- }
120
- }
121
- }
122
-
123
- /**
124
- * Simple heuristic to check if an object looks like an entity.
125
- */
126
- private isEntityLike(obj: Record<string, unknown>): boolean {
127
- return 'id' in obj || Object.keys(obj).some(k =>
128
- k.endsWith('Id') || k === 'createdAt' || k === 'updatedAt'
129
- );
130
- }
131
-
132
- private materializeEntityProxy<T>(ctor: EntityConstructor<T>, row: Record<string, unknown>): T {
133
- const proxy = row as Record<string, unknown>;
134
- const baseline = this.strategy.materialize(ctor, {}) as Record<string, unknown>;
135
- for (const key of Object.keys(baseline)) {
136
- if (!Object.prototype.hasOwnProperty.call(proxy, key)) {
137
- proxy[key] = baseline[key];
138
- }
139
- }
140
- Object.setPrototypeOf(proxy, ctor.prototype);
141
- return proxy as T;
142
- }
143
- }
144
-
145
- /**
146
- * Convenience function to materialize query results as real class instances.
147
- *
148
- * @example
149
- * const results = await selectFromEntity(User).execute(session);
150
- * const users = materializeAs(User, results);
151
- * users[0] instanceof User; // true!
152
- */
153
- export const materializeAs = <TEntity extends object>(
154
- ctor: EntityConstructor<TEntity>,
155
- results: Record<string, unknown>[]
156
- ): TEntity[] => {
157
- const materializer = new DefaultEntityMaterializer();
158
- return materializer.materializeMany(ctor, results);
159
- };
1
+ import { EntityConstructor } from './entity-metadata.js';
2
+ import { rebuildRegistry } from './entity-registry.js';
3
+ import { hasEntityMeta } from './entity-meta.js';
4
+
5
+ /**
6
+ * Strategy interface for materializing entity instances (Open/Closed Principle).
7
+ */
8
+ export interface EntityMaterializationStrategy {
9
+ /**
10
+ * Creates an instance of the entity class and populates it with data.
11
+ * @param ctor - The entity constructor
12
+ * @param data - The raw data to populate
13
+ * @returns The materialized entity instance
14
+ */
15
+ materialize<T>(ctor: EntityConstructor<T>, data: Record<string, unknown>): T;
16
+ }
17
+
18
+ /**
19
+ * Default strategy: Uses Object.create() to create instance without calling constructor.
20
+ * Safe for classes with required constructor parameters.
21
+ */
22
+ export class PrototypeMaterializationStrategy implements EntityMaterializationStrategy {
23
+ materialize<T>(ctor: EntityConstructor<T>, data: Record<string, unknown>): T {
24
+ const instance = Object.create(ctor.prototype) as T;
25
+ Object.assign(instance, data);
26
+ return instance;
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Alternative strategy: Calls default constructor then assigns properties.
32
+ * Use when class constructor initializes important state.
33
+ */
34
+ export class ConstructorMaterializationStrategy implements EntityMaterializationStrategy {
35
+ materialize<T>(ctor: EntityConstructor<T>, data: Record<string, unknown>): T {
36
+ const instance = Reflect.construct(ctor, []) as T & Record<string, unknown>;
37
+ Object.assign(instance, data);
38
+ return instance;
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Interface for materializing query results into real entity class instances.
44
+ */
45
+ export interface EntityMaterializer {
46
+ /**
47
+ * Materializes a single row into a real entity instance.
48
+ * @param entityClass - The entity constructor
49
+ * @param row - The raw data row
50
+ * @returns The materialized entity instance
51
+ */
52
+ materialize<T>(entityClass: EntityConstructor<T>, row: Record<string, unknown>): T;
53
+
54
+ /**
55
+ * Materializes multiple rows into real entity instances.
56
+ * @param entityClass - The entity constructor
57
+ * @param rows - The raw data rows
58
+ * @returns Array of materialized entity instances
59
+ */
60
+ materializeMany<T>(entityClass: EntityConstructor<T>, rows: Record<string, unknown>[]): T[];
61
+ }
62
+
63
+ /**
64
+ * Default implementation of EntityMaterializer.
65
+ * Converts query results into actual class instances with working methods.
66
+ *
67
+ * @example
68
+ * const materializer = new DefaultEntityMaterializer();
69
+ * const users = materializer.materializeMany(User, queryResults);
70
+ * users[0] instanceof User; // true
71
+ * users[0].getFullName(); // works!
72
+ */
73
+ export class DefaultEntityMaterializer implements EntityMaterializer {
74
+ constructor(
75
+ private readonly strategy: EntityMaterializationStrategy = new ConstructorMaterializationStrategy()
76
+ ) { }
77
+
78
+ materialize<T>(ctor: EntityConstructor<T>, row: Record<string, unknown>): T {
79
+ if (hasEntityMeta(row)) {
80
+ return this.materializeEntityProxy(ctor, row);
81
+ }
82
+
83
+ const instance = this.strategy.materialize(ctor, row);
84
+ this.materializeRelations(instance as Record<string, unknown>);
85
+ return instance;
86
+ }
87
+
88
+ materializeMany<T>(ctor: EntityConstructor<T>, rows: Record<string, unknown>[]): T[] {
89
+ return rows.map(row => this.materialize(ctor, row));
90
+ }
91
+
92
+ /**
93
+ * Recursively materializes nested relation data.
94
+ */
95
+ private materializeRelations(instance: Record<string, unknown>): void {
96
+ // Rebuild registry to ensure we have latest metadata
97
+ rebuildRegistry();
98
+
99
+ for (const value of Object.values(instance)) {
100
+ if (value === null || value === undefined) continue;
101
+
102
+ // Handle has-one / belongs-to (single object)
103
+ if (typeof value === 'object' && !Array.isArray(value)) {
104
+ const nested = value as Record<string, unknown>;
105
+ // Check if this looks like an entity (has common entity patterns)
106
+ if (this.isEntityLike(nested)) {
107
+ // For now, keep as-is since we don't have relation metadata here
108
+ // Future: use relation metadata to get target constructor
109
+ }
110
+ }
111
+
112
+ // Handle has-many / belongs-to-many (array)
113
+ if (Array.isArray(value) && value.length > 0) {
114
+ const first = value[0];
115
+ if (typeof first === 'object' && first !== null && this.isEntityLike(first)) {
116
+ // For now, keep array as-is
117
+ // Future: materialize each item if we can resolve the target class
118
+ }
119
+ }
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Simple heuristic to check if an object looks like an entity.
125
+ */
126
+ private isEntityLike(obj: Record<string, unknown>): boolean {
127
+ return 'id' in obj || Object.keys(obj).some(k =>
128
+ k.endsWith('Id') || k === 'createdAt' || k === 'updatedAt'
129
+ );
130
+ }
131
+
132
+ private materializeEntityProxy<T>(ctor: EntityConstructor<T>, row: Record<string, unknown>): T {
133
+ const proxy = row as Record<string, unknown>;
134
+ const baseline = this.strategy.materialize(ctor, {}) as Record<string, unknown>;
135
+ for (const key of Object.keys(baseline)) {
136
+ if (!Object.prototype.hasOwnProperty.call(proxy, key)) {
137
+ proxy[key] = baseline[key];
138
+ }
139
+ }
140
+ Object.setPrototypeOf(proxy, ctor.prototype);
141
+ return proxy as T;
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Convenience function to materialize query results as real class instances.
147
+ *
148
+ * @example
149
+ * const results = await selectFromEntity(User).execute(session);
150
+ * const users = materializeAs(User, results);
151
+ * users[0] instanceof User; // true!
152
+ */
153
+ export const materializeAs = <TEntity extends object>(
154
+ ctor: EntityConstructor<TEntity>,
155
+ results: Record<string, unknown>[]
156
+ ): TEntity[] => {
157
+ const materializer = new DefaultEntityMaterializer();
158
+ return materializer.materializeMany(ctor, results);
159
+ };
@@ -1,97 +1,97 @@
1
- import { TableDef } from '../schema/table.js';
2
- import { RelationIncludeOptions } from '../query-builder/relation-types.js';
3
- import { EntityContext } from './entity-context.js';
4
- import { RelationMap } from '../schema/types.js';
5
-
6
- /**
7
- * Symbol used to store entity metadata on entity instances
8
- */
9
- export const ENTITY_META = Symbol('EntityMeta');
10
-
11
- const toKey = (value: unknown): string => (value === null || value === undefined ? '' : String(value));
12
-
13
- export type RelationKey<TTable extends TableDef> = Extract<keyof RelationMap<TTable>, string>;
14
-
15
- /**
16
- * Metadata stored on entity instances for ORM internal use
17
- * @typeParam TTable - Table definition type
18
- */
19
- export interface EntityMeta<TTable extends TableDef> {
20
- /** Entity context */
21
- ctx: EntityContext;
22
- /** Table definition */
23
- table: TTable;
24
- /** Relations that should be loaded lazily */
25
- lazyRelations: RelationKey<TTable>[];
26
- /** Include options for lazy relations */
27
- lazyRelationOptions: Map<string, RelationIncludeOptions>;
28
- /** Cache for relation promises */
29
- relationCache: Map<string, Promise<unknown>>;
30
- /** Hydration data for relations */
31
- relationHydration: Map<string, Map<string, unknown>>;
32
- /** Relation wrapper instances */
33
- relationWrappers: Map<string, unknown>;
34
- }
35
-
36
- /**
37
- * Gets hydration rows for a specific relation and key
38
- * @param meta - Entity metadata
39
- * @param relationName - Name of the relation
40
- * @param key - Key to look up in the hydration map
41
- * @returns Array of hydration rows or undefined if not found
42
- * @typeParam TTable - Table definition type
43
- */
44
- export const getHydrationRows = <TTable extends TableDef>(
45
- meta: EntityMeta<TTable>,
46
- relationName: string,
47
- key: unknown
48
- ): Record<string, unknown>[] | undefined => {
49
- const map = meta.relationHydration.get(relationName);
50
- if (!map) return undefined;
51
- const rows = map.get(toKey(key));
52
- if (!rows) return undefined;
53
- return Array.isArray(rows) ? rows : undefined;
54
- };
55
-
56
- /**
57
- * Gets a single hydration record for a specific relation and key
58
- * @param meta - Entity metadata
59
- * @param relationName - Name of the relation
60
- * @param key - Key to look up in the hydration map
61
- * @returns Single hydration record or undefined if not found
62
- * @typeParam TTable - Table definition type
63
- */
64
- export const getHydrationRecord = <TTable extends TableDef>(
65
- meta: EntityMeta<TTable>,
66
- relationName: string,
67
- key: unknown
68
- ): Record<string, unknown> | undefined => {
69
- const map = meta.relationHydration.get(relationName);
70
- if (!map) return undefined;
71
- const value = map.get(toKey(key));
72
- if (!value) return undefined;
73
- if (Array.isArray(value)) {
74
- return value[0];
75
- }
76
- return value as Record<string, unknown>;
77
- };
78
-
79
- /**
80
- * Gets entity metadata from an entity instance
81
- * @param entity - Entity instance to get metadata from
82
- * @returns Entity metadata or undefined if not found
83
- * @typeParam TTable - Table definition type
84
- */
85
- export const getEntityMeta = <TTable extends TableDef>(entity: unknown): EntityMeta<TTable> | undefined => {
86
- if (!entity || typeof entity !== 'object') return undefined;
87
- return (entity as { [ENTITY_META]: EntityMeta<TTable> })[ENTITY_META];
88
- };
89
-
90
- /**
91
- * Checks if an entity has metadata attached
92
- * @param entity - Entity instance to check
93
- * @returns True if the entity has metadata, false otherwise
94
- */
95
- export const hasEntityMeta = (entity: unknown): entity is { [ENTITY_META]: EntityMeta<TableDef> } => {
96
- return Boolean(getEntityMeta(entity));
97
- };
1
+ import { TableDef } from '../schema/table.js';
2
+ import { RelationIncludeOptions } from '../query-builder/relation-types.js';
3
+ import { EntityContext } from './entity-context.js';
4
+ import { RelationMap } from '../schema/types.js';
5
+
6
+ /**
7
+ * Symbol used to store entity metadata on entity instances
8
+ */
9
+ export const ENTITY_META = Symbol('EntityMeta');
10
+
11
+ const toKey = (value: unknown): string => (value === null || value === undefined ? '' : String(value));
12
+
13
+ export type RelationKey<TTable extends TableDef> = Extract<keyof RelationMap<TTable>, string>;
14
+
15
+ /**
16
+ * Metadata stored on entity instances for ORM internal use
17
+ * @typeParam TTable - Table definition type
18
+ */
19
+ export interface EntityMeta<TTable extends TableDef> {
20
+ /** Entity context */
21
+ ctx: EntityContext;
22
+ /** Table definition */
23
+ table: TTable;
24
+ /** Relations that should be loaded lazily */
25
+ lazyRelations: RelationKey<TTable>[];
26
+ /** Include options for lazy relations */
27
+ lazyRelationOptions: Map<string, RelationIncludeOptions>;
28
+ /** Cache for relation promises */
29
+ relationCache: Map<string, Promise<unknown>>;
30
+ /** Hydration data for relations */
31
+ relationHydration: Map<string, Map<string, unknown>>;
32
+ /** Relation wrapper instances */
33
+ relationWrappers: Map<string, unknown>;
34
+ }
35
+
36
+ /**
37
+ * Gets hydration rows for a specific relation and key
38
+ * @param meta - Entity metadata
39
+ * @param relationName - Name of the relation
40
+ * @param key - Key to look up in the hydration map
41
+ * @returns Array of hydration rows or undefined if not found
42
+ * @typeParam TTable - Table definition type
43
+ */
44
+ export const getHydrationRows = <TTable extends TableDef>(
45
+ meta: EntityMeta<TTable>,
46
+ relationName: string,
47
+ key: unknown
48
+ ): Record<string, unknown>[] | undefined => {
49
+ const map = meta.relationHydration.get(relationName);
50
+ if (!map) return undefined;
51
+ const rows = map.get(toKey(key));
52
+ if (!rows) return undefined;
53
+ return Array.isArray(rows) ? rows : undefined;
54
+ };
55
+
56
+ /**
57
+ * Gets a single hydration record for a specific relation and key
58
+ * @param meta - Entity metadata
59
+ * @param relationName - Name of the relation
60
+ * @param key - Key to look up in the hydration map
61
+ * @returns Single hydration record or undefined if not found
62
+ * @typeParam TTable - Table definition type
63
+ */
64
+ export const getHydrationRecord = <TTable extends TableDef>(
65
+ meta: EntityMeta<TTable>,
66
+ relationName: string,
67
+ key: unknown
68
+ ): Record<string, unknown> | undefined => {
69
+ const map = meta.relationHydration.get(relationName);
70
+ if (!map) return undefined;
71
+ const value = map.get(toKey(key));
72
+ if (!value) return undefined;
73
+ if (Array.isArray(value)) {
74
+ return value[0];
75
+ }
76
+ return value as Record<string, unknown>;
77
+ };
78
+
79
+ /**
80
+ * Gets entity metadata from an entity instance
81
+ * @param entity - Entity instance to get metadata from
82
+ * @returns Entity metadata or undefined if not found
83
+ * @typeParam TTable - Table definition type
84
+ */
85
+ export const getEntityMeta = <TTable extends TableDef>(entity: unknown): EntityMeta<TTable> | undefined => {
86
+ if (!entity || typeof entity !== 'object') return undefined;
87
+ return (entity as { [ENTITY_META]: EntityMeta<TTable> })[ENTITY_META];
88
+ };
89
+
90
+ /**
91
+ * Checks if an entity has metadata attached
92
+ * @param entity - Entity instance to check
93
+ * @returns True if the entity has metadata, false otherwise
94
+ */
95
+ export const hasEntityMeta = (entity: unknown): entity is { [ENTITY_META]: EntityMeta<TableDef> } => {
96
+ return Boolean(getEntityMeta(entity));
97
+ };
@@ -1,39 +1,39 @@
1
- import { TableDef } from '../schema/table.js';
2
- import { EntityConstructor, getAllEntityMetadata } from './entity-metadata.js';
3
-
4
- /**
5
- * Reverse lookup registry: TableDef → EntityConstructor
6
- */
7
- const tableToConstructor = new Map<TableDef, EntityConstructor>();
8
-
9
- /**
10
- * Gets the entity constructor for a given table definition.
11
- * @param table - The table definition
12
- * @returns The entity constructor or undefined if not found
13
- */
14
- export const getConstructorForTable = (table: TableDef): EntityConstructor | undefined => {
15
- if (!tableToConstructor.size) {
16
- rebuildRegistry();
17
- }
18
- return tableToConstructor.get(table);
19
- };
20
-
21
- /**
22
- * Rebuilds the registry from entity metadata.
23
- * Called automatically on first lookup or when metadata changes.
24
- */
25
- export const rebuildRegistry = (): void => {
26
- tableToConstructor.clear();
27
- for (const meta of getAllEntityMetadata()) {
28
- if (meta.table) {
29
- tableToConstructor.set(meta.table, meta.target);
30
- }
31
- }
32
- };
33
-
34
- /**
35
- * Clears the entity registry.
36
- */
37
- export const clearEntityRegistry = (): void => {
38
- tableToConstructor.clear();
39
- };
1
+ import { TableDef } from '../schema/table.js';
2
+ import { EntityConstructor, getAllEntityMetadata } from './entity-metadata.js';
3
+
4
+ /**
5
+ * Reverse lookup registry: TableDef → EntityConstructor
6
+ */
7
+ const tableToConstructor = new Map<TableDef, EntityConstructor>();
8
+
9
+ /**
10
+ * Gets the entity constructor for a given table definition.
11
+ * @param table - The table definition
12
+ * @returns The entity constructor or undefined if not found
13
+ */
14
+ export const getConstructorForTable = (table: TableDef): EntityConstructor | undefined => {
15
+ if (!tableToConstructor.size) {
16
+ rebuildRegistry();
17
+ }
18
+ return tableToConstructor.get(table);
19
+ };
20
+
21
+ /**
22
+ * Rebuilds the registry from entity metadata.
23
+ * Called automatically on first lookup or when metadata changes.
24
+ */
25
+ export const rebuildRegistry = (): void => {
26
+ tableToConstructor.clear();
27
+ for (const meta of getAllEntityMetadata()) {
28
+ if (meta.table) {
29
+ tableToConstructor.set(meta.table, meta.target);
30
+ }
31
+ }
32
+ };
33
+
34
+ /**
35
+ * Clears the entity registry.
36
+ */
37
+ export const clearEntityRegistry = (): void => {
38
+ tableToConstructor.clear();
39
+ };