metal-orm 1.0.42 → 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.
- package/README.md +195 -37
- package/dist/index.cjs +1014 -538
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1267 -371
- package/dist/index.d.ts +1267 -371
- package/dist/index.js +1012 -536
- package/dist/index.js.map +1 -1
- package/package.json +8 -2
- package/scripts/run-eslint.mjs +34 -0
- package/src/codegen/typescript.ts +32 -15
- package/src/core/ast/adapters.ts +8 -2
- package/src/core/ast/builders.ts +105 -76
- package/src/core/ast/expression-builders.ts +430 -392
- package/src/core/ast/expression-nodes.ts +14 -5
- package/src/core/ast/expression-visitor.ts +56 -14
- package/src/core/ast/helpers.ts +23 -0
- package/src/core/ast/join-node.ts +18 -2
- package/src/core/ast/query.ts +6 -6
- package/src/core/ast/window-functions.ts +10 -2
- package/src/core/ddl/dialects/base-schema-dialect.ts +37 -4
- package/src/core/ddl/dialects/index.ts +1 -0
- package/src/core/ddl/dialects/mssql-schema-dialect.ts +5 -0
- package/src/core/ddl/dialects/mysql-schema-dialect.ts +3 -0
- package/src/core/ddl/dialects/postgres-schema-dialect.ts +14 -1
- package/src/core/ddl/dialects/render-reference.test.ts +69 -0
- package/src/core/ddl/dialects/sqlite-schema-dialect.ts +10 -0
- package/src/core/ddl/introspect/catalogs/index.ts +1 -0
- package/src/core/ddl/introspect/catalogs/postgres.ts +2 -0
- package/src/core/ddl/introspect/context.ts +6 -0
- package/src/core/ddl/introspect/functions/postgres.ts +13 -0
- package/src/core/ddl/introspect/mssql.ts +53 -8
- package/src/core/ddl/introspect/mysql.ts +32 -6
- package/src/core/ddl/introspect/postgres.ts +102 -34
- package/src/core/ddl/introspect/registry.ts +14 -0
- package/src/core/ddl/introspect/run-select.ts +19 -4
- package/src/core/ddl/introspect/sqlite.ts +78 -11
- package/src/core/ddl/introspect/types.ts +0 -1
- package/src/core/ddl/introspect/utils.ts +21 -3
- package/src/core/ddl/naming-strategy.ts +6 -0
- package/src/core/ddl/schema-dialect.ts +20 -6
- package/src/core/ddl/schema-diff.ts +22 -0
- package/src/core/ddl/schema-generator.ts +26 -12
- package/src/core/ddl/schema-plan-executor.ts +6 -0
- package/src/core/ddl/schema-types.ts +6 -0
- package/src/core/ddl/sql-writing.ts +4 -4
- package/src/core/dialect/abstract.ts +19 -7
- package/src/core/dialect/base/function-table-formatter.ts +3 -2
- package/src/core/dialect/base/join-compiler.ts +5 -3
- package/src/core/dialect/base/returning-strategy.ts +1 -0
- package/src/core/dialect/base/sql-dialect.ts +3 -3
- package/src/core/dialect/mssql/functions.ts +24 -25
- package/src/core/dialect/mssql/index.ts +1 -4
- package/src/core/dialect/mysql/functions.ts +0 -1
- package/src/core/dialect/postgres/functions.ts +33 -34
- package/src/core/dialect/postgres/index.ts +1 -0
- package/src/core/dialect/sqlite/functions.ts +18 -19
- package/src/core/dialect/sqlite/index.ts +2 -0
- package/src/core/execution/db-executor.ts +1 -1
- package/src/core/execution/executors/mysql-executor.ts +2 -2
- package/src/core/execution/executors/postgres-executor.ts +1 -1
- package/src/core/execution/pooling/pool.ts +12 -5
- package/src/core/functions/datetime.ts +58 -34
- package/src/core/functions/numeric.ts +96 -31
- package/src/core/functions/standard-strategy.ts +35 -0
- package/src/core/functions/text.ts +84 -23
- package/src/core/functions/types.ts +23 -8
- package/src/decorators/bootstrap.ts +42 -11
- package/src/decorators/column.ts +20 -11
- package/src/decorators/decorator-metadata.ts +30 -9
- package/src/decorators/entity.ts +29 -5
- package/src/decorators/index.ts +3 -0
- package/src/decorators/relations.ts +34 -11
- package/src/orm/als.ts +34 -9
- package/src/orm/entity-context.ts +62 -8
- package/src/orm/entity-meta.ts +8 -8
- package/src/orm/entity-metadata.ts +131 -16
- package/src/orm/entity.ts +28 -29
- package/src/orm/execute.ts +19 -4
- package/src/orm/hydration.ts +42 -39
- package/src/orm/identity-map.ts +1 -1
- package/src/orm/lazy-batch.ts +74 -104
- package/src/orm/orm-session.ts +24 -23
- package/src/orm/orm.ts +2 -5
- package/src/orm/relation-change-processor.ts +12 -11
- package/src/orm/relations/belongs-to.ts +11 -11
- package/src/orm/relations/has-many.ts +54 -10
- package/src/orm/relations/has-one.ts +8 -7
- package/src/orm/relations/many-to-many.ts +13 -13
- package/src/orm/runtime-types.ts +4 -4
- package/src/orm/save-graph.ts +31 -25
- package/src/orm/unit-of-work.ts +17 -17
- package/src/query/index.ts +74 -0
- package/src/query/target.ts +46 -0
- package/src/query-builder/delete-query-state.ts +30 -0
- package/src/query-builder/delete.ts +64 -18
- package/src/query-builder/hydration-manager.ts +52 -5
- package/src/query-builder/insert-query-state.ts +30 -0
- package/src/query-builder/insert.ts +58 -10
- package/src/query-builder/query-ast-service.ts +7 -2
- package/src/query-builder/query-resolution.ts +78 -0
- package/src/query-builder/raw-column-parser.ts +7 -1
- package/src/query-builder/relation-alias.ts +7 -0
- package/src/query-builder/relation-conditions.ts +61 -48
- package/src/query-builder/relation-service.ts +68 -63
- package/src/query-builder/relation-utils.ts +3 -0
- package/src/query-builder/select/cte-facet.ts +40 -0
- package/src/query-builder/select/from-facet.ts +80 -0
- package/src/query-builder/select/join-facet.ts +62 -0
- package/src/query-builder/select/predicate-facet.ts +103 -0
- package/src/query-builder/select/projection-facet.ts +69 -0
- package/src/query-builder/select/relation-facet.ts +81 -0
- package/src/query-builder/select/setop-facet.ts +36 -0
- package/src/query-builder/select-helpers.ts +15 -2
- package/src/query-builder/select-query-builder-deps.ts +19 -1
- package/src/query-builder/select-query-state.ts +2 -1
- package/src/query-builder/select.ts +795 -1163
- package/src/query-builder/update-query-state.ts +52 -0
- package/src/query-builder/update.ts +69 -18
- package/src/schema/column.ts +26 -26
- package/src/schema/table-guards.ts +31 -0
- package/src/schema/table.ts +47 -18
- package/src/schema/types.ts +22 -22
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
DualModePropertyDecorator,
|
|
10
10
|
getOrCreateMetadataBag,
|
|
11
11
|
isStandardDecoratorContext,
|
|
12
|
-
registerInitializer,
|
|
13
12
|
StandardDecoratorContext
|
|
14
13
|
} from './decorator-metadata.js';
|
|
15
14
|
|
|
@@ -19,18 +18,30 @@ interface BaseRelationOptions {
|
|
|
19
18
|
localKey?: string;
|
|
20
19
|
}
|
|
21
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Options for HasMany relation.
|
|
23
|
+
*/
|
|
22
24
|
export interface HasManyOptions extends BaseRelationOptions {
|
|
23
25
|
foreignKey: string;
|
|
24
26
|
}
|
|
25
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Options for HasOne relation.
|
|
30
|
+
*/
|
|
26
31
|
export interface HasOneOptions extends BaseRelationOptions {
|
|
27
32
|
foreignKey: string;
|
|
28
33
|
}
|
|
29
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Options for BelongsTo relation.
|
|
37
|
+
*/
|
|
30
38
|
export interface BelongsToOptions extends BaseRelationOptions {
|
|
31
39
|
foreignKey: string;
|
|
32
40
|
}
|
|
33
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Options for BelongsToMany relation.
|
|
44
|
+
*/
|
|
34
45
|
export interface BelongsToManyOptions {
|
|
35
46
|
target: EntityOrTableTargetResolver;
|
|
36
47
|
pivotTable: EntityOrTableTargetResolver;
|
|
@@ -54,8 +65,8 @@ const resolveConstructor = (instanceOrCtor: unknown): EntityConstructor | undefi
|
|
|
54
65
|
if (typeof instanceOrCtor === 'function') {
|
|
55
66
|
return instanceOrCtor as EntityConstructor;
|
|
56
67
|
}
|
|
57
|
-
if (instanceOrCtor && typeof (instanceOrCtor as
|
|
58
|
-
return (instanceOrCtor as
|
|
68
|
+
if (instanceOrCtor && typeof (instanceOrCtor as { constructor: new (...args: unknown[]) => unknown }).constructor === 'function') {
|
|
69
|
+
return (instanceOrCtor as { constructor: new (...args: unknown[]) => unknown }).constructor as EntityConstructor;
|
|
59
70
|
}
|
|
60
71
|
return undefined;
|
|
61
72
|
};
|
|
@@ -80,14 +91,6 @@ const createFieldDecorator = (
|
|
|
80
91
|
if (!bag.relations.some(entry => entry.propertyName === propertyName)) {
|
|
81
92
|
bag.relations.push({ propertyName, relation: relationMetadata });
|
|
82
93
|
}
|
|
83
|
-
|
|
84
|
-
registerInitializer(ctx, function () {
|
|
85
|
-
const ctor = resolveConstructor(this);
|
|
86
|
-
if (!ctor) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
registerRelation(ctor, propertyName, relationMetadata);
|
|
90
|
-
});
|
|
91
94
|
return;
|
|
92
95
|
}
|
|
93
96
|
|
|
@@ -102,6 +105,11 @@ const createFieldDecorator = (
|
|
|
102
105
|
return decorator;
|
|
103
106
|
};
|
|
104
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Decorator to define a HasMany relation on an entity property.
|
|
110
|
+
* @param options - The relation options.
|
|
111
|
+
* @returns A property decorator that registers the relation metadata.
|
|
112
|
+
*/
|
|
105
113
|
export function HasMany(options: HasManyOptions) {
|
|
106
114
|
return createFieldDecorator(propertyName => ({
|
|
107
115
|
kind: RelationKinds.HasMany,
|
|
@@ -113,6 +121,11 @@ export function HasMany(options: HasManyOptions) {
|
|
|
113
121
|
}));
|
|
114
122
|
}
|
|
115
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Decorator to define a HasOne relation on an entity property.
|
|
126
|
+
* @param options - The relation options.
|
|
127
|
+
* @returns A property decorator that registers the relation metadata.
|
|
128
|
+
*/
|
|
116
129
|
export function HasOne(options: HasOneOptions) {
|
|
117
130
|
return createFieldDecorator(propertyName => ({
|
|
118
131
|
kind: RelationKinds.HasOne,
|
|
@@ -124,6 +137,11 @@ export function HasOne(options: HasOneOptions) {
|
|
|
124
137
|
}));
|
|
125
138
|
}
|
|
126
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Decorator to define a BelongsTo relation on an entity property.
|
|
142
|
+
* @param options - The relation options.
|
|
143
|
+
* @returns A property decorator that registers the relation metadata.
|
|
144
|
+
*/
|
|
127
145
|
export function BelongsTo(options: BelongsToOptions) {
|
|
128
146
|
return createFieldDecorator(propertyName => ({
|
|
129
147
|
kind: RelationKinds.BelongsTo,
|
|
@@ -135,6 +153,11 @@ export function BelongsTo(options: BelongsToOptions) {
|
|
|
135
153
|
}));
|
|
136
154
|
}
|
|
137
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Decorator to define a BelongsToMany relation on an entity property.
|
|
158
|
+
* @param options - The relation options.
|
|
159
|
+
* @returns A property decorator that registers the relation metadata.
|
|
160
|
+
*/
|
|
138
161
|
export function BelongsToMany(options: BelongsToManyOptions) {
|
|
139
162
|
return createFieldDecorator(propertyName => ({
|
|
140
163
|
kind: RelationKinds.BelongsToMany,
|
package/src/orm/als.ts
CHANGED
|
@@ -1,18 +1,31 @@
|
|
|
1
1
|
// In a real Node environment: import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Browser-compatible implementation of AsyncLocalStorage
|
|
5
|
-
* Provides a simple in-memory store for browser environments
|
|
6
|
-
*
|
|
4
|
+
* Browser-compatible implementation of AsyncLocalStorage.
|
|
5
|
+
* Provides a simple in-memory store for browser environments while maintaining
|
|
6
|
+
* Node.js AsyncLocalStorage API compatibility.
|
|
7
|
+
*
|
|
8
|
+
* @template T Type of the data stored in the async context
|
|
7
9
|
*/
|
|
8
10
|
export class AsyncLocalStorage<T> {
|
|
9
11
|
private store: T | undefined;
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
|
-
* Executes a callback
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* Executes a callback function within a context containing the specified store value.
|
|
15
|
+
* The store value is only available during the callback's execution and is automatically
|
|
16
|
+
* cleared afterward.
|
|
17
|
+
*
|
|
18
|
+
* @param store - The context value to make available during callback execution
|
|
19
|
+
* @param callback - Function to execute with the store value available
|
|
20
|
+
* @returns Result of the callback function execution
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```
|
|
24
|
+
* const als = new AsyncLocalStorage<number>();
|
|
25
|
+
* als.run(42, () => {
|
|
26
|
+
* console.log(als.getStore()); // Outputs: 42
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
16
29
|
*/
|
|
17
30
|
run<R>(store: T, callback: () => R): R {
|
|
18
31
|
this.store = store;
|
|
@@ -24,8 +37,20 @@ export class AsyncLocalStorage<T> {
|
|
|
24
37
|
}
|
|
25
38
|
|
|
26
39
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
40
|
+
* Retrieves the current store value from the async context.
|
|
41
|
+
* Returns undefined if called outside of a `run()` callback execution.
|
|
42
|
+
*
|
|
43
|
+
* @returns Current store value or undefined if no context exists
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```
|
|
47
|
+
* const als = new AsyncLocalStorage<string>();
|
|
48
|
+
* console.log(als.getStore()); // Outputs: undefined
|
|
49
|
+
*
|
|
50
|
+
* als.run('hello', () => {
|
|
51
|
+
* console.log(als.getStore()); // Outputs: 'hello'
|
|
52
|
+
* });
|
|
53
|
+
* ```
|
|
29
54
|
*/
|
|
30
55
|
getStore(): T | undefined {
|
|
31
56
|
return this.store;
|
|
@@ -4,27 +4,81 @@ import { TableDef } from '../schema/table.js';
|
|
|
4
4
|
import { RelationDef } from '../schema/relation.js';
|
|
5
5
|
import { RelationChange, RelationKey, TrackedEntity } from './runtime-types.js';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Interface for entity context providing entity tracking and management.
|
|
9
|
+
*/
|
|
7
10
|
export interface EntityContext {
|
|
11
|
+
/** The database dialect */
|
|
8
12
|
dialect: Dialect;
|
|
13
|
+
/** The database executor */
|
|
9
14
|
executor: DbExecutor;
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Gets an entity by table and primary key.
|
|
18
|
+
* @param table - The table definition
|
|
19
|
+
* @param pk - The primary key value
|
|
20
|
+
* @returns The entity or undefined
|
|
21
|
+
*/
|
|
22
|
+
getEntity(table: TableDef, pk: unknown): unknown;
|
|
13
23
|
|
|
14
|
-
|
|
15
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Sets an entity in the context.
|
|
26
|
+
* @param table - The table definition
|
|
27
|
+
* @param pk - The primary key value
|
|
28
|
+
* @param entity - The entity to set
|
|
29
|
+
*/
|
|
30
|
+
setEntity(table: TableDef, pk: unknown, entity: unknown): void;
|
|
16
31
|
|
|
17
|
-
|
|
18
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Tracks a new entity.
|
|
34
|
+
* @param table - The table definition
|
|
35
|
+
* @param entity - The new entity
|
|
36
|
+
* @param pk - Optional primary key
|
|
37
|
+
*/
|
|
38
|
+
trackNew(table: TableDef, entity: unknown, pk?: unknown): void;
|
|
19
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Tracks a managed entity.
|
|
42
|
+
* @param table - The table definition
|
|
43
|
+
* @param pk - The primary key
|
|
44
|
+
* @param entity - The managed entity
|
|
45
|
+
*/
|
|
46
|
+
trackManaged(table: TableDef, pk: unknown, entity: unknown): void;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Marks an entity as dirty.
|
|
50
|
+
* @param entity - The entity to mark
|
|
51
|
+
*/
|
|
52
|
+
markDirty(entity: unknown): void;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Marks an entity as removed.
|
|
56
|
+
* @param entity - The entity to mark
|
|
57
|
+
*/
|
|
58
|
+
markRemoved(entity: unknown): void;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Gets all tracked entities for a table.
|
|
62
|
+
* @param table - The table definition
|
|
63
|
+
* @returns Array of tracked entities
|
|
64
|
+
*/
|
|
20
65
|
getEntitiesForTable(table: TableDef): TrackedEntity[];
|
|
21
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Registers a relation change.
|
|
69
|
+
* @param root - The root entity
|
|
70
|
+
* @param relationKey - The relation key
|
|
71
|
+
* @param rootTable - The root table definition
|
|
72
|
+
* @param relationName - The relation name
|
|
73
|
+
* @param relation - The relation definition
|
|
74
|
+
* @param change - The relation change
|
|
75
|
+
*/
|
|
22
76
|
registerRelationChange(
|
|
23
|
-
root:
|
|
77
|
+
root: unknown,
|
|
24
78
|
relationKey: RelationKey,
|
|
25
79
|
rootTable: TableDef,
|
|
26
80
|
relationName: string,
|
|
27
81
|
relation: RelationDef,
|
|
28
|
-
change: RelationChange<
|
|
82
|
+
change: RelationChange<unknown>
|
|
29
83
|
): void;
|
|
30
84
|
}
|
package/src/orm/entity-meta.ts
CHANGED
|
@@ -21,9 +21,9 @@ export interface EntityMeta<TTable extends TableDef> {
|
|
|
21
21
|
/** Relations that should be loaded lazily */
|
|
22
22
|
lazyRelations: (keyof RelationMap<TTable>)[];
|
|
23
23
|
/** Cache for relation promises */
|
|
24
|
-
relationCache: Map<string, Promise<
|
|
24
|
+
relationCache: Map<string, Promise<unknown>>;
|
|
25
25
|
/** Hydration data for relations */
|
|
26
|
-
relationHydration: Map<string, Map<string,
|
|
26
|
+
relationHydration: Map<string, Map<string, unknown>>;
|
|
27
27
|
/** Relation wrapper instances */
|
|
28
28
|
relationWrappers: Map<string, unknown>;
|
|
29
29
|
}
|
|
@@ -40,7 +40,7 @@ export const getHydrationRows = <TTable extends TableDef>(
|
|
|
40
40
|
meta: EntityMeta<TTable>,
|
|
41
41
|
relationName: string,
|
|
42
42
|
key: unknown
|
|
43
|
-
): Record<string,
|
|
43
|
+
): Record<string, unknown>[] | undefined => {
|
|
44
44
|
const map = meta.relationHydration.get(relationName);
|
|
45
45
|
if (!map) return undefined;
|
|
46
46
|
const rows = map.get(toKey(key));
|
|
@@ -60,7 +60,7 @@ export const getHydrationRecord = <TTable extends TableDef>(
|
|
|
60
60
|
meta: EntityMeta<TTable>,
|
|
61
61
|
relationName: string,
|
|
62
62
|
key: unknown
|
|
63
|
-
): Record<string,
|
|
63
|
+
): Record<string, unknown> | undefined => {
|
|
64
64
|
const map = meta.relationHydration.get(relationName);
|
|
65
65
|
if (!map) return undefined;
|
|
66
66
|
const value = map.get(toKey(key));
|
|
@@ -68,7 +68,7 @@ export const getHydrationRecord = <TTable extends TableDef>(
|
|
|
68
68
|
if (Array.isArray(value)) {
|
|
69
69
|
return value[0];
|
|
70
70
|
}
|
|
71
|
-
return value
|
|
71
|
+
return value as Record<string, unknown>;
|
|
72
72
|
};
|
|
73
73
|
|
|
74
74
|
/**
|
|
@@ -77,9 +77,9 @@ export const getHydrationRecord = <TTable extends TableDef>(
|
|
|
77
77
|
* @returns Entity metadata or undefined if not found
|
|
78
78
|
* @typeParam TTable - Table definition type
|
|
79
79
|
*/
|
|
80
|
-
export const getEntityMeta = <TTable extends TableDef>(entity:
|
|
80
|
+
export const getEntityMeta = <TTable extends TableDef>(entity: unknown): EntityMeta<TTable> | undefined => {
|
|
81
81
|
if (!entity || typeof entity !== 'object') return undefined;
|
|
82
|
-
return (entity as
|
|
82
|
+
return (entity as { [ENTITY_META]: EntityMeta<TTable> })[ENTITY_META];
|
|
83
83
|
};
|
|
84
84
|
|
|
85
85
|
/**
|
|
@@ -87,6 +87,6 @@ export const getEntityMeta = <TTable extends TableDef>(entity: any): EntityMeta<
|
|
|
87
87
|
* @param entity - Entity instance to check
|
|
88
88
|
* @returns True if the entity has metadata, false otherwise
|
|
89
89
|
*/
|
|
90
|
-
export const hasEntityMeta = (entity:
|
|
90
|
+
export const hasEntityMeta = (entity: unknown): entity is { [ENTITY_META]: EntityMeta<TableDef> } => {
|
|
91
91
|
return Boolean(getEntityMeta(entity));
|
|
92
92
|
};
|
|
@@ -1,13 +1,34 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ColumnDef } from '../schema/column.js';
|
|
2
2
|
import { defineTable, TableDef, TableHooks } from '../schema/table.js';
|
|
3
3
|
import { CascadeMode, RelationKinds } from '../schema/relation.js';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Constructor type for entities.
|
|
7
|
+
* Supports any constructor signature for maximum flexibility with decorator-based entities.
|
|
8
|
+
* @template T - The entity type
|
|
9
|
+
*/
|
|
10
|
+
export type EntityConstructor<T = object> = new (...args: never[]) => T;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Target that can be an entity constructor or table definition.
|
|
14
|
+
*/
|
|
15
|
+
export type EntityOrTableTarget = EntityConstructor | TableDef;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Resolver for entity or table target, can be direct or function.
|
|
19
|
+
*/
|
|
7
20
|
export type EntityOrTableTargetResolver = EntityOrTableTarget | (() => EntityOrTableTarget);
|
|
8
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Simplified column definition structure used during metadata registration.
|
|
24
|
+
* @template T - Concrete column definition type being extended
|
|
25
|
+
*/
|
|
9
26
|
export type ColumnDefLike<T extends ColumnDef = ColumnDef> = Omit<T, 'name' | 'table'>;
|
|
10
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Transforms simplified column metadata into full ColumnDef objects during table building.
|
|
30
|
+
* @template TColumns - Mapping of column names to simplified definitions
|
|
31
|
+
*/
|
|
11
32
|
type MaterializeColumns<TColumns extends Record<string, ColumnDefLike>> = {
|
|
12
33
|
[K in keyof TColumns]: ColumnDef<TColumns[K]['type'], TColumns[K]['tsType']> & Omit<
|
|
13
34
|
TColumns[K],
|
|
@@ -15,63 +36,120 @@ type MaterializeColumns<TColumns extends Record<string, ColumnDefLike>> = {
|
|
|
15
36
|
> & { name: string; table: string };
|
|
16
37
|
};
|
|
17
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Common properties shared by all relation metadata types.
|
|
41
|
+
*/
|
|
18
42
|
interface BaseRelationMetadata {
|
|
43
|
+
/** The property key for the relation */
|
|
19
44
|
propertyKey: string;
|
|
45
|
+
/** The target entity or table */
|
|
20
46
|
target: EntityOrTableTargetResolver;
|
|
47
|
+
/** Optional cascade mode */
|
|
21
48
|
cascade?: CascadeMode;
|
|
22
49
|
}
|
|
23
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Metadata for has many relations.
|
|
53
|
+
*/
|
|
24
54
|
export interface HasManyRelationMetadata extends BaseRelationMetadata {
|
|
55
|
+
/** The relation kind */
|
|
25
56
|
kind: typeof RelationKinds.HasMany;
|
|
57
|
+
/** The foreign key */
|
|
26
58
|
foreignKey: string;
|
|
59
|
+
/** Optional local key */
|
|
27
60
|
localKey?: string;
|
|
28
61
|
}
|
|
29
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Metadata for has one relations.
|
|
65
|
+
*/
|
|
30
66
|
export interface HasOneRelationMetadata extends BaseRelationMetadata {
|
|
67
|
+
/** The relation kind */
|
|
31
68
|
kind: typeof RelationKinds.HasOne;
|
|
69
|
+
/** The foreign key */
|
|
32
70
|
foreignKey: string;
|
|
71
|
+
/** Optional local key */
|
|
33
72
|
localKey?: string;
|
|
34
73
|
}
|
|
35
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Metadata for belongs to relations.
|
|
77
|
+
*/
|
|
36
78
|
export interface BelongsToRelationMetadata extends BaseRelationMetadata {
|
|
79
|
+
/** The relation kind */
|
|
37
80
|
kind: typeof RelationKinds.BelongsTo;
|
|
81
|
+
/** The foreign key */
|
|
38
82
|
foreignKey: string;
|
|
83
|
+
/** Optional local key */
|
|
39
84
|
localKey?: string;
|
|
40
85
|
}
|
|
41
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Metadata for belongs to many relations.
|
|
89
|
+
*/
|
|
42
90
|
export interface BelongsToManyRelationMetadata extends BaseRelationMetadata {
|
|
91
|
+
/** The relation kind */
|
|
43
92
|
kind: typeof RelationKinds.BelongsToMany;
|
|
93
|
+
/** The pivot table */
|
|
44
94
|
pivotTable: EntityOrTableTargetResolver;
|
|
95
|
+
/** The pivot foreign key to root */
|
|
45
96
|
pivotForeignKeyToRoot: string;
|
|
97
|
+
/** The pivot foreign key to target */
|
|
46
98
|
pivotForeignKeyToTarget: string;
|
|
99
|
+
/** Optional local key */
|
|
47
100
|
localKey?: string;
|
|
101
|
+
/** Optional target key */
|
|
48
102
|
targetKey?: string;
|
|
103
|
+
/** Optional pivot primary key */
|
|
49
104
|
pivotPrimaryKey?: string;
|
|
105
|
+
/** Optional default pivot columns */
|
|
50
106
|
defaultPivotColumns?: string[];
|
|
51
107
|
}
|
|
52
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Union type for all relation metadata.
|
|
111
|
+
*/
|
|
53
112
|
export type RelationMetadata =
|
|
54
113
|
| HasManyRelationMetadata
|
|
55
114
|
| HasOneRelationMetadata
|
|
56
115
|
| BelongsToRelationMetadata
|
|
57
116
|
| BelongsToManyRelationMetadata;
|
|
58
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Metadata for entities.
|
|
120
|
+
* @template TColumns - The columns type
|
|
121
|
+
*/
|
|
59
122
|
export interface EntityMetadata<TColumns extends Record<string, ColumnDefLike> = Record<string, ColumnDefLike>> {
|
|
60
|
-
|
|
123
|
+
/** The entity constructor */
|
|
124
|
+
target: EntityConstructor;
|
|
125
|
+
/** The table name */
|
|
61
126
|
tableName: string;
|
|
127
|
+
/** The columns */
|
|
62
128
|
columns: TColumns;
|
|
129
|
+
/** The relations */
|
|
63
130
|
relations: Record<string, RelationMetadata>;
|
|
131
|
+
/** Optional hooks */
|
|
64
132
|
hooks?: TableHooks;
|
|
133
|
+
/** Optional table definition */
|
|
65
134
|
table?: TableDef<MaterializeColumns<TColumns>>;
|
|
66
135
|
}
|
|
67
136
|
|
|
68
|
-
const metadataMap = new Map<EntityConstructor
|
|
137
|
+
const metadataMap = new Map<EntityConstructor, EntityMetadata>();
|
|
69
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Registers entity metadata.
|
|
141
|
+
* @param meta - The entity metadata to register
|
|
142
|
+
*/
|
|
70
143
|
export const registerEntityMetadata = (meta: EntityMetadata): void => {
|
|
71
144
|
metadataMap.set(meta.target, meta);
|
|
72
145
|
};
|
|
73
146
|
|
|
74
|
-
|
|
147
|
+
/**
|
|
148
|
+
* Ensures entity metadata exists for the target, creating it if necessary.
|
|
149
|
+
* @param target - The entity constructor
|
|
150
|
+
* @returns The entity metadata
|
|
151
|
+
*/
|
|
152
|
+
export const ensureEntityMetadata = (target: EntityConstructor): EntityMetadata => {
|
|
75
153
|
let meta = metadataMap.get(target);
|
|
76
154
|
if (!meta) {
|
|
77
155
|
meta = {
|
|
@@ -85,20 +163,38 @@ export const ensureEntityMetadata = (target: EntityConstructor<any>): EntityMeta
|
|
|
85
163
|
return meta;
|
|
86
164
|
};
|
|
87
165
|
|
|
88
|
-
|
|
166
|
+
/**
|
|
167
|
+
* Gets entity metadata for the target.
|
|
168
|
+
* @param target - The entity constructor
|
|
169
|
+
* @returns The entity metadata or undefined if not found
|
|
170
|
+
*/
|
|
171
|
+
export const getEntityMetadata = (target: EntityConstructor): EntityMetadata | undefined => {
|
|
89
172
|
return metadataMap.get(target);
|
|
90
173
|
};
|
|
91
174
|
|
|
175
|
+
/**
|
|
176
|
+
* Gets all entity metadata.
|
|
177
|
+
* @returns Array of all entity metadata
|
|
178
|
+
*/
|
|
92
179
|
export const getAllEntityMetadata = (): EntityMetadata[] => {
|
|
93
180
|
return Array.from(metadataMap.values());
|
|
94
181
|
};
|
|
95
182
|
|
|
183
|
+
/**
|
|
184
|
+
* Clears all entity metadata.
|
|
185
|
+
*/
|
|
96
186
|
export const clearEntityMetadata = (): void => {
|
|
97
187
|
metadataMap.clear();
|
|
98
188
|
};
|
|
99
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Adds column metadata to an entity.
|
|
192
|
+
* @param target - The entity constructor
|
|
193
|
+
* @param propertyKey - The property key
|
|
194
|
+
* @param column - The column definition
|
|
195
|
+
*/
|
|
100
196
|
export const addColumnMetadata = (
|
|
101
|
-
target: EntityConstructor
|
|
197
|
+
target: EntityConstructor,
|
|
102
198
|
propertyKey: string,
|
|
103
199
|
column: ColumnDefLike
|
|
104
200
|
): void => {
|
|
@@ -106,8 +202,14 @@ export const addColumnMetadata = (
|
|
|
106
202
|
(meta.columns as Record<string, ColumnDefLike>)[propertyKey] = { ...column };
|
|
107
203
|
};
|
|
108
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Adds relation metadata to an entity.
|
|
207
|
+
* @param target - The entity constructor
|
|
208
|
+
* @param propertyKey - The property key
|
|
209
|
+
* @param relation - The relation metadata
|
|
210
|
+
*/
|
|
109
211
|
export const addRelationMetadata = (
|
|
110
|
-
target: EntityConstructor
|
|
212
|
+
target: EntityConstructor,
|
|
111
213
|
propertyKey: string,
|
|
112
214
|
relation: RelationMetadata
|
|
113
215
|
): void => {
|
|
@@ -115,8 +217,14 @@ export const addRelationMetadata = (
|
|
|
115
217
|
meta.relations[propertyKey] = relation;
|
|
116
218
|
};
|
|
117
219
|
|
|
220
|
+
/**
|
|
221
|
+
* Sets the table name and hooks for an entity.
|
|
222
|
+
* @param target - The entity constructor
|
|
223
|
+
* @param tableName - The table name
|
|
224
|
+
* @param hooks - Optional table hooks
|
|
225
|
+
*/
|
|
118
226
|
export const setEntityTableName = (
|
|
119
|
-
target: EntityConstructor
|
|
227
|
+
target: EntityConstructor,
|
|
120
228
|
tableName: string,
|
|
121
229
|
hooks?: TableHooks
|
|
122
230
|
): void => {
|
|
@@ -129,21 +237,28 @@ export const setEntityTableName = (
|
|
|
129
237
|
}
|
|
130
238
|
};
|
|
131
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Builds a table definition from entity metadata.
|
|
242
|
+
* @template TColumns - The columns type
|
|
243
|
+
* @param meta - The entity metadata
|
|
244
|
+
* @returns The table definition
|
|
245
|
+
*/
|
|
132
246
|
export const buildTableDef = <TColumns extends Record<string, ColumnDefLike>>(meta: EntityMetadata<TColumns>): TableDef<MaterializeColumns<TColumns>> => {
|
|
133
247
|
if (meta.table) {
|
|
134
248
|
return meta.table;
|
|
135
249
|
}
|
|
136
250
|
|
|
137
|
-
|
|
138
|
-
|
|
251
|
+
// Build columns using a simpler approach that avoids type assertion
|
|
252
|
+
const columns: Record<string, ColumnDef> = {};
|
|
253
|
+
for (const [key, def] of Object.entries(meta.columns)) {
|
|
254
|
+
columns[key] = {
|
|
139
255
|
...def,
|
|
140
256
|
name: key,
|
|
141
257
|
table: meta.tableName
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
}, {} as MaterializeColumns<TColumns>);
|
|
258
|
+
} as ColumnDef;
|
|
259
|
+
}
|
|
145
260
|
|
|
146
|
-
const table = defineTable(meta.tableName, columns
|
|
261
|
+
const table = defineTable(meta.tableName, columns as MaterializeColumns<TColumns>, {}, meta.hooks);
|
|
147
262
|
meta.table = table;
|
|
148
263
|
return table;
|
|
149
264
|
};
|