metal-orm 1.1.7 → 1.1.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.
- package/README.md +1 -1
- package/dist/index.cjs +481 -203
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -3
- package/dist/index.d.ts +58 -3
- package/dist/index.js +480 -203
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
- package/scripts/generate-entities/schema.mjs +196 -195
- package/src/decorators/decorator-metadata.ts +52 -46
- package/src/decorators/entity.ts +73 -68
- package/src/orm/entity-metadata.ts +301 -301
- package/src/orm/entity.ts +199 -199
- package/src/orm/save-graph.ts +446 -446
- package/src/orm/unit-of-work.ts +6 -6
- package/src/query-builder/select/cursor-pagination.ts +323 -0
- package/src/query-builder/select.ts +42 -1
- package/src/tree/tree-decorator.ts +137 -54
|
@@ -1,301 +1,301 @@
|
|
|
1
|
-
import { ColumnDef } from '../schema/column-types.js';
|
|
2
|
-
import { defineTable, TableDef, TableHooks } from '../schema/table.js';
|
|
3
|
-
import { CascadeMode, RelationKinds } from '../schema/relation.js';
|
|
4
|
-
import type { TransformerMetadata } from '../decorators/transformers/transformer-metadata.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Constructor type for entities.
|
|
8
|
-
* Supports any constructor signature for maximum flexibility with decorator-based entities.
|
|
9
|
-
* @template T - The entity type
|
|
10
|
-
*/
|
|
11
|
-
export type EntityConstructor<T = object> = new (...args: never[]) => T;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Target that can be an entity constructor or table definition.
|
|
15
|
-
*/
|
|
16
|
-
export type EntityOrTableTarget = EntityConstructor | TableDef;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Resolver for entity or table target, can be direct or function.
|
|
20
|
-
* @typeParam T - Specific target type that should be resolved
|
|
21
|
-
*/
|
|
22
|
-
export type EntityOrTableTargetResolver<T extends EntityOrTableTarget = EntityOrTableTarget> =
|
|
23
|
-
T | (() => T);
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Simplified column definition structure used during metadata registration.
|
|
27
|
-
* @template T - Concrete column definition type being extended
|
|
28
|
-
*/
|
|
29
|
-
export type ColumnDefLike<T extends ColumnDef = ColumnDef> = Omit<T, 'table'>;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Transforms simplified column metadata into full ColumnDef objects during table building.
|
|
33
|
-
* @template TColumns - Mapping of column names to simplified definitions
|
|
34
|
-
*/
|
|
35
|
-
type MaterializeColumns<TColumns extends Record<string, ColumnDefLike>> = {
|
|
36
|
-
[K in keyof TColumns]: ColumnDef<TColumns[K]['type'], TColumns[K]['tsType']> & Omit<
|
|
37
|
-
TColumns[K],
|
|
38
|
-
'name' | 'table' | 'type' | 'tsType'
|
|
39
|
-
> & { name: string; table: string };
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Common properties shared by all relation metadata types.
|
|
44
|
-
*/
|
|
45
|
-
interface BaseRelationMetadata {
|
|
46
|
-
/** The property key for the relation */
|
|
47
|
-
propertyKey: string;
|
|
48
|
-
/** The target entity or table */
|
|
49
|
-
target: EntityOrTableTargetResolver;
|
|
50
|
-
/** Optional cascade mode */
|
|
51
|
-
cascade?: CascadeMode;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Metadata for has many relations.
|
|
56
|
-
*/
|
|
57
|
-
export interface HasManyRelationMetadata extends BaseRelationMetadata {
|
|
58
|
-
/** The relation kind */
|
|
59
|
-
kind: typeof RelationKinds.HasMany;
|
|
60
|
-
/** The foreign key */
|
|
61
|
-
foreignKey?: string;
|
|
62
|
-
/** Optional local key */
|
|
63
|
-
localKey?: string;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Metadata for has one relations.
|
|
68
|
-
*/
|
|
69
|
-
export interface HasOneRelationMetadata extends BaseRelationMetadata {
|
|
70
|
-
/** The relation kind */
|
|
71
|
-
kind: typeof RelationKinds.HasOne;
|
|
72
|
-
/** The foreign key */
|
|
73
|
-
foreignKey?: string;
|
|
74
|
-
/** Optional local key */
|
|
75
|
-
localKey?: string;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Metadata for belongs to relations.
|
|
80
|
-
*/
|
|
81
|
-
export interface BelongsToRelationMetadata extends BaseRelationMetadata {
|
|
82
|
-
/** The relation kind */
|
|
83
|
-
kind: typeof RelationKinds.BelongsTo;
|
|
84
|
-
/** The foreign key */
|
|
85
|
-
foreignKey: string;
|
|
86
|
-
/** Optional local key */
|
|
87
|
-
localKey?: string;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Metadata for belongs to many relations.
|
|
92
|
-
*/
|
|
93
|
-
export interface BelongsToManyRelationMetadata extends BaseRelationMetadata {
|
|
94
|
-
/** The relation kind */
|
|
95
|
-
kind: typeof RelationKinds.BelongsToMany;
|
|
96
|
-
/** The pivot table */
|
|
97
|
-
pivotTable: EntityOrTableTargetResolver;
|
|
98
|
-
/** The pivot foreign key to root */
|
|
99
|
-
pivotForeignKeyToRoot?: string;
|
|
100
|
-
/** The pivot foreign key to target */
|
|
101
|
-
pivotForeignKeyToTarget?: string;
|
|
102
|
-
/** Optional local key */
|
|
103
|
-
localKey?: string;
|
|
104
|
-
/** Optional target key */
|
|
105
|
-
targetKey?: string;
|
|
106
|
-
/** Optional pivot primary key */
|
|
107
|
-
pivotPrimaryKey?: string;
|
|
108
|
-
/** Optional default pivot columns */
|
|
109
|
-
defaultPivotColumns?: string[];
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Union type for all relation metadata.
|
|
114
|
-
*/
|
|
115
|
-
export type RelationMetadata =
|
|
116
|
-
| HasManyRelationMetadata
|
|
117
|
-
| HasOneRelationMetadata
|
|
118
|
-
| BelongsToRelationMetadata
|
|
119
|
-
| BelongsToManyRelationMetadata;
|
|
120
|
-
|
|
121
|
-
/** Entity type: 'table' (default) or 'view'. */
|
|
122
|
-
export type EntityType = 'table' | 'view';
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Metadata for entities.
|
|
126
|
-
* @template TColumns - The columns type
|
|
127
|
-
*/
|
|
128
|
-
export interface EntityMetadata<TColumns extends Record<string, ColumnDefLike> = Record<string, ColumnDefLike>> {
|
|
129
|
-
/** The entity constructor */
|
|
130
|
-
target: EntityConstructor;
|
|
131
|
-
/** The table name */
|
|
132
|
-
tableName: string;
|
|
133
|
-
/** The entity type: 'table' or 'view' */
|
|
134
|
-
type: EntityType;
|
|
135
|
-
/** The columns */
|
|
136
|
-
columns: TColumns;
|
|
137
|
-
/** The relations */
|
|
138
|
-
relations: Record<string, RelationMetadata>;
|
|
139
|
-
/** The transformers */
|
|
140
|
-
transformers: Record<string, TransformerMetadata>;
|
|
141
|
-
/** Optional hooks */
|
|
142
|
-
hooks?: TableHooks;
|
|
143
|
-
/** Optional table definition */
|
|
144
|
-
table?: TableDef<MaterializeColumns<TColumns>>;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
const GLOBAL_KEY = Symbol.for('metal-orm:entity-metadata');
|
|
148
|
-
const globalStore = globalThis as unknown as {
|
|
149
|
-
[GLOBAL_KEY]?: Map<EntityConstructor, EntityMetadata>;
|
|
150
|
-
};
|
|
151
|
-
const metadataMap = globalStore[GLOBAL_KEY] ?? (globalStore[GLOBAL_KEY] = new Map());
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Registers entity metadata.
|
|
155
|
-
* @param meta - The entity metadata to register
|
|
156
|
-
*/
|
|
157
|
-
export const registerEntityMetadata = (meta: EntityMetadata): void => {
|
|
158
|
-
metadataMap.set(meta.target, meta);
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Ensures entity metadata exists for the target, creating it if necessary.
|
|
163
|
-
* @param target - The entity constructor
|
|
164
|
-
* @returns The entity metadata
|
|
165
|
-
*/
|
|
166
|
-
export const ensureEntityMetadata = (target: EntityConstructor): EntityMetadata => {
|
|
167
|
-
let meta = metadataMap.get(target);
|
|
168
|
-
if (!meta) {
|
|
169
|
-
meta = {
|
|
170
|
-
target,
|
|
171
|
-
tableName: target.name || 'unknown',
|
|
172
|
-
type: 'table',
|
|
173
|
-
columns: {},
|
|
174
|
-
relations: {},
|
|
175
|
-
transformers: {}
|
|
176
|
-
};
|
|
177
|
-
metadataMap.set(target, meta);
|
|
178
|
-
}
|
|
179
|
-
return meta;
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Gets entity metadata for the target.
|
|
184
|
-
* @param target - The entity constructor
|
|
185
|
-
* @returns The entity metadata or undefined if not found
|
|
186
|
-
*/
|
|
187
|
-
export const getEntityMetadata = (target: EntityConstructor): EntityMetadata | undefined => {
|
|
188
|
-
return metadataMap.get(target);
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Gets all entity metadata.
|
|
193
|
-
* @returns Array of all entity metadata
|
|
194
|
-
*/
|
|
195
|
-
export const getAllEntityMetadata = (): EntityMetadata[] => {
|
|
196
|
-
return Array.from(metadataMap.values());
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Clears all entity metadata.
|
|
201
|
-
*/
|
|
202
|
-
export const clearEntityMetadata = (): void => {
|
|
203
|
-
metadataMap.clear();
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Adds column metadata to an entity.
|
|
208
|
-
* @param target - The entity constructor
|
|
209
|
-
* @param propertyKey - The property key
|
|
210
|
-
* @param column - The column definition
|
|
211
|
-
*/
|
|
212
|
-
export const addColumnMetadata = (
|
|
213
|
-
target: EntityConstructor,
|
|
214
|
-
propertyKey: string,
|
|
215
|
-
column: ColumnDefLike
|
|
216
|
-
): void => {
|
|
217
|
-
const meta = ensureEntityMetadata(target);
|
|
218
|
-
(meta.columns as Record<string, ColumnDefLike>)[propertyKey] = { ...column };
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Adds relation metadata to an entity.
|
|
223
|
-
* @param target - The entity constructor
|
|
224
|
-
* @param propertyKey - The property key
|
|
225
|
-
* @param relation - The relation metadata
|
|
226
|
-
*/
|
|
227
|
-
export const addRelationMetadata = (
|
|
228
|
-
target: EntityConstructor,
|
|
229
|
-
propertyKey: string,
|
|
230
|
-
relation: RelationMetadata
|
|
231
|
-
): void => {
|
|
232
|
-
const meta = ensureEntityMetadata(target);
|
|
233
|
-
meta.relations[propertyKey] = relation;
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Adds transformer metadata to an entity.
|
|
238
|
-
* @param target - The entity constructor
|
|
239
|
-
* @param propertyKey - The property key
|
|
240
|
-
* @param transformer - The transformer metadata
|
|
241
|
-
*/
|
|
242
|
-
export const addTransformerMetadata = (
|
|
243
|
-
target: EntityConstructor,
|
|
244
|
-
propertyKey: string,
|
|
245
|
-
transformer: TransformerMetadata
|
|
246
|
-
): void => {
|
|
247
|
-
const meta = ensureEntityMetadata(target);
|
|
248
|
-
meta.transformers[propertyKey] = transformer;
|
|
249
|
-
};
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Sets the table name, hooks, and type for an entity.
|
|
253
|
-
* @param target - The entity constructor
|
|
254
|
-
* @param tableName - The table name
|
|
255
|
-
* @param hooks - Optional table hooks
|
|
256
|
-
* @param type - Entity type: 'table' or 'view'
|
|
257
|
-
*/
|
|
258
|
-
export const setEntityTableName = (
|
|
259
|
-
target: EntityConstructor,
|
|
260
|
-
tableName: string,
|
|
261
|
-
hooks?: TableHooks,
|
|
262
|
-
type?: EntityType
|
|
263
|
-
): void => {
|
|
264
|
-
const meta = ensureEntityMetadata(target);
|
|
265
|
-
if (tableName && tableName.length > 0) {
|
|
266
|
-
meta.tableName = tableName;
|
|
267
|
-
}
|
|
268
|
-
if (hooks) {
|
|
269
|
-
meta.hooks = hooks;
|
|
270
|
-
}
|
|
271
|
-
if (type) {
|
|
272
|
-
meta.type = type;
|
|
273
|
-
}
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Builds a table definition from entity metadata.
|
|
278
|
-
* @template TColumns - The columns type
|
|
279
|
-
* @param meta - The entity metadata
|
|
280
|
-
* @returns The table definition
|
|
281
|
-
*/
|
|
282
|
-
export const buildTableDef = <TColumns extends Record<string, ColumnDefLike>>(meta: EntityMetadata<TColumns>): TableDef<MaterializeColumns<TColumns>> => {
|
|
283
|
-
if (meta.table) {
|
|
284
|
-
return meta.table;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// Build columns using a simpler approach that avoids type assertion
|
|
288
|
-
const columns: Record<string, ColumnDef> = {};
|
|
289
|
-
for (const [key, def] of Object.entries(meta.columns)) {
|
|
290
|
-
columns[key] = {
|
|
291
|
-
...def,
|
|
292
|
-
name: def.name ?? key,
|
|
293
|
-
table: meta.tableName
|
|
294
|
-
} as ColumnDef;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
const table = defineTable(meta.tableName, columns as MaterializeColumns<TColumns>, {}, meta.hooks);
|
|
298
|
-
meta.table = table;
|
|
299
|
-
return table;
|
|
300
|
-
};
|
|
301
|
-
|
|
1
|
+
import { ColumnDef } from '../schema/column-types.js';
|
|
2
|
+
import { defineTable, TableDef, TableHooks } from '../schema/table.js';
|
|
3
|
+
import { CascadeMode, RelationKinds } from '../schema/relation.js';
|
|
4
|
+
import type { TransformerMetadata } from '../decorators/transformers/transformer-metadata.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Constructor type for entities.
|
|
8
|
+
* Supports any constructor signature for maximum flexibility with decorator-based entities.
|
|
9
|
+
* @template T - The entity type
|
|
10
|
+
*/
|
|
11
|
+
export type EntityConstructor<T = object> = new (...args: never[]) => T;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Target that can be an entity constructor or table definition.
|
|
15
|
+
*/
|
|
16
|
+
export type EntityOrTableTarget = EntityConstructor | TableDef;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Resolver for entity or table target, can be direct or function.
|
|
20
|
+
* @typeParam T - Specific target type that should be resolved
|
|
21
|
+
*/
|
|
22
|
+
export type EntityOrTableTargetResolver<T extends EntityOrTableTarget = EntityOrTableTarget> =
|
|
23
|
+
T | (() => T);
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Simplified column definition structure used during metadata registration.
|
|
27
|
+
* @template T - Concrete column definition type being extended
|
|
28
|
+
*/
|
|
29
|
+
export type ColumnDefLike<T extends ColumnDef = ColumnDef> = Omit<T, 'table'>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Transforms simplified column metadata into full ColumnDef objects during table building.
|
|
33
|
+
* @template TColumns - Mapping of column names to simplified definitions
|
|
34
|
+
*/
|
|
35
|
+
type MaterializeColumns<TColumns extends Record<string, ColumnDefLike>> = {
|
|
36
|
+
[K in keyof TColumns]: ColumnDef<TColumns[K]['type'], TColumns[K]['tsType']> & Omit<
|
|
37
|
+
TColumns[K],
|
|
38
|
+
'name' | 'table' | 'type' | 'tsType'
|
|
39
|
+
> & { name: string; table: string };
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Common properties shared by all relation metadata types.
|
|
44
|
+
*/
|
|
45
|
+
interface BaseRelationMetadata {
|
|
46
|
+
/** The property key for the relation */
|
|
47
|
+
propertyKey: string;
|
|
48
|
+
/** The target entity or table */
|
|
49
|
+
target: EntityOrTableTargetResolver;
|
|
50
|
+
/** Optional cascade mode */
|
|
51
|
+
cascade?: CascadeMode;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Metadata for has many relations.
|
|
56
|
+
*/
|
|
57
|
+
export interface HasManyRelationMetadata extends BaseRelationMetadata {
|
|
58
|
+
/** The relation kind */
|
|
59
|
+
kind: typeof RelationKinds.HasMany;
|
|
60
|
+
/** The foreign key */
|
|
61
|
+
foreignKey?: string;
|
|
62
|
+
/** Optional local key */
|
|
63
|
+
localKey?: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Metadata for has one relations.
|
|
68
|
+
*/
|
|
69
|
+
export interface HasOneRelationMetadata extends BaseRelationMetadata {
|
|
70
|
+
/** The relation kind */
|
|
71
|
+
kind: typeof RelationKinds.HasOne;
|
|
72
|
+
/** The foreign key */
|
|
73
|
+
foreignKey?: string;
|
|
74
|
+
/** Optional local key */
|
|
75
|
+
localKey?: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Metadata for belongs to relations.
|
|
80
|
+
*/
|
|
81
|
+
export interface BelongsToRelationMetadata extends BaseRelationMetadata {
|
|
82
|
+
/** The relation kind */
|
|
83
|
+
kind: typeof RelationKinds.BelongsTo;
|
|
84
|
+
/** The foreign key */
|
|
85
|
+
foreignKey: string;
|
|
86
|
+
/** Optional local key */
|
|
87
|
+
localKey?: string;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Metadata for belongs to many relations.
|
|
92
|
+
*/
|
|
93
|
+
export interface BelongsToManyRelationMetadata extends BaseRelationMetadata {
|
|
94
|
+
/** The relation kind */
|
|
95
|
+
kind: typeof RelationKinds.BelongsToMany;
|
|
96
|
+
/** The pivot table */
|
|
97
|
+
pivotTable: EntityOrTableTargetResolver;
|
|
98
|
+
/** The pivot foreign key to root */
|
|
99
|
+
pivotForeignKeyToRoot?: string;
|
|
100
|
+
/** The pivot foreign key to target */
|
|
101
|
+
pivotForeignKeyToTarget?: string;
|
|
102
|
+
/** Optional local key */
|
|
103
|
+
localKey?: string;
|
|
104
|
+
/** Optional target key */
|
|
105
|
+
targetKey?: string;
|
|
106
|
+
/** Optional pivot primary key */
|
|
107
|
+
pivotPrimaryKey?: string;
|
|
108
|
+
/** Optional default pivot columns */
|
|
109
|
+
defaultPivotColumns?: string[];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Union type for all relation metadata.
|
|
114
|
+
*/
|
|
115
|
+
export type RelationMetadata =
|
|
116
|
+
| HasManyRelationMetadata
|
|
117
|
+
| HasOneRelationMetadata
|
|
118
|
+
| BelongsToRelationMetadata
|
|
119
|
+
| BelongsToManyRelationMetadata;
|
|
120
|
+
|
|
121
|
+
/** Entity type: 'table' (default) or 'view'. */
|
|
122
|
+
export type EntityType = 'table' | 'view';
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Metadata for entities.
|
|
126
|
+
* @template TColumns - The columns type
|
|
127
|
+
*/
|
|
128
|
+
export interface EntityMetadata<TColumns extends Record<string, ColumnDefLike> = Record<string, ColumnDefLike>> {
|
|
129
|
+
/** The entity constructor */
|
|
130
|
+
target: EntityConstructor;
|
|
131
|
+
/** The table name */
|
|
132
|
+
tableName: string;
|
|
133
|
+
/** The entity type: 'table' or 'view' */
|
|
134
|
+
type: EntityType;
|
|
135
|
+
/** The columns */
|
|
136
|
+
columns: TColumns;
|
|
137
|
+
/** The relations */
|
|
138
|
+
relations: Record<string, RelationMetadata>;
|
|
139
|
+
/** The transformers */
|
|
140
|
+
transformers: Record<string, TransformerMetadata>;
|
|
141
|
+
/** Optional hooks */
|
|
142
|
+
hooks?: TableHooks;
|
|
143
|
+
/** Optional table definition */
|
|
144
|
+
table?: TableDef<MaterializeColumns<TColumns>>;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const GLOBAL_KEY = Symbol.for('metal-orm:entity-metadata');
|
|
148
|
+
const globalStore = globalThis as unknown as {
|
|
149
|
+
[GLOBAL_KEY]?: Map<EntityConstructor, EntityMetadata>;
|
|
150
|
+
};
|
|
151
|
+
const metadataMap = globalStore[GLOBAL_KEY] ?? (globalStore[GLOBAL_KEY] = new Map());
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Registers entity metadata.
|
|
155
|
+
* @param meta - The entity metadata to register
|
|
156
|
+
*/
|
|
157
|
+
export const registerEntityMetadata = (meta: EntityMetadata): void => {
|
|
158
|
+
metadataMap.set(meta.target, meta);
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Ensures entity metadata exists for the target, creating it if necessary.
|
|
163
|
+
* @param target - The entity constructor
|
|
164
|
+
* @returns The entity metadata
|
|
165
|
+
*/
|
|
166
|
+
export const ensureEntityMetadata = (target: EntityConstructor): EntityMetadata => {
|
|
167
|
+
let meta = metadataMap.get(target);
|
|
168
|
+
if (!meta) {
|
|
169
|
+
meta = {
|
|
170
|
+
target,
|
|
171
|
+
tableName: target.name || 'unknown',
|
|
172
|
+
type: 'table',
|
|
173
|
+
columns: {},
|
|
174
|
+
relations: {},
|
|
175
|
+
transformers: {}
|
|
176
|
+
};
|
|
177
|
+
metadataMap.set(target, meta);
|
|
178
|
+
}
|
|
179
|
+
return meta;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Gets entity metadata for the target.
|
|
184
|
+
* @param target - The entity constructor
|
|
185
|
+
* @returns The entity metadata or undefined if not found
|
|
186
|
+
*/
|
|
187
|
+
export const getEntityMetadata = (target: EntityConstructor): EntityMetadata | undefined => {
|
|
188
|
+
return metadataMap.get(target);
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Gets all entity metadata.
|
|
193
|
+
* @returns Array of all entity metadata
|
|
194
|
+
*/
|
|
195
|
+
export const getAllEntityMetadata = (): EntityMetadata[] => {
|
|
196
|
+
return Array.from(metadataMap.values());
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Clears all entity metadata.
|
|
201
|
+
*/
|
|
202
|
+
export const clearEntityMetadata = (): void => {
|
|
203
|
+
metadataMap.clear();
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Adds column metadata to an entity.
|
|
208
|
+
* @param target - The entity constructor
|
|
209
|
+
* @param propertyKey - The property key
|
|
210
|
+
* @param column - The column definition
|
|
211
|
+
*/
|
|
212
|
+
export const addColumnMetadata = (
|
|
213
|
+
target: EntityConstructor,
|
|
214
|
+
propertyKey: string,
|
|
215
|
+
column: ColumnDefLike
|
|
216
|
+
): void => {
|
|
217
|
+
const meta = ensureEntityMetadata(target);
|
|
218
|
+
(meta.columns as Record<string, ColumnDefLike>)[propertyKey] = { ...column };
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Adds relation metadata to an entity.
|
|
223
|
+
* @param target - The entity constructor
|
|
224
|
+
* @param propertyKey - The property key
|
|
225
|
+
* @param relation - The relation metadata
|
|
226
|
+
*/
|
|
227
|
+
export const addRelationMetadata = (
|
|
228
|
+
target: EntityConstructor,
|
|
229
|
+
propertyKey: string,
|
|
230
|
+
relation: RelationMetadata
|
|
231
|
+
): void => {
|
|
232
|
+
const meta = ensureEntityMetadata(target);
|
|
233
|
+
meta.relations[propertyKey] = relation;
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Adds transformer metadata to an entity.
|
|
238
|
+
* @param target - The entity constructor
|
|
239
|
+
* @param propertyKey - The property key
|
|
240
|
+
* @param transformer - The transformer metadata
|
|
241
|
+
*/
|
|
242
|
+
export const addTransformerMetadata = (
|
|
243
|
+
target: EntityConstructor,
|
|
244
|
+
propertyKey: string,
|
|
245
|
+
transformer: TransformerMetadata
|
|
246
|
+
): void => {
|
|
247
|
+
const meta = ensureEntityMetadata(target);
|
|
248
|
+
meta.transformers[propertyKey] = transformer;
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Sets the table name, hooks, and type for an entity.
|
|
253
|
+
* @param target - The entity constructor
|
|
254
|
+
* @param tableName - The table name
|
|
255
|
+
* @param hooks - Optional table hooks
|
|
256
|
+
* @param type - Entity type: 'table' or 'view'
|
|
257
|
+
*/
|
|
258
|
+
export const setEntityTableName = (
|
|
259
|
+
target: EntityConstructor,
|
|
260
|
+
tableName: string,
|
|
261
|
+
hooks?: TableHooks,
|
|
262
|
+
type?: EntityType
|
|
263
|
+
): void => {
|
|
264
|
+
const meta = ensureEntityMetadata(target);
|
|
265
|
+
if (tableName && tableName.length > 0) {
|
|
266
|
+
meta.tableName = tableName;
|
|
267
|
+
}
|
|
268
|
+
if (hooks) {
|
|
269
|
+
meta.hooks = hooks;
|
|
270
|
+
}
|
|
271
|
+
if (type) {
|
|
272
|
+
meta.type = type;
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Builds a table definition from entity metadata.
|
|
278
|
+
* @template TColumns - The columns type
|
|
279
|
+
* @param meta - The entity metadata
|
|
280
|
+
* @returns The table definition
|
|
281
|
+
*/
|
|
282
|
+
export const buildTableDef = <TColumns extends Record<string, ColumnDefLike>>(meta: EntityMetadata<TColumns>): TableDef<MaterializeColumns<TColumns>> => {
|
|
283
|
+
if (meta.table) {
|
|
284
|
+
return meta.table;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Build columns using a simpler approach that avoids type assertion
|
|
288
|
+
const columns: Record<string, ColumnDef> = {};
|
|
289
|
+
for (const [key, def] of Object.entries(meta.columns)) {
|
|
290
|
+
columns[key] = {
|
|
291
|
+
...def,
|
|
292
|
+
name: def.name ?? key,
|
|
293
|
+
table: meta.tableName
|
|
294
|
+
} as ColumnDef;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const table = defineTable(meta.tableName, columns as MaterializeColumns<TColumns>, {}, meta.hooks);
|
|
298
|
+
meta.table = table;
|
|
299
|
+
return table;
|
|
300
|
+
};
|
|
301
|
+
|