@mikro-orm/core 7.0.0-dev.64 → 7.0.0-dev.66
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.js +3 -3
- package/MikroORM.js +1 -1
- package/entity/Collection.js +1 -1
- package/entity/EntityFactory.js +1 -1
- package/entity/EntityValidator.js +2 -2
- package/metadata/EntitySchema.js +3 -3
- package/metadata/MetadataDiscovery.d.ts +1 -0
- package/metadata/MetadataDiscovery.js +15 -4
- package/metadata/MetadataStorage.d.ts +0 -4
- package/metadata/MetadataStorage.js +6 -10
- package/metadata/MetadataValidator.d.ts +0 -7
- package/metadata/MetadataValidator.js +0 -10
- package/package.json +2 -2
- package/platforms/Platform.d.ts +1 -1
- package/platforms/Platform.js +2 -2
- package/types/ArrayType.d.ts +1 -1
- package/types/ArrayType.js +1 -2
- package/typings.d.ts +1 -1
- package/typings.js +1 -1
- package/unit-of-work/UnitOfWork.js +1 -1
- package/utils/Configuration.js +1 -1
- package/utils/ConfigurationLoader.d.ts +3 -30
- package/utils/ConfigurationLoader.js +19 -200
- package/utils/EntityComparator.js +2 -2
- package/utils/QueryHelper.js +5 -5
- package/utils/Utils.d.ts +2 -50
- package/utils/Utils.js +2 -140
package/EntityManager.js
CHANGED
|
@@ -627,7 +627,7 @@ export class EntityManager {
|
|
|
627
627
|
where = await em.processWhere(entityName, where, options, 'read');
|
|
628
628
|
em.validator.validateEmptyWhere(where);
|
|
629
629
|
em.checkLockRequirements(options.lockMode, meta);
|
|
630
|
-
const isOptimisticLocking =
|
|
630
|
+
const isOptimisticLocking = options.lockMode == null || options.lockMode === LockMode.OPTIMISTIC;
|
|
631
631
|
if (entity && !em.shouldRefresh(meta, entity, options) && isOptimisticLocking) {
|
|
632
632
|
return em.lockAndPopulate(meta, entity, where, options);
|
|
633
633
|
}
|
|
@@ -1711,7 +1711,7 @@ export class EntityManager {
|
|
|
1711
1711
|
options.flags.push(QueryFlag.INFER_POPULATE);
|
|
1712
1712
|
return [];
|
|
1713
1713
|
}
|
|
1714
|
-
if (
|
|
1714
|
+
if (typeof field === 'string') {
|
|
1715
1715
|
return [{ field, strategy: options.strategy }];
|
|
1716
1716
|
}
|
|
1717
1717
|
return [field];
|
|
@@ -1818,7 +1818,7 @@ export class EntityManager {
|
|
|
1818
1818
|
config ??= this.config.get('resultCache').global;
|
|
1819
1819
|
if (config) {
|
|
1820
1820
|
const em = this.getContext();
|
|
1821
|
-
const expiration = Array.isArray(config) ? config[1] : (
|
|
1821
|
+
const expiration = Array.isArray(config) ? config[1] : (typeof config === 'number' ? config : undefined);
|
|
1822
1822
|
await em.resultCache.set(key.key, data instanceof Function ? data() : data, '', expiration);
|
|
1823
1823
|
}
|
|
1824
1824
|
}
|
package/MikroORM.js
CHANGED
|
@@ -37,7 +37,7 @@ export class MikroORM {
|
|
|
37
37
|
* - no support for folder based discovery
|
|
38
38
|
*/
|
|
39
39
|
constructor(options) {
|
|
40
|
-
const env = ConfigurationLoader.
|
|
40
|
+
const env = ConfigurationLoader.loadEnvironmentVars();
|
|
41
41
|
const coreVersion = ConfigurationLoader.checkPackageVersion();
|
|
42
42
|
options = Utils.merge(options, env);
|
|
43
43
|
this.config = new Configuration(options);
|
package/entity/Collection.js
CHANGED
|
@@ -63,7 +63,7 @@ export class Collection extends ArrayCollection {
|
|
|
63
63
|
async loadCount(options = {}) {
|
|
64
64
|
options = typeof options === 'boolean' ? { refresh: options } : options;
|
|
65
65
|
const { refresh, where, ...countOptions } = options;
|
|
66
|
-
if (!refresh && !where &&
|
|
66
|
+
if (!refresh && !where && this._count != null) {
|
|
67
67
|
return this._count;
|
|
68
68
|
}
|
|
69
69
|
const em = this.getEntityManager();
|
package/entity/EntityFactory.js
CHANGED
|
@@ -290,7 +290,7 @@ export class EntityFactory {
|
|
|
290
290
|
if (!spk?.serializedPrimaryKey) {
|
|
291
291
|
return;
|
|
292
292
|
}
|
|
293
|
-
if (pk.type
|
|
293
|
+
if (pk.type === 'ObjectId' && (data[pk.name] != null || data[spk.name] != null)) {
|
|
294
294
|
data[pk.name] = this.platform.denormalizePrimaryKey((data[spk.name] || data[pk.name]));
|
|
295
295
|
delete data[spk.name];
|
|
296
296
|
}
|
|
@@ -43,7 +43,7 @@ export class EntityValidator {
|
|
|
43
43
|
!prop.embedded &&
|
|
44
44
|
![ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(prop.kind) &&
|
|
45
45
|
prop.name !== wrapped.__meta.root.discriminatorColumn &&
|
|
46
|
-
prop.type
|
|
46
|
+
prop.type !== 'ObjectId' &&
|
|
47
47
|
prop.persist !== false &&
|
|
48
48
|
entity[prop.name] == null) {
|
|
49
49
|
throw ValidationError.propertyRequired(entity, prop);
|
|
@@ -131,7 +131,7 @@ export class EntityValidator {
|
|
|
131
131
|
}
|
|
132
132
|
fixDateType(givenValue) {
|
|
133
133
|
let date;
|
|
134
|
-
if (
|
|
134
|
+
if (typeof givenValue === 'string' && givenValue.match(/^-?\d+(\.\d+)?$/)) {
|
|
135
135
|
date = new Date(+givenValue);
|
|
136
136
|
}
|
|
137
137
|
else {
|
package/metadata/EntitySchema.js
CHANGED
|
@@ -39,8 +39,8 @@ export class EntitySchema {
|
|
|
39
39
|
if (type && Type.isMappedType(type.prototype)) {
|
|
40
40
|
prop.type = type;
|
|
41
41
|
}
|
|
42
|
-
if (
|
|
43
|
-
const formula = prop.formula;
|
|
42
|
+
if (typeof prop.formula === 'string') {
|
|
43
|
+
const formula = prop.formula;
|
|
44
44
|
prop.formula = () => formula;
|
|
45
45
|
}
|
|
46
46
|
if (prop.formula) {
|
|
@@ -263,7 +263,7 @@ export class EntitySchema {
|
|
|
263
263
|
}
|
|
264
264
|
normalizeType(options, type) {
|
|
265
265
|
if ('entity' in options) {
|
|
266
|
-
if (
|
|
266
|
+
if (typeof options.entity === 'string') {
|
|
267
267
|
type = options.type = options.entity;
|
|
268
268
|
}
|
|
269
269
|
else if (options.entity) {
|
|
@@ -27,6 +27,7 @@ export declare class MetadataDiscovery {
|
|
|
27
27
|
discoverReferences<T>(refs: Iterable<EntityClass<T> | EntitySchema<T>>, validate?: boolean): EntityMetadata<T>[];
|
|
28
28
|
reset(className: string): void;
|
|
29
29
|
private getSchema;
|
|
30
|
+
private getRootEntity;
|
|
30
31
|
private discoverEntity;
|
|
31
32
|
private saveToCache;
|
|
32
33
|
private initNullability;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { extname } from 'node:path';
|
|
2
|
-
import { EntityMetadata } from '../typings.js';
|
|
2
|
+
import { EntityMetadata, } from '../typings.js';
|
|
3
3
|
import { Utils } from '../utils/Utils.js';
|
|
4
4
|
import { MetadataValidator } from './MetadataValidator.js';
|
|
5
5
|
import { MetadataStorage } from './MetadataStorage.js';
|
|
@@ -270,11 +270,22 @@ export class MetadataDiscovery {
|
|
|
270
270
|
schema.setClass(entity);
|
|
271
271
|
return schema;
|
|
272
272
|
}
|
|
273
|
+
getRootEntity(meta) {
|
|
274
|
+
const base = meta.extends && this.metadata.find(Utils.className(meta.extends));
|
|
275
|
+
if (!base || base === meta) { // make sure we do not fall into infinite loop
|
|
276
|
+
return meta;
|
|
277
|
+
}
|
|
278
|
+
const root = this.getRootEntity(base);
|
|
279
|
+
if (root.discriminatorColumn) {
|
|
280
|
+
return root;
|
|
281
|
+
}
|
|
282
|
+
return meta;
|
|
283
|
+
}
|
|
273
284
|
discoverEntity(schema) {
|
|
274
285
|
const meta = schema.meta;
|
|
275
286
|
const path = meta.path;
|
|
276
287
|
this.logger.log('discovery', `- processing entity ${colors.cyan(meta.className)}${colors.grey(path ? ` (${path})` : '')}`);
|
|
277
|
-
const root =
|
|
288
|
+
const root = this.getRootEntity(meta);
|
|
278
289
|
schema.meta.path = Utils.relativePath(meta.path, this.config.get('baseDir'));
|
|
279
290
|
const cache = this.metadataProvider.useCache() && meta.path && this.cache.get(meta.className + extname(meta.path));
|
|
280
291
|
if (cache) {
|
|
@@ -971,7 +982,7 @@ export class MetadataDiscovery {
|
|
|
971
982
|
}
|
|
972
983
|
if (this.platform.usesEnumCheckConstraints() && !meta.embeddable) {
|
|
973
984
|
for (const prop of meta.props) {
|
|
974
|
-
if (prop.enum && !prop.nativeEnumName && prop.items?.every(item =>
|
|
985
|
+
if (prop.enum && !prop.nativeEnumName && prop.items?.every(item => typeof item === 'string')) {
|
|
975
986
|
this.initFieldName(prop);
|
|
976
987
|
meta.checks.push({
|
|
977
988
|
name: this.namingStrategy.indexName(meta.tableName, prop.fieldNames, 'check'),
|
|
@@ -1277,7 +1288,7 @@ export class MetadataDiscovery {
|
|
|
1277
1288
|
t = 'enum';
|
|
1278
1289
|
}
|
|
1279
1290
|
else if (prop.enum) {
|
|
1280
|
-
t = prop.items?.every(item =>
|
|
1291
|
+
t = prop.items?.every(item => typeof item === 'string') ? 'enum' : 'tinyint';
|
|
1281
1292
|
}
|
|
1282
1293
|
if (t === 'Date') {
|
|
1283
1294
|
t = 'datetime';
|
|
@@ -8,10 +8,6 @@ export declare class MetadataStorage {
|
|
|
8
8
|
static getMetadata(): Dictionary<EntityMetadata>;
|
|
9
9
|
static getMetadata<T = any>(entity: string, path: string): EntityMetadata<T>;
|
|
10
10
|
static isKnownEntity(name: string): boolean;
|
|
11
|
-
static getMetadataFromDecorator<T = any>(target: T & Dictionary & {
|
|
12
|
-
[MetadataStorage.PATH_SYMBOL]?: string;
|
|
13
|
-
}): EntityMetadata<T>;
|
|
14
|
-
static init(): MetadataStorage;
|
|
15
11
|
static clear(): void;
|
|
16
12
|
getAll(): Dictionary<EntityMetadata>;
|
|
17
13
|
getByDiscriminatorColumn<T>(meta: EntityMetadata<T>, data: EntityData<T>): EntityMetadata<T> | undefined;
|
|
@@ -2,9 +2,14 @@ import { EntityMetadata } from '../typings.js';
|
|
|
2
2
|
import { Utils } from '../utils/Utils.js';
|
|
3
3
|
import { MetadataError } from '../errors.js';
|
|
4
4
|
import { EntityHelper } from '../entity/EntityHelper.js';
|
|
5
|
+
function getGlobalStorage(namespace) {
|
|
6
|
+
const key = `mikro-orm-${namespace}`;
|
|
7
|
+
globalThis[key] = globalThis[key] || {};
|
|
8
|
+
return globalThis[key];
|
|
9
|
+
}
|
|
5
10
|
export class MetadataStorage {
|
|
6
11
|
static PATH_SYMBOL = Symbol('MetadataStorage.PATH_SYMBOL');
|
|
7
|
-
static metadata =
|
|
12
|
+
static metadata = getGlobalStorage('metadata');
|
|
8
13
|
metadata;
|
|
9
14
|
constructor(metadata = {}) {
|
|
10
15
|
this.metadata = Utils.copy(metadata, false);
|
|
@@ -22,15 +27,6 @@ export class MetadataStorage {
|
|
|
22
27
|
static isKnownEntity(name) {
|
|
23
28
|
return !!Object.values(this.metadata).find(meta => meta.className === name);
|
|
24
29
|
}
|
|
25
|
-
static getMetadataFromDecorator(target) {
|
|
26
|
-
if (!Object.hasOwn(target, MetadataStorage.PATH_SYMBOL)) {
|
|
27
|
-
Object.defineProperty(target, MetadataStorage.PATH_SYMBOL, { value: Utils.lookupPathFromDecorator(target.name), writable: true });
|
|
28
|
-
}
|
|
29
|
-
return MetadataStorage.getMetadata(target.name, target[MetadataStorage.PATH_SYMBOL]);
|
|
30
|
-
}
|
|
31
|
-
static init() {
|
|
32
|
-
return new MetadataStorage(MetadataStorage.metadata);
|
|
33
|
-
}
|
|
34
30
|
static clear() {
|
|
35
31
|
Object.keys(this.metadata).forEach(k => delete this.metadata[k]);
|
|
36
32
|
}
|
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
import type { EntityMetadata } from '../typings.js';
|
|
2
2
|
import { type MetadataDiscoveryOptions } from '../utils/Configuration.js';
|
|
3
|
-
import { ReferenceKind } from '../enums.js';
|
|
4
3
|
import type { MetadataStorage } from './MetadataStorage.js';
|
|
5
4
|
/**
|
|
6
5
|
* @internal
|
|
7
6
|
*/
|
|
8
7
|
export declare class MetadataValidator {
|
|
9
|
-
/**
|
|
10
|
-
* Validate there is only one property decorator. This disallows using `@Property()` together with e.g. `@ManyToOne()`
|
|
11
|
-
* on the same property. One should use only `@ManyToOne()` in such case.
|
|
12
|
-
* We allow the existence of the property in metadata if the reference type is the same, this should allow things like HMR to work.
|
|
13
|
-
*/
|
|
14
|
-
static validateSingleDecorator(meta: EntityMetadata, propertyName: string, reference: ReferenceKind): void;
|
|
15
8
|
validateEntityDefinition<T>(metadata: MetadataStorage, name: string, options: MetadataDiscoveryOptions): void;
|
|
16
9
|
validateDiscovered(discovered: EntityMetadata[], options: MetadataDiscoveryOptions): void;
|
|
17
10
|
private validateReference;
|
|
@@ -5,16 +5,6 @@ import { ReferenceKind } from '../enums.js';
|
|
|
5
5
|
* @internal
|
|
6
6
|
*/
|
|
7
7
|
export class MetadataValidator {
|
|
8
|
-
/**
|
|
9
|
-
* Validate there is only one property decorator. This disallows using `@Property()` together with e.g. `@ManyToOne()`
|
|
10
|
-
* on the same property. One should use only `@ManyToOne()` in such case.
|
|
11
|
-
* We allow the existence of the property in metadata if the reference type is the same, this should allow things like HMR to work.
|
|
12
|
-
*/
|
|
13
|
-
static validateSingleDecorator(meta, propertyName, reference) {
|
|
14
|
-
if (meta.properties[propertyName] && meta.properties[propertyName].kind !== reference) {
|
|
15
|
-
throw MetadataError.multipleDecorators(meta.className, propertyName);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
8
|
validateEntityDefinition(metadata, name, options) {
|
|
19
9
|
const meta = metadata.get(name);
|
|
20
10
|
if (meta.virtual || meta.expression) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "7.0.0-dev.
|
|
4
|
+
"version": "7.0.0-dev.66",
|
|
5
5
|
"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.",
|
|
6
6
|
"exports": {
|
|
7
7
|
"./package.json": "./package.json",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"access": "public"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"mikro-orm": "7.0.0-dev.
|
|
55
|
+
"mikro-orm": "7.0.0-dev.66"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
58
|
"dataloader": "2.2.3"
|
package/platforms/Platform.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { inspect } from 'node:util';
|
|
2
2
|
import { EntityRepository } from '../entity/EntityRepository.js';
|
|
3
3
|
import { type NamingStrategy } from '../naming-strategy/NamingStrategy.js';
|
|
4
|
-
import type { Constructor, EntityProperty, IPrimaryKey, ISchemaGenerator, PopulateOptions, Primary,
|
|
4
|
+
import type { Constructor, EntityMetadata, EntityProperty, IPrimaryKey, ISchemaGenerator, PopulateOptions, Primary, SimpleColumnMeta } from '../typings.js';
|
|
5
5
|
import { ExceptionConverter } from './ExceptionConverter.js';
|
|
6
6
|
import type { EntityManager } from '../EntityManager.js';
|
|
7
7
|
import type { Configuration } from '../utils/Configuration.js';
|
package/platforms/Platform.js
CHANGED
|
@@ -3,7 +3,7 @@ import { clone } from '../utils/clone.js';
|
|
|
3
3
|
import { EntityRepository } from '../entity/EntityRepository.js';
|
|
4
4
|
import { UnderscoreNamingStrategy } from '../naming-strategy/UnderscoreNamingStrategy.js';
|
|
5
5
|
import { ExceptionConverter } from './ExceptionConverter.js';
|
|
6
|
-
import { ArrayType, BigIntType, BlobType,
|
|
6
|
+
import { ArrayType, BigIntType, BlobType, BooleanType, CharacterType, DateTimeType, DateType, DecimalType, DoubleType, EnumType, FloatType, IntegerType, IntervalType, JsonType, MediumIntType, SmallIntType, StringType, TextType, TimeType, TinyIntType, Type, Uint8ArrayType, UnknownType, UuidType, } from '../types/index.js';
|
|
7
7
|
import { parseJsonSafe, Utils } from '../utils/Utils.js';
|
|
8
8
|
import { ReferenceKind } from '../enums.js';
|
|
9
9
|
import { RawQueryFragment } from '../utils/RawQueryFragment.js';
|
|
@@ -160,7 +160,7 @@ export class Platform {
|
|
|
160
160
|
return `text`;
|
|
161
161
|
}
|
|
162
162
|
getEnumTypeDeclarationSQL(column) {
|
|
163
|
-
if (column.items?.every(item =>
|
|
163
|
+
if (column.items?.every(item => typeof item === 'string')) {
|
|
164
164
|
return `enum('${column.items.join("','")}')`;
|
|
165
165
|
}
|
|
166
166
|
return this.getTinyIntTypeDeclarationSQL(column);
|
package/types/ArrayType.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type TransformContext, Type } from './Type.js';
|
|
2
2
|
import type { EntityProperty } from '../typings.js';
|
|
3
3
|
import type { Platform } from '../platforms/Platform.js';
|
|
4
4
|
export declare class ArrayType<T = string> extends Type<T[] | null, string | null> {
|
package/types/ArrayType.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Type } from './Type.js';
|
|
2
|
-
import { Utils } from '../utils/Utils.js';
|
|
3
2
|
import { ValidationError } from '../errors.js';
|
|
4
3
|
export class ArrayType extends Type {
|
|
5
4
|
toJsValue;
|
|
@@ -26,7 +25,7 @@ export class ArrayType extends Type {
|
|
|
26
25
|
if (value == null) {
|
|
27
26
|
return value;
|
|
28
27
|
}
|
|
29
|
-
if (
|
|
28
|
+
if (typeof value === 'string') {
|
|
30
29
|
value = platform.unmarshallArray(value);
|
|
31
30
|
}
|
|
32
31
|
return value.map(i => this.toJsValue(i));
|
package/typings.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Transaction } from './connections/Connection.js';
|
|
2
|
-
import { type Cascade, type DeferMode, type EventType, type LoadStrategy, type PopulatePath, type QueryOrderMap, ReferenceKind
|
|
2
|
+
import { type Cascade, type DeferMode, type EmbeddedPrefixMode, type EventType, type LoadStrategy, type PopulatePath, type QueryOrderMap, ReferenceKind } from './enums.js';
|
|
3
3
|
import { type AssignOptions } from './entity/EntityAssigner.js';
|
|
4
4
|
import { type EntityIdentifier } from './entity/EntityIdentifier.js';
|
|
5
5
|
import { type EntityLoaderOptions } from './entity/EntityLoader.js';
|
package/typings.js
CHANGED
|
@@ -100,7 +100,7 @@ export class EntityMetadata {
|
|
|
100
100
|
this.virtual = !!this.expression;
|
|
101
101
|
if (config) {
|
|
102
102
|
for (const prop of this.props) {
|
|
103
|
-
if (prop.enum && !prop.nativeEnumName && prop.items?.every(item =>
|
|
103
|
+
if (prop.enum && !prop.nativeEnumName && prop.items?.every(item => typeof item === 'string')) {
|
|
104
104
|
const name = config.getNamingStrategy().indexName(this.tableName, prop.fieldNames, 'check');
|
|
105
105
|
const exists = this.checks.findIndex(check => check.name === name);
|
|
106
106
|
if (exists !== -1) {
|
package/utils/Configuration.js
CHANGED
|
@@ -144,7 +144,7 @@ export class Configuration {
|
|
|
144
144
|
extensions = new Map();
|
|
145
145
|
constructor(options, validate = true) {
|
|
146
146
|
if (options.dynamicImportProvider) {
|
|
147
|
-
Utils.
|
|
147
|
+
Utils.dynamicImportProvider = options.dynamicImportProvider;
|
|
148
148
|
}
|
|
149
149
|
this.options = Utils.mergeConfig({}, DEFAULTS, options);
|
|
150
150
|
this.options.baseDir = Utils.absolutePath(this.options.baseDir);
|
|
@@ -1,40 +1,13 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { EntityManagerType, IDatabaseDriver } from '../drivers/IDatabaseDriver.js';
|
|
1
|
+
import type { IDatabaseDriver } from '../drivers/IDatabaseDriver.js';
|
|
3
2
|
import type { Dictionary } from '../typings.js';
|
|
4
|
-
import {
|
|
3
|
+
import { type Options } from './Configuration.js';
|
|
5
4
|
/**
|
|
6
5
|
* @internal
|
|
7
6
|
*/
|
|
8
7
|
export declare class ConfigurationLoader {
|
|
9
|
-
|
|
10
|
-
* Gets a named configuration
|
|
11
|
-
*
|
|
12
|
-
* @param contextName Load a config with the given `contextName` value. Used when config file exports array or factory function. Setting it to "default" matches also config objects without `contextName` set.
|
|
13
|
-
* @param paths Array of possible paths for a configuration file. Files will be checked in order, and the first existing one will be used. Defaults to the output of {@link ConfigurationLoader.getConfigPaths}.
|
|
14
|
-
* @param options Additional options to augment the final configuration with.
|
|
15
|
-
*/
|
|
16
|
-
static getConfiguration<D extends IDatabaseDriver = IDatabaseDriver, EM extends D[typeof EntityManagerType] & EntityManager<D> = D[typeof EntityManagerType] & EntityManager<D>>(contextName?: string, paths?: string[], options?: Partial<Options>): Promise<Configuration<D, EM>>;
|
|
17
|
-
static getConfigFile(paths: string[]): Promise<[string, unknown] | []>;
|
|
8
|
+
static loadEnvironmentVars<D extends IDatabaseDriver>(): Partial<Options<D>>;
|
|
18
9
|
static getPackageConfig(basePath?: string): Dictionary;
|
|
19
|
-
static getSettings(): Settings;
|
|
20
|
-
static getConfigPaths(): string[];
|
|
21
|
-
static isESM(): boolean;
|
|
22
|
-
/**
|
|
23
|
-
* Tries to register TS support in the following order: swc, tsx, jiti, tsimp
|
|
24
|
-
* Use `MIKRO_ORM_CLI_TS_LOADER` env var to set the loader explicitly.
|
|
25
|
-
* This method is used only in CLI context.
|
|
26
|
-
*/
|
|
27
|
-
static registerTypeScriptSupport(configPath?: string, tsLoader?: 'swc' | 'tsx' | 'jiti' | 'tsimp' | 'auto'): Promise<boolean>;
|
|
28
|
-
static loadEnvironmentVars<D extends IDatabaseDriver>(): Promise<Partial<Options<D>>>;
|
|
29
|
-
static loadEnvironmentVarsSync<D extends IDatabaseDriver>(): Partial<Options<D>>;
|
|
30
10
|
static getORMPackages(): Set<string>;
|
|
31
11
|
static getORMPackageVersion(name: string): string | undefined;
|
|
32
12
|
static checkPackageVersion(): string;
|
|
33
13
|
}
|
|
34
|
-
export interface Settings {
|
|
35
|
-
verbose?: boolean;
|
|
36
|
-
preferTs?: boolean;
|
|
37
|
-
tsLoader?: 'swc' | 'tsx' | 'jiti' | 'tsimp' | 'auto';
|
|
38
|
-
tsConfigPath?: string;
|
|
39
|
-
configPaths?: string[];
|
|
40
|
-
}
|
|
@@ -1,209 +1,11 @@
|
|
|
1
1
|
import { realpathSync } from 'node:fs';
|
|
2
|
-
import { colors } from '../logging/colors.js';
|
|
3
|
-
import { Configuration } from './Configuration.js';
|
|
4
2
|
import { Utils } from './Utils.js';
|
|
3
|
+
import { colors } from '../logging/colors.js';
|
|
5
4
|
/**
|
|
6
5
|
* @internal
|
|
7
6
|
*/
|
|
8
7
|
export class ConfigurationLoader {
|
|
9
|
-
|
|
10
|
-
* Gets a named configuration
|
|
11
|
-
*
|
|
12
|
-
* @param contextName Load a config with the given `contextName` value. Used when config file exports array or factory function. Setting it to "default" matches also config objects without `contextName` set.
|
|
13
|
-
* @param paths Array of possible paths for a configuration file. Files will be checked in order, and the first existing one will be used. Defaults to the output of {@link ConfigurationLoader.getConfigPaths}.
|
|
14
|
-
* @param options Additional options to augment the final configuration with.
|
|
15
|
-
*/
|
|
16
|
-
static async getConfiguration(contextName = 'default', paths = ConfigurationLoader.getConfigPaths(), options = {}) {
|
|
17
|
-
const env = await this.loadEnvironmentVars();
|
|
18
|
-
const configFinder = (cfg) => {
|
|
19
|
-
return typeof cfg === 'object' && cfg !== null && ('contextName' in cfg ? cfg.contextName === contextName : (contextName === 'default'));
|
|
20
|
-
};
|
|
21
|
-
const isValidConfigFactoryResult = (cfg) => {
|
|
22
|
-
return typeof cfg === 'object' && cfg !== null && (!('contextName' in cfg) || cfg.contextName === contextName);
|
|
23
|
-
};
|
|
24
|
-
const result = await this.getConfigFile(paths);
|
|
25
|
-
if (!result[0]) {
|
|
26
|
-
if (Utils.hasObjectKeys(env)) {
|
|
27
|
-
return new Configuration(Utils.mergeConfig({ contextName }, options, env));
|
|
28
|
-
}
|
|
29
|
-
throw new Error(`MikroORM config file not found in ['${paths.join(`', '`)}']`);
|
|
30
|
-
}
|
|
31
|
-
const path = result[0];
|
|
32
|
-
let tmp = result[1];
|
|
33
|
-
if (Array.isArray(tmp)) {
|
|
34
|
-
const tmpFirstIndex = tmp.findIndex(configFinder);
|
|
35
|
-
if (tmpFirstIndex === -1) {
|
|
36
|
-
// Static config not found. Try factory functions
|
|
37
|
-
let configCandidate;
|
|
38
|
-
for (let i = 0, l = tmp.length; i < l; ++i) {
|
|
39
|
-
const f = tmp[i];
|
|
40
|
-
if (typeof f !== 'function') {
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
configCandidate = await f(contextName);
|
|
44
|
-
if (!isValidConfigFactoryResult(configCandidate)) {
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
tmp = configCandidate;
|
|
48
|
-
break;
|
|
49
|
-
}
|
|
50
|
-
if (Array.isArray(tmp)) {
|
|
51
|
-
throw new Error(`MikroORM config '${contextName}' was not found within the config file '${path}'. Either add a config with this name to the array, or add a function that when given this name will return a configuration object without a name, or with name set to this name.`);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
const tmpLastIndex = tmp.findLastIndex(configFinder);
|
|
56
|
-
if (tmpLastIndex !== tmpFirstIndex) {
|
|
57
|
-
throw new Error(`MikroORM config '${contextName}' is not unique within the array exported by '${path}' (first occurrence index: ${tmpFirstIndex}; last occurrence index: ${tmpLastIndex})`);
|
|
58
|
-
}
|
|
59
|
-
tmp = tmp[tmpFirstIndex];
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
if (tmp instanceof Function) {
|
|
64
|
-
tmp = await tmp(contextName);
|
|
65
|
-
if (!isValidConfigFactoryResult(tmp)) {
|
|
66
|
-
throw new Error(`MikroORM config '${contextName}' was not what the function exported from '${path}' provided. Ensure it returns a config object with no name, or name matching the requested one.`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
if (!configFinder(tmp)) {
|
|
71
|
-
throw new Error(`MikroORM config '${contextName}' was not what the default export from '${path}' provided.`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
const esmConfigOptions = this.isESM() ? { entityGenerator: { esmImport: true } } : {};
|
|
76
|
-
return new Configuration(Utils.mergeConfig({}, esmConfigOptions, tmp, options, env));
|
|
77
|
-
}
|
|
78
|
-
static async getConfigFile(paths) {
|
|
79
|
-
for (let path of paths) {
|
|
80
|
-
path = Utils.absolutePath(path);
|
|
81
|
-
path = Utils.normalizePath(path);
|
|
82
|
-
if (Utils.pathExists(path)) {
|
|
83
|
-
const config = await Utils.dynamicImport(path);
|
|
84
|
-
/* v8 ignore next */
|
|
85
|
-
return [path, await (config.default ?? config)];
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return [];
|
|
89
|
-
}
|
|
90
|
-
static getPackageConfig(basePath = process.cwd()) {
|
|
91
|
-
if (Utils.pathExists(`${basePath}/package.json`)) {
|
|
92
|
-
/* v8 ignore next 5 */
|
|
93
|
-
try {
|
|
94
|
-
return Utils.readJSONSync(`${basePath}/package.json`);
|
|
95
|
-
}
|
|
96
|
-
catch {
|
|
97
|
-
return {};
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
const parentFolder = realpathSync(`${basePath}/..`);
|
|
101
|
-
// we reached the root folder
|
|
102
|
-
if (basePath === parentFolder) {
|
|
103
|
-
return {};
|
|
104
|
-
}
|
|
105
|
-
return this.getPackageConfig(parentFolder);
|
|
106
|
-
}
|
|
107
|
-
static getSettings() {
|
|
108
|
-
const config = ConfigurationLoader.getPackageConfig();
|
|
109
|
-
const settings = { ...config['mikro-orm'] };
|
|
110
|
-
const bool = (v) => ['true', 't', '1'].includes(v.toLowerCase());
|
|
111
|
-
settings.preferTs = process.env.MIKRO_ORM_CLI_PREFER_TS != null ? bool(process.env.MIKRO_ORM_CLI_PREFER_TS) : settings.preferTs;
|
|
112
|
-
settings.tsLoader = process.env.MIKRO_ORM_CLI_TS_LOADER ?? settings.tsLoader;
|
|
113
|
-
settings.tsConfigPath = process.env.MIKRO_ORM_CLI_TS_CONFIG_PATH ?? settings.tsConfigPath;
|
|
114
|
-
settings.verbose = process.env.MIKRO_ORM_CLI_VERBOSE != null ? bool(process.env.MIKRO_ORM_CLI_VERBOSE) : settings.verbose;
|
|
115
|
-
if (process.env.MIKRO_ORM_CLI_CONFIG?.endsWith('.ts')) {
|
|
116
|
-
settings.preferTs = true;
|
|
117
|
-
}
|
|
118
|
-
return settings;
|
|
119
|
-
}
|
|
120
|
-
static getConfigPaths() {
|
|
121
|
-
const settings = ConfigurationLoader.getSettings();
|
|
122
|
-
const typeScriptSupport = settings.preferTs ?? Utils.detectTypeScriptSupport();
|
|
123
|
-
const paths = [];
|
|
124
|
-
if (process.env.MIKRO_ORM_CLI_CONFIG) {
|
|
125
|
-
paths.push(process.env.MIKRO_ORM_CLI_CONFIG);
|
|
126
|
-
}
|
|
127
|
-
paths.push(...(settings.configPaths || []));
|
|
128
|
-
if (typeScriptSupport) {
|
|
129
|
-
paths.push('./src/mikro-orm.config.ts');
|
|
130
|
-
paths.push('./mikro-orm.config.ts');
|
|
131
|
-
}
|
|
132
|
-
const distDir = Utils.pathExists(process.cwd() + '/dist');
|
|
133
|
-
const buildDir = Utils.pathExists(process.cwd() + '/build');
|
|
134
|
-
/* v8 ignore next */
|
|
135
|
-
const path = distDir ? 'dist' : (buildDir ? 'build' : 'src');
|
|
136
|
-
paths.push(`./${path}/mikro-orm.config.js`);
|
|
137
|
-
paths.push('./mikro-orm.config.js');
|
|
138
|
-
/* v8 ignore next */
|
|
139
|
-
return Utils.unique(paths).filter(p => !p.match(/\.[mc]?ts$/) || typeScriptSupport);
|
|
140
|
-
}
|
|
141
|
-
static isESM() {
|
|
142
|
-
const config = ConfigurationLoader.getPackageConfig();
|
|
143
|
-
const type = config?.type ?? '';
|
|
144
|
-
return type === 'module';
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Tries to register TS support in the following order: swc, tsx, jiti, tsimp
|
|
148
|
-
* Use `MIKRO_ORM_CLI_TS_LOADER` env var to set the loader explicitly.
|
|
149
|
-
* This method is used only in CLI context.
|
|
150
|
-
*/
|
|
151
|
-
static async registerTypeScriptSupport(configPath = 'tsconfig.json', tsLoader) {
|
|
152
|
-
/* v8 ignore next 3 */
|
|
153
|
-
if (process.versions.bun) {
|
|
154
|
-
return true;
|
|
155
|
-
}
|
|
156
|
-
process.env.SWC_NODE_PROJECT ??= configPath;
|
|
157
|
-
process.env.TSIMP_PROJECT ??= configPath;
|
|
158
|
-
process.env.MIKRO_ORM_CLI_ALWAYS_ALLOW_TS ??= '1';
|
|
159
|
-
const isEsm = this.isESM();
|
|
160
|
-
/* v8 ignore next */
|
|
161
|
-
const importMethod = isEsm ? 'tryImport' : 'tryRequire';
|
|
162
|
-
const explicitLoader = tsLoader ?? process.env.MIKRO_ORM_CLI_TS_LOADER ?? 'auto';
|
|
163
|
-
const loaders = {
|
|
164
|
-
swc: { esm: '@swc-node/register/esm-register', cjs: '@swc-node/register' },
|
|
165
|
-
tsx: { esm: 'tsx/esm/api', cjs: 'tsx/cjs/api', cb: (tsx) => tsx.register({ tsconfig: configPath }) },
|
|
166
|
-
jiti: { esm: 'jiti/register', cjs: 'jiti/register', cb: () => Utils.setDynamicImportProvider(id => import(id).then(mod => mod?.default ?? mod)) },
|
|
167
|
-
tsimp: { esm: 'tsimp/import', cjs: 'tsimp/import' },
|
|
168
|
-
};
|
|
169
|
-
for (const loader of Utils.keys(loaders)) {
|
|
170
|
-
if (explicitLoader !== 'auto' && loader !== explicitLoader) {
|
|
171
|
-
continue;
|
|
172
|
-
}
|
|
173
|
-
const { esm, cjs, cb } = loaders[loader];
|
|
174
|
-
/* v8 ignore next */
|
|
175
|
-
const module = isEsm ? esm : cjs;
|
|
176
|
-
const mod = await Utils[importMethod]({ module });
|
|
177
|
-
if (mod) {
|
|
178
|
-
cb?.(mod);
|
|
179
|
-
process.env.MIKRO_ORM_CLI_TS_LOADER = loader;
|
|
180
|
-
return true;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
// eslint-disable-next-line no-console
|
|
184
|
-
console.warn('Neither `swc`, `tsx`, `jiti` nor `tsimp` found in the project dependencies, support for working with TypeScript files might not work. To use `swc`, you need to install both `@swc-node/register` and `@swc/core`.');
|
|
185
|
-
return false;
|
|
186
|
-
}
|
|
187
|
-
static async loadEnvironmentVars() {
|
|
188
|
-
const ret = this.loadEnvironmentVarsSync();
|
|
189
|
-
// only to keep some sort of back compatibility with those using env vars only, to support `MIKRO_ORM_TYPE`
|
|
190
|
-
const PLATFORMS = {
|
|
191
|
-
mongo: { className: 'MongoDriver', module: '@mikro-orm/mongodb' },
|
|
192
|
-
mysql: { className: 'MySqlDriver', module: '@mikro-orm/mysql' },
|
|
193
|
-
mssql: { className: 'MsSqlDriver', module: '@mikro-orm/mssql' },
|
|
194
|
-
mariadb: { className: 'MariaDbDriver', module: '@mikro-orm/mariadb' },
|
|
195
|
-
postgresql: { className: 'PostgreSqlDriver', module: '@mikro-orm/postgresql' },
|
|
196
|
-
sqlite: { className: 'SqliteDriver', module: '@mikro-orm/sqlite' },
|
|
197
|
-
libsql: { className: 'LibSqlDriver', module: '@mikro-orm/libsql' },
|
|
198
|
-
};
|
|
199
|
-
if (process.env.MIKRO_ORM_TYPE) {
|
|
200
|
-
const val = process.env.MIKRO_ORM_TYPE;
|
|
201
|
-
const driver = await import(PLATFORMS[val].module);
|
|
202
|
-
ret.driver = driver[PLATFORMS[val].className];
|
|
203
|
-
}
|
|
204
|
-
return ret;
|
|
205
|
-
}
|
|
206
|
-
static loadEnvironmentVarsSync() {
|
|
8
|
+
static loadEnvironmentVars() {
|
|
207
9
|
const ret = {};
|
|
208
10
|
const array = (v) => v.split(',').map(vv => vv.trim());
|
|
209
11
|
const bool = (v) => ['true', 't', '1'].includes(v.toLowerCase());
|
|
@@ -280,6 +82,23 @@ export class ConfigurationLoader {
|
|
|
280
82
|
cleanup(ret, 'seeder');
|
|
281
83
|
return ret;
|
|
282
84
|
}
|
|
85
|
+
static getPackageConfig(basePath = process.cwd()) {
|
|
86
|
+
if (Utils.pathExists(`${basePath}/package.json`)) {
|
|
87
|
+
/* v8 ignore next 5 */
|
|
88
|
+
try {
|
|
89
|
+
return Utils.readJSONSync(`${basePath}/package.json`);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return {};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const parentFolder = realpathSync(`${basePath}/..`);
|
|
96
|
+
// we reached the root folder
|
|
97
|
+
if (basePath === parentFolder) {
|
|
98
|
+
return {};
|
|
99
|
+
}
|
|
100
|
+
return this.getPackageConfig(parentFolder);
|
|
101
|
+
}
|
|
283
102
|
static getORMPackages() {
|
|
284
103
|
const pkg = this.getPackageConfig();
|
|
285
104
|
return new Set([
|
|
@@ -613,10 +613,10 @@ export class EntityComparator {
|
|
|
613
613
|
if (['buffer', 'uint8array'].includes(type)) {
|
|
614
614
|
return this.getGenericComparator(this.wrap(prop.name), `!compareBuffers(last${this.wrap(prop.name)}, current${this.wrap(prop.name)})`);
|
|
615
615
|
}
|
|
616
|
-
if (
|
|
616
|
+
if (type === 'date') {
|
|
617
617
|
return this.getGenericComparator(this.wrap(prop.name), `last${this.wrap(prop.name)}.valueOf() !== current${this.wrap(prop.name)}.valueOf()`);
|
|
618
618
|
}
|
|
619
|
-
if (
|
|
619
|
+
if (type === 'objectid') {
|
|
620
620
|
// We might be comparing PK to object, in case we compare with cached data of populated entity
|
|
621
621
|
// in such case we just ignore the comparison and fallback to `equals()` (which will still mark
|
|
622
622
|
// it as not equal as we compare PK to plain object).
|
package/utils/QueryHelper.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Reference } from '../entity/Reference.js';
|
|
2
2
|
import { Utils } from './Utils.js';
|
|
3
|
-
import { GroupOperator, ReferenceKind } from '../enums.js';
|
|
3
|
+
import { ARRAY_OPERATORS, GroupOperator, JSON_KEY_OPERATORS, ReferenceKind } from '../enums.js';
|
|
4
4
|
import { JsonType } from '../types/JsonType.js';
|
|
5
5
|
import { helper } from '../entity/wrap.js';
|
|
6
|
-
import {
|
|
6
|
+
import { isRaw, RawQueryFragment } from './RawQueryFragment.js';
|
|
7
7
|
/** @internal */
|
|
8
8
|
export class QueryHelper {
|
|
9
9
|
static SUPPORTED_OPERATORS = ['>', '<', '<=', '>=', '!', '!='];
|
|
@@ -44,7 +44,7 @@ export class QueryHelper {
|
|
|
44
44
|
}
|
|
45
45
|
const keys = Object.keys(where);
|
|
46
46
|
const groupOperator = keys.find(k => {
|
|
47
|
-
return
|
|
47
|
+
return k in GroupOperator && Array.isArray(where[k]) && where[k].every(cond => {
|
|
48
48
|
return Utils.isPlainObject(cond) && Object.keys(cond).every(k2 => {
|
|
49
49
|
if (Utils.isOperator(k2, false)) {
|
|
50
50
|
if (k2 === '$not') {
|
|
@@ -241,12 +241,12 @@ export class QueryHelper {
|
|
|
241
241
|
return o;
|
|
242
242
|
}, {});
|
|
243
243
|
}
|
|
244
|
-
if (key &&
|
|
244
|
+
if (key && JSON_KEY_OPERATORS.includes(key)) {
|
|
245
245
|
return Array.isArray(cond)
|
|
246
246
|
? platform.marshallArray(cond)
|
|
247
247
|
: cond;
|
|
248
248
|
}
|
|
249
|
-
if (Array.isArray(cond) && !(key &&
|
|
249
|
+
if (Array.isArray(cond) && !(key && ARRAY_OPERATORS.includes(key))) {
|
|
250
250
|
return cond.map(v => QueryHelper.processCustomType(prop, v, platform, key, fromQuery));
|
|
251
251
|
}
|
|
252
252
|
if (isRaw(cond)) {
|
package/utils/Utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Dictionary, EntityData, EntityDictionary, EntityKey, EntityMetadata, EntityName, EntityProperty,
|
|
1
|
+
import type { Dictionary, EntityData, EntityDictionary, EntityKey, EntityMetadata, EntityName, EntityProperty, Primary } from '../typings.js';
|
|
2
2
|
import type { Collection } from '../entity/Collection.js';
|
|
3
3
|
import type { Platform } from '../platforms/Platform.js';
|
|
4
4
|
import type { ScalarReference } from '../entity/Reference.js';
|
|
@@ -14,32 +14,14 @@ export declare function parseJsonSafe<T = unknown>(value: unknown): T;
|
|
|
14
14
|
export declare class Utils {
|
|
15
15
|
static readonly PK_SEPARATOR = "~~~";
|
|
16
16
|
static dynamicImportProvider: (id: string) => Promise<any>;
|
|
17
|
-
/**
|
|
18
|
-
* Checks if the argument is not undefined
|
|
19
|
-
*/
|
|
20
|
-
static isDefined<T = Record<string, unknown>>(data: any): data is T;
|
|
21
17
|
/**
|
|
22
18
|
* Checks if the argument is instance of `Object`. Returns false for arrays.
|
|
23
19
|
*/
|
|
24
20
|
static isObject<T = Dictionary>(o: any): o is T;
|
|
25
|
-
/**
|
|
26
|
-
* Relation decorators allow using two signatures
|
|
27
|
-
* - using first parameter as options object
|
|
28
|
-
* - using all parameters
|
|
29
|
-
*
|
|
30
|
-
* This function validates those two ways are not mixed and returns the final options object.
|
|
31
|
-
* If the second way is used, we always consider the last parameter as options object.
|
|
32
|
-
* @internal
|
|
33
|
-
*/
|
|
34
|
-
static processDecoratorParameters<T>(params: Dictionary): T;
|
|
35
|
-
/**
|
|
36
|
-
* Checks if the argument is instance of `Object`, but not one of the blacklisted types. Returns false for arrays.
|
|
37
|
-
*/
|
|
38
|
-
static isNotObject<T = Dictionary>(o: any, not: any[]): o is T;
|
|
39
21
|
/**
|
|
40
22
|
* Removes `undefined` properties (recursively) so they are not saved as nulls
|
|
41
23
|
*/
|
|
42
|
-
static dropUndefinedProperties
|
|
24
|
+
static dropUndefinedProperties(o: any, value?: undefined | null, visited?: Set<unknown>): void;
|
|
43
25
|
/**
|
|
44
26
|
* Returns the number of properties on `obj`. This is 20x faster than Object.keys(obj).length.
|
|
45
27
|
* @see https://github.com/deepkit/deepkit-framework/blob/master/packages/core/src/core.ts
|
|
@@ -50,14 +32,6 @@ export declare class Utils {
|
|
|
50
32
|
* @see https://github.com/deepkit/deepkit-framework/blob/master/packages/core/src/core.ts
|
|
51
33
|
*/
|
|
52
34
|
static hasObjectKeys(object: Dictionary): boolean;
|
|
53
|
-
/**
|
|
54
|
-
* Checks if the argument is string
|
|
55
|
-
*/
|
|
56
|
-
static isString(s: any): s is string;
|
|
57
|
-
/**
|
|
58
|
-
* Checks if the argument is number
|
|
59
|
-
*/
|
|
60
|
-
static isNumber<T = number>(s: any): s is T;
|
|
61
35
|
/**
|
|
62
36
|
* Checks if arguments are deeply (but not strictly) equal.
|
|
63
37
|
*/
|
|
@@ -78,11 +52,6 @@ export declare class Utils {
|
|
|
78
52
|
* Merges all sources into the target recursively.
|
|
79
53
|
*/
|
|
80
54
|
private static _merge;
|
|
81
|
-
static getRootEntity(metadata: IMetadataStorage, meta: EntityMetadata): EntityMetadata;
|
|
82
|
-
/**
|
|
83
|
-
* Computes difference between two objects, ignoring items missing in `b`.
|
|
84
|
-
*/
|
|
85
|
-
static diff(a: Dictionary, b: Dictionary): Record<keyof (typeof a & typeof b), any>;
|
|
86
55
|
/**
|
|
87
56
|
* Creates deep copy of given object.
|
|
88
57
|
*/
|
|
@@ -133,12 +102,6 @@ export declare class Utils {
|
|
|
133
102
|
* Checks whether given object is a scalar reference.
|
|
134
103
|
*/
|
|
135
104
|
static isScalarReference<T = unknown>(data: any, allowReference?: boolean): data is ScalarReference<any> & {};
|
|
136
|
-
/**
|
|
137
|
-
* Checks whether the argument is ObjectId instance
|
|
138
|
-
*/
|
|
139
|
-
static isObjectID(key: any): key is {
|
|
140
|
-
toHexString: () => string;
|
|
141
|
-
};
|
|
142
105
|
/**
|
|
143
106
|
* Checks whether the argument is empty (array without items, object without keys or falsy value).
|
|
144
107
|
*/
|
|
@@ -152,11 +115,6 @@ export declare class Utils {
|
|
|
152
115
|
* Tries to detect TypeScript support.
|
|
153
116
|
*/
|
|
154
117
|
static detectTypeScriptSupport(): boolean;
|
|
155
|
-
/**
|
|
156
|
-
* Uses some dark magic to get source path to caller where decorator is used.
|
|
157
|
-
* Analyses stack trace of error created inside the function call.
|
|
158
|
-
*/
|
|
159
|
-
static lookupPathFromDecorator(name: string, stack?: string[]): string;
|
|
160
118
|
/**
|
|
161
119
|
* Gets the type of the argument.
|
|
162
120
|
*/
|
|
@@ -203,11 +161,7 @@ export declare class Utils {
|
|
|
203
161
|
static extractEnumValues(target: Dictionary): (string | number)[];
|
|
204
162
|
static flatten<T>(arrays: T[][]): T[];
|
|
205
163
|
static isOperator(key: PropertyKey, includeGroupOperators?: boolean): boolean;
|
|
206
|
-
static isGroupOperator(key: PropertyKey): boolean;
|
|
207
|
-
static isArrayOperator(key: PropertyKey): boolean;
|
|
208
|
-
static isJsonKeyOperator(key: PropertyKey): boolean;
|
|
209
164
|
static hasNestedKey(object: unknown, key: string): boolean;
|
|
210
|
-
static getGlobalStorage(namespace: string): Dictionary;
|
|
211
165
|
/**
|
|
212
166
|
* Require a module from a specific location
|
|
213
167
|
* @param id The module to require
|
|
@@ -221,7 +175,6 @@ export declare class Utils {
|
|
|
221
175
|
*/
|
|
222
176
|
static resolveModulePath(id: string, from?: string): string;
|
|
223
177
|
static dynamicImport<T = any>(id: string): Promise<T>;
|
|
224
|
-
static setDynamicImportProvider(provider: (id: string) => Promise<unknown>): void;
|
|
225
178
|
static ensureDir(path: string): void;
|
|
226
179
|
static readJSONSync(path: string): Dictionary;
|
|
227
180
|
static getORMVersion(): string;
|
|
@@ -239,7 +192,6 @@ export declare class Utils {
|
|
|
239
192
|
module: string;
|
|
240
193
|
warning?: string;
|
|
241
194
|
}): Promise<T | undefined>;
|
|
242
|
-
static stripRelativePath(str: string): string;
|
|
243
195
|
static xor(a: boolean, b: boolean): boolean;
|
|
244
196
|
static keys<T extends object>(obj: T): (keyof T)[];
|
|
245
197
|
static values<T extends object>(obj: T): T[keyof T][];
|
package/utils/Utils.js
CHANGED
|
@@ -4,7 +4,7 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
4
4
|
import { existsSync, globSync, statSync, mkdirSync, readFileSync } from 'node:fs';
|
|
5
5
|
import { createHash } from 'node:crypto';
|
|
6
6
|
import { clone } from './clone.js';
|
|
7
|
-
import {
|
|
7
|
+
import { GroupOperator, PlainObject, QueryOperator, ReferenceKind } from '../enums.js';
|
|
8
8
|
import { helper } from '../entity/wrap.js';
|
|
9
9
|
function compareConstructors(a, b) {
|
|
10
10
|
if (a.constructor === b.constructor) {
|
|
@@ -130,50 +130,12 @@ export class Utils {
|
|
|
130
130
|
static PK_SEPARATOR = '~~~';
|
|
131
131
|
/* v8 ignore next */
|
|
132
132
|
static dynamicImportProvider = (id) => import(id);
|
|
133
|
-
/**
|
|
134
|
-
* Checks if the argument is not undefined
|
|
135
|
-
*/
|
|
136
|
-
static isDefined(data) {
|
|
137
|
-
return typeof data !== 'undefined';
|
|
138
|
-
}
|
|
139
133
|
/**
|
|
140
134
|
* Checks if the argument is instance of `Object`. Returns false for arrays.
|
|
141
135
|
*/
|
|
142
136
|
static isObject(o) {
|
|
143
137
|
return !!o && typeof o === 'object' && !Array.isArray(o);
|
|
144
138
|
}
|
|
145
|
-
/**
|
|
146
|
-
* Relation decorators allow using two signatures
|
|
147
|
-
* - using first parameter as options object
|
|
148
|
-
* - using all parameters
|
|
149
|
-
*
|
|
150
|
-
* This function validates those two ways are not mixed and returns the final options object.
|
|
151
|
-
* If the second way is used, we always consider the last parameter as options object.
|
|
152
|
-
* @internal
|
|
153
|
-
*/
|
|
154
|
-
static processDecoratorParameters(params) {
|
|
155
|
-
const keys = Object.keys(params);
|
|
156
|
-
const values = Object.values(params);
|
|
157
|
-
if (!Utils.isPlainObject(values[0])) {
|
|
158
|
-
const lastKey = keys[keys.length - 1];
|
|
159
|
-
const last = params[lastKey];
|
|
160
|
-
delete params[lastKey];
|
|
161
|
-
return { ...last, ...params };
|
|
162
|
-
}
|
|
163
|
-
// validate only first parameter is used if its an option object
|
|
164
|
-
const empty = (v) => v == null || (Utils.isPlainObject(v) && !Utils.hasObjectKeys(v));
|
|
165
|
-
if (values.slice(1).some(v => !empty(v))) {
|
|
166
|
-
throw new Error('Mixing first decorator parameter as options object with other parameters is forbidden. ' +
|
|
167
|
-
'If you want to use the options parameter at first position, provide all options inside it.');
|
|
168
|
-
}
|
|
169
|
-
return values[0];
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Checks if the argument is instance of `Object`, but not one of the blacklisted types. Returns false for arrays.
|
|
173
|
-
*/
|
|
174
|
-
static isNotObject(o, not) {
|
|
175
|
-
return this.isObject(o) && !not.some(cls => o instanceof cls);
|
|
176
|
-
}
|
|
177
139
|
/**
|
|
178
140
|
* Removes `undefined` properties (recursively) so they are not saved as nulls
|
|
179
141
|
*/
|
|
@@ -221,18 +183,6 @@ export class Utils {
|
|
|
221
183
|
}
|
|
222
184
|
return false;
|
|
223
185
|
}
|
|
224
|
-
/**
|
|
225
|
-
* Checks if the argument is string
|
|
226
|
-
*/
|
|
227
|
-
static isString(s) {
|
|
228
|
-
return typeof s === 'string';
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Checks if the argument is number
|
|
232
|
-
*/
|
|
233
|
-
static isNumber(s) {
|
|
234
|
-
return typeof s === 'number';
|
|
235
|
-
}
|
|
236
186
|
/**
|
|
237
187
|
* Checks if arguments are deeply (but not strictly) equal.
|
|
238
188
|
*/
|
|
@@ -291,30 +241,6 @@ export class Utils {
|
|
|
291
241
|
}
|
|
292
242
|
return Utils._merge(target, sources, ignoreUndefined);
|
|
293
243
|
}
|
|
294
|
-
static getRootEntity(metadata, meta) {
|
|
295
|
-
const base = meta.extends && metadata.find(Utils.className(meta.extends));
|
|
296
|
-
if (!base || base === meta) { // make sure we do not fall into infinite loop
|
|
297
|
-
return meta;
|
|
298
|
-
}
|
|
299
|
-
const root = Utils.getRootEntity(metadata, base);
|
|
300
|
-
if (root.discriminatorColumn) {
|
|
301
|
-
return root;
|
|
302
|
-
}
|
|
303
|
-
return meta;
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* Computes difference between two objects, ignoring items missing in `b`.
|
|
307
|
-
*/
|
|
308
|
-
static diff(a, b) {
|
|
309
|
-
const ret = {};
|
|
310
|
-
for (const k of Object.keys(b)) {
|
|
311
|
-
if (Utils.equals(a[k], b[k])) {
|
|
312
|
-
continue;
|
|
313
|
-
}
|
|
314
|
-
ret[k] = b[k];
|
|
315
|
-
}
|
|
316
|
-
return ret;
|
|
317
|
-
}
|
|
318
244
|
/**
|
|
319
245
|
* Creates deep copy of given object.
|
|
320
246
|
*/
|
|
@@ -398,7 +324,7 @@ export class Utils {
|
|
|
398
324
|
return true;
|
|
399
325
|
}
|
|
400
326
|
if (Utils.isObject(key)) {
|
|
401
|
-
if (key.constructor
|
|
327
|
+
if (key.constructor?.name === 'ObjectId') {
|
|
402
328
|
return true;
|
|
403
329
|
}
|
|
404
330
|
if (!Utils.isPlainObject(key) && !Utils.isEntity(key, true)) {
|
|
@@ -583,12 +509,6 @@ export class Utils {
|
|
|
583
509
|
static isScalarReference(data, allowReference = false) {
|
|
584
510
|
return typeof data === 'object' && data?.__scalarReference;
|
|
585
511
|
}
|
|
586
|
-
/**
|
|
587
|
-
* Checks whether the argument is ObjectId instance
|
|
588
|
-
*/
|
|
589
|
-
static isObjectID(key) {
|
|
590
|
-
return Utils.isObject(key) && key.constructor && key.constructor.name.toLowerCase() === 'objectid';
|
|
591
|
-
}
|
|
592
512
|
/**
|
|
593
513
|
* Checks whether the argument is empty (array without items, object without keys or falsy value).
|
|
594
514
|
*/
|
|
@@ -632,43 +552,6 @@ export class Utils {
|
|
|
632
552
|
|| arg.includes('node_modules/tsx/'); // check for tsx loader
|
|
633
553
|
});
|
|
634
554
|
}
|
|
635
|
-
/**
|
|
636
|
-
* Uses some dark magic to get source path to caller where decorator is used.
|
|
637
|
-
* Analyses stack trace of error created inside the function call.
|
|
638
|
-
*/
|
|
639
|
-
static lookupPathFromDecorator(name, stack) {
|
|
640
|
-
// use some dark magic to get source path to caller
|
|
641
|
-
stack = stack || new Error().stack.split('\n');
|
|
642
|
-
// In some situations (e.g. swc 1.3.4+), the presence of a source map can obscure the call to
|
|
643
|
-
// __decorate(), replacing it with the constructor name. To support these cases we look for
|
|
644
|
-
// Reflect.decorate() as well. Also when babel is used, we need to check
|
|
645
|
-
// the `_applyDecoratedDescriptor` method instead.
|
|
646
|
-
let line = stack.findIndex(line => line.match(/__decorate|Reflect\.decorate|_applyDecoratedDescriptor/));
|
|
647
|
-
// bun does not have those lines at all, only the DecorateProperty/DecorateConstructor,
|
|
648
|
-
// but those are also present in node, so we need to check this only if they weren't found.
|
|
649
|
-
if (line === -1) {
|
|
650
|
-
// here we handle bun which stack is different from nodejs so we search for reflect-metadata
|
|
651
|
-
// Different bun versions might have different stack traces. The "last index" works for both 1.2.6 and 1.2.7.
|
|
652
|
-
const reflectLine = stack.findLastIndex(line => Utils.normalizePath(line).includes('node_modules/reflect-metadata/Reflect.js'));
|
|
653
|
-
if (reflectLine === -1 || reflectLine + 2 >= stack.length || !stack[reflectLine + 1].includes('bun:wrap')) {
|
|
654
|
-
return name;
|
|
655
|
-
}
|
|
656
|
-
line = reflectLine + 2;
|
|
657
|
-
}
|
|
658
|
-
if (stack[line].includes('Reflect.decorate')) {
|
|
659
|
-
line++;
|
|
660
|
-
}
|
|
661
|
-
if (Utils.normalizePath(stack[line]).includes('node_modules/tslib/tslib')) {
|
|
662
|
-
line++;
|
|
663
|
-
}
|
|
664
|
-
try {
|
|
665
|
-
const re = stack[line].match(/\(.+\)/i) ? /\((.*):\d+:\d+\)/ : /at\s*(.*):\d+:\d+$/;
|
|
666
|
-
return Utils.normalizePath(stack[line].match(re)[1]);
|
|
667
|
-
}
|
|
668
|
-
catch {
|
|
669
|
-
return name;
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
555
|
/**
|
|
673
556
|
* Gets the type of the argument.
|
|
674
557
|
*/
|
|
@@ -852,15 +735,6 @@ export class Utils {
|
|
|
852
735
|
}
|
|
853
736
|
return key in GroupOperator || key in QueryOperator;
|
|
854
737
|
}
|
|
855
|
-
static isGroupOperator(key) {
|
|
856
|
-
return key in GroupOperator;
|
|
857
|
-
}
|
|
858
|
-
static isArrayOperator(key) {
|
|
859
|
-
return ARRAY_OPERATORS.includes(key);
|
|
860
|
-
}
|
|
861
|
-
static isJsonKeyOperator(key) {
|
|
862
|
-
return JSON_KEY_OPERATORS.includes(key);
|
|
863
|
-
}
|
|
864
738
|
static hasNestedKey(object, key) {
|
|
865
739
|
if (!object) {
|
|
866
740
|
return false;
|
|
@@ -873,11 +747,6 @@ export class Utils {
|
|
|
873
747
|
}
|
|
874
748
|
return false;
|
|
875
749
|
}
|
|
876
|
-
static getGlobalStorage(namespace) {
|
|
877
|
-
const key = `mikro-orm-${namespace}`;
|
|
878
|
-
globalThis[key] = globalThis[key] || {};
|
|
879
|
-
return globalThis[key];
|
|
880
|
-
}
|
|
881
750
|
/**
|
|
882
751
|
* Require a module from a specific location
|
|
883
752
|
* @param id The module to require
|
|
@@ -909,10 +778,6 @@ export class Utils {
|
|
|
909
778
|
const specifier = id.startsWith('file://') ? id : pathToFileURL(id).href;
|
|
910
779
|
return this.dynamicImportProvider(specifier);
|
|
911
780
|
}
|
|
912
|
-
/* v8 ignore next 3 */
|
|
913
|
-
static setDynamicImportProvider(provider) {
|
|
914
|
-
this.dynamicImportProvider = provider;
|
|
915
|
-
}
|
|
916
781
|
static ensureDir(path) {
|
|
917
782
|
if (!existsSync(path)) {
|
|
918
783
|
mkdirSync(path, { recursive: true });
|
|
@@ -1086,9 +951,6 @@ export class Utils {
|
|
|
1086
951
|
throw err;
|
|
1087
952
|
}
|
|
1088
953
|
}
|
|
1089
|
-
static stripRelativePath(str) {
|
|
1090
|
-
return str.replace(/^(?:\.\.\/|\.\/)+/, '/');
|
|
1091
|
-
}
|
|
1092
954
|
static xor(a, b) {
|
|
1093
955
|
return (a || b) && !(a && b);
|
|
1094
956
|
}
|