metal-orm 1.1.9 → 1.1.11
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 +769 -764
- package/dist/index.cjs +2255 -284
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +559 -39
- package/dist/index.d.ts +559 -39
- package/dist/index.js +2227 -284
- package/dist/index.js.map +1 -1
- package/package.json +17 -12
- package/scripts/generate-entities/render.mjs +21 -12
- package/scripts/generate-entities/schema.mjs +87 -73
- package/scripts/generate-entities/tree-detection.mjs +67 -61
- package/src/bulk/bulk-context.ts +83 -0
- package/src/bulk/bulk-delete-executor.ts +87 -0
- package/src/bulk/bulk-executor.base.ts +73 -0
- package/src/bulk/bulk-insert-executor.ts +74 -0
- package/src/bulk/bulk-types.ts +70 -0
- package/src/bulk/bulk-update-executor.ts +192 -0
- package/src/bulk/bulk-upsert-executor.ts +93 -0
- package/src/bulk/bulk-utils.ts +91 -0
- package/src/bulk/index.ts +18 -0
- package/src/codegen/typescript.ts +30 -21
- package/src/core/ast/expression-builders.ts +107 -10
- package/src/core/ast/expression-nodes.ts +52 -22
- package/src/core/ast/expression-visitor.ts +23 -13
- package/src/core/ddl/introspect/mysql.ts +113 -36
- package/src/core/dialect/abstract.ts +30 -17
- package/src/core/dialect/mysql/index.ts +20 -5
- package/src/core/execution/db-executor.ts +96 -64
- package/src/core/execution/executors/better-sqlite3-executor.ts +94 -0
- package/src/core/execution/executors/mssql-executor.ts +66 -34
- package/src/core/execution/executors/mysql-executor.ts +98 -66
- package/src/core/execution/executors/postgres-executor.ts +33 -11
- package/src/core/execution/executors/sqlite-executor.ts +86 -30
- package/src/decorators/bootstrap.ts +482 -398
- package/src/decorators/column-decorator.ts +87 -96
- package/src/decorators/decorator-metadata.ts +100 -24
- package/src/decorators/entity.ts +27 -24
- package/src/decorators/relations.ts +231 -149
- package/src/decorators/transformers/transformer-decorators.ts +26 -29
- package/src/decorators/validators/country-validators-decorators.ts +9 -15
- package/src/dto/apply-filter.ts +568 -551
- package/src/index.ts +16 -9
- package/src/orm/entity-hydration.ts +116 -72
- package/src/orm/entity-metadata.ts +347 -301
- package/src/orm/entity-relations.ts +264 -207
- package/src/orm/entity.ts +199 -199
- package/src/orm/execute.ts +13 -13
- package/src/orm/lazy-batch/morph-many.ts +70 -0
- package/src/orm/lazy-batch/morph-one.ts +69 -0
- package/src/orm/lazy-batch/morph-to.ts +59 -0
- package/src/orm/lazy-batch.ts +4 -1
- package/src/orm/orm-session.ts +170 -104
- package/src/orm/pooled-executor-factory.ts +99 -58
- package/src/orm/query-logger.ts +49 -40
- package/src/orm/relation-change-processor.ts +198 -96
- package/src/orm/relations/belongs-to.ts +143 -143
- package/src/orm/relations/has-many.ts +204 -204
- package/src/orm/relations/has-one.ts +174 -174
- package/src/orm/relations/many-to-many.ts +288 -288
- package/src/orm/relations/morph-many.ts +156 -0
- package/src/orm/relations/morph-one.ts +151 -0
- package/src/orm/relations/morph-to.ts +162 -0
- package/src/orm/save-graph.ts +116 -1
- package/src/query-builder/expression-table-mapper.ts +5 -0
- package/src/query-builder/hydration-manager.ts +345 -345
- package/src/query-builder/hydration-planner.ts +178 -148
- package/src/query-builder/relation-conditions.ts +171 -151
- package/src/query-builder/relation-cte-builder.ts +5 -1
- package/src/query-builder/relation-filter-utils.ts +9 -6
- package/src/query-builder/relation-include-strategies.ts +44 -2
- package/src/query-builder/relation-join-strategies.ts +8 -1
- package/src/query-builder/relation-service.ts +250 -241
- package/src/query-builder/select/select-operations.ts +110 -105
- package/src/query-builder/update-include.ts +4 -0
- package/src/schema/relation.ts +296 -188
- package/src/schema/types.ts +138 -123
- package/src/tree/tree-decorator.ts +127 -137
|
@@ -1,96 +1,87 @@
|
|
|
1
|
-
import { ColumnDef, ColumnType } from '../schema/column-types.js';
|
|
2
|
-
import { ColumnDefLike } from '../orm/entity-metadata.js';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Options for defining a column in an entity.
|
|
7
|
-
*/
|
|
8
|
-
export interface ColumnOptions {
|
|
9
|
-
type: ColumnType;
|
|
10
|
-
args?: ColumnDef['args'];
|
|
11
|
-
dialectTypes?: ColumnDef['dialectTypes'];
|
|
12
|
-
notNull?: boolean;
|
|
13
|
-
primary?: boolean;
|
|
14
|
-
tsType?: ColumnDef['tsType'];
|
|
15
|
-
name?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Input type for column definitions, either as options object or direct ColumnDef.
|
|
20
|
-
*/
|
|
21
|
-
export type ColumnInput = ColumnOptions | ColumnDef;
|
|
22
|
-
|
|
23
|
-
const normalizeColumnInput = (input: ColumnInput): ColumnDefLike => {
|
|
24
|
-
const asOptions = input as ColumnOptions;
|
|
25
|
-
const asDefinition = input as ColumnDef;
|
|
26
|
-
const column: ColumnDefLike = {
|
|
27
|
-
type: asOptions.type ?? asDefinition.type,
|
|
28
|
-
args: asOptions.args ?? asDefinition.args,
|
|
29
|
-
dialectTypes: asOptions.dialectTypes ?? asDefinition.dialectTypes,
|
|
30
|
-
notNull: asOptions.notNull ?? asDefinition.notNull,
|
|
31
|
-
primary: asOptions.primary ?? asDefinition.primary,
|
|
32
|
-
tsType: asDefinition.tsType ?? asOptions.tsType,
|
|
33
|
-
unique: asDefinition.unique,
|
|
34
|
-
default: asDefinition.default,
|
|
35
|
-
autoIncrement: asDefinition.autoIncrement,
|
|
36
|
-
generated: asDefinition.generated,
|
|
37
|
-
check: asDefinition.check,
|
|
38
|
-
references: asDefinition.references,
|
|
39
|
-
comment: asDefinition.comment,
|
|
40
|
-
name: asOptions.name ?? asDefinition.name
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
if (!column.type) {
|
|
44
|
-
throw new Error('Column decorator requires a column type');
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return column;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
* Sets the primary flag to true and delegates to Column decorator.
|
|
89
|
-
* @param definition - The column definition or options.
|
|
90
|
-
* @returns A property decorator that registers the primary key column metadata.
|
|
91
|
-
*/
|
|
92
|
-
export function PrimaryKey(definition: ColumnInput) {
|
|
93
|
-
const normalized = normalizeColumnInput(definition);
|
|
94
|
-
normalized.primary = true;
|
|
95
|
-
return Column(normalized);
|
|
96
|
-
}
|
|
1
|
+
import { ColumnDef, ColumnType } from '../schema/column-types.js';
|
|
2
|
+
import { ColumnDefLike } from '../orm/entity-metadata.js';
|
|
3
|
+
import { resolveFieldDecoratorInfo } from './decorator-metadata.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Options for defining a column in an entity.
|
|
7
|
+
*/
|
|
8
|
+
export interface ColumnOptions {
|
|
9
|
+
type: ColumnType;
|
|
10
|
+
args?: ColumnDef['args'];
|
|
11
|
+
dialectTypes?: ColumnDef['dialectTypes'];
|
|
12
|
+
notNull?: boolean;
|
|
13
|
+
primary?: boolean;
|
|
14
|
+
tsType?: ColumnDef['tsType'];
|
|
15
|
+
name?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Input type for column definitions, either as options object or direct ColumnDef.
|
|
20
|
+
*/
|
|
21
|
+
export type ColumnInput = ColumnOptions | ColumnDef;
|
|
22
|
+
|
|
23
|
+
const normalizeColumnInput = (input: ColumnInput): ColumnDefLike => {
|
|
24
|
+
const asOptions = input as ColumnOptions;
|
|
25
|
+
const asDefinition = input as ColumnDef;
|
|
26
|
+
const column: ColumnDefLike = {
|
|
27
|
+
type: asOptions.type ?? asDefinition.type,
|
|
28
|
+
args: asOptions.args ?? asDefinition.args,
|
|
29
|
+
dialectTypes: asOptions.dialectTypes ?? asDefinition.dialectTypes,
|
|
30
|
+
notNull: asOptions.notNull ?? asDefinition.notNull,
|
|
31
|
+
primary: asOptions.primary ?? asDefinition.primary,
|
|
32
|
+
tsType: asDefinition.tsType ?? asOptions.tsType,
|
|
33
|
+
unique: asDefinition.unique,
|
|
34
|
+
default: asDefinition.default,
|
|
35
|
+
autoIncrement: asDefinition.autoIncrement,
|
|
36
|
+
generated: asDefinition.generated,
|
|
37
|
+
check: asDefinition.check,
|
|
38
|
+
references: asDefinition.references,
|
|
39
|
+
comment: asDefinition.comment,
|
|
40
|
+
name: asOptions.name ?? asDefinition.name
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
if (!column.type) {
|
|
44
|
+
throw new Error('Column decorator requires a column type');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return column;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const registerColumnFromContext = (
|
|
51
|
+
targetOrValue: unknown,
|
|
52
|
+
contextOrProperty: unknown,
|
|
53
|
+
column: ColumnDefLike
|
|
54
|
+
): void => {
|
|
55
|
+
const { propertyName, bag } = resolveFieldDecoratorInfo(
|
|
56
|
+
targetOrValue,
|
|
57
|
+
contextOrProperty,
|
|
58
|
+
'Column'
|
|
59
|
+
);
|
|
60
|
+
if (!bag.columns.some(entry => entry.propertyName === propertyName)) {
|
|
61
|
+
bag.columns.push({ propertyName, column: { ...column } });
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Decorator to define a column on an entity property.
|
|
67
|
+
* @param definition - The column definition or options.
|
|
68
|
+
* @returns A property decorator that registers the column metadata.
|
|
69
|
+
*/
|
|
70
|
+
export function Column(definition: ColumnInput) {
|
|
71
|
+
const normalized = normalizeColumnInput(definition);
|
|
72
|
+
return function (targetOrValue: unknown, contextOrProperty: unknown) {
|
|
73
|
+
registerColumnFromContext(targetOrValue, contextOrProperty, normalized);
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Decorator to define a primary key column on an entity property.
|
|
79
|
+
* Sets the primary flag to true and delegates to Column decorator.
|
|
80
|
+
* @param definition - The column definition or options.
|
|
81
|
+
* @returns A property decorator that registers the primary key column metadata.
|
|
82
|
+
*/
|
|
83
|
+
export function PrimaryKey(definition: ColumnInput) {
|
|
84
|
+
const normalized = normalizeColumnInput(definition);
|
|
85
|
+
normalized.primary = true;
|
|
86
|
+
return Column(normalized);
|
|
87
|
+
}
|
|
@@ -1,27 +1,32 @@
|
|
|
1
1
|
import { ColumnDefLike, RelationMetadata } from '../orm/entity-metadata.js';
|
|
2
2
|
import type { TransformerMetadata } from './transformers/transformer-metadata.js';
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* Bag for storing decorator metadata during the decoration phase.
|
|
6
|
-
*/
|
|
7
|
-
export interface DecoratorTreeMetadata {
|
|
8
|
-
parentProperty?: string;
|
|
9
|
-
childrenProperty?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface DecoratorMetadataBag {
|
|
13
|
-
columns: Array<{ propertyName: string; column: ColumnDefLike }>;
|
|
14
|
-
relations: Array<{ propertyName: string; relation: RelationMetadata }>;
|
|
15
|
-
transformers: Array<{ propertyName: string; metadata: TransformerMetadata }>;
|
|
16
|
-
tree?: DecoratorTreeMetadata;
|
|
17
|
-
}
|
|
4
|
+
/**
|
|
5
|
+
* Bag for storing decorator metadata during the decoration phase.
|
|
6
|
+
*/
|
|
7
|
+
export interface DecoratorTreeMetadata {
|
|
8
|
+
parentProperty?: string;
|
|
9
|
+
childrenProperty?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface DecoratorMetadataBag {
|
|
13
|
+
columns: Array<{ propertyName: string; column: ColumnDefLike }>;
|
|
14
|
+
relations: Array<{ propertyName: string; relation: RelationMetadata }>;
|
|
15
|
+
transformers: Array<{ propertyName: string; metadata: TransformerMetadata }>;
|
|
16
|
+
tree?: DecoratorTreeMetadata;
|
|
17
|
+
}
|
|
18
18
|
|
|
19
19
|
const METADATA_KEY = 'metal-orm:decorators';
|
|
20
|
+
const LEGACY_METADATA_KEY = Symbol.for('metal-orm:decorators:legacy');
|
|
20
21
|
|
|
21
22
|
type MetadataCarrier = {
|
|
22
23
|
metadata?: Record<PropertyKey, unknown>;
|
|
23
24
|
};
|
|
24
25
|
|
|
26
|
+
type LegacyMetadataCarrier = {
|
|
27
|
+
constructor?: object;
|
|
28
|
+
};
|
|
29
|
+
|
|
25
30
|
/**
|
|
26
31
|
* Gets or creates a metadata bag for the given decorator context.
|
|
27
32
|
* @param context - The decorator context with metadata support.
|
|
@@ -29,13 +34,23 @@ type MetadataCarrier = {
|
|
|
29
34
|
*/
|
|
30
35
|
export const getOrCreateMetadataBag = (context: MetadataCarrier): DecoratorMetadataBag => {
|
|
31
36
|
const metadata = context.metadata || (context.metadata = {} as Record<PropertyKey, unknown>);
|
|
32
|
-
let bag = metadata[METADATA_KEY] as DecoratorMetadataBag | undefined;
|
|
33
|
-
if (!bag) {
|
|
34
|
-
bag = { columns: [], relations: [], transformers: [] };
|
|
35
|
-
metadata[METADATA_KEY] = bag;
|
|
36
|
-
}
|
|
37
|
-
return bag;
|
|
38
|
-
};
|
|
37
|
+
let bag = metadata[METADATA_KEY] as DecoratorMetadataBag | undefined;
|
|
38
|
+
if (!bag) {
|
|
39
|
+
bag = { columns: [], relations: [], transformers: [] };
|
|
40
|
+
metadata[METADATA_KEY] = bag;
|
|
41
|
+
}
|
|
42
|
+
return bag;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const getOrCreateMetadataBagOnConstructor = (ctor: object): DecoratorMetadataBag => {
|
|
46
|
+
const carrier = ctor as Record<PropertyKey, unknown>;
|
|
47
|
+
let bag = carrier[LEGACY_METADATA_KEY] as DecoratorMetadataBag | undefined;
|
|
48
|
+
if (!bag) {
|
|
49
|
+
bag = { columns: [], relations: [], transformers: [] };
|
|
50
|
+
carrier[LEGACY_METADATA_KEY] = bag;
|
|
51
|
+
}
|
|
52
|
+
return bag;
|
|
53
|
+
};
|
|
39
54
|
|
|
40
55
|
/**
|
|
41
56
|
* Reads the metadata bag from the given decorator context.
|
|
@@ -53,9 +68,14 @@ export const readMetadataBag = (context: MetadataCarrier): DecoratorMetadataBag
|
|
|
53
68
|
*/
|
|
54
69
|
export const readMetadataBagFromConstructor = (ctor: object): DecoratorMetadataBag | undefined => {
|
|
55
70
|
const metadataSymbol = (Symbol as { metadata?: symbol }).metadata;
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
71
|
+
if (metadataSymbol) {
|
|
72
|
+
const metadata = Reflect.get(ctor, metadataSymbol) as Record<PropertyKey, unknown> | undefined;
|
|
73
|
+
const stage3Bag = metadata?.[METADATA_KEY] as DecoratorMetadataBag | undefined;
|
|
74
|
+
if (stage3Bag) {
|
|
75
|
+
return stage3Bag;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return (ctor as Record<PropertyKey, unknown>)[LEGACY_METADATA_KEY] as DecoratorMetadataBag | undefined;
|
|
59
79
|
};
|
|
60
80
|
|
|
61
81
|
/**
|
|
@@ -65,3 +85,59 @@ export const readMetadataBagFromConstructor = (ctor: object): DecoratorMetadataB
|
|
|
65
85
|
*/
|
|
66
86
|
export const getDecoratorMetadata = (ctor: object): DecoratorMetadataBag | undefined =>
|
|
67
87
|
readMetadataBagFromConstructor(ctor);
|
|
88
|
+
|
|
89
|
+
const normalizePropertyName = (name: string | symbol): string => {
|
|
90
|
+
if (typeof name === 'symbol') {
|
|
91
|
+
return name.description ?? name.toString();
|
|
92
|
+
}
|
|
93
|
+
return name;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const isStage3FieldContext = (value: unknown): value is ClassFieldDecoratorContext => {
|
|
97
|
+
return (
|
|
98
|
+
typeof value === 'object' &&
|
|
99
|
+
value !== null &&
|
|
100
|
+
'name' in value &&
|
|
101
|
+
'private' in value &&
|
|
102
|
+
'metadata' in value
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export interface ResolvedFieldDecoratorInfo {
|
|
107
|
+
bag: DecoratorMetadataBag;
|
|
108
|
+
propertyName: string;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export const resolveFieldDecoratorInfo = (
|
|
112
|
+
targetOrValue: unknown,
|
|
113
|
+
contextOrProperty: unknown,
|
|
114
|
+
decoratorName: string
|
|
115
|
+
): ResolvedFieldDecoratorInfo => {
|
|
116
|
+
if (isStage3FieldContext(contextOrProperty)) {
|
|
117
|
+
if (!contextOrProperty.name) {
|
|
118
|
+
throw new Error(`${decoratorName} decorator requires a property name`);
|
|
119
|
+
}
|
|
120
|
+
if (contextOrProperty.private) {
|
|
121
|
+
throw new Error(`${decoratorName} decorator does not support private fields`);
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
propertyName: normalizePropertyName(contextOrProperty.name),
|
|
125
|
+
bag: getOrCreateMetadataBag(contextOrProperty)
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (typeof contextOrProperty === 'string' || typeof contextOrProperty === 'symbol') {
|
|
130
|
+
const legacyTarget = targetOrValue as LegacyMetadataCarrier | undefined;
|
|
131
|
+
const ctor =
|
|
132
|
+
typeof legacyTarget === 'function' ? legacyTarget : legacyTarget?.constructor;
|
|
133
|
+
if (!ctor || (typeof ctor !== 'function' && typeof ctor !== 'object')) {
|
|
134
|
+
throw new Error(`${decoratorName} decorator requires a class field target`);
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
propertyName: normalizePropertyName(contextOrProperty),
|
|
138
|
+
bag: getOrCreateMetadataBagOnConstructor(ctor)
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
throw new Error(`${decoratorName} decorator received an unsupported decorator context`);
|
|
143
|
+
};
|
package/src/decorators/entity.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { TableHooks } from '../schema/table.js';
|
|
2
2
|
import { RelationKinds } from '../schema/relation.js';
|
|
3
|
-
import {
|
|
4
|
-
addColumnMetadata,
|
|
5
|
-
addRelationMetadata,
|
|
6
|
-
EntityConstructor,
|
|
3
|
+
import {
|
|
4
|
+
addColumnMetadata,
|
|
5
|
+
addRelationMetadata,
|
|
6
|
+
EntityConstructor,
|
|
7
7
|
ensureEntityMetadata,
|
|
8
|
-
setEntityTableName
|
|
9
|
-
} from '../orm/entity-metadata.js';
|
|
10
|
-
import { readMetadataBag } from './decorator-metadata.js';
|
|
11
|
-
import { syncTreeEntityMetadata } from '../tree/tree-decorator.js';
|
|
8
|
+
setEntityTableName
|
|
9
|
+
} from '../orm/entity-metadata.js';
|
|
10
|
+
import { readMetadataBag, readMetadataBagFromConstructor } from './decorator-metadata.js';
|
|
11
|
+
import { syncTreeEntityMetadata } from '../tree/tree-decorator.js';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Options for defining an entity.
|
|
@@ -46,15 +46,18 @@ const deriveTableNameFromConstructor = (ctor: EntityConstructor<unknown>): strin
|
|
|
46
46
|
* @returns A class decorator that registers the entity metadata.
|
|
47
47
|
*/
|
|
48
48
|
export function Entity(options: EntityOptions = {}) {
|
|
49
|
-
return function <T extends EntityConstructor>(
|
|
49
|
+
return function <T extends EntityConstructor>(
|
|
50
|
+
value: T,
|
|
51
|
+
context?: ClassDecoratorContext
|
|
52
|
+
): T {
|
|
50
53
|
const ctor = value;
|
|
51
54
|
const tableName = options.tableName ?? deriveTableNameFromConstructor(ctor);
|
|
52
55
|
setEntityTableName(ctor, tableName, options.hooks, options.type);
|
|
53
56
|
|
|
54
|
-
const bag = readMetadataBag(context);
|
|
55
|
-
if (bag) {
|
|
56
|
-
const meta = ensureEntityMetadata(ctor);
|
|
57
|
-
for (const entry of bag.columns) {
|
|
57
|
+
const bag = context ? readMetadataBag(context) : readMetadataBagFromConstructor(ctor);
|
|
58
|
+
if (bag) {
|
|
59
|
+
const meta = ensureEntityMetadata(ctor);
|
|
60
|
+
for (const entry of bag.columns) {
|
|
58
61
|
if (meta.columns[entry.propertyName]) {
|
|
59
62
|
throw new Error(
|
|
60
63
|
`Column '${entry.propertyName}' is already defined on entity '${ctor.name}'.`
|
|
@@ -77,14 +80,14 @@ export function Entity(options: EntityOptions = {}) {
|
|
|
77
80
|
: undefined
|
|
78
81
|
}
|
|
79
82
|
: { ...entry.relation };
|
|
80
|
-
addRelationMetadata(ctor, entry.propertyName, relationCopy);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Supports both decorator orders:
|
|
85
|
-
// @Entity() above @Tree() and @Tree() above @Entity().
|
|
86
|
-
syncTreeEntityMetadata(ctor, bag?.tree);
|
|
87
|
-
|
|
88
|
-
return ctor;
|
|
89
|
-
};
|
|
90
|
-
}
|
|
83
|
+
addRelationMetadata(ctor, entry.propertyName, relationCopy);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Supports both decorator orders:
|
|
88
|
+
// @Entity() above @Tree() and @Tree() above @Entity().
|
|
89
|
+
syncTreeEntityMetadata(ctor, bag?.tree);
|
|
90
|
+
|
|
91
|
+
return ctor;
|
|
92
|
+
};
|
|
93
|
+
}
|