@mikro-orm/core 7.0.0-dev.3 → 7.0.0-dev.30
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/EntityManager.d.ts +50 -7
- package/EntityManager.js +141 -97
- package/MikroORM.js +0 -1
- package/README.md +1 -2
- package/cache/FileCacheAdapter.d.ts +2 -1
- package/cache/FileCacheAdapter.js +6 -4
- package/connections/Connection.d.ts +4 -2
- package/connections/Connection.js +2 -2
- package/decorators/Check.d.ts +2 -2
- package/decorators/Embeddable.d.ts +5 -5
- package/decorators/Embeddable.js +1 -1
- package/decorators/Embedded.d.ts +6 -12
- package/decorators/Entity.d.ts +20 -5
- package/decorators/Entity.js +0 -1
- package/decorators/Enum.d.ts +1 -1
- package/decorators/Formula.d.ts +1 -2
- package/decorators/Indexed.d.ts +10 -8
- package/decorators/Indexed.js +1 -1
- package/decorators/ManyToMany.d.ts +4 -2
- package/decorators/ManyToOne.d.ts +6 -2
- package/decorators/OneToMany.d.ts +4 -4
- package/decorators/OneToOne.d.ts +5 -1
- package/decorators/PrimaryKey.d.ts +2 -3
- package/decorators/Property.d.ts +1 -1
- package/decorators/Transactional.d.ts +1 -0
- package/decorators/Transactional.js +3 -3
- package/drivers/IDatabaseDriver.d.ts +8 -1
- package/entity/ArrayCollection.d.ts +4 -2
- package/entity/ArrayCollection.js +18 -6
- package/entity/Collection.d.ts +1 -2
- package/entity/Collection.js +16 -10
- package/entity/EntityAssigner.d.ts +1 -1
- package/entity/EntityAssigner.js +9 -1
- package/entity/EntityFactory.d.ts +6 -0
- package/entity/EntityFactory.js +21 -7
- package/entity/EntityHelper.js +8 -1
- package/entity/EntityLoader.d.ts +3 -2
- package/entity/EntityLoader.js +54 -35
- package/entity/EntityRepository.d.ts +1 -1
- package/entity/EntityValidator.js +1 -1
- package/entity/Reference.d.ts +8 -7
- package/entity/Reference.js +22 -1
- package/entity/WrappedEntity.js +1 -1
- package/entity/defineEntity.d.ts +537 -0
- package/entity/defineEntity.js +693 -0
- package/entity/index.d.ts +2 -0
- package/entity/index.js +2 -0
- package/entity/utils.d.ts +7 -0
- package/entity/utils.js +15 -3
- package/enums.d.ts +16 -3
- package/enums.js +13 -0
- package/errors.d.ts +6 -0
- package/errors.js +14 -0
- package/events/EventSubscriber.d.ts +3 -1
- package/hydration/ObjectHydrator.js +10 -2
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/metadata/EntitySchema.d.ts +6 -4
- package/metadata/EntitySchema.js +33 -19
- package/metadata/MetadataDiscovery.d.ts +0 -1
- package/metadata/MetadataDiscovery.js +51 -29
- package/metadata/MetadataStorage.js +1 -1
- package/metadata/MetadataValidator.js +4 -3
- package/package.json +5 -5
- package/platforms/Platform.d.ts +3 -1
- package/serialization/EntitySerializer.d.ts +2 -0
- package/serialization/EntitySerializer.js +1 -1
- package/serialization/SerializationContext.js +13 -10
- package/types/BigIntType.d.ts +9 -6
- package/types/BigIntType.js +3 -0
- package/types/BooleanType.d.ts +1 -1
- package/types/DecimalType.d.ts +6 -4
- package/types/DecimalType.js +1 -1
- package/types/DoubleType.js +1 -1
- package/typings.d.ts +72 -35
- package/typings.js +24 -4
- package/unit-of-work/ChangeSetComputer.js +3 -1
- package/unit-of-work/ChangeSetPersister.d.ts +4 -2
- package/unit-of-work/ChangeSetPersister.js +21 -11
- package/unit-of-work/UnitOfWork.d.ts +2 -1
- package/unit-of-work/UnitOfWork.js +71 -24
- package/utils/AbstractSchemaGenerator.js +5 -2
- package/utils/Configuration.d.ts +15 -5
- package/utils/Configuration.js +7 -7
- package/utils/ConfigurationLoader.d.ts +0 -2
- package/utils/ConfigurationLoader.js +2 -24
- package/utils/Cursor.d.ts +3 -3
- package/utils/Cursor.js +3 -0
- package/utils/DataloaderUtils.d.ts +7 -2
- package/utils/DataloaderUtils.js +38 -7
- package/utils/EntityComparator.d.ts +6 -2
- package/utils/EntityComparator.js +98 -59
- package/utils/QueryHelper.d.ts +6 -0
- package/utils/QueryHelper.js +48 -5
- package/utils/RawQueryFragment.d.ts +34 -0
- package/utils/RawQueryFragment.js +40 -1
- package/utils/TransactionManager.d.ts +65 -0
- package/utils/TransactionManager.js +220 -0
- package/utils/Utils.d.ts +11 -7
- package/utils/Utils.js +67 -33
- package/utils/index.d.ts +1 -0
- package/utils/index.js +1 -0
- package/utils/upsert-utils.js +9 -1
package/entity/index.d.ts
CHANGED
package/entity/index.js
CHANGED
package/entity/utils.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import type { EntityMetadata, PopulateOptions } from '../typings.js';
|
|
2
|
+
import { LoadStrategy, ReferenceKind } from '../enums.js';
|
|
2
3
|
/**
|
|
3
4
|
* @internal
|
|
4
5
|
*/
|
|
5
6
|
export declare function expandDotPaths<Entity>(meta: EntityMetadata<Entity>, populate?: readonly (string | PopulateOptions<Entity>)[], normalized?: boolean): PopulateOptions<Entity>[];
|
|
7
|
+
/**
|
|
8
|
+
* Returns the loading strategy based on the provided hint.
|
|
9
|
+
* If `BALANCED` strategy is used, it will return JOINED if the property is a to-one relation.
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
export declare function getLoadingStrategy(strategy: LoadStrategy | `${LoadStrategy}`, kind: ReferenceKind): LoadStrategy.SELECT_IN | LoadStrategy.JOINED;
|
package/entity/utils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PopulatePath, ReferenceKind } from '../enums.js';
|
|
2
|
-
import { Utils } from '
|
|
1
|
+
import { LoadStrategy, PopulatePath, ReferenceKind } from '../enums.js';
|
|
2
|
+
import { Utils } from '../utils/Utils.js';
|
|
3
3
|
/**
|
|
4
4
|
* Expands `books.perex` like populate to use `children` array instead of the dot syntax
|
|
5
5
|
*/
|
|
@@ -34,7 +34,6 @@ export function expandDotPaths(meta, populate, normalized = false) {
|
|
|
34
34
|
p.field = f;
|
|
35
35
|
p.children ??= [];
|
|
36
36
|
const prop = meta.properties[p.field];
|
|
37
|
-
p.strategy ??= prop.strategy;
|
|
38
37
|
if (parts[0] === PopulatePath.ALL) {
|
|
39
38
|
prop.targetMeta.props
|
|
40
39
|
.filter(prop => prop.lazy || prop.kind !== ReferenceKind.SCALAR)
|
|
@@ -55,3 +54,16 @@ export function expandDotPaths(meta, populate, normalized = false) {
|
|
|
55
54
|
}
|
|
56
55
|
return ret;
|
|
57
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Returns the loading strategy based on the provided hint.
|
|
59
|
+
* If `BALANCED` strategy is used, it will return JOINED if the property is a to-one relation.
|
|
60
|
+
* @internal
|
|
61
|
+
*/
|
|
62
|
+
export function getLoadingStrategy(strategy, kind) {
|
|
63
|
+
if (strategy === LoadStrategy.BALANCED) {
|
|
64
|
+
return [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(kind)
|
|
65
|
+
? LoadStrategy.JOINED
|
|
66
|
+
: LoadStrategy.SELECT_IN;
|
|
67
|
+
}
|
|
68
|
+
return strategy;
|
|
69
|
+
}
|
package/enums.d.ts
CHANGED
|
@@ -66,7 +66,7 @@ export declare enum QueryOrderNumeric {
|
|
|
66
66
|
ASC = 1,
|
|
67
67
|
DESC = -1
|
|
68
68
|
}
|
|
69
|
-
export type QueryOrderKeysFlat = QueryOrder | QueryOrderNumeric |
|
|
69
|
+
export type QueryOrderKeysFlat = QueryOrder | QueryOrderNumeric | `${QueryOrder}`;
|
|
70
70
|
export type QueryOrderKeys<T> = QueryOrderKeysFlat | QueryOrderMap<T>;
|
|
71
71
|
export type QueryOrderMap<T> = {
|
|
72
72
|
[K in EntityKey<T>]?: QueryOrderKeys<ExpandProperty<T[K]>>;
|
|
@@ -85,7 +85,9 @@ export declare enum QueryFlag {
|
|
|
85
85
|
INCLUDE_LAZY_FORMULAS = "INCLUDE_LAZY_FORMULAS",
|
|
86
86
|
AUTO_JOIN_ONE_TO_ONE_OWNER = "AUTO_JOIN_ONE_TO_ONE_OWNER",
|
|
87
87
|
INFER_POPULATE = "INFER_POPULATE",
|
|
88
|
-
|
|
88
|
+
DISABLE_NESTED_INNER_JOIN = "DISABLE_NESTED_INNER_JOIN",
|
|
89
|
+
IDENTITY_INSERT = "IDENTITY_INSERT",// mssql only
|
|
90
|
+
OUTPUT_TABLE = "OUTPUT_TABLE"
|
|
89
91
|
}
|
|
90
92
|
export declare const SCALAR_TYPES: string[];
|
|
91
93
|
export declare enum ReferenceKind {
|
|
@@ -108,7 +110,8 @@ export declare enum Cascade {
|
|
|
108
110
|
}
|
|
109
111
|
export declare enum LoadStrategy {
|
|
110
112
|
SELECT_IN = "select-in",
|
|
111
|
-
JOINED = "joined"
|
|
113
|
+
JOINED = "joined",
|
|
114
|
+
BALANCED = "balanced"
|
|
112
115
|
}
|
|
113
116
|
export declare enum DataloaderType {
|
|
114
117
|
NONE = 0,
|
|
@@ -156,8 +159,18 @@ export declare enum EventType {
|
|
|
156
159
|
}
|
|
157
160
|
export declare const EventTypeMap: Record<EventType, number>;
|
|
158
161
|
export type TransactionEventType = EventType.beforeTransactionStart | EventType.afterTransactionStart | EventType.beforeTransactionCommit | EventType.afterTransactionCommit | EventType.beforeTransactionRollback | EventType.afterTransactionRollback;
|
|
162
|
+
export declare enum TransactionPropagation {
|
|
163
|
+
REQUIRED = "required",
|
|
164
|
+
REQUIRES_NEW = "requires_new",
|
|
165
|
+
NESTED = "nested",
|
|
166
|
+
NOT_SUPPORTED = "not_supported",
|
|
167
|
+
SUPPORTS = "supports",
|
|
168
|
+
MANDATORY = "mandatory",
|
|
169
|
+
NEVER = "never"
|
|
170
|
+
}
|
|
159
171
|
export interface TransactionOptions {
|
|
160
172
|
ctx?: Transaction;
|
|
173
|
+
propagation?: TransactionPropagation;
|
|
161
174
|
isolationLevel?: IsolationLevel;
|
|
162
175
|
readOnly?: boolean;
|
|
163
176
|
clear?: boolean;
|
package/enums.js
CHANGED
|
@@ -95,7 +95,9 @@ export var QueryFlag;
|
|
|
95
95
|
QueryFlag["INCLUDE_LAZY_FORMULAS"] = "INCLUDE_LAZY_FORMULAS";
|
|
96
96
|
QueryFlag["AUTO_JOIN_ONE_TO_ONE_OWNER"] = "AUTO_JOIN_ONE_TO_ONE_OWNER";
|
|
97
97
|
QueryFlag["INFER_POPULATE"] = "INFER_POPULATE";
|
|
98
|
+
QueryFlag["DISABLE_NESTED_INNER_JOIN"] = "DISABLE_NESTED_INNER_JOIN";
|
|
98
99
|
QueryFlag["IDENTITY_INSERT"] = "IDENTITY_INSERT";
|
|
100
|
+
QueryFlag["OUTPUT_TABLE"] = "OUTPUT_TABLE";
|
|
99
101
|
})(QueryFlag || (QueryFlag = {}));
|
|
100
102
|
export const SCALAR_TYPES = ['string', 'number', 'boolean', 'bigint', 'Date', 'Buffer', 'RegExp'];
|
|
101
103
|
export var ReferenceKind;
|
|
@@ -122,6 +124,7 @@ export var LoadStrategy;
|
|
|
122
124
|
(function (LoadStrategy) {
|
|
123
125
|
LoadStrategy["SELECT_IN"] = "select-in";
|
|
124
126
|
LoadStrategy["JOINED"] = "joined";
|
|
127
|
+
LoadStrategy["BALANCED"] = "balanced";
|
|
125
128
|
})(LoadStrategy || (LoadStrategy = {}));
|
|
126
129
|
export var DataloaderType;
|
|
127
130
|
(function (DataloaderType) {
|
|
@@ -175,6 +178,16 @@ export const EventTypeMap = Object.keys(EventType).reduce((a, b, i) => {
|
|
|
175
178
|
a[b] = i;
|
|
176
179
|
return a;
|
|
177
180
|
}, {});
|
|
181
|
+
export var TransactionPropagation;
|
|
182
|
+
(function (TransactionPropagation) {
|
|
183
|
+
TransactionPropagation["REQUIRED"] = "required";
|
|
184
|
+
TransactionPropagation["REQUIRES_NEW"] = "requires_new";
|
|
185
|
+
TransactionPropagation["NESTED"] = "nested";
|
|
186
|
+
TransactionPropagation["NOT_SUPPORTED"] = "not_supported";
|
|
187
|
+
TransactionPropagation["SUPPORTS"] = "supports";
|
|
188
|
+
TransactionPropagation["MANDATORY"] = "mandatory";
|
|
189
|
+
TransactionPropagation["NEVER"] = "never";
|
|
190
|
+
})(TransactionPropagation || (TransactionPropagation = {}));
|
|
178
191
|
export class PlainObject {
|
|
179
192
|
}
|
|
180
193
|
export var DeferMode;
|
package/errors.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export declare class ValidationError<T extends AnyEntity = AnyEntity> extends Er
|
|
|
24
24
|
static cannotCommit(): ValidationError;
|
|
25
25
|
static cannotUseGlobalContext(): ValidationError;
|
|
26
26
|
static cannotUseOperatorsInsideEmbeddables(className: string, propName: string, payload: unknown): ValidationError;
|
|
27
|
+
static cannotUseGroupOperatorsInsideScalars(className: string, propName: string, payload: unknown): ValidationError;
|
|
27
28
|
static invalidEmbeddableQuery(className: string, propName: string, embeddableType: string): ValidationError;
|
|
28
29
|
}
|
|
29
30
|
export declare class CursorError<T extends AnyEntity = AnyEntity> extends ValidationError<T> {
|
|
@@ -66,3 +67,8 @@ export declare class NotFoundError<T extends AnyEntity = AnyEntity> extends Vali
|
|
|
66
67
|
static findOneFailed(name: string, where: Dictionary | IPrimaryKey): NotFoundError;
|
|
67
68
|
static findExactlyOneFailed(name: string, where: Dictionary | IPrimaryKey): NotFoundError;
|
|
68
69
|
}
|
|
70
|
+
export declare class TransactionStateError extends ValidationError {
|
|
71
|
+
static requiredTransactionNotFound(propagation: string): TransactionStateError;
|
|
72
|
+
static transactionNotAllowed(propagation: string): TransactionStateError;
|
|
73
|
+
static invalidPropagation(propagation: string): TransactionStateError;
|
|
74
|
+
}
|
package/errors.js
CHANGED
|
@@ -94,6 +94,9 @@ export class ValidationError extends Error {
|
|
|
94
94
|
static cannotUseOperatorsInsideEmbeddables(className, propName, payload) {
|
|
95
95
|
return new ValidationError(`Using operators inside embeddables is not allowed, move the operator above. (property: ${className}.${propName}, payload: ${inspect(payload)})`);
|
|
96
96
|
}
|
|
97
|
+
static cannotUseGroupOperatorsInsideScalars(className, propName, payload) {
|
|
98
|
+
return new ValidationError(`Using group operators ($and/$or) inside scalar properties is not allowed, move the operator above. (property: ${className}.${propName}, payload: ${inspect(payload)})`);
|
|
99
|
+
}
|
|
97
100
|
static invalidEmbeddableQuery(className, propName, embeddableType) {
|
|
98
101
|
return new ValidationError(`Invalid query for entity '${className}', property '${propName}' does not exist in embeddable '${embeddableType}'`);
|
|
99
102
|
}
|
|
@@ -220,3 +223,14 @@ export class NotFoundError extends ValidationError {
|
|
|
220
223
|
return new NotFoundError(`Wrong number of ${name} entities found for query ${inspect(where)}, expected exactly one`);
|
|
221
224
|
}
|
|
222
225
|
}
|
|
226
|
+
export class TransactionStateError extends ValidationError {
|
|
227
|
+
static requiredTransactionNotFound(propagation) {
|
|
228
|
+
return new TransactionStateError(`No existing transaction found for transaction marked with propagation "${propagation}"`);
|
|
229
|
+
}
|
|
230
|
+
static transactionNotAllowed(propagation) {
|
|
231
|
+
return new TransactionStateError(`Existing transaction found for transaction marked with propagation "${propagation}"`);
|
|
232
|
+
}
|
|
233
|
+
static invalidPropagation(propagation) {
|
|
234
|
+
return new TransactionStateError(`Unsupported transaction propagation type: ${propagation}`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
@@ -13,7 +13,9 @@ export interface FlushEventArgs extends Omit<EventArgs<any>, 'entity' | 'changeS
|
|
|
13
13
|
uow: UnitOfWork;
|
|
14
14
|
}
|
|
15
15
|
export interface TransactionEventArgs extends Omit<EventArgs<any>, 'entity' | 'meta' | 'changeSet'> {
|
|
16
|
-
transaction?: Transaction
|
|
16
|
+
transaction?: Transaction & {
|
|
17
|
+
savepointName?: string;
|
|
18
|
+
};
|
|
17
19
|
uow?: UnitOfWork;
|
|
18
20
|
}
|
|
19
21
|
export interface EventSubscriber<T = any> {
|
|
@@ -63,7 +63,7 @@ export class ObjectHydrator extends Hydrator {
|
|
|
63
63
|
const ret = [];
|
|
64
64
|
const idx = this.tmpIndex++;
|
|
65
65
|
const nullVal = this.config.get('forceUndefined') ? 'undefined' : 'null';
|
|
66
|
-
if (prop.getter && !prop.setter) {
|
|
66
|
+
if (prop.getter && !prop.setter && prop.persist === false) {
|
|
67
67
|
return [];
|
|
68
68
|
}
|
|
69
69
|
if (prop.ref) {
|
|
@@ -71,7 +71,14 @@ export class ObjectHydrator extends Hydrator {
|
|
|
71
71
|
ret.push(` const oldValue_${idx} = entity${entityKey};`);
|
|
72
72
|
}
|
|
73
73
|
ret.push(` if (data${dataKey} === null) {`);
|
|
74
|
-
|
|
74
|
+
if (prop.ref) {
|
|
75
|
+
ret.push(` entity${entityKey} = new ScalarReference();`);
|
|
76
|
+
ret.push(` entity${entityKey}.bind(entity, '${prop.name}');`);
|
|
77
|
+
ret.push(` entity${entityKey}.set(${nullVal});`);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
ret.push(` entity${entityKey} = ${nullVal};`);
|
|
81
|
+
}
|
|
75
82
|
ret.push(` } else if (typeof data${dataKey} !== 'undefined') {`);
|
|
76
83
|
if (prop.customType) {
|
|
77
84
|
registerCustomType(prop, convertorKey, 'convertToJSValue', context);
|
|
@@ -256,6 +263,7 @@ export class ObjectHydrator extends Hydrator {
|
|
|
256
263
|
...prop2,
|
|
257
264
|
name: childProp.name,
|
|
258
265
|
embedded: childProp.embedded,
|
|
266
|
+
embeddedProps: childProp.embeddedProps,
|
|
259
267
|
};
|
|
260
268
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
261
269
|
ret.push(...hydrateProperty(prop3, childProp.object, [...path, childProp.embedded[1]], childDataKey).map(l => ' ' + l));
|
package/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @packageDocumentation
|
|
3
3
|
* @module core
|
|
4
4
|
*/
|
|
5
|
-
export { Constructor, ConnectionType, Dictionary, PrimaryKeyProp, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, EntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, EntityMetadata, QBFilterQuery, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, EntityRepositoryType, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, MigrationDiff, GenerateOptions, FilterObject, IEntityGenerator, ISeedManager, EntityClassGroup, OptionalProps, EagerProps, HiddenProps, RequiredEntityData, CheckCallback, SimpleColumnMeta, Rel, Ref, ScalarRef, EntityRef, ISchemaGenerator, UmzugMigration, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, FilterKey, Opt, EntityType, FromEntityType, Selected, IsSubset, NoInfer, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, Hidden, FilterValue, MergeLoaded, MergeSelected, Config, DefineConfig, TypeConfig, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, } from './typings.js';
|
|
5
|
+
export { Constructor, ConnectionType, Dictionary, PrimaryKeyProp, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, EntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, EntityMetadata, QBFilterQuery, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, EntityRepositoryType, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, MigrationDiff, GenerateOptions, FilterObject, IEntityGenerator, ISeedManager, EntityClassGroup, OptionalProps, EagerProps, HiddenProps, RequiredEntityData, CheckCallback, IndexCallback, SimpleColumnMeta, Rel, Ref, ScalarRef, EntityRef, ISchemaGenerator, UmzugMigration, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, EntityDataValue, FilterKey, Opt, EntityType, FromEntityType, Selected, IsSubset, NoInfer, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, Hidden, FilterValue, MergeLoaded, MergeSelected, Config, DefineConfig, TypeConfig, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, RequiredNullable, } from './typings.js';
|
|
6
6
|
export * from './enums.js';
|
|
7
7
|
export * from './errors.js';
|
|
8
8
|
export * from './exceptions.js';
|
package/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @packageDocumentation
|
|
3
3
|
* @module core
|
|
4
4
|
*/
|
|
5
|
-
export { PrimaryKeyProp, EntityMetadata, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Config, } from './typings.js';
|
|
5
|
+
export { PrimaryKeyProp, EntityMetadata, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Opt, Hidden, Config, DefineConfig, RequiredNullable, } from './typings.js';
|
|
6
6
|
export * from './enums.js';
|
|
7
7
|
export * from './errors.js';
|
|
8
8
|
export * from './exceptions.js';
|
|
@@ -31,7 +31,7 @@ export type EntitySchemaProperty<Target, Owner> = ({
|
|
|
31
31
|
kind: ReferenceKind.MANY_TO_MANY | 'm:n';
|
|
32
32
|
} & TypeDef<Target> & ManyToManyOptions<Owner, Target>) | ({
|
|
33
33
|
kind: ReferenceKind.EMBEDDED | 'embedded';
|
|
34
|
-
} & EmbeddedTypeDef<Target> & EmbeddedOptions & PropertyOptions<Owner>) | ({
|
|
34
|
+
} & EmbeddedTypeDef<Target> & EmbeddedOptions<Owner, Target> & PropertyOptions<Owner>) | ({
|
|
35
35
|
enum: true;
|
|
36
36
|
} & EnumOptions<Owner>) | (TypeDef<Target> & PropertyOptions<Owner>);
|
|
37
37
|
type OmitBaseProps<Entity, Base> = IsNever<Base> extends true ? Entity : Omit<Entity, keyof Base>;
|
|
@@ -63,13 +63,13 @@ export declare class EntitySchema<Entity = any, Base = never> {
|
|
|
63
63
|
addVersion(name: EntityKey<Entity>, type: TypeType, options?: PropertyOptions<Entity>): void;
|
|
64
64
|
addPrimaryKey(name: EntityKey<Entity>, type: TypeType, options?: PrimaryKeyOptions<Entity>): void;
|
|
65
65
|
addSerializedPrimaryKey(name: EntityKey<Entity>, type: TypeType, options?: SerializedPrimaryKeyOptions<Entity>): void;
|
|
66
|
-
addEmbedded<Target = AnyEntity>(name: EntityKey<Entity>, options: EmbeddedOptions): void;
|
|
66
|
+
addEmbedded<Target = AnyEntity>(name: EntityKey<Entity>, options: EmbeddedOptions<Entity, Target>): void;
|
|
67
67
|
addManyToOne<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: ManyToOneOptions<Entity, Target>): void;
|
|
68
68
|
addManyToMany<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: ManyToManyOptions<Entity, Target>): void;
|
|
69
69
|
addOneToMany<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: OneToManyOptions<Entity, Target>): void;
|
|
70
70
|
addOneToOne<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: OneToOneOptions<Entity, Target>): void;
|
|
71
|
-
addIndex(options: IndexOptions<Entity>): void;
|
|
72
|
-
addUnique(options: UniqueOptions<Entity>): void;
|
|
71
|
+
addIndex<Key extends string>(options: IndexOptions<Entity, Key>): void;
|
|
72
|
+
addUnique<Key extends string>(options: UniqueOptions<Entity, Key>): void;
|
|
73
73
|
setCustomRepository(repository: () => Constructor): void;
|
|
74
74
|
setExtends(base: string | EntitySchema): void;
|
|
75
75
|
setClass(proto: EntityClass<Entity>): void;
|
|
@@ -83,5 +83,7 @@ export declare class EntitySchema<Entity = any, Base = never> {
|
|
|
83
83
|
private initPrimaryKeys;
|
|
84
84
|
private normalizeType;
|
|
85
85
|
private createProperty;
|
|
86
|
+
private rename;
|
|
87
|
+
private renameCompositeOptions;
|
|
86
88
|
}
|
|
87
89
|
export {};
|
package/metadata/EntitySchema.js
CHANGED
|
@@ -34,23 +34,7 @@ export class EntitySchema {
|
|
|
34
34
|
return schema;
|
|
35
35
|
}
|
|
36
36
|
addProperty(name, type, options = {}) {
|
|
37
|
-
|
|
38
|
-
if (from in options && !(to in options)) {
|
|
39
|
-
// @ts-ignore
|
|
40
|
-
options[to] = [options[from]];
|
|
41
|
-
// @ts-ignore
|
|
42
|
-
delete options[from];
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
if (name !== options.name) {
|
|
46
|
-
Utils.renameKey(options, 'name', 'fieldName');
|
|
47
|
-
}
|
|
48
|
-
rename(options, 'fieldName', 'fieldNames');
|
|
49
|
-
rename(options, 'ref', 'ref');
|
|
50
|
-
rename(options, 'joinColumn', 'joinColumns');
|
|
51
|
-
rename(options, 'inverseJoinColumn', 'inverseJoinColumns');
|
|
52
|
-
rename(options, 'referenceColumnName', 'referencedColumnNames');
|
|
53
|
-
rename(options, 'columnType', 'columnTypes');
|
|
37
|
+
this.renameCompositeOptions(name, options);
|
|
54
38
|
const prop = { name, kind: ReferenceKind.SCALAR, ...options, type: this.normalizeType(options, type) };
|
|
55
39
|
if (type && Type.isMappedType(type.prototype)) {
|
|
56
40
|
prop.type = type;
|
|
@@ -94,6 +78,7 @@ export class EntitySchema {
|
|
|
94
78
|
this.addProperty(name, type, options);
|
|
95
79
|
}
|
|
96
80
|
addEmbedded(name, options) {
|
|
81
|
+
this.renameCompositeOptions(name, options);
|
|
97
82
|
Utils.defaultValue(options, 'prefix', true);
|
|
98
83
|
if (options.array) {
|
|
99
84
|
options.object = true; // force object mode for arrays
|
|
@@ -114,6 +99,8 @@ export class EntitySchema {
|
|
|
114
99
|
if (prop.fieldNames && !prop.joinColumns) {
|
|
115
100
|
prop.joinColumns = prop.fieldNames;
|
|
116
101
|
}
|
|
102
|
+
// By default, the foreign key constraint is created on the relation
|
|
103
|
+
Utils.defaultValue(prop, 'createForeignKeyConstraint', true);
|
|
117
104
|
this.addProperty(name, type, prop);
|
|
118
105
|
}
|
|
119
106
|
addManyToMany(name, type, options) {
|
|
@@ -123,6 +110,8 @@ export class EntitySchema {
|
|
|
123
110
|
}
|
|
124
111
|
if (options.owner) {
|
|
125
112
|
Utils.renameKey(options, 'mappedBy', 'inversedBy');
|
|
113
|
+
// By default, the foreign key constraint is created on the relation
|
|
114
|
+
Utils.defaultValue(options, 'createForeignKeyConstraint', true);
|
|
126
115
|
}
|
|
127
116
|
const prop = this.createProperty(ReferenceKind.MANY_TO_MANY, options);
|
|
128
117
|
this.addProperty(name, type, prop);
|
|
@@ -135,8 +124,12 @@ export class EntitySchema {
|
|
|
135
124
|
const prop = this.createProperty(ReferenceKind.ONE_TO_ONE, options);
|
|
136
125
|
Utils.defaultValue(prop, 'owner', !!prop.inversedBy || !prop.mappedBy);
|
|
137
126
|
Utils.defaultValue(prop, 'unique', prop.owner);
|
|
138
|
-
if (prop.owner
|
|
139
|
-
|
|
127
|
+
if (prop.owner) {
|
|
128
|
+
if (options.mappedBy) {
|
|
129
|
+
Utils.renameKey(prop, 'mappedBy', 'inversedBy');
|
|
130
|
+
}
|
|
131
|
+
// By default, the foreign key constraint is created on the relation
|
|
132
|
+
Utils.defaultValue(prop, 'createForeignKeyConstraint', true);
|
|
140
133
|
}
|
|
141
134
|
if (prop.joinColumns && !prop.fieldNames) {
|
|
142
135
|
prop.fieldNames = prop.joinColumns;
|
|
@@ -289,4 +282,25 @@ export class EntitySchema {
|
|
|
289
282
|
...options,
|
|
290
283
|
};
|
|
291
284
|
}
|
|
285
|
+
rename(data, from, to) {
|
|
286
|
+
if (from in data && !(to in data)) {
|
|
287
|
+
// @ts-ignore
|
|
288
|
+
data[to] = [data[from]];
|
|
289
|
+
// @ts-ignore
|
|
290
|
+
delete data[from];
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
renameCompositeOptions(name, options = {}) {
|
|
294
|
+
if (name !== options.name && !options.fieldNames) {
|
|
295
|
+
Utils.renameKey(options, 'name', 'fieldName');
|
|
296
|
+
}
|
|
297
|
+
else if (options.name && (options.fieldNames?.length ?? 0) > 1) {
|
|
298
|
+
delete options.name;
|
|
299
|
+
}
|
|
300
|
+
this.rename(options, 'fieldName', 'fieldNames');
|
|
301
|
+
this.rename(options, 'joinColumn', 'joinColumns');
|
|
302
|
+
this.rename(options, 'inverseJoinColumn', 'inverseJoinColumns');
|
|
303
|
+
this.rename(options, 'referenceColumnName', 'referencedColumnNames');
|
|
304
|
+
this.rename(options, 'columnType', 'columnTypes');
|
|
305
|
+
}
|
|
292
306
|
}
|
|
@@ -54,7 +54,6 @@ export declare class MetadataDiscovery {
|
|
|
54
54
|
private initAutoincrement;
|
|
55
55
|
private initCheckConstraints;
|
|
56
56
|
private initGeneratedColumn;
|
|
57
|
-
private createColumnMappingObject;
|
|
58
57
|
private getDefaultVersionValue;
|
|
59
58
|
private inferDefaultValue;
|
|
60
59
|
private initDefaultValue;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { basename, extname } from 'node:path';
|
|
2
|
-
import
|
|
2
|
+
import { glob } from 'tinyglobby';
|
|
3
3
|
import { EntityMetadata, } from '../typings.js';
|
|
4
4
|
import { Utils } from '../utils/Utils.js';
|
|
5
5
|
import { MetadataValidator } from './MetadataValidator.js';
|
|
@@ -7,7 +7,7 @@ import { MetadataStorage } from './MetadataStorage.js';
|
|
|
7
7
|
import { EntitySchema } from './EntitySchema.js';
|
|
8
8
|
import { Cascade, ReferenceKind } from '../enums.js';
|
|
9
9
|
import { MetadataError } from '../errors.js';
|
|
10
|
-
import { ArrayType, BigIntType, BlobType, DecimalType, DoubleType, EnumArrayType, IntervalType, JsonType, t, Type, Uint8ArrayType, UnknownType, } from '../types/index.js';
|
|
10
|
+
import { ArrayType, BigIntType, BlobType, DateType, DecimalType, DoubleType, EnumArrayType, IntervalType, JsonType, t, Type, Uint8ArrayType, UnknownType, } from '../types/index.js';
|
|
11
11
|
import { colors } from '../logging/colors.js';
|
|
12
12
|
import { raw, RawQueryFragment } from '../utils/RawQueryFragment.js';
|
|
13
13
|
export class MetadataDiscovery {
|
|
@@ -181,7 +181,7 @@ export class MetadataDiscovery {
|
|
|
181
181
|
}
|
|
182
182
|
async discoverDirectories(paths) {
|
|
183
183
|
paths = paths.map(path => Utils.normalizePath(path));
|
|
184
|
-
const files = await
|
|
184
|
+
const files = await glob(paths, { cwd: Utils.normalizePath(this.config.get('baseDir')) });
|
|
185
185
|
this.logger.log('discovery', `- processing ${colors.cyan('' + files.length)} files`);
|
|
186
186
|
const found = [];
|
|
187
187
|
for (const filepath of files) {
|
|
@@ -264,7 +264,8 @@ export class MetadataDiscovery {
|
|
|
264
264
|
// initialize global metadata for given entity
|
|
265
265
|
MetadataStorage.getMetadata(entity.meta.className, filepath);
|
|
266
266
|
}
|
|
267
|
-
|
|
267
|
+
const meta = Utils.copy(entity.meta, false);
|
|
268
|
+
return EntitySchema.fromMetadata(meta);
|
|
268
269
|
}
|
|
269
270
|
const path = entity[MetadataStorage.PATH_SYMBOL];
|
|
270
271
|
if (path) {
|
|
@@ -618,7 +619,7 @@ export class MetadataDiscovery {
|
|
|
618
619
|
}
|
|
619
620
|
data.properties[meta.name + '_owner'] = this.definePivotProperty(prop, meta.name + '_owner', meta.className, targetType + '_inverse', true, meta.className === targetType);
|
|
620
621
|
data.properties[targetType + '_inverse'] = this.definePivotProperty(prop, targetType + '_inverse', targetType, meta.name + '_owner', false, meta.className === targetType);
|
|
621
|
-
return this.metadata.set(data.className, data);
|
|
622
|
+
return this.metadata.set(data.className, EntitySchema.fromMetadata(data).init().meta);
|
|
622
623
|
}
|
|
623
624
|
defineFixedOrderProperty(prop, targetType) {
|
|
624
625
|
const pk = prop.fixedOrderColumn || this.namingStrategy.referenceColumnName();
|
|
@@ -653,6 +654,7 @@ export class MetadataDiscovery {
|
|
|
653
654
|
autoincrement: false,
|
|
654
655
|
updateRule: prop.updateRule,
|
|
655
656
|
deleteRule: prop.deleteRule,
|
|
657
|
+
createForeignKeyConstraint: prop.createForeignKeyConstraint,
|
|
656
658
|
};
|
|
657
659
|
if (selfReferencing && !this.platform.supportsMultipleCascadePaths()) {
|
|
658
660
|
ret.updateRule ??= 'no action';
|
|
@@ -765,6 +767,7 @@ export class MetadataDiscovery {
|
|
|
765
767
|
delete prop.default;
|
|
766
768
|
if (properties[prop.name] && properties[prop.name].type !== prop.type) {
|
|
767
769
|
properties[prop.name].type = `${properties[prop.name].type} | ${prop.type}`;
|
|
770
|
+
properties[prop.name].runtimeType = 'any';
|
|
768
771
|
return properties[prop.name];
|
|
769
772
|
}
|
|
770
773
|
return properties[prop.name] = prop;
|
|
@@ -819,9 +822,16 @@ export class MetadataDiscovery {
|
|
|
819
822
|
}
|
|
820
823
|
return prop.embedded ? isParentObject(meta.properties[prop.embedded[0]]) : false;
|
|
821
824
|
};
|
|
825
|
+
const isParentArray = (prop) => {
|
|
826
|
+
if (prop.array) {
|
|
827
|
+
return true;
|
|
828
|
+
}
|
|
829
|
+
return prop.embedded ? isParentArray(meta.properties[prop.embedded[0]]) : false;
|
|
830
|
+
};
|
|
822
831
|
const rootProperty = getRootProperty(embeddedProp);
|
|
823
832
|
const parentProperty = meta.properties[embeddedProp.embedded?.[0] ?? ''];
|
|
824
833
|
const object = isParentObject(embeddedProp);
|
|
834
|
+
const array = isParentArray(embeddedProp);
|
|
825
835
|
this.initFieldName(embeddedProp, rootProperty !== embeddedProp && object);
|
|
826
836
|
// the prefix of the parent cannot be a boolean; it already passed here
|
|
827
837
|
const prefix = this.getPrefix(embeddedProp, parentProperty);
|
|
@@ -834,7 +844,8 @@ export class MetadataDiscovery {
|
|
|
834
844
|
meta.propertyOrder.set(name, (order += 0.01));
|
|
835
845
|
embeddedProp.embeddedProps[prop.name] = meta.properties[name];
|
|
836
846
|
meta.properties[name].persist ??= embeddedProp.persist;
|
|
837
|
-
|
|
847
|
+
const refInArray = array && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && prop.owner;
|
|
848
|
+
if (embeddedProp.nullable || refInArray) {
|
|
838
849
|
meta.properties[name].nullable = true;
|
|
839
850
|
}
|
|
840
851
|
if (meta.properties[name].fieldNames) {
|
|
@@ -872,6 +883,7 @@ export class MetadataDiscovery {
|
|
|
872
883
|
meta.properties[name].persist = false; // only virtual as we store the whole object
|
|
873
884
|
meta.properties[name].userDefined = false; // mark this as a generated/internal property, so we can distinguish from user-defined non-persist properties
|
|
874
885
|
meta.properties[name].object = true;
|
|
886
|
+
this.initCustomType(meta, meta.properties[name], false, true);
|
|
875
887
|
}
|
|
876
888
|
this.initEmbeddables(meta, meta.properties[name], visited);
|
|
877
889
|
}
|
|
@@ -905,11 +917,13 @@ export class MetadataDiscovery {
|
|
|
905
917
|
}
|
|
906
918
|
if (!meta.root.discriminatorMap) {
|
|
907
919
|
meta.root.discriminatorMap = {};
|
|
908
|
-
const children = metadata
|
|
909
|
-
|
|
920
|
+
const children = metadata
|
|
921
|
+
.filter(m => m.root.className === meta.root.className && !m.abstract)
|
|
922
|
+
.sort((a, b) => a.className.localeCompare(b.className));
|
|
923
|
+
for (const m of children) {
|
|
910
924
|
const name = m.discriminatorValue ?? this.namingStrategy.classToTableName(m.className);
|
|
911
925
|
meta.root.discriminatorMap[name] = m.className;
|
|
912
|
-
}
|
|
926
|
+
}
|
|
913
927
|
}
|
|
914
928
|
meta.discriminatorValue = Object.entries(meta.root.discriminatorMap).find(([, className]) => className === meta.className)?.[0];
|
|
915
929
|
if (!meta.root.properties[meta.root.discriminatorColumn]) {
|
|
@@ -922,7 +936,7 @@ export class MetadataDiscovery {
|
|
|
922
936
|
}
|
|
923
937
|
let i = 1;
|
|
924
938
|
Object.values(meta.properties).forEach(prop => {
|
|
925
|
-
const newProp =
|
|
939
|
+
const newProp = { ...prop };
|
|
926
940
|
if (meta.root.properties[prop.name] && meta.root.properties[prop.name].type !== prop.type) {
|
|
927
941
|
const name = newProp.name;
|
|
928
942
|
this.initFieldName(newProp, newProp.object);
|
|
@@ -944,6 +958,7 @@ export class MetadataDiscovery {
|
|
|
944
958
|
meta.collection = meta.root.collection;
|
|
945
959
|
meta.root.indexes = Utils.unique([...meta.root.indexes, ...meta.indexes]);
|
|
946
960
|
meta.root.uniques = Utils.unique([...meta.root.uniques, ...meta.uniques]);
|
|
961
|
+
meta.root.checks = Utils.unique([...meta.root.checks, ...meta.checks]);
|
|
947
962
|
}
|
|
948
963
|
createDiscriminatorProperty(meta) {
|
|
949
964
|
meta.addProperty({
|
|
@@ -962,7 +977,7 @@ export class MetadataDiscovery {
|
|
|
962
977
|
}
|
|
963
978
|
}
|
|
964
979
|
initCheckConstraints(meta) {
|
|
965
|
-
const map =
|
|
980
|
+
const map = meta.createColumnMappingObject();
|
|
966
981
|
for (const check of meta.checks) {
|
|
967
982
|
const columns = check.property ? meta.properties[check.property].fieldNames : [];
|
|
968
983
|
check.name ??= this.namingStrategy.indexName(meta.tableName, columns, 'check');
|
|
@@ -997,20 +1012,12 @@ export class MetadataDiscovery {
|
|
|
997
1012
|
}
|
|
998
1013
|
return;
|
|
999
1014
|
}
|
|
1000
|
-
const map =
|
|
1015
|
+
const map = meta.createColumnMappingObject();
|
|
1001
1016
|
if (prop.generated instanceof Function) {
|
|
1002
1017
|
prop.generated = prop.generated(map);
|
|
1003
1018
|
}
|
|
1004
1019
|
}
|
|
1005
|
-
|
|
1006
|
-
return Object.values(meta.properties).reduce((o, prop) => {
|
|
1007
|
-
if (prop.fieldNames) {
|
|
1008
|
-
o[prop.name] = prop.fieldNames[0];
|
|
1009
|
-
}
|
|
1010
|
-
return o;
|
|
1011
|
-
}, {});
|
|
1012
|
-
}
|
|
1013
|
-
getDefaultVersionValue(prop) {
|
|
1020
|
+
getDefaultVersionValue(meta, prop) {
|
|
1014
1021
|
if (typeof prop.defaultRaw !== 'undefined') {
|
|
1015
1022
|
return prop.defaultRaw;
|
|
1016
1023
|
}
|
|
@@ -1018,7 +1025,9 @@ export class MetadataDiscovery {
|
|
|
1018
1025
|
if (prop.default != null) {
|
|
1019
1026
|
return '' + this.platform.quoteVersionValue(prop.default, prop);
|
|
1020
1027
|
}
|
|
1021
|
-
|
|
1028
|
+
this.initCustomType(meta, prop, true);
|
|
1029
|
+
const type = prop.customType?.runtimeType ?? prop.runtimeType ?? prop.type;
|
|
1030
|
+
if (type === 'Date') {
|
|
1022
1031
|
prop.length ??= this.platform.getDefaultVersionLength();
|
|
1023
1032
|
return this.platform.getCurrentTimestampSQL(prop.length);
|
|
1024
1033
|
}
|
|
@@ -1061,7 +1070,7 @@ export class MetadataDiscovery {
|
|
|
1061
1070
|
prop.defaultRaw = this.platform.formatQuery(raw.sql, raw.params);
|
|
1062
1071
|
return;
|
|
1063
1072
|
}
|
|
1064
|
-
if (
|
|
1073
|
+
if (Array.isArray(prop.default) && prop.customType) {
|
|
1065
1074
|
val = prop.customType.convertToDatabaseValue(prop.default, this.platform);
|
|
1066
1075
|
}
|
|
1067
1076
|
prop.defaultRaw = typeof val === 'string' ? `'${val}'` : '' + val;
|
|
@@ -1089,13 +1098,13 @@ export class MetadataDiscovery {
|
|
|
1089
1098
|
if (prop.version) {
|
|
1090
1099
|
this.initDefaultValue(prop);
|
|
1091
1100
|
meta.versionProperty = prop.name;
|
|
1092
|
-
prop.defaultRaw = this.getDefaultVersionValue(prop);
|
|
1101
|
+
prop.defaultRaw = this.getDefaultVersionValue(meta, prop);
|
|
1093
1102
|
}
|
|
1094
1103
|
if (prop.concurrencyCheck && !prop.primary) {
|
|
1095
1104
|
meta.concurrencyCheckKeys.add(prop.name);
|
|
1096
1105
|
}
|
|
1097
1106
|
}
|
|
1098
|
-
initCustomType(meta, prop) {
|
|
1107
|
+
initCustomType(meta, prop, simple = false, objectEmbeddable = false) {
|
|
1099
1108
|
// `prop.type` might be actually instance of custom type class
|
|
1100
1109
|
if (Type.isMappedType(prop.type) && !prop.customType) {
|
|
1101
1110
|
prop.customType = prop.type;
|
|
@@ -1106,21 +1115,31 @@ export class MetadataDiscovery {
|
|
|
1106
1115
|
prop.customType = new prop.type();
|
|
1107
1116
|
prop.type = prop.customType.constructor.name;
|
|
1108
1117
|
}
|
|
1118
|
+
if (simple) {
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1109
1121
|
if (!prop.customType && ['json', 'jsonb'].includes(prop.type?.toLowerCase())) {
|
|
1110
1122
|
prop.customType = new JsonType();
|
|
1111
1123
|
}
|
|
1112
1124
|
if (prop.kind === ReferenceKind.SCALAR && !prop.customType && prop.columnTypes && ['json', 'jsonb'].includes(prop.columnTypes[0])) {
|
|
1113
1125
|
prop.customType = new JsonType();
|
|
1114
1126
|
}
|
|
1127
|
+
if (prop.kind === ReferenceKind.EMBEDDED && !prop.customType && (prop.object || prop.array)) {
|
|
1128
|
+
prop.customType = new JsonType();
|
|
1129
|
+
}
|
|
1115
1130
|
if (!prop.customType && prop.array && prop.items) {
|
|
1116
1131
|
prop.customType = new EnumArrayType(`${meta.className}.${prop.name}`, prop.items);
|
|
1117
1132
|
}
|
|
1133
|
+
const isArray = prop.type?.toLowerCase() === 'array' || prop.type?.toString().endsWith('[]');
|
|
1134
|
+
if (objectEmbeddable && !prop.customType && isArray) {
|
|
1135
|
+
prop.customType = new JsonType();
|
|
1136
|
+
}
|
|
1118
1137
|
// for number arrays we make sure to convert the items to numbers
|
|
1119
1138
|
if (!prop.customType && prop.type === 'number[]') {
|
|
1120
1139
|
prop.customType = new ArrayType(i => +i);
|
|
1121
1140
|
}
|
|
1122
1141
|
// `string[]` can be returned via ts-morph, while reflect metadata will give us just `array`
|
|
1123
|
-
if (!prop.customType &&
|
|
1142
|
+
if (!prop.customType && isArray) {
|
|
1124
1143
|
prop.customType = new ArrayType();
|
|
1125
1144
|
}
|
|
1126
1145
|
if (!prop.customType && prop.type?.toLowerCase() === 'buffer') {
|
|
@@ -1131,9 +1150,9 @@ export class MetadataDiscovery {
|
|
|
1131
1150
|
}
|
|
1132
1151
|
const mappedType = this.getMappedType(prop);
|
|
1133
1152
|
if (prop.fieldNames?.length === 1 && !prop.customType) {
|
|
1134
|
-
[BigIntType, DoubleType, DecimalType, IntervalType]
|
|
1153
|
+
[BigIntType, DoubleType, DecimalType, IntervalType, DateType]
|
|
1135
1154
|
.filter(type => mappedType instanceof type)
|
|
1136
|
-
.forEach(type => prop.customType = new type());
|
|
1155
|
+
.forEach((type) => prop.customType = new type());
|
|
1137
1156
|
}
|
|
1138
1157
|
if (prop.customType && !prop.columnTypes) {
|
|
1139
1158
|
const mappedType = this.getMappedType({ columnTypes: [prop.customType.getColumnType(prop, this.platform)] });
|
|
@@ -1144,6 +1163,9 @@ export class MetadataDiscovery {
|
|
|
1144
1163
|
prop.runtimeType ??= prop.customType.runtimeType;
|
|
1145
1164
|
}
|
|
1146
1165
|
}
|
|
1166
|
+
else if (prop.runtimeType === 'object') {
|
|
1167
|
+
prop.runtimeType = mappedType.runtimeType;
|
|
1168
|
+
}
|
|
1147
1169
|
else {
|
|
1148
1170
|
prop.runtimeType ??= mappedType.runtimeType;
|
|
1149
1171
|
}
|
|
@@ -1158,7 +1180,7 @@ export class MetadataDiscovery {
|
|
|
1158
1180
|
prop.customType.mode = prop.runtimeType.toLowerCase();
|
|
1159
1181
|
}
|
|
1160
1182
|
}
|
|
1161
|
-
if (Type.isMappedType(prop.customType) && prop.kind === ReferenceKind.SCALAR && !
|
|
1183
|
+
if (Type.isMappedType(prop.customType) && prop.kind === ReferenceKind.SCALAR && !isArray) {
|
|
1162
1184
|
prop.type = prop.customType.name;
|
|
1163
1185
|
}
|
|
1164
1186
|
if (!prop.customType && [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind) && this.metadata.get(prop.type).compositePK) {
|