@mikro-orm/core 7.0.0-dev.99 → 7.0.0-rc.1
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 +34 -17
- package/EntityManager.js +95 -103
- package/MikroORM.d.ts +5 -5
- package/MikroORM.js +25 -20
- package/cache/FileCacheAdapter.js +11 -3
- package/connections/Connection.d.ts +3 -2
- package/connections/Connection.js +4 -3
- package/drivers/DatabaseDriver.d.ts +11 -11
- package/drivers/DatabaseDriver.js +91 -25
- package/drivers/IDatabaseDriver.d.ts +50 -20
- package/entity/BaseEntity.d.ts +61 -1
- package/entity/Collection.d.ts +8 -1
- package/entity/Collection.js +12 -13
- package/entity/EntityAssigner.js +9 -9
- package/entity/EntityFactory.d.ts +6 -1
- package/entity/EntityFactory.js +40 -22
- package/entity/EntityHelper.d.ts +2 -2
- package/entity/EntityHelper.js +27 -4
- package/entity/EntityLoader.d.ts +5 -4
- package/entity/EntityLoader.js +193 -80
- package/entity/EntityRepository.d.ts +27 -7
- package/entity/EntityRepository.js +8 -2
- package/entity/PolymorphicRef.d.ts +12 -0
- package/entity/PolymorphicRef.js +18 -0
- package/entity/WrappedEntity.d.ts +2 -2
- package/entity/WrappedEntity.js +1 -1
- package/entity/defineEntity.d.ts +89 -50
- package/entity/defineEntity.js +12 -0
- package/entity/index.d.ts +1 -0
- package/entity/index.js +1 -0
- package/entity/utils.d.ts +6 -1
- package/entity/utils.js +33 -0
- package/entity/validators.js +2 -2
- package/enums.d.ts +2 -2
- package/enums.js +1 -0
- package/errors.d.ts +16 -8
- package/errors.js +40 -13
- package/hydration/ObjectHydrator.js +63 -21
- package/index.d.ts +1 -1
- package/logging/colors.d.ts +1 -1
- package/logging/colors.js +7 -6
- package/logging/inspect.js +1 -6
- package/metadata/EntitySchema.d.ts +43 -13
- package/metadata/EntitySchema.js +82 -27
- package/metadata/MetadataDiscovery.d.ts +60 -3
- package/metadata/MetadataDiscovery.js +665 -154
- package/metadata/MetadataProvider.js +3 -1
- package/metadata/MetadataStorage.d.ts +13 -6
- package/metadata/MetadataStorage.js +64 -19
- package/metadata/MetadataValidator.d.ts +32 -2
- package/metadata/MetadataValidator.js +196 -31
- package/metadata/discover-entities.js +5 -5
- package/metadata/types.d.ts +111 -14
- package/naming-strategy/AbstractNamingStrategy.d.ts +11 -3
- package/naming-strategy/AbstractNamingStrategy.js +12 -0
- package/naming-strategy/EntityCaseNamingStrategy.d.ts +3 -3
- package/naming-strategy/EntityCaseNamingStrategy.js +6 -5
- package/naming-strategy/MongoNamingStrategy.d.ts +3 -3
- package/naming-strategy/MongoNamingStrategy.js +6 -6
- package/naming-strategy/NamingStrategy.d.ts +17 -3
- package/naming-strategy/UnderscoreNamingStrategy.d.ts +3 -3
- package/naming-strategy/UnderscoreNamingStrategy.js +6 -6
- package/package.json +2 -2
- package/platforms/Platform.d.ts +4 -2
- package/platforms/Platform.js +5 -2
- package/serialization/EntitySerializer.d.ts +3 -0
- package/serialization/EntitySerializer.js +15 -13
- package/serialization/EntityTransformer.js +6 -6
- package/serialization/SerializationContext.d.ts +6 -6
- package/typings.d.ts +325 -110
- package/typings.js +84 -17
- package/unit-of-work/ChangeSet.d.ts +4 -3
- package/unit-of-work/ChangeSet.js +2 -3
- package/unit-of-work/ChangeSetComputer.d.ts +3 -6
- package/unit-of-work/ChangeSetComputer.js +34 -13
- package/unit-of-work/ChangeSetPersister.d.ts +12 -10
- package/unit-of-work/ChangeSetPersister.js +55 -25
- package/unit-of-work/CommitOrderCalculator.d.ts +12 -10
- package/unit-of-work/CommitOrderCalculator.js +13 -13
- package/unit-of-work/IdentityMap.d.ts +12 -0
- package/unit-of-work/IdentityMap.js +39 -1
- package/unit-of-work/UnitOfWork.d.ts +21 -3
- package/unit-of-work/UnitOfWork.js +203 -56
- package/utils/AbstractSchemaGenerator.js +17 -8
- package/utils/AsyncContext.d.ts +6 -0
- package/utils/AsyncContext.js +42 -0
- package/utils/Configuration.d.ts +52 -11
- package/utils/Configuration.js +12 -8
- package/utils/Cursor.js +21 -8
- package/utils/DataloaderUtils.js +13 -11
- package/utils/EntityComparator.d.ts +14 -7
- package/utils/EntityComparator.js +132 -46
- package/utils/QueryHelper.d.ts +16 -6
- package/utils/QueryHelper.js +53 -18
- package/utils/RawQueryFragment.d.ts +28 -23
- package/utils/RawQueryFragment.js +34 -56
- package/utils/RequestContext.js +2 -2
- package/utils/TransactionContext.js +2 -2
- package/utils/TransactionManager.js +1 -1
- package/utils/Utils.d.ts +7 -26
- package/utils/Utils.js +25 -79
- package/utils/clone.js +7 -21
- package/utils/env-vars.d.ts +4 -0
- package/utils/env-vars.js +13 -3
- package/utils/fs-utils.d.ts +21 -0
- package/utils/fs-utils.js +106 -11
- package/utils/upsert-utils.d.ts +4 -4
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { Hydrator } from './Hydrator.js';
|
|
2
2
|
import { Collection } from '../entity/Collection.js';
|
|
3
3
|
import { Reference, ScalarReference } from '../entity/Reference.js';
|
|
4
|
+
import { PolymorphicRef } from '../entity/PolymorphicRef.js';
|
|
4
5
|
import { parseJsonSafe, Utils } from '../utils/Utils.js';
|
|
5
6
|
import { ReferenceKind } from '../enums.js';
|
|
6
|
-
import {
|
|
7
|
+
import { Raw } from '../utils/RawQueryFragment.js';
|
|
8
|
+
import { ValidationError } from '../errors.js';
|
|
7
9
|
export class ObjectHydrator extends Hydrator {
|
|
8
10
|
hydrators = {
|
|
9
11
|
'full~true': new Map(),
|
|
@@ -39,7 +41,7 @@ export class ObjectHydrator extends Hydrator {
|
|
|
39
41
|
*/
|
|
40
42
|
getEntityHydrator(meta, type, normalizeAccessors = false) {
|
|
41
43
|
const key = `${type}~${normalizeAccessors}`;
|
|
42
|
-
const exists = this.hydrators[key].get(meta.
|
|
44
|
+
const exists = this.hydrators[key].get(meta.class);
|
|
43
45
|
if (exists) {
|
|
44
46
|
return exists;
|
|
45
47
|
}
|
|
@@ -49,17 +51,19 @@ export class ObjectHydrator extends Hydrator {
|
|
|
49
51
|
context.set('isPrimaryKey', Utils.isPrimaryKey);
|
|
50
52
|
context.set('Collection', Collection);
|
|
51
53
|
context.set('Reference', Reference);
|
|
54
|
+
context.set('PolymorphicRef', PolymorphicRef);
|
|
55
|
+
context.set('ValidationError', ValidationError);
|
|
52
56
|
const registerCustomType = (prop, convertorKey, method, context) => {
|
|
53
57
|
context.set(`${method}_${convertorKey}`, (val) => {
|
|
54
58
|
/* v8 ignore next */
|
|
55
|
-
if (
|
|
59
|
+
if (Raw.isKnownFragment(val)) {
|
|
56
60
|
return val;
|
|
57
61
|
}
|
|
58
62
|
return prop.customType[method](val, this.platform, { mode: 'serialization' });
|
|
59
63
|
});
|
|
60
64
|
return convertorKey;
|
|
61
65
|
};
|
|
62
|
-
const hydrateScalar = (prop,
|
|
66
|
+
const hydrateScalar = (prop, path, dataKey) => {
|
|
63
67
|
const entityKey = path.map(k => this.wrap(k)).join('');
|
|
64
68
|
const tz = this.platform.getTimezone();
|
|
65
69
|
const convertorKey = path.filter(k => !k.match(/\[idx_\d+]/)).map(k => this.safeKey(k)).join('_');
|
|
@@ -134,24 +138,56 @@ export class ObjectHydrator extends Hydrator {
|
|
|
134
138
|
const nullVal = this.config.get('forceUndefined') ? 'undefined' : 'null';
|
|
135
139
|
ret.push(` if (data${dataKey} === null) {\n entity${entityKey} = ${nullVal};`);
|
|
136
140
|
ret.push(` } else if (typeof data${dataKey} !== 'undefined') {`);
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
141
|
+
// For polymorphic: instanceof check; for regular: isPrimaryKey() check
|
|
142
|
+
const pkCheck = prop.polymorphic ? `data${dataKey} instanceof PolymorphicRef` : `isPrimaryKey(data${dataKey}, true)`;
|
|
143
|
+
ret.push(` if (${pkCheck}) {`);
|
|
144
|
+
// When targetKey is set, pass the key option to createReference so it uses the alternate key
|
|
145
|
+
const keyOption = prop.targetKey ? `, key: '${prop.targetKey}'` : '';
|
|
146
|
+
if (prop.polymorphic) {
|
|
147
|
+
// For polymorphic: target class from discriminator map, PK from data.id
|
|
148
|
+
const discriminatorMapKey = this.safeKey(`discriminatorMap_${prop.name}_${this.tmpIndex++}`);
|
|
149
|
+
context.set(discriminatorMapKey, prop.discriminatorMap);
|
|
150
|
+
ret.push(` const targetClass = ${discriminatorMapKey}[data${dataKey}.discriminator];`);
|
|
151
|
+
ret.push(` if (!targetClass) throw new ValidationError(\`Unknown discriminator value '\${data${dataKey}.discriminator}' for polymorphic relation '${prop.name}'. Valid values: \${Object.keys(${discriminatorMapKey}).join(', ')}\`);`);
|
|
152
|
+
if (prop.ref) {
|
|
153
|
+
ret.push(` entity${entityKey} = Reference.create(factory.createReference(targetClass, data${dataKey}.id, { merge: true, convertCustomTypes, normalizeAccessors, schema${keyOption} }));`);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
ret.push(` entity${entityKey} = factory.createReference(targetClass, data${dataKey}.id, { merge: true, convertCustomTypes, normalizeAccessors, schema${keyOption} });`);
|
|
157
|
+
}
|
|
140
158
|
}
|
|
141
159
|
else {
|
|
142
|
-
|
|
160
|
+
// For regular: fixed target class, PK is the data itself
|
|
161
|
+
const targetKey = this.safeKey(`${prop.targetMeta.tableName}_${this.tmpIndex++}`);
|
|
162
|
+
context.set(targetKey, prop.targetMeta.class);
|
|
163
|
+
if (prop.ref) {
|
|
164
|
+
ret.push(` entity${entityKey} = Reference.create(factory.createReference(${targetKey}, data${dataKey}, { merge: true, convertCustomTypes, normalizeAccessors, schema${keyOption} }));`);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
ret.push(` entity${entityKey} = factory.createReference(${targetKey}, data${dataKey}, { merge: true, convertCustomTypes, normalizeAccessors, schema${keyOption} });`);
|
|
168
|
+
}
|
|
143
169
|
}
|
|
144
170
|
ret.push(` } else if (data${dataKey} && typeof data${dataKey} === 'object') {`);
|
|
171
|
+
// For full entity hydration, polymorphic needs to determine target class from entity itself
|
|
172
|
+
let hydrateTargetExpr;
|
|
173
|
+
if (prop.polymorphic) {
|
|
174
|
+
hydrateTargetExpr = `data${dataKey}.constructor`;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
const targetKey = this.safeKey(`${prop.targetMeta.tableName}_${this.tmpIndex++}`);
|
|
178
|
+
context.set(targetKey, prop.targetMeta.class);
|
|
179
|
+
hydrateTargetExpr = targetKey;
|
|
180
|
+
}
|
|
145
181
|
if (prop.ref) {
|
|
146
|
-
ret.push(` entity${entityKey} = Reference.create(factory.${method}(
|
|
182
|
+
ret.push(` entity${entityKey} = Reference.create(factory.${method}(${hydrateTargetExpr}, data${dataKey}, { initialized: true, merge: true, newEntity, convertCustomTypes, normalizeAccessors, schema }));`);
|
|
147
183
|
}
|
|
148
184
|
else {
|
|
149
|
-
ret.push(` entity${entityKey} = factory.${method}(
|
|
185
|
+
ret.push(` entity${entityKey} = factory.${method}(${hydrateTargetExpr}, data${dataKey}, { initialized: true, merge: true, newEntity, convertCustomTypes, normalizeAccessors, schema });`);
|
|
150
186
|
}
|
|
151
187
|
ret.push(` }`);
|
|
152
188
|
ret.push(` }`);
|
|
153
189
|
if (prop.kind === ReferenceKind.ONE_TO_ONE) {
|
|
154
|
-
const meta2 = this.metadata.get(prop.
|
|
190
|
+
const meta2 = this.metadata.get(prop.targetMeta.class);
|
|
155
191
|
const prop2 = meta2.properties[prop.inversedBy || prop.mappedBy];
|
|
156
192
|
if (prop2 && !prop2.mapToPk) {
|
|
157
193
|
ret.push(` if (data${dataKey} && entity${entityKey} && !entity${entityKey}.${this.safeKey(prop2.name)}) {`);
|
|
@@ -169,7 +205,7 @@ export class ObjectHydrator extends Hydrator {
|
|
|
169
205
|
};
|
|
170
206
|
const hydrateToMany = (prop, dataKey, entityKey) => {
|
|
171
207
|
const ret = [];
|
|
172
|
-
ret.push(...this.createCollectionItemMapper(prop));
|
|
208
|
+
ret.push(...this.createCollectionItemMapper(prop, context));
|
|
173
209
|
ret.push(` if (data${dataKey} && !Array.isArray(data${dataKey}) && typeof data${dataKey} === 'object') {`);
|
|
174
210
|
ret.push(` data${dataKey} = [data${dataKey}];`);
|
|
175
211
|
ret.push(` }`);
|
|
@@ -252,10 +288,11 @@ export class ObjectHydrator extends Hydrator {
|
|
|
252
288
|
prop.targetMeta.polymorphs.forEach(childMeta => {
|
|
253
289
|
const childProp = prop.embeddedProps[prop.targetMeta.discriminatorColumn];
|
|
254
290
|
const childDataKey = prop.object ? dataKey + this.wrap(childProp.embedded[1]) : this.wrap(childProp.name);
|
|
291
|
+
context.set(childMeta.className, childMeta.class);
|
|
255
292
|
// weak comparison as we can have numbers that might have been converted to strings due to being object keys
|
|
256
293
|
ret.push(` if (data${childDataKey} == '${childMeta.discriminatorValue}') {`);
|
|
257
294
|
ret.push(` if (entity${entityKey} == null) {`);
|
|
258
|
-
ret.push(` entity${entityKey} = factory.createEmbeddable(
|
|
295
|
+
ret.push(` entity${entityKey} = factory.createEmbeddable(${childMeta.className}, embeddedData, { newEntity, convertCustomTypes, normalizeAccessors });`);
|
|
259
296
|
ret.push(` }`);
|
|
260
297
|
meta.props
|
|
261
298
|
.filter(p => p.embedded?.[0] === prop.name)
|
|
@@ -275,8 +312,10 @@ export class ObjectHydrator extends Hydrator {
|
|
|
275
312
|
});
|
|
276
313
|
}
|
|
277
314
|
else {
|
|
315
|
+
const targetKey = this.safeKey(`${prop.targetMeta.tableName}_${this.tmpIndex++}`);
|
|
316
|
+
context.set(targetKey, prop.targetMeta.class);
|
|
278
317
|
ret.push(` if (entity${entityKey} == null) {`);
|
|
279
|
-
ret.push(` entity${entityKey} = factory.createEmbeddable(
|
|
318
|
+
ret.push(` entity${entityKey} = factory.createEmbeddable(${targetKey}, embeddedData, { newEntity, convertCustomTypes, normalizeAccessors });`);
|
|
280
319
|
ret.push(` }`);
|
|
281
320
|
meta.props
|
|
282
321
|
.filter(p => p.embedded?.[0] === prop.name)
|
|
@@ -334,7 +373,7 @@ export class ObjectHydrator extends Hydrator {
|
|
|
334
373
|
}
|
|
335
374
|
}
|
|
336
375
|
else { // ReferenceKind.SCALAR
|
|
337
|
-
ret.push(...hydrateScalar(prop,
|
|
376
|
+
ret.push(...hydrateScalar(prop, path, dataKey));
|
|
338
377
|
}
|
|
339
378
|
if (this.config.get('forceUndefined')) {
|
|
340
379
|
ret.push(` if (data${dataKey} === null) entity${entityKey} = undefined;`);
|
|
@@ -347,12 +386,13 @@ export class ObjectHydrator extends Hydrator {
|
|
|
347
386
|
const code = `// compiled hydrator for entity ${meta.className} (${type + normalizeAccessors ? ' normalized' : ''})\n`
|
|
348
387
|
+ `return function(entity, data, factory, newEntity, convertCustomTypes, schema, parentSchema, normalizeAccessors) {\n`
|
|
349
388
|
+ `${lines.join('\n')}\n}`;
|
|
350
|
-
const
|
|
351
|
-
this.
|
|
389
|
+
const fnKey = `hydrator-${meta.uniqueName}-${type}-${normalizeAccessors}`;
|
|
390
|
+
const hydrator = Utils.createFunction(context, code, this.config.get('compiledFunctions'), fnKey);
|
|
391
|
+
this.hydrators[key].set(meta.class, hydrator);
|
|
352
392
|
return hydrator;
|
|
353
393
|
}
|
|
354
|
-
createCollectionItemMapper(prop) {
|
|
355
|
-
const meta = this.metadata.get(prop.
|
|
394
|
+
createCollectionItemMapper(prop, context) {
|
|
395
|
+
const meta = this.metadata.get(prop.targetMeta.class);
|
|
356
396
|
const lines = [];
|
|
357
397
|
lines.push(` const createCollectionItem_${this.safeKey(prop.name)} = (value, entity) => {`);
|
|
358
398
|
const prop2 = prop.targetMeta.properties[prop.mappedBy];
|
|
@@ -361,9 +401,11 @@ export class ObjectHydrator extends Hydrator {
|
|
|
361
401
|
lines.push(` value = { ...value, ['${prop2.name}']: Reference.wrapReference(entity, { ref: ${prop2.ref} }) };`);
|
|
362
402
|
lines.push(` }`);
|
|
363
403
|
}
|
|
364
|
-
|
|
404
|
+
const targetKey = this.safeKey(`${prop.targetMeta.tableName}_${this.tmpIndex++}`);
|
|
405
|
+
context.set(targetKey, prop.targetMeta.class);
|
|
406
|
+
lines.push(` if (isPrimaryKey(value, ${meta.compositePK})) return factory.createReference(${targetKey}, value, { convertCustomTypes, schema, normalizeAccessors, merge: true });`);
|
|
365
407
|
lines.push(` if (value && value.__entity) return value;`);
|
|
366
|
-
lines.push(` return factory.create(
|
|
408
|
+
lines.push(` return factory.create(${targetKey}, value, { newEntity, convertCustomTypes, schema, normalizeAccessors, merge: true });`);
|
|
367
409
|
lines.push(` }`);
|
|
368
410
|
return lines;
|
|
369
411
|
}
|
package/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @module core
|
|
4
4
|
*/
|
|
5
5
|
export { EntityMetadata, PrimaryKeyProp, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Config } from './typings.js';
|
|
6
|
-
export type { Constructor, ConnectionType, Dictionary, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, EntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty,
|
|
6
|
+
export type { CompiledFunctions, Constructor, ConnectionType, Dictionary, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, EntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, MigrationDiff, GenerateOptions, FilterObject, IEntityGenerator, ISeedManager, RequiredEntityData, CheckCallback, IndexCallback, FormulaCallback, FormulaTable, SchemaTable, SchemaColumns, SimpleColumnMeta, Rel, Ref, ScalarRef, EntityRef, ISchemaGenerator, UmzugMigration, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, EntityDataValue, FilterKey, EntityType, FromEntityType, Selected, IsSubset, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, FilterValue, MergeLoaded, MergeSelected, TypeConfig, AnyString, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, RequiredNullable, DefineConfig, Opt, Hidden, EntitySchemaWithMeta, InferEntity, CheckConstraint, GeneratedColumnCallback, FilterDef, EntityCtor, Subquery, PopulateHintOptions, Prefixes, } from './typings.js';
|
|
7
7
|
export * from './enums.js';
|
|
8
8
|
export * from './errors.js';
|
|
9
9
|
export * from './exceptions.js';
|
package/logging/colors.d.ts
CHANGED
package/logging/colors.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
&&
|
|
6
|
-
&& boolIfDefined(
|
|
1
|
+
import { getEnv } from '../utils/env-vars.js';
|
|
2
|
+
const bool = (k) => ['true', 't', '1'].includes(getEnv(k)?.toLowerCase() ?? '');
|
|
3
|
+
const boolIfDefined = (k) => getEnv(k) != null ? bool(k) : true;
|
|
4
|
+
const enabled = () => !bool('NO_COLOR')
|
|
5
|
+
&& !bool('MIKRO_ORM_NO_COLOR')
|
|
6
|
+
&& boolIfDefined('FORCE_COLOR')
|
|
7
|
+
&& boolIfDefined('MIKRO_ORM_COLORS');
|
|
7
8
|
const wrap = (fn) => (text) => enabled() ? fn(text) : text;
|
|
8
9
|
/** @internal */
|
|
9
10
|
export const colors = {
|
package/logging/inspect.js
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
let nodeInspect;
|
|
2
2
|
/** @internal */
|
|
3
3
|
export function inspect(value, options) {
|
|
4
|
-
|
|
5
|
-
/* v8 ignore else */
|
|
6
|
-
if (globalThis.process?.getBuiltinModule) {
|
|
7
|
-
nodeInspect = globalThis.process.getBuiltinModule('node:util').inspect;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
4
|
+
nodeInspect ??= globalThis.process?.getBuiltinModule?.('node:util').inspect;
|
|
10
5
|
/* v8 ignore else */
|
|
11
6
|
if (nodeInspect) {
|
|
12
7
|
return nodeInspect(value, options);
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import { EntityMetadata, type AnyEntity, type EntityKey, type Constructor, type DeepPartial, type EntityName, type EntityProperty, type CleanKeys, type ExpandProperty, type IsNever, type
|
|
2
|
-
import { ReferenceKind } from '../enums.js';
|
|
1
|
+
import { EntityMetadata, type AnyEntity, type EntityKey, type Constructor, type DeepPartial, type EntityName, type EntityProperty, type CleanKeys, type ExpandProperty, type IsNever, type EntityCtor } from '../typings.js';
|
|
2
|
+
import { type EventType, ReferenceKind } from '../enums.js';
|
|
3
|
+
import type { EventSubscriber } from '../events/EventSubscriber.js';
|
|
3
4
|
import { Type } from '../types/Type.js';
|
|
4
5
|
import type { PropertyOptions, ManyToOneOptions, OneToOneOptions, OneToManyOptions, ManyToManyOptions, EmbeddedOptions, EnumOptions, PrimaryKeyOptions, SerializedPrimaryKeyOptions, IndexOptions, UniqueOptions } from './types.js';
|
|
5
6
|
type TypeType = string | NumberConstructor | StringConstructor | BooleanConstructor | DateConstructor | ArrayConstructor | Constructor<Type<any>> | Type<any>;
|
|
6
7
|
type TypeDef<Target> = {
|
|
7
8
|
type: TypeType;
|
|
8
9
|
} | {
|
|
9
|
-
entity:
|
|
10
|
+
entity: () => EntityName<Target> | EntityName[];
|
|
10
11
|
};
|
|
11
12
|
type EmbeddedTypeDef<Target> = {
|
|
12
13
|
type: TypeType;
|
|
13
14
|
} | {
|
|
14
|
-
entity:
|
|
15
|
+
entity: () => EntityName<Target> | EntityName[];
|
|
15
16
|
};
|
|
16
17
|
export type EntitySchemaProperty<Target, Owner> = ({
|
|
17
18
|
kind: ReferenceKind.MANY_TO_ONE | 'm:1';
|
|
@@ -27,10 +28,10 @@ export type EntitySchemaProperty<Target, Owner> = ({
|
|
|
27
28
|
enum: true;
|
|
28
29
|
} & EnumOptions<Owner>) | (TypeDef<Target> & PropertyOptions<Owner>);
|
|
29
30
|
type OmitBaseProps<Entity, Base> = IsNever<Base> extends true ? Entity : Omit<Entity, keyof Base>;
|
|
30
|
-
export type EntitySchemaMetadata<Entity, Base = never
|
|
31
|
+
export type EntitySchemaMetadata<Entity, Base = never, Class extends EntityCtor = EntityCtor<Entity>> = Omit<Partial<EntityMetadata<Entity>>, 'name' | 'properties' | 'extends'> & ({
|
|
31
32
|
name: string;
|
|
32
33
|
} | {
|
|
33
|
-
class:
|
|
34
|
+
class: Class;
|
|
34
35
|
name?: string;
|
|
35
36
|
}) & {
|
|
36
37
|
extends?: EntityName<Base>;
|
|
@@ -38,17 +39,21 @@ export type EntitySchemaMetadata<Entity, Base = never> = Omit<Partial<EntityMeta
|
|
|
38
39
|
properties?: {
|
|
39
40
|
[Key in keyof OmitBaseProps<Entity, Base> as CleanKeys<OmitBaseProps<Entity, Base>, Key>]-?: EntitySchemaProperty<ExpandProperty<NonNullable<Entity[Key]>>, Entity>;
|
|
40
41
|
};
|
|
42
|
+
} & {
|
|
43
|
+
inheritance?: 'tpt';
|
|
41
44
|
};
|
|
42
|
-
export declare class EntitySchema<Entity = any, Base = never
|
|
45
|
+
export declare class EntitySchema<Entity = any, Base = never, Class extends EntityCtor = EntityCtor<Entity>> {
|
|
43
46
|
/**
|
|
44
47
|
* When schema links the entity class via `class` option, this registry allows the lookup from opposite side,
|
|
45
48
|
* so we can use the class in `entities` option just like the EntitySchema instance.
|
|
46
49
|
*/
|
|
47
|
-
static REGISTRY: Map<Partial<any>, EntitySchema<any, never
|
|
50
|
+
static REGISTRY: Map<Partial<any>, EntitySchema<any, never, EntityCtor<any>>>;
|
|
51
|
+
/** @internal Type-level marker for fast entity type inference */
|
|
52
|
+
readonly '~entity': Entity;
|
|
48
53
|
private readonly _meta;
|
|
49
54
|
private internal;
|
|
50
55
|
private initialized;
|
|
51
|
-
constructor(meta: EntitySchemaMetadata<Entity, Base>);
|
|
56
|
+
constructor(meta: EntitySchemaMetadata<Entity, Base, Class>);
|
|
52
57
|
static fromMetadata<T = AnyEntity, U = never>(meta: EntityMetadata<T> | DeepPartial<EntityMetadata<T>>): EntitySchema<T, U>;
|
|
53
58
|
addProperty(name: EntityKey<Entity>, type?: TypeType, options?: PropertyOptions<Entity> | EntityProperty<Entity>): void;
|
|
54
59
|
addEnum(name: EntityKey<Entity>, type?: TypeType, options?: EnumOptions<Entity>): void;
|
|
@@ -63,21 +68,46 @@ export declare class EntitySchema<Entity = any, Base = never> {
|
|
|
63
68
|
addIndex<Key extends string>(options: IndexOptions<Entity, Key>): void;
|
|
64
69
|
addUnique<Key extends string>(options: UniqueOptions<Entity, Key>): void;
|
|
65
70
|
setCustomRepository(repository: () => Constructor): void;
|
|
66
|
-
setExtends(base: EntityName
|
|
67
|
-
setClass(
|
|
68
|
-
get meta(): EntityMetadata<Entity>;
|
|
69
|
-
get name(): EntityName<Entity>;
|
|
71
|
+
setExtends(base: EntityName): void;
|
|
72
|
+
setClass(cls: Class): void;
|
|
73
|
+
get meta(): EntityMetadata<Entity, Class>;
|
|
74
|
+
get name(): string | EntityName<Entity>;
|
|
70
75
|
get tableName(): string;
|
|
76
|
+
get class(): Class;
|
|
71
77
|
get properties(): Record<string, any>;
|
|
78
|
+
new(...params: ConstructorParameters<Class>): Entity;
|
|
72
79
|
/**
|
|
73
80
|
* @internal
|
|
74
81
|
*/
|
|
75
82
|
init(): this;
|
|
83
|
+
/**
|
|
84
|
+
* Check if this entity is part of a TPT hierarchy by walking up the extends chain.
|
|
85
|
+
* This handles mid-level abstract entities (e.g., Animal -> Mammal -> Dog where Mammal is abstract).
|
|
86
|
+
*/
|
|
87
|
+
private isPartOfTPTHierarchy;
|
|
76
88
|
private initProperties;
|
|
77
89
|
private initPrimaryKeys;
|
|
78
90
|
private normalizeType;
|
|
79
91
|
private createProperty;
|
|
80
92
|
private rename;
|
|
81
93
|
private renameCompositeOptions;
|
|
94
|
+
/**
|
|
95
|
+
* Adds a lifecycle hook handler to the entity schema.
|
|
96
|
+
* This method allows registering hooks after the entity is defined,
|
|
97
|
+
* which can be useful for avoiding circular type references.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```ts
|
|
101
|
+
* export const Article = defineEntity({
|
|
102
|
+
* name: 'Article',
|
|
103
|
+
* properties: { ... },
|
|
104
|
+
* });
|
|
105
|
+
*
|
|
106
|
+
* Article.addHook('beforeCreate', async args => {
|
|
107
|
+
* args.entity.slug = args.entity.title.toLowerCase();
|
|
108
|
+
* });
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
addHook<Event extends EventType | `${EventType}`>(event: Event, handler: NonNullable<EventSubscriber<Entity>[Event]>): this;
|
|
82
112
|
}
|
|
83
113
|
export {};
|
package/metadata/EntitySchema.js
CHANGED
|
@@ -10,7 +10,7 @@ export class EntitySchema {
|
|
|
10
10
|
* so we can use the class in `entities` option just like the EntitySchema instance.
|
|
11
11
|
*/
|
|
12
12
|
static REGISTRY = new Map();
|
|
13
|
-
_meta
|
|
13
|
+
_meta;
|
|
14
14
|
internal = false;
|
|
15
15
|
initialized = false;
|
|
16
16
|
constructor(meta) {
|
|
@@ -18,15 +18,14 @@ export class EntitySchema {
|
|
|
18
18
|
if (meta.name) {
|
|
19
19
|
meta.abstract ??= false;
|
|
20
20
|
}
|
|
21
|
+
this._meta = new EntityMetadata({
|
|
22
|
+
className: meta.name,
|
|
23
|
+
...meta,
|
|
24
|
+
});
|
|
25
|
+
this._meta.root ??= this._meta;
|
|
21
26
|
if (meta.class && !meta.internal) {
|
|
22
27
|
EntitySchema.REGISTRY.set(meta.class, this);
|
|
23
28
|
}
|
|
24
|
-
if (meta.tableName || meta.collection) {
|
|
25
|
-
Utils.renameKey(meta, 'tableName', 'collection');
|
|
26
|
-
meta.tableName = meta.collection;
|
|
27
|
-
}
|
|
28
|
-
Object.assign(this._meta, { className: meta.name }, meta);
|
|
29
|
-
this._meta.root ??= this._meta;
|
|
30
29
|
}
|
|
31
30
|
static fromMetadata(meta) {
|
|
32
31
|
const schema = new EntitySchema({ ...meta, internal: true });
|
|
@@ -35,7 +34,7 @@ export class EntitySchema {
|
|
|
35
34
|
}
|
|
36
35
|
addProperty(name, type, options = {}) {
|
|
37
36
|
this.renameCompositeOptions(name, options);
|
|
38
|
-
const prop = { name, kind: ReferenceKind.SCALAR, ...options,
|
|
37
|
+
const prop = { name, kind: ReferenceKind.SCALAR, ...options, ...this.normalizeType(options, type) };
|
|
39
38
|
if (type && Type.isMappedType(type.prototype)) {
|
|
40
39
|
prop.type = type;
|
|
41
40
|
}
|
|
@@ -85,8 +84,8 @@ export class EntitySchema {
|
|
|
85
84
|
}
|
|
86
85
|
this._meta.properties[name] = {
|
|
87
86
|
name,
|
|
88
|
-
type: this.normalizeType(options),
|
|
89
87
|
kind: ReferenceKind.EMBEDDED,
|
|
88
|
+
...this.normalizeType(options),
|
|
90
89
|
...options,
|
|
91
90
|
};
|
|
92
91
|
}
|
|
@@ -151,19 +150,29 @@ export class EntitySchema {
|
|
|
151
150
|
setExtends(base) {
|
|
152
151
|
this._meta.extends = base;
|
|
153
152
|
}
|
|
154
|
-
setClass(
|
|
155
|
-
const
|
|
156
|
-
this._meta.class
|
|
157
|
-
this._meta.
|
|
158
|
-
this._meta.
|
|
153
|
+
setClass(cls) {
|
|
154
|
+
const oldClass = this._meta.class;
|
|
155
|
+
const sameClass = this._meta.class === cls;
|
|
156
|
+
this._meta.class = cls;
|
|
157
|
+
this._meta.prototype = cls.prototype;
|
|
158
|
+
this._meta.className = this._meta.name ?? cls.name;
|
|
159
159
|
if (!sameClass || !this._meta.constructorParams) {
|
|
160
|
-
this._meta.constructorParams = Utils.getConstructorParams(
|
|
160
|
+
this._meta.constructorParams = Utils.getConstructorParams(cls);
|
|
161
161
|
}
|
|
162
162
|
if (!this.internal) {
|
|
163
|
-
|
|
163
|
+
// Remove old class from registry if it's being replaced with a different class
|
|
164
|
+
if (oldClass && oldClass !== cls && EntitySchema.REGISTRY.get(oldClass) === this) {
|
|
165
|
+
EntitySchema.REGISTRY.delete(oldClass);
|
|
166
|
+
}
|
|
167
|
+
EntitySchema.REGISTRY.set(cls, this);
|
|
164
168
|
}
|
|
165
|
-
|
|
166
|
-
|
|
169
|
+
const base = Object.getPrototypeOf(cls);
|
|
170
|
+
// Only set extends if the parent is NOT the auto-generated class for this same entity.
|
|
171
|
+
// When the user extends the auto-generated class (from defineEntity without a class option)
|
|
172
|
+
// and registers their custom class via setClass, we don't want to discover the
|
|
173
|
+
// auto-generated class as a separate parent entity.
|
|
174
|
+
if (base !== BaseEntity && base.name !== this._meta.className) {
|
|
175
|
+
this._meta.extends ??= base.name ? base : undefined;
|
|
167
176
|
}
|
|
168
177
|
}
|
|
169
178
|
get meta() {
|
|
@@ -175,9 +184,15 @@ export class EntitySchema {
|
|
|
175
184
|
get tableName() {
|
|
176
185
|
return this._meta.tableName;
|
|
177
186
|
}
|
|
187
|
+
get class() {
|
|
188
|
+
return this._meta.class;
|
|
189
|
+
}
|
|
178
190
|
get properties() {
|
|
179
191
|
return this._meta.properties;
|
|
180
192
|
}
|
|
193
|
+
new(...params) {
|
|
194
|
+
return new this._meta.class(...params);
|
|
195
|
+
}
|
|
181
196
|
/**
|
|
182
197
|
* @internal
|
|
183
198
|
*/
|
|
@@ -185,19 +200,16 @@ export class EntitySchema {
|
|
|
185
200
|
if (this.initialized) {
|
|
186
201
|
return this;
|
|
187
202
|
}
|
|
188
|
-
if (!this._meta.class) {
|
|
189
|
-
const name = this.name;
|
|
190
|
-
this._meta.class = ({ [name]: class {
|
|
191
|
-
} })[name];
|
|
192
|
-
}
|
|
193
203
|
this.setClass(this._meta.class);
|
|
194
|
-
|
|
204
|
+
// Abstract TPT entities keep their name because they have their own table
|
|
205
|
+
const isTPT = this._meta.inheritance === 'tpt' || this.isPartOfTPTHierarchy();
|
|
206
|
+
if (this._meta.abstract && !this._meta.discriminatorColumn && !isTPT) {
|
|
195
207
|
delete this._meta.name;
|
|
196
208
|
}
|
|
197
209
|
const tableName = this._meta.collection ?? this._meta.tableName;
|
|
198
210
|
if (tableName?.includes('.') && !this._meta.schema) {
|
|
199
211
|
this._meta.schema = tableName.substring(0, tableName.indexOf('.'));
|
|
200
|
-
this._meta.
|
|
212
|
+
this._meta.tableName = tableName.substring(tableName.indexOf('.') + 1);
|
|
201
213
|
}
|
|
202
214
|
this.initProperties();
|
|
203
215
|
this.initPrimaryKeys();
|
|
@@ -206,6 +218,24 @@ export class EntitySchema {
|
|
|
206
218
|
this.initialized = true;
|
|
207
219
|
return this;
|
|
208
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* Check if this entity is part of a TPT hierarchy by walking up the extends chain.
|
|
223
|
+
* This handles mid-level abstract entities (e.g., Animal -> Mammal -> Dog where Mammal is abstract).
|
|
224
|
+
*/
|
|
225
|
+
isPartOfTPTHierarchy() {
|
|
226
|
+
let parent = this._meta.extends;
|
|
227
|
+
while (parent) {
|
|
228
|
+
const parentSchema = parent instanceof EntitySchema ? parent : EntitySchema.REGISTRY.get(parent);
|
|
229
|
+
if (!parentSchema) {
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
if (parentSchema._meta.inheritance === 'tpt') {
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
parent = parentSchema._meta.extends;
|
|
236
|
+
}
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
209
239
|
initProperties() {
|
|
210
240
|
Utils.entries(this._meta.properties).forEach(([name, options]) => {
|
|
211
241
|
if (Type.isMappedType(options.type)) {
|
|
@@ -263,12 +293,15 @@ export class EntitySchema {
|
|
|
263
293
|
}
|
|
264
294
|
normalizeType(options, type) {
|
|
265
295
|
if ('entity' in options) {
|
|
296
|
+
/* v8 ignore next */
|
|
266
297
|
if (typeof options.entity === 'string') {
|
|
267
|
-
|
|
298
|
+
throw new Error(`Relation target needs to be an entity class or EntitySchema instance, string '${options.entity}' given instead for ${this._meta.className}.${options.name}.`);
|
|
268
299
|
}
|
|
269
300
|
else if (options.entity) {
|
|
270
301
|
const tmp = options.entity();
|
|
271
302
|
type = options.type = Array.isArray(tmp) ? tmp.map(t => Utils.className(t)).sort().join(' | ') : Utils.className(tmp);
|
|
303
|
+
const target = tmp instanceof EntitySchema ? tmp.meta.class : tmp;
|
|
304
|
+
return { type, target };
|
|
272
305
|
}
|
|
273
306
|
}
|
|
274
307
|
if (type instanceof Function) {
|
|
@@ -277,7 +310,7 @@ export class EntitySchema {
|
|
|
277
310
|
if (['String', 'Number', 'Boolean', 'Array'].includes(type)) {
|
|
278
311
|
type = type.toLowerCase();
|
|
279
312
|
}
|
|
280
|
-
return type;
|
|
313
|
+
return { type };
|
|
281
314
|
}
|
|
282
315
|
createProperty(kind, options) {
|
|
283
316
|
return {
|
|
@@ -307,4 +340,26 @@ export class EntitySchema {
|
|
|
307
340
|
this.rename(options, 'referenceColumnName', 'referencedColumnNames');
|
|
308
341
|
this.rename(options, 'columnType', 'columnTypes');
|
|
309
342
|
}
|
|
343
|
+
/**
|
|
344
|
+
* Adds a lifecycle hook handler to the entity schema.
|
|
345
|
+
* This method allows registering hooks after the entity is defined,
|
|
346
|
+
* which can be useful for avoiding circular type references.
|
|
347
|
+
*
|
|
348
|
+
* @example
|
|
349
|
+
* ```ts
|
|
350
|
+
* export const Article = defineEntity({
|
|
351
|
+
* name: 'Article',
|
|
352
|
+
* properties: { ... },
|
|
353
|
+
* });
|
|
354
|
+
*
|
|
355
|
+
* Article.addHook('beforeCreate', async args => {
|
|
356
|
+
* args.entity.slug = args.entity.title.toLowerCase();
|
|
357
|
+
* });
|
|
358
|
+
* ```
|
|
359
|
+
*/
|
|
360
|
+
addHook(event, handler) {
|
|
361
|
+
this._meta.hooks[event] ??= [];
|
|
362
|
+
this._meta.hooks[event].push(handler);
|
|
363
|
+
return this;
|
|
364
|
+
}
|
|
310
365
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type EntityClass, EntityMetadata } from '../typings.js';
|
|
1
|
+
import { type EntityClass, EntityMetadata, type EntityName } from '../typings.js';
|
|
2
2
|
import type { Configuration } from '../utils/Configuration.js';
|
|
3
3
|
import { MetadataStorage } from './MetadataStorage.js';
|
|
4
4
|
import { EntitySchema } from './EntitySchema.js';
|
|
@@ -16,7 +16,6 @@ export declare class MetadataDiscovery {
|
|
|
16
16
|
constructor(metadata: MetadataStorage, platform: Platform, config: Configuration);
|
|
17
17
|
discover(preferTs?: boolean): Promise<MetadataStorage>;
|
|
18
18
|
discoverSync(): MetadataStorage;
|
|
19
|
-
validateDiscovered(metadata: EntityMetadata[]): void;
|
|
20
19
|
private mapDiscoveredEntities;
|
|
21
20
|
private initAccessors;
|
|
22
21
|
processDiscoveredEntities(discovered: EntityMetadata[]): EntityMetadata[];
|
|
@@ -24,7 +23,7 @@ export declare class MetadataDiscovery {
|
|
|
24
23
|
private discoverMissingTargets;
|
|
25
24
|
private tryDiscoverTargets;
|
|
26
25
|
discoverReferences<T>(refs: Iterable<EntityClass<T> | EntitySchema<T>>, validate?: boolean): EntityMetadata<T>[];
|
|
27
|
-
reset(
|
|
26
|
+
reset<T>(entityName: EntityName<T>): void;
|
|
28
27
|
private getSchema;
|
|
29
28
|
private getRootEntity;
|
|
30
29
|
private discoverEntity;
|
|
@@ -35,6 +34,7 @@ export declare class MetadataDiscovery {
|
|
|
35
34
|
private initManyToOneFieldName;
|
|
36
35
|
private initManyToManyFieldName;
|
|
37
36
|
private initManyToManyFields;
|
|
37
|
+
private isExplicitTableName;
|
|
38
38
|
private initManyToOneFields;
|
|
39
39
|
private initOneToManyFields;
|
|
40
40
|
private processEntity;
|
|
@@ -42,15 +42,72 @@ export declare class MetadataDiscovery {
|
|
|
42
42
|
private initFactoryField;
|
|
43
43
|
private ensureCorrectFKOrderInPivotEntity;
|
|
44
44
|
private definePivotTableEntity;
|
|
45
|
+
/**
|
|
46
|
+
* Create a scalar property for a pivot table column.
|
|
47
|
+
*/
|
|
48
|
+
private createPivotScalarProperty;
|
|
49
|
+
/**
|
|
50
|
+
* Get column types for an entity's primary keys, initializing them if needed.
|
|
51
|
+
*/
|
|
52
|
+
private getPrimaryKeyColumnTypes;
|
|
53
|
+
/**
|
|
54
|
+
* Add missing FK columns for a polymorphic entity to an existing pivot table.
|
|
55
|
+
*/
|
|
56
|
+
private addPolymorphicPivotColumns;
|
|
57
|
+
/**
|
|
58
|
+
* Define properties for a polymorphic pivot table.
|
|
59
|
+
*/
|
|
60
|
+
private definePolymorphicPivotProperties;
|
|
61
|
+
/**
|
|
62
|
+
* Create a virtual M:1 relation from pivot to a polymorphic owner entity.
|
|
63
|
+
* This enables single-query join loading for inverse-side polymorphic M:N.
|
|
64
|
+
*/
|
|
65
|
+
private definePolymorphicOwnerRelation;
|
|
45
66
|
private defineFixedOrderProperty;
|
|
46
67
|
private definePivotProperty;
|
|
47
68
|
private autoWireBidirectionalProperties;
|
|
48
69
|
private defineBaseEntityProperties;
|
|
49
70
|
private initPolyEmbeddables;
|
|
71
|
+
private initPolymorphicRelation;
|
|
50
72
|
private initEmbeddables;
|
|
51
73
|
private initSingleTableInheritance;
|
|
74
|
+
/**
|
|
75
|
+
* First pass of TPT initialization: sets up hierarchy relationships
|
|
76
|
+
* (inheritanceType, tptParent, tptChildren) before properties have fieldNames.
|
|
77
|
+
*/
|
|
78
|
+
private initTPTRelationships;
|
|
79
|
+
/**
|
|
80
|
+
* Second pass of TPT initialization: re-resolves metadata references after fieldNames
|
|
81
|
+
* are set, syncs to registry metadata, and sets up discriminators.
|
|
82
|
+
*/
|
|
83
|
+
private finalizeTPTInheritance;
|
|
84
|
+
/**
|
|
85
|
+
* Initialize TPT discriminator map and virtual discriminator property.
|
|
86
|
+
* Unlike STI where the discriminator is a persisted column, TPT discriminator is computed
|
|
87
|
+
* at query time using CASE WHEN expressions based on which child table has data.
|
|
88
|
+
*/
|
|
89
|
+
private initTPTDiscriminator;
|
|
90
|
+
/**
|
|
91
|
+
* Recursively collect all TPT descendants (children, grandchildren, etc.)
|
|
92
|
+
*/
|
|
93
|
+
private collectAllTPTDescendants;
|
|
94
|
+
/**
|
|
95
|
+
* Computes ownProps for TPT entities - only properties defined in THIS entity,
|
|
96
|
+
* not inherited from parent. Also creates synthetic join properties for parent/child relationships.
|
|
97
|
+
*
|
|
98
|
+
* Called multiple times during discovery as metadata is progressively built.
|
|
99
|
+
* Each pass overwrites earlier results to reflect the final state of properties.
|
|
100
|
+
*/
|
|
101
|
+
private computeTPTOwnProps;
|
|
102
|
+
/** Returns the depth of a TPT entity in its hierarchy (0 for root). */
|
|
103
|
+
private getTPTDepth;
|
|
104
|
+
/**
|
|
105
|
+
* Find the direct TPT parent entity for the given entity.
|
|
106
|
+
*/
|
|
107
|
+
private getTPTParent;
|
|
52
108
|
private createDiscriminatorProperty;
|
|
53
109
|
private initAutoincrement;
|
|
110
|
+
private createSchemaTable;
|
|
54
111
|
private initCheckConstraints;
|
|
55
112
|
private initGeneratedColumn;
|
|
56
113
|
private getDefaultVersionValue;
|