@mikro-orm/core 7.2.0-dev.2 → 7.2.0-dev.21
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 +42 -8
- package/EntityManager.js +256 -70
- package/MikroORM.d.ts +4 -0
- package/MikroORM.js +9 -0
- package/cache/CacheAdapter.d.ts +6 -4
- package/cache/FileCacheAdapter.d.ts +1 -1
- package/cache/FileCacheAdapter.js +7 -2
- package/connections/Connection.d.ts +10 -1
- package/connections/Connection.js +9 -0
- package/drivers/DatabaseDriver.d.ts +17 -1
- package/drivers/DatabaseDriver.js +203 -41
- package/drivers/IDatabaseDriver.d.ts +1 -0
- package/entity/Collection.js +4 -2
- package/entity/EntityFactory.js +6 -0
- package/entity/EntityLoader.d.ts +7 -1
- package/entity/EntityLoader.js +46 -11
- package/entity/EntityRepository.d.ts +4 -5
- package/entity/EntityRepository.js +7 -2
- package/entity/defineEntity.d.ts +48 -14
- package/entity/defineEntity.js +32 -1
- package/enums.d.ts +5 -1
- package/enums.js +2 -0
- package/errors.d.ts +36 -0
- package/errors.js +90 -0
- package/events/EventManager.js +6 -3
- package/exceptions.d.ts +5 -0
- package/exceptions.js +5 -0
- package/hydration/ObjectHydrator.d.ts +2 -0
- package/hydration/ObjectHydrator.js +15 -8
- package/index.d.ts +1 -1
- package/metadata/EntitySchema.js +5 -2
- package/metadata/MetadataDiscovery.d.ts +3 -0
- package/metadata/MetadataDiscovery.js +161 -28
- package/metadata/MetadataProvider.js +1 -1
- package/metadata/MetadataStorage.d.ts +4 -3
- package/metadata/MetadataStorage.js +32 -2
- package/metadata/Routine.js +4 -1
- package/metadata/types.d.ts +19 -3
- package/naming-strategy/AbstractNamingStrategy.js +2 -1
- package/naming-strategy/NamingStrategy.d.ts +2 -1
- package/package.json +1 -1
- package/platforms/Platform.d.ts +24 -3
- package/platforms/Platform.js +63 -1
- package/types/BigIntType.d.ts +1 -0
- package/types/BigIntType.js +23 -0
- package/types/DateTimeType.d.ts +1 -0
- package/types/DateTimeType.js +8 -0
- package/types/StringType.d.ts +14 -3
- package/types/StringType.js +34 -4
- package/types/TextType.d.ts +2 -4
- package/types/TextType.js +2 -8
- package/types/Type.d.ts +11 -0
- package/types/Type.js +4 -4
- package/types/index.d.ts +2 -2
- package/typings.d.ts +58 -2
- package/typings.js +24 -1
- package/unit-of-work/ChangeSet.js +10 -7
- package/unit-of-work/ChangeSetPersister.js +32 -20
- package/unit-of-work/UnitOfWork.js +11 -4
- package/utils/AbstractMigrator.d.ts +1 -1
- package/utils/AbstractMigrator.js +3 -2
- package/utils/Configuration.d.ts +15 -1
- package/utils/Configuration.js +13 -2
- package/utils/Cursor.d.ts +2 -0
- package/utils/Cursor.js +44 -39
- package/utils/DataloaderUtils.js +2 -1
- package/utils/EntityComparator.d.ts +2 -0
- package/utils/EntityComparator.js +11 -4
- package/utils/QueryHelper.d.ts +17 -0
- package/utils/QueryHelper.js +100 -4
- package/utils/RawQueryFragment.d.ts +6 -0
- package/utils/RawQueryFragment.js +15 -6
- package/utils/RequestContext.d.ts +2 -2
- package/utils/RequestContext.js +11 -2
- package/utils/TransactionManager.d.ts +6 -0
- package/utils/TransactionManager.js +36 -3
- package/utils/Utils.d.ts +14 -2
- package/utils/Utils.js +36 -6
- package/utils/clone.js +6 -0
- package/utils/env-vars.js +1 -0
- package/utils/index.d.ts +1 -0
- package/utils/index.js +1 -0
- package/utils/rls-utils.d.ts +35 -0
- package/utils/rls-utils.js +97 -0
- package/utils/upsert-utils.d.ts +9 -1
- package/utils/upsert-utils.js +26 -3
|
@@ -165,10 +165,14 @@ export class MetadataDiscovery {
|
|
|
165
165
|
filtered.forEach(meta => this.initAutoincrement(meta)); // once again after we init custom types
|
|
166
166
|
filtered.forEach(meta => this.initCheckConstraints(meta));
|
|
167
167
|
filtered.forEach(meta => this.initTriggers(meta));
|
|
168
|
-
|
|
168
|
+
// filter names are load-bearing for RLS (policy and session variable names), backfill from the dictionary key
|
|
169
|
+
filtered.forEach(meta => Object.entries(meta.filters).forEach(([key, filter]) => (filter.name ??= key)));
|
|
170
|
+
filtered.forEach(meta => this.initPolicies(meta));
|
|
171
|
+
forEachProp((m, p) => {
|
|
169
172
|
this.initDefaultValue(p);
|
|
170
173
|
this.inferTypeFromDefault(p);
|
|
171
174
|
this.initRelation(p);
|
|
175
|
+
this.initThroughRelation(m, p);
|
|
172
176
|
this.initColumnType(p);
|
|
173
177
|
});
|
|
174
178
|
forEachProp((m, p) => this.initIndexes(m, p));
|
|
@@ -212,14 +216,18 @@ export class MetadataDiscovery {
|
|
|
212
216
|
.replace(/Array<(.*)>/, '$1') // unwrap array
|
|
213
217
|
.replace(/\[]$/, '') // remove array suffix
|
|
214
218
|
.replace(/\((.*)\)/, '$1'); // unwrap union types
|
|
219
|
+
// Names can be ambiguous when a minifier mangles two classes to the same name,
|
|
220
|
+
// so class references also need to be checked by identity.
|
|
221
|
+
const discoveredByIdentity = (target) => {
|
|
222
|
+
const cls = EntitySchema.is(target) ? target.meta.class : target;
|
|
223
|
+
return typeof cls !== 'function' || this.#discovered.some(m => m.class === cls);
|
|
224
|
+
};
|
|
215
225
|
const missing = [];
|
|
216
226
|
this.#discovered.forEach(meta => Object.values(meta.properties).forEach(prop => {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
const target = typeof
|
|
220
|
-
|
|
221
|
-
: pivotEntity;
|
|
222
|
-
if (!this.#discovered.find(m => m.className === Utils.className(target))) {
|
|
227
|
+
const indirect = (prop.kind === ReferenceKind.MANY_TO_MANY ? prop.pivotEntity : prop.through);
|
|
228
|
+
if (indirect) {
|
|
229
|
+
const target = typeof indirect === 'function' && !indirect.prototype ? indirect() : indirect;
|
|
230
|
+
if (!this.#discovered.find(m => m.className === Utils.className(target)) || !discoveredByIdentity(target)) {
|
|
223
231
|
missing.push(target);
|
|
224
232
|
}
|
|
225
233
|
}
|
|
@@ -227,7 +235,8 @@ export class MetadataDiscovery {
|
|
|
227
235
|
const target = typeof prop.entity === 'function' && !prop.entity.prototype ? prop.entity() : prop.type;
|
|
228
236
|
if (!unwrap(prop.type)
|
|
229
237
|
.split(/ ?\| ?/)
|
|
230
|
-
.every(type => this.#discovered.find(m => m.className === type))
|
|
238
|
+
.every(type => this.#discovered.find(m => m.className === type)) ||
|
|
239
|
+
!Utils.asArray(target).every(discoveredByIdentity)) {
|
|
231
240
|
missing.push(...Utils.asArray(target));
|
|
232
241
|
}
|
|
233
242
|
}
|
|
@@ -275,9 +284,11 @@ export class MetadataDiscovery {
|
|
|
275
284
|
continue;
|
|
276
285
|
}
|
|
277
286
|
parent = Object.getPrototypeOf(meta.class);
|
|
278
|
-
// Skip if parent is the auto-generated base class for the same entity (from setClass usage)
|
|
287
|
+
// Skip if parent is the auto-generated base class for the same entity (from setClass usage).
|
|
288
|
+
// A parent carrying its own decorator metadata is a real base class even when a minifier
|
|
289
|
+
// mangles it to the same name as the child.
|
|
279
290
|
if (parent.name !== '' &&
|
|
280
|
-
parent.name !== meta.className &&
|
|
291
|
+
(parent.name !== meta.className || Object.hasOwn(parent, MetadataStorage.META_SYMBOL)) &&
|
|
281
292
|
!this.#metadata.has(parent) &&
|
|
282
293
|
parent !== BaseEntity) {
|
|
283
294
|
this.discoverReferences([parent], false);
|
|
@@ -311,7 +322,12 @@ export class MetadataDiscovery {
|
|
|
311
322
|
const cls = entity;
|
|
312
323
|
const path = cls[MetadataStorage.PATH_SYMBOL];
|
|
313
324
|
if (path) {
|
|
314
|
-
|
|
325
|
+
// Prefer the metadata stored on the class reference, the `className-path` key can
|
|
326
|
+
// collide when a minifier mangles two classes to the same name.
|
|
327
|
+
const stored = Object.hasOwn(cls, MetadataStorage.META_SYMBOL)
|
|
328
|
+
? cls[MetadataStorage.META_SYMBOL]
|
|
329
|
+
: MetadataStorage.getMetadata(cls.name, path);
|
|
330
|
+
const meta = Utils.copy(stored, false);
|
|
315
331
|
meta.path = path;
|
|
316
332
|
this.#metadata.set(cls, meta);
|
|
317
333
|
}
|
|
@@ -427,7 +443,18 @@ export class MetadataDiscovery {
|
|
|
427
443
|
if (prop.kind === ReferenceKind.SCALAR || prop.kind === ReferenceKind.EMBEDDED) {
|
|
428
444
|
prop.fieldNames = [this.#namingStrategy.propertyToColumnName(prop.name, object)];
|
|
429
445
|
}
|
|
430
|
-
else if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
|
|
446
|
+
else if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && prop.polymorphic) {
|
|
447
|
+
if (prop.targetMeta) {
|
|
448
|
+
// same layout as `initManyToOneFields` builds later: `[discriminatorColumn, ...fkIdColumns]`
|
|
449
|
+
const pkFields = prop.targetMeta.getPrimaryProps().flatMap(pk => {
|
|
450
|
+
this.initFieldName(pk);
|
|
451
|
+
return pk.fieldNames;
|
|
452
|
+
});
|
|
453
|
+
const idColumns = pkFields.map(fieldName => this.#namingStrategy.joinKeyColumnName(prop.discriminator, fieldName, pkFields.length > 1));
|
|
454
|
+
prop.fieldNames = [prop.discriminatorColumn, ...idColumns];
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
else if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind)) {
|
|
431
458
|
prop.fieldNames = this.initManyToOneFieldName(prop, prop.name);
|
|
432
459
|
}
|
|
433
460
|
else if (prop.kind === ReferenceKind.MANY_TO_MANY && prop.owner) {
|
|
@@ -437,10 +464,13 @@ export class MetadataDiscovery {
|
|
|
437
464
|
initManyToOneFieldName(prop, name) {
|
|
438
465
|
const meta2 = prop.targetMeta;
|
|
439
466
|
const ret = [];
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
467
|
+
// with `targetKey` on a composite PK target, derive the FK field name from that property
|
|
468
|
+
// instead of the PKs (simple PK targets keep the PK based naming for backwards compatibility)
|
|
469
|
+
const referencedKeys = prop.targetKey && meta2.compositePK ? [prop.targetKey] : meta2.primaryKeys;
|
|
470
|
+
for (const referencedKey of referencedKeys) {
|
|
471
|
+
this.initFieldName(meta2.properties[referencedKey]);
|
|
472
|
+
for (const fieldName of meta2.properties[referencedKey].fieldNames) {
|
|
473
|
+
ret.push(this.#namingStrategy.joinKeyColumnName(name, fieldName, !prop.targetKey && meta2.compositePK));
|
|
444
474
|
}
|
|
445
475
|
}
|
|
446
476
|
return ret;
|
|
@@ -834,7 +864,7 @@ export class MetadataDiscovery {
|
|
|
834
864
|
pivotMeta.properties[primaryProp.name] = primaryProp;
|
|
835
865
|
pivotMeta.compositePK = false;
|
|
836
866
|
}
|
|
837
|
-
const discriminatorProp = this.createPivotScalarProperty(discriminatorColumn, [this.#platform.getVarcharTypeDeclarationSQL(prop)], [discriminatorColumn], { type: 'string', primary: !
|
|
867
|
+
const discriminatorProp = this.createPivotScalarProperty(discriminatorColumn, [this.#platform.getVarcharTypeDeclarationSQL(prop)], [discriminatorColumn], { type: 'string', primary: !prop.fixedOrder, nullable: false });
|
|
838
868
|
this.initFieldName(discriminatorProp);
|
|
839
869
|
pivotMeta.properties[discriminatorColumn] = discriminatorProp;
|
|
840
870
|
const columnTypes = this.getPrimaryKeyColumnTypes(meta);
|
|
@@ -849,7 +879,7 @@ export class MetadataDiscovery {
|
|
|
849
879
|
pivotMeta.properties[prop.discriminator] = this.createPivotScalarProperty(prop.discriminator, columnTypes, [...prop.joinColumns], { type: meta.className, persist: false });
|
|
850
880
|
}
|
|
851
881
|
else {
|
|
852
|
-
pivotMeta.properties[prop.discriminator] = this.createPivotScalarProperty(prop.discriminator, columnTypes, [...prop.joinColumns], { type: meta.className, primary:
|
|
882
|
+
pivotMeta.properties[prop.discriminator] = this.createPivotScalarProperty(prop.discriminator, columnTypes, [...prop.joinColumns], { type: meta.className, primary: !prop.fixedOrder, nullable: false });
|
|
853
883
|
}
|
|
854
884
|
pivotMeta.properties[targetMeta.className + '_inverse'] = this.definePivotProperty(prop, targetMeta.className + '_inverse', targetMeta.class, prop.discriminator, false, false);
|
|
855
885
|
// Create virtual M:1 relation to the polymorphic owner for single-query join loading
|
|
@@ -871,11 +901,11 @@ export class MetadataDiscovery {
|
|
|
871
901
|
const discriminatorColumn = prop.discriminatorColumn;
|
|
872
902
|
const targets = prop.polymorphTargets;
|
|
873
903
|
pivotMeta.properties[meta.name + '_owner'] = this.definePivotProperty(prop, meta.name + '_owner', meta.class, prop.discriminator, true, false);
|
|
874
|
-
const discriminatorProp = this.createPivotScalarProperty(discriminatorColumn, [this.#platform.getVarcharTypeDeclarationSQL(prop)], [discriminatorColumn], { type: 'string', primary:
|
|
904
|
+
const discriminatorProp = this.createPivotScalarProperty(discriminatorColumn, [this.#platform.getVarcharTypeDeclarationSQL(prop)], [discriminatorColumn], { type: 'string', primary: !prop.fixedOrder, nullable: false });
|
|
875
905
|
this.initFieldName(discriminatorProp);
|
|
876
906
|
pivotMeta.properties[discriminatorColumn] = discriminatorProp;
|
|
877
907
|
const firstTargetColumnTypes = this.getPrimaryKeyColumnTypes(targets[0]);
|
|
878
|
-
pivotMeta.properties[prop.discriminator] = this.createPivotScalarProperty(prop.discriminator, firstTargetColumnTypes, [...prop.inverseJoinColumns], { type: targets[0].className, primary:
|
|
908
|
+
pivotMeta.properties[prop.discriminator] = this.createPivotScalarProperty(prop.discriminator, firstTargetColumnTypes, [...prop.inverseJoinColumns], { type: targets[0].className, primary: !prop.fixedOrder, nullable: false });
|
|
879
909
|
pivotMeta.polymorphicDiscriminatorMap ??= {};
|
|
880
910
|
for (const targetMeta of targets) {
|
|
881
911
|
const relationName = `${prop.discriminator}_${targetMeta.tableName}`;
|
|
@@ -942,6 +972,11 @@ export class MetadataDiscovery {
|
|
|
942
972
|
return primaryProp;
|
|
943
973
|
}
|
|
944
974
|
definePivotProperty(prop, name, type, inverse, owner, selfReferencing) {
|
|
975
|
+
let index = prop.index ?? this.#platform.indexForeignKeys();
|
|
976
|
+
if (owner && prop.index) {
|
|
977
|
+
// owner join columns are the leading prefix of the composite PK, so an explicit `index` only applies to them with `fixedOrder`; a custom index name always belongs to the inverse side
|
|
978
|
+
index = prop.fixedOrder ? true : this.#platform.indexForeignKeys();
|
|
979
|
+
}
|
|
945
980
|
const ret = {
|
|
946
981
|
name,
|
|
947
982
|
type: Utils.className(type),
|
|
@@ -950,7 +985,7 @@ export class MetadataDiscovery {
|
|
|
950
985
|
cascade: [Cascade.ALL],
|
|
951
986
|
fixedOrder: prop.fixedOrder,
|
|
952
987
|
fixedOrderColumn: prop.fixedOrderColumn,
|
|
953
|
-
index
|
|
988
|
+
index,
|
|
954
989
|
primary: !prop.fixedOrder,
|
|
955
990
|
autoincrement: false,
|
|
956
991
|
updateRule: prop.updateRule,
|
|
@@ -1036,11 +1071,18 @@ export class MetadataDiscovery {
|
|
|
1036
1071
|
}
|
|
1037
1072
|
// TPT children have their own tables that don't contain the parent's columns,
|
|
1038
1073
|
// so propagating parent indexes/uniques/checks/triggers would target missing columns.
|
|
1074
|
+
// deep equality, as the subclass items might be copies of the base class ones (e.g. with TC39 decorators)
|
|
1039
1075
|
if (meta.inheritanceType !== 'tpt' || !meta.tptParent) {
|
|
1040
|
-
meta.indexes = Utils.unique([...base.indexes, ...meta.indexes]);
|
|
1041
|
-
meta.uniques = Utils.unique([...base.uniques, ...meta.uniques]);
|
|
1042
|
-
meta.checks = Utils.unique([...base.checks, ...meta.checks]);
|
|
1043
|
-
meta.triggers = Utils.unique([...base.triggers, ...meta.triggers]);
|
|
1076
|
+
meta.indexes = Utils.unique([...base.indexes, ...meta.indexes], Utils.equals);
|
|
1077
|
+
meta.uniques = Utils.unique([...base.uniques, ...meta.uniques], Utils.equals);
|
|
1078
|
+
meta.checks = Utils.unique([...base.checks, ...meta.checks], Utils.equals);
|
|
1079
|
+
meta.triggers = Utils.unique([...base.triggers, ...meta.triggers], Utils.equals);
|
|
1080
|
+
}
|
|
1081
|
+
// Policies pass down only from inlined abstract bases; STI children share the root table
|
|
1082
|
+
// and TPT children own their tables, so both declare policies directly on the root/child.
|
|
1083
|
+
if (base.abstract && base.inheritanceType !== 'sti' && (meta.inheritanceType !== 'tpt' || !meta.tptParent)) {
|
|
1084
|
+
meta.policies = Utils.unique([...base.policies, ...meta.policies]);
|
|
1085
|
+
meta.rowLevelSecurity ??= base.rowLevelSecurity;
|
|
1044
1086
|
}
|
|
1045
1087
|
const pks = Object.values(meta.properties)
|
|
1046
1088
|
.filter(p => p.primary)
|
|
@@ -1184,7 +1226,11 @@ export class MetadataDiscovery {
|
|
|
1184
1226
|
return;
|
|
1185
1227
|
}
|
|
1186
1228
|
visited.add(embeddedProp);
|
|
1187
|
-
|
|
1229
|
+
// Prefer resolution via the class reference, the name can be ambiguous when a minifier
|
|
1230
|
+
// mangles two classes to the same name. Only named metadata counts, an auto-discovered
|
|
1231
|
+
// class without the `@Embeddable()` decorator should still fail as unknown below.
|
|
1232
|
+
const embeddable = this.#discovered.find(m => m.name && m.class === embeddedProp.target) ??
|
|
1233
|
+
this.#discovered.find(m => m.name === embeddedProp.type);
|
|
1188
1234
|
if (!embeddable) {
|
|
1189
1235
|
throw MetadataError.fromUnknownEntity(embeddedProp.type, `${meta.className}.${embeddedProp.name}`);
|
|
1190
1236
|
}
|
|
@@ -1224,8 +1270,17 @@ export class MetadataDiscovery {
|
|
|
1224
1270
|
if (embeddedProp.nullable || refInArray) {
|
|
1225
1271
|
meta.properties[name].nullable = true;
|
|
1226
1272
|
}
|
|
1273
|
+
// polymorphic relations derive their column names from the discriminator, so prefix it too
|
|
1274
|
+
if (meta.properties[name].polymorphic && !object) {
|
|
1275
|
+
meta.properties[name].discriminator = prefix + meta.properties[name].discriminator;
|
|
1276
|
+
meta.properties[name].discriminatorColumn = prefix + meta.properties[name].discriminatorColumn;
|
|
1277
|
+
}
|
|
1227
1278
|
if (meta.properties[name].fieldNames) {
|
|
1228
|
-
|
|
1279
|
+
const { fieldNames, polymorphic } = meta.properties[name];
|
|
1280
|
+
// polymorphic `fieldNames` hold `[discriminatorColumn, ...fkIdColumns]`, so prefix all of them
|
|
1281
|
+
for (let i = 0; i < (polymorphic ? fieldNames.length : 1); i++) {
|
|
1282
|
+
fieldNames[i] = prefix + fieldNames[i];
|
|
1283
|
+
}
|
|
1229
1284
|
}
|
|
1230
1285
|
else {
|
|
1231
1286
|
const name2 = meta.properties[name].name;
|
|
@@ -1654,6 +1709,9 @@ export class MetadataDiscovery {
|
|
|
1654
1709
|
if (prop.persist === false || prop.nativeEnumName || !prop.items?.every(item => typeof item === 'string')) {
|
|
1655
1710
|
continue;
|
|
1656
1711
|
}
|
|
1712
|
+
if (prop.customType instanceof t.json || ['json', 'jsonb'].includes(prop.columnTypes?.[0])) {
|
|
1713
|
+
continue;
|
|
1714
|
+
}
|
|
1657
1715
|
this.initFieldName(prop);
|
|
1658
1716
|
let expression = null;
|
|
1659
1717
|
if (prop.enum) {
|
|
@@ -1693,6 +1751,28 @@ export class MetadataDiscovery {
|
|
|
1693
1751
|
}
|
|
1694
1752
|
meta.hasTriggers = true;
|
|
1695
1753
|
}
|
|
1754
|
+
initPolicies(meta) {
|
|
1755
|
+
if (meta.policies.length === 0) {
|
|
1756
|
+
return;
|
|
1757
|
+
}
|
|
1758
|
+
const columns = meta.createSchemaColumnMappingObject();
|
|
1759
|
+
const table = this.createSchemaTable(meta);
|
|
1760
|
+
// resolve callbacks into a copy — the defs can be shared with siblings via an inlined abstract base,
|
|
1761
|
+
// and resolving in place would bake the first child's table into every other child's policy
|
|
1762
|
+
meta.policies = meta.policies.map(policy => {
|
|
1763
|
+
if (!(policy.using instanceof Function) && !(policy.check instanceof Function)) {
|
|
1764
|
+
return policy;
|
|
1765
|
+
}
|
|
1766
|
+
const resolved = { ...policy };
|
|
1767
|
+
if (resolved.using instanceof Function) {
|
|
1768
|
+
resolved.using = resolved.using(columns, table);
|
|
1769
|
+
}
|
|
1770
|
+
if (resolved.check instanceof Function) {
|
|
1771
|
+
resolved.check = resolved.check(columns, table);
|
|
1772
|
+
}
|
|
1773
|
+
return resolved;
|
|
1774
|
+
});
|
|
1775
|
+
}
|
|
1696
1776
|
initGeneratedColumn(meta, prop) {
|
|
1697
1777
|
if (!prop.generated && prop.columnTypes) {
|
|
1698
1778
|
const match = /(.*) generated always as (.*)/i.exec(prop.columnTypes[0]);
|
|
@@ -1997,6 +2077,58 @@ export class MetadataDiscovery {
|
|
|
1997
2077
|
}
|
|
1998
2078
|
}
|
|
1999
2079
|
}
|
|
2080
|
+
/** Resolves the `through` option of a virtual to-one relation into a read-only formula property. */
|
|
2081
|
+
initThroughRelation(meta, prop) {
|
|
2082
|
+
// already resolved, or not a through relation at all
|
|
2083
|
+
if (prop.through?.ownerProperty || !prop.through) {
|
|
2084
|
+
return;
|
|
2085
|
+
}
|
|
2086
|
+
if (![ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind)) {
|
|
2087
|
+
throw MetadataError.throughRelationInvalidKind(meta, prop);
|
|
2088
|
+
}
|
|
2089
|
+
const targetMeta = prop.targetMeta;
|
|
2090
|
+
// the subquery selects a single column
|
|
2091
|
+
if (targetMeta.compositePK) {
|
|
2092
|
+
throw MetadataError.throughRelationCompositeTarget(meta, prop);
|
|
2093
|
+
}
|
|
2094
|
+
const through = prop.through;
|
|
2095
|
+
const throughMeta = this.#metadata.get(!through.prototype ? through() : through);
|
|
2096
|
+
// a property is considered to point at an entity when it targets it or one of its parents
|
|
2097
|
+
const pointsTo = (p, m) => {
|
|
2098
|
+
const candidate = this.#metadata.find(p.target);
|
|
2099
|
+
/* v8 ignore next 3 */
|
|
2100
|
+
if (!candidate) {
|
|
2101
|
+
return false;
|
|
2102
|
+
}
|
|
2103
|
+
return candidate.class === m.class || m.class.prototype instanceof candidate.class;
|
|
2104
|
+
};
|
|
2105
|
+
const fks = Object.values(throughMeta.properties).filter(p => p.kind === ReferenceKind.MANY_TO_ONE);
|
|
2106
|
+
const ownerProp = fks.find(p => pointsTo(p, meta));
|
|
2107
|
+
if (!ownerProp) {
|
|
2108
|
+
throw MetadataError.throughRelationMissingProperty(meta, prop, throughMeta, 'owner');
|
|
2109
|
+
}
|
|
2110
|
+
let targetProperty;
|
|
2111
|
+
const selectsTarget = throughMeta.class === targetMeta.class || throughMeta.class.prototype instanceof targetMeta.class;
|
|
2112
|
+
if (!selectsTarget) {
|
|
2113
|
+
const targetProp = fks.find(p => p !== ownerProp && pointsTo(p, targetMeta));
|
|
2114
|
+
if (!targetProp) {
|
|
2115
|
+
throw MetadataError.throughRelationMissingProperty(meta, prop, throughMeta, 'target');
|
|
2116
|
+
}
|
|
2117
|
+
targetProperty = targetProp.name;
|
|
2118
|
+
}
|
|
2119
|
+
prop.through = {
|
|
2120
|
+
entity: throughMeta.class,
|
|
2121
|
+
where: prop.where,
|
|
2122
|
+
orderBy: prop.orderBy ? Utils.asArray(prop.orderBy) : undefined,
|
|
2123
|
+
ownerProperty: ownerProp.name,
|
|
2124
|
+
targetProperty,
|
|
2125
|
+
};
|
|
2126
|
+
// the condition and ordering apply to the `through` entity, not to the target, so they must not leak into the target joins
|
|
2127
|
+
delete prop.where;
|
|
2128
|
+
delete prop.orderBy;
|
|
2129
|
+
prop.persist = false;
|
|
2130
|
+
prop.formula = columns => this.#platform.getThroughRelationFormula(prop, columns);
|
|
2131
|
+
}
|
|
2000
2132
|
initColumnType(prop) {
|
|
2001
2133
|
this.initUnsigned(prop);
|
|
2002
2134
|
// Get the target properties for FK relations - use targetKey property if specified, otherwise PKs
|
|
@@ -2057,6 +2189,7 @@ export class MetadataDiscovery {
|
|
|
2057
2189
|
prop.columnTypes.push(...columnTypes);
|
|
2058
2190
|
if (!targetMeta.compositePK || prop.targetKey) {
|
|
2059
2191
|
prop.customType = referencedProp.customType;
|
|
2192
|
+
prop.collation ??= referencedProp.collation;
|
|
2060
2193
|
}
|
|
2061
2194
|
}
|
|
2062
2195
|
}
|
|
@@ -2112,7 +2245,7 @@ export class MetadataDiscovery {
|
|
|
2112
2245
|
shouldForceConstructorUsage(meta) {
|
|
2113
2246
|
const forceConstructor = this.#config.get('forceEntityConstructor');
|
|
2114
2247
|
if (Array.isArray(forceConstructor)) {
|
|
2115
|
-
return forceConstructor.some(cls => Utils.
|
|
2248
|
+
return forceConstructor.some(cls => Utils.matchesEntity(cls, meta));
|
|
2116
2249
|
}
|
|
2117
2250
|
return forceConstructor;
|
|
2118
2251
|
}
|
|
@@ -92,7 +92,7 @@ export class MetadataProvider {
|
|
|
92
92
|
if (!this.useCache()) {
|
|
93
93
|
return undefined;
|
|
94
94
|
}
|
|
95
|
-
const cache = meta.path && this.config.getMetadataCacheAdapter().get(this.getCacheKey(meta));
|
|
95
|
+
const cache = meta.path && this.config.getMetadataCacheAdapter().get(this.getCacheKey(meta), meta.path);
|
|
96
96
|
if (cache) {
|
|
97
97
|
this.loadFromCache(meta, cache);
|
|
98
98
|
meta.root = root;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { type Dictionary, EntityMetadata, type EntityName } from '../typings.js';
|
|
1
|
+
import { type Dictionary, type EntityCtor, EntityMetadata, type EntityName } from '../typings.js';
|
|
2
2
|
import type { EntityManager } from '../EntityManager.js';
|
|
3
3
|
/** Registry that stores and provides access to entity metadata by class, name, or id. */
|
|
4
4
|
export declare class MetadataStorage {
|
|
5
5
|
#private;
|
|
6
6
|
static readonly PATH_SYMBOL: unique symbol;
|
|
7
|
+
static readonly META_SYMBOL: unique symbol;
|
|
7
8
|
constructor(metadata?: Dictionary<EntityMetadata>);
|
|
8
|
-
/** Returns the global metadata dictionary, or a specific entry by entity name and path. */
|
|
9
|
+
/** Returns the global metadata dictionary, or a specific entry by entity name and path (keyed by the class reference when `target` is provided). */
|
|
9
10
|
static getMetadata(): Dictionary<EntityMetadata>;
|
|
10
|
-
static getMetadata<T = any>(entity: string, path: string): EntityMetadata<T>;
|
|
11
|
+
static getMetadata<T = any>(entity: string, path: string, target?: EntityCtor): EntityMetadata<T>;
|
|
11
12
|
/** Checks whether an entity with the given class name exists in the global metadata. */
|
|
12
13
|
static isKnownEntity(name: string): boolean;
|
|
13
14
|
/** Clears all entries from the global metadata registry. */
|
|
@@ -11,11 +11,13 @@ function getGlobalStorage(namespace) {
|
|
|
11
11
|
/** Registry that stores and provides access to entity metadata by class, name, or id. */
|
|
12
12
|
export class MetadataStorage {
|
|
13
13
|
static PATH_SYMBOL = Symbol.for('@mikro-orm/core/MetadataStorage.PATH_SYMBOL');
|
|
14
|
+
static META_SYMBOL = Symbol.for('@mikro-orm/core/MetadataStorage.META_SYMBOL');
|
|
14
15
|
static #metadata = getGlobalStorage('metadata');
|
|
15
16
|
#metadataMap = new Map();
|
|
16
17
|
#idMap;
|
|
17
18
|
#classNameMap;
|
|
18
19
|
#uniqueNameMap;
|
|
20
|
+
#ambiguousNames = new Set();
|
|
19
21
|
constructor(metadata = {}) {
|
|
20
22
|
this.#idMap = {};
|
|
21
23
|
this.#uniqueNameMap = {};
|
|
@@ -26,8 +28,21 @@ export class MetadataStorage {
|
|
|
26
28
|
this.#metadataMap.set(meta.class, meta);
|
|
27
29
|
}
|
|
28
30
|
}
|
|
29
|
-
static getMetadata(entity, path) {
|
|
31
|
+
static getMetadata(entity, path, target) {
|
|
30
32
|
const key = entity && path ? entity + '-' + Utils.hash(path) : null;
|
|
33
|
+
// Key the registry by the class reference when available, so two classes minified
|
|
34
|
+
// to the same mangled name don't collide on the `className-path` key.
|
|
35
|
+
if (key && target) {
|
|
36
|
+
if (!Object.hasOwn(target, MetadataStorage.META_SYMBOL)) {
|
|
37
|
+
Object.defineProperty(target, MetadataStorage.META_SYMBOL, {
|
|
38
|
+
value: new EntityMetadata({ className: entity, path }),
|
|
39
|
+
writable: true,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
// Keep the name-keyed entry in sync, the class-keyed metadata survives `MetadataStorage.clear()`.
|
|
43
|
+
MetadataStorage.#metadata[key] = target[MetadataStorage.META_SYMBOL];
|
|
44
|
+
return target[MetadataStorage.META_SYMBOL];
|
|
45
|
+
}
|
|
31
46
|
if (key && !MetadataStorage.#metadata[key]) {
|
|
32
47
|
MetadataStorage.#metadata[key] = new EntityMetadata({ className: entity, path });
|
|
33
48
|
}
|
|
@@ -50,6 +65,10 @@ export class MetadataStorage {
|
|
|
50
65
|
}
|
|
51
66
|
/** Returns metadata for the given entity, optionally initializing it if not found. */
|
|
52
67
|
get(entityName, init = false) {
|
|
68
|
+
// string lookups cannot be resolved when several classes were minified to the same name
|
|
69
|
+
if (typeof entityName === 'string' && this.#ambiguousNames.has(entityName)) {
|
|
70
|
+
throw MetadataError.ambiguousEntityName(entityName);
|
|
71
|
+
}
|
|
53
72
|
const exists = this.find(entityName);
|
|
54
73
|
if (exists) {
|
|
55
74
|
return exists;
|
|
@@ -85,7 +104,13 @@ export class MetadataStorage {
|
|
|
85
104
|
this.#metadataMap.set(entityName, meta);
|
|
86
105
|
this.#idMap[meta._id] = meta;
|
|
87
106
|
this.#uniqueNameMap[meta.uniqueName] = meta;
|
|
88
|
-
|
|
107
|
+
const className = Utils.className(entityName);
|
|
108
|
+
const existing = this.#classNameMap[className];
|
|
109
|
+
// track name collisions caused by minifiers mangling two classes to the same name
|
|
110
|
+
if (existing && existing !== meta && existing.class !== meta.class) {
|
|
111
|
+
this.#ambiguousNames.add(className);
|
|
112
|
+
}
|
|
113
|
+
this.#classNameMap[className] = meta;
|
|
89
114
|
return meta;
|
|
90
115
|
}
|
|
91
116
|
/** Removes metadata for the given entity from all internal maps. */
|
|
@@ -96,6 +121,11 @@ export class MetadataStorage {
|
|
|
96
121
|
delete this.#idMap[meta._id];
|
|
97
122
|
delete this.#uniqueNameMap[meta.uniqueName];
|
|
98
123
|
delete this.#classNameMap[meta.className];
|
|
124
|
+
// the name may still be ambiguous among the remaining metas
|
|
125
|
+
const remaining = new Set([...this.#metadataMap.values()].filter(m => m.className === meta.className).map(m => m.class));
|
|
126
|
+
if (remaining.size <= 1) {
|
|
127
|
+
this.#ambiguousNames.delete(meta.className);
|
|
128
|
+
}
|
|
99
129
|
}
|
|
100
130
|
}
|
|
101
131
|
/** Decorates all entity prototypes with helper methods (e.g. init, toJSON). */
|
package/metadata/Routine.js
CHANGED
|
@@ -135,6 +135,9 @@ export class Routine {
|
|
|
135
135
|
return new Routine(config);
|
|
136
136
|
}
|
|
137
137
|
static is(item) {
|
|
138
|
-
|
|
138
|
+
if (item instanceof Routine) {
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
return item != null && typeof item === 'object' && item.constructor?.name === 'Routine' && 'type' in item;
|
|
139
142
|
}
|
|
140
143
|
}
|
package/metadata/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyEntity, Constructor, EntityName, AnyString, CheckCallback, GeneratedColumnCallback, FormulaCallback, FilterQuery, Dictionary, AutoPath, EntityClass, IndexCallback, ObjectQuery, Raw, SchemaColumns, TriggerDef } from '../typings.js';
|
|
1
|
+
import type { AnyEntity, Constructor, EntityName, AnyString, CheckCallback, GeneratedColumnCallback, FormulaCallback, FilterQuery, Dictionary, AutoPath, EntityClass, IndexCallback, ObjectQuery, Raw, SchemaColumns, TriggerDef, PolicyDef } from '../typings.js';
|
|
2
2
|
import type { Cascade, LoadStrategy, DeferMode, QueryOrderMap, EmbeddedPrefixMode } from '../enums.js';
|
|
3
3
|
import type { Type, types } from '../types/index.js';
|
|
4
4
|
import type { EntityManager } from '../EntityManager.js';
|
|
@@ -104,6 +104,10 @@ export type EntityOptions<T, E = T extends EntityClass<infer P> ? P : T> = {
|
|
|
104
104
|
hasTriggers?: boolean;
|
|
105
105
|
/** Database triggers to create for this entity's table. (SQL drivers only) */
|
|
106
106
|
triggers?: TriggerDef<E>[];
|
|
107
|
+
/** PostgreSQL row level security policies for this entity's table. Declaring policies implicitly enables RLS. */
|
|
108
|
+
policies?: PolicyDef<E>[];
|
|
109
|
+
/** Enables PostgreSQL row level security on this entity's table. `'force'` also enforces it for the table owner. Set to `false` to keep declared policies staged while leaving RLS disabled. */
|
|
110
|
+
rowLevelSecurity?: boolean | 'force';
|
|
107
111
|
/**
|
|
108
112
|
* PostgreSQL partitioning definition for this table.
|
|
109
113
|
*
|
|
@@ -427,9 +431,15 @@ interface PolymorphicOptions {
|
|
|
427
431
|
*/
|
|
428
432
|
discriminatorMap?: Dictionary<string>;
|
|
429
433
|
}
|
|
430
|
-
export interface ManyToOneOptions<Owner, Target> extends ReferenceOptions<Owner, Target>, PolymorphicOptions {
|
|
434
|
+
export interface ManyToOneOptions<Owner, Target, Through = Target> extends ReferenceOptions<Owner, Target>, PolymorphicOptions {
|
|
431
435
|
/** Point to the inverse side property name. */
|
|
432
436
|
inversedBy?: (string & keyof Target) | ((e: Target) => any);
|
|
437
|
+
/** Resolve this read-only relation via a subquery on another entity: a pivot entity with FKs to both sides, or the target itself to pick a single item out of a to-many relation (see {@doclink relationships#to-one-relations-through-another-entity | To-one relations through another entity}). */
|
|
438
|
+
through?: () => EntityName<Through>;
|
|
439
|
+
/** Condition applied on the `through` entity. */
|
|
440
|
+
where?: FilterQuery<Through>;
|
|
441
|
+
/** Ordering applied on the `through` entity, the first matching row is used. */
|
|
442
|
+
orderBy?: QueryOrderMap<Through> | QueryOrderMap<Through>[];
|
|
433
443
|
/** Wrap the entity in {@apilink Reference} wrapper. */
|
|
434
444
|
ref?: boolean;
|
|
435
445
|
/** Use this relation as a primary key. */
|
|
@@ -481,9 +491,15 @@ export interface OneToManyOptions<Owner, Target> extends ReferenceOptions<Owner,
|
|
|
481
491
|
/** Point to the owning side property name. */
|
|
482
492
|
mappedBy: (string & keyof Target) | ((e: Target) => any);
|
|
483
493
|
}
|
|
484
|
-
export interface OneToOneOptions<Owner, Target> extends Partial<Omit<OneToManyOptions<Owner, Target>, 'orderBy'>>, PolymorphicOptions {
|
|
494
|
+
export interface OneToOneOptions<Owner, Target, Through = Target> extends Partial<Omit<OneToManyOptions<Owner, Target>, 'orderBy' | 'where'>>, PolymorphicOptions {
|
|
485
495
|
/** Set this side as owning. Owning side is where the foreign key is defined. This option is not required if you use `inversedBy` or `mappedBy` to distinguish owning and inverse side. */
|
|
486
496
|
owner?: boolean;
|
|
497
|
+
/** Resolve this read-only relation via a subquery on another entity: a pivot entity with FKs to both sides, or the target itself to pick a single item out of a to-many relation (see {@doclink relationships#to-one-relations-through-another-entity | To-one relations through another entity}). */
|
|
498
|
+
through?: () => EntityName<Through>;
|
|
499
|
+
/** Condition for {@doclink collections#declarative-partial-loading | Declarative partial loading}, or the condition applied on the `through` entity. */
|
|
500
|
+
where?: FilterQuery<Through>;
|
|
501
|
+
/** Ordering applied on the `through` entity, the first matching row is used. */
|
|
502
|
+
orderBy?: QueryOrderMap<Through> | QueryOrderMap<Through>[];
|
|
487
503
|
/** Point to the inverse side property name. */
|
|
488
504
|
inversedBy?: (string & keyof Target) | ((e: Target) => any);
|
|
489
505
|
/** Wrap the entity in {@apilink Reference} wrapper. */
|
|
@@ -10,7 +10,8 @@ export class AbstractNamingStrategy {
|
|
|
10
10
|
classToMigrationName(timestamp, customMigrationName) {
|
|
11
11
|
let migrationName = `Migration${timestamp}`;
|
|
12
12
|
if (customMigrationName) {
|
|
13
|
-
|
|
13
|
+
// the name becomes part of a class identifier
|
|
14
|
+
migrationName += `_${customMigrationName.replace(/[^$\p{ID_Continue}]+/gu, '_')}`;
|
|
14
15
|
}
|
|
15
16
|
return migrationName;
|
|
16
17
|
}
|
|
@@ -9,7 +9,8 @@ export interface NamingStrategy {
|
|
|
9
9
|
*/
|
|
10
10
|
classToTableName(entityName: string, tableName?: string): string;
|
|
11
11
|
/**
|
|
12
|
-
* Return a migration name. This name should allow ordering
|
|
12
|
+
* Return a migration name. This name should allow ordering, and has to be a valid class identifier,
|
|
13
|
+
* as it is used as the class name in the generated migration file.
|
|
13
14
|
*/
|
|
14
15
|
classToMigrationName(timestamp: string, customMigrationName?: string): string;
|
|
15
16
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/core",
|
|
3
|
-
"version": "7.2.0-dev.
|
|
3
|
+
"version": "7.2.0-dev.21",
|
|
4
4
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"data-mapper",
|
package/platforms/Platform.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EntityRepository } from '../entity/EntityRepository.js';
|
|
2
2
|
import { type NamingStrategy } from '../naming-strategy/NamingStrategy.js';
|
|
3
|
-
import type { Constructor, EntityMetadata, EntityProperty, IPrimaryKey, ISchemaGenerator, PopulateOptions, Primary, SimpleColumnMeta, FilterQuery, EntityValue, EntityKey } from '../typings.js';
|
|
3
|
+
import type { Constructor, EntityMetadata, EntityProperty, IPrimaryKey, ISchemaGenerator, PopulateOptions, Primary, SimpleColumnMeta, FilterQuery, EntityValue, EntityKey, FormulaColumns } from '../typings.js';
|
|
4
4
|
import { ExceptionConverter } from './ExceptionConverter.js';
|
|
5
5
|
import type { EntityManager } from '../EntityManager.js';
|
|
6
6
|
import type { Configuration } from '../utils/Configuration.js';
|
|
@@ -211,8 +211,9 @@ export declare abstract class Platform {
|
|
|
211
211
|
getBlobDeclarationSQL(): string;
|
|
212
212
|
getJsonDeclarationSQL(): string;
|
|
213
213
|
getSearchJsonPropertySQL(path: string, type: string, aliased: boolean): string | Raw;
|
|
214
|
-
|
|
215
|
-
|
|
214
|
+
/** When `aliased` is a string, it holds an explicit alias the key was prefixed with. */
|
|
215
|
+
getSearchJsonPropertyKey(path: string[], type: string, aliased: boolean | string, value?: unknown): string | Raw;
|
|
216
|
+
processJsonCondition<T extends object>(o: FilterQuery<T>, value: EntityValue<T>, path: EntityKey<T>[], alias: boolean | string): FilterQuery<T>;
|
|
216
217
|
protected getJsonValueType(value: unknown): string;
|
|
217
218
|
getJsonIndexDefinition(index: {
|
|
218
219
|
columnNames: string[];
|
|
@@ -227,6 +228,12 @@ export declare abstract class Platform {
|
|
|
227
228
|
formatIndexHint(indexNames: string[]): string | undefined;
|
|
228
229
|
/** Whether the driver automatically parses JSON columns into JS objects. */
|
|
229
230
|
convertsJsonAutomatically(): boolean;
|
|
231
|
+
/** Whether date values inside JSON documents keep their native type (e.g. BSON dates), instead of being serialized to ISO strings. */
|
|
232
|
+
preservesDatesInsideJson(): boolean;
|
|
233
|
+
/** Whether `nulls first`/`nulls last` can be requested in an `orderBy`. */
|
|
234
|
+
supportsNullsOrdering(): boolean;
|
|
235
|
+
/** Where nulls land when an `orderBy` requests no explicit placement: lowest (`asc` puts them first) or highest. */
|
|
236
|
+
sortsNullsLowest(): boolean;
|
|
230
237
|
/** Converts a JS value to its JSON database representation (typically JSON.stringify). */
|
|
231
238
|
convertJsonToDatabaseValue(value: unknown, context?: TransformContext): unknown;
|
|
232
239
|
/** Converts a database JSON value to its JS representation. */
|
|
@@ -272,6 +279,11 @@ export declare abstract class Platform {
|
|
|
272
279
|
formatQuery(sql: string, params: readonly any[]): string;
|
|
273
280
|
/** Deep-clones embeddable data and tags it for JSON serialization. */
|
|
274
281
|
cloneEmbeddable<T>(data: T): T;
|
|
282
|
+
/**
|
|
283
|
+
* Builds the correlated subquery used as the formula of a virtual to-one relation defined via `through`.
|
|
284
|
+
* @internal
|
|
285
|
+
*/
|
|
286
|
+
getThroughRelationFormula(prop: EntityProperty, columns: FormulaColumns<any>): string;
|
|
275
287
|
/** Initializes the platform with the ORM configuration. */
|
|
276
288
|
setConfig(config: Configuration): void;
|
|
277
289
|
/** Returns the current ORM configuration. */
|
|
@@ -313,6 +325,15 @@ export declare abstract class Platform {
|
|
|
313
325
|
supportsDownMigrations(): boolean;
|
|
314
326
|
/** Whether the platform supports deferred unique constraints. */
|
|
315
327
|
supportsDeferredUniqueConstraints(): boolean;
|
|
328
|
+
/** Whether the platform supports row level security (PostgreSQL). */
|
|
329
|
+
supportsRowLevelSecurity(): boolean;
|
|
330
|
+
/** Whether the driver can apply the session context on every pooled connection acquire (`sessionContext: 'connection'`). */
|
|
331
|
+
supportsConnectionSessionContext(): boolean;
|
|
332
|
+
/**
|
|
333
|
+
* SQL cast suffix (e.g. `'::uuid'`, or `''` when none is needed) applied when an RLS filter reads a session
|
|
334
|
+
* variable via `current_setting()` as the given column type, or `null` if the type has no automatic cast.
|
|
335
|
+
*/
|
|
336
|
+
getCurrentSettingCast(mappedType: Type<unknown>): string | null;
|
|
316
337
|
/** Platform-specific validation of entity metadata. */
|
|
317
338
|
validateMetadata(meta: EntityMetadata): void;
|
|
318
339
|
/**
|