@mikro-orm/core 7.0.0-dev.60 → 7.0.0-dev.62
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/MikroORM.js +0 -1
- package/decorators/Embeddable.d.ts +2 -0
- package/decorators/Entity.d.ts +2 -0
- package/entity/ArrayCollection.js +1 -3
- package/entity/EntityFactory.js +24 -19
- package/entity/EntityHelper.js +1 -1
- package/metadata/EntitySchema.js +1 -3
- package/metadata/MetadataDiscovery.js +1 -4
- package/package.json +2 -4
- package/typings.d.ts +1 -2
- package/utils/ConfigurationLoader.d.ts +0 -1
- package/utils/ConfigurationLoader.js +0 -12
- package/utils/Utils.d.ts +3 -19
- package/utils/Utils.js +25 -43
package/MikroORM.js
CHANGED
|
@@ -39,7 +39,6 @@ export class MikroORM {
|
|
|
39
39
|
* - no support for folder based discovery
|
|
40
40
|
*/
|
|
41
41
|
constructor(options) {
|
|
42
|
-
ConfigurationLoader.registerDotenv(options);
|
|
43
42
|
const env = ConfigurationLoader.loadEnvironmentVarsSync();
|
|
44
43
|
const coreVersion = ConfigurationLoader.checkPackageVersion();
|
|
45
44
|
options = Utils.merge(options, env);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { AnyString, Dictionary, EntityClass } from '../typings.js';
|
|
2
2
|
export declare function Embeddable<T>(options?: EmbeddableOptions<T>): (target: T) => T;
|
|
3
3
|
export interface EmbeddableOptions<T> {
|
|
4
|
+
/** Specify constructor parameters to be used in `em.create` or when `forceConstructor` is enabled. Those should be names of declared entity properties in the same order as your constructor uses them. The ORM tries to infer those automatically, use this option in case the inference fails. */
|
|
5
|
+
constructorParams?: (T extends EntityClass<infer P> ? keyof P : string)[];
|
|
4
6
|
discriminatorColumn?: (T extends EntityClass<infer P> ? keyof P : string) | AnyString;
|
|
5
7
|
discriminatorMap?: Dictionary<string>;
|
|
6
8
|
discriminatorValue?: number | string;
|
package/decorators/Entity.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export type EntityOptions<T, E = T extends EntityClass<infer P> ? P : T> = {
|
|
|
16
16
|
discriminatorValue?: number | string;
|
|
17
17
|
/** Enforce use of constructor when creating managed entity instances. */
|
|
18
18
|
forceConstructor?: boolean;
|
|
19
|
+
/** Specify constructor parameters to be used in `em.create` or when `forceConstructor` is enabled. Those should be names of declared entity properties in the same order as your constructor uses them. The ORM tries to infer those automatically, use this option in case the inference fails. */
|
|
20
|
+
constructorParams?: (T extends EntityClass<infer P> ? keyof P : string)[];
|
|
19
21
|
/** Specify comment to table. (SQL only) */
|
|
20
22
|
comment?: string;
|
|
21
23
|
/** Marks entity as abstract, such entities are inlined during discovery. */
|
|
@@ -32,9 +32,7 @@ export class ArrayCollection {
|
|
|
32
32
|
if (this.items.size === 0) {
|
|
33
33
|
return [];
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
const args = meta.toJsonParams.map(() => undefined);
|
|
37
|
-
return this.map(item => wrap(item).toJSON(...args));
|
|
35
|
+
return this.map(item => wrap(item).toJSON());
|
|
38
36
|
}
|
|
39
37
|
toJSON() {
|
|
40
38
|
return this.toArray();
|
package/entity/EntityFactory.js
CHANGED
|
@@ -60,7 +60,7 @@ export class EntityFactory {
|
|
|
60
60
|
wrapped.__initialized = options.initialized;
|
|
61
61
|
if (options.newEntity || meta.forceConstructor || meta.virtual) {
|
|
62
62
|
const tmp = { ...data };
|
|
63
|
-
meta.constructorParams
|
|
63
|
+
meta.constructorParams?.forEach(prop => delete tmp[prop]);
|
|
64
64
|
this.hydrate(entity, meta2, tmp, options);
|
|
65
65
|
// since we now process only a copy of the `data` via hydrator, but later we register the state with the full snapshot,
|
|
66
66
|
// we need to go through all props with custom types that have `ensureComparable: true` and ensure they are comparable
|
|
@@ -299,32 +299,37 @@ export class EntityFactory {
|
|
|
299
299
|
* returns parameters for entity constructor, creating references from plain ids
|
|
300
300
|
*/
|
|
301
301
|
extractConstructorParams(meta, data, options) {
|
|
302
|
+
if (!meta.constructorParams) {
|
|
303
|
+
return [data];
|
|
304
|
+
}
|
|
302
305
|
return meta.constructorParams.map(k => {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
+
const prop = meta.properties[k];
|
|
307
|
+
const value = data[k];
|
|
308
|
+
if (prop && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && value) {
|
|
309
|
+
const pk = Reference.unwrapReference(value);
|
|
310
|
+
const entity = this.unitOfWork.getById(prop.type, pk, options.schema, true);
|
|
306
311
|
if (entity) {
|
|
307
312
|
return entity;
|
|
308
313
|
}
|
|
309
|
-
if (Utils.isEntity(
|
|
310
|
-
return
|
|
314
|
+
if (Utils.isEntity(value)) {
|
|
315
|
+
return value;
|
|
311
316
|
}
|
|
312
|
-
const nakedPk = Utils.extractPK(
|
|
313
|
-
if (Utils.isObject(
|
|
314
|
-
return this.create(
|
|
317
|
+
const nakedPk = Utils.extractPK(value, prop.targetMeta, true);
|
|
318
|
+
if (Utils.isObject(value) && !nakedPk) {
|
|
319
|
+
return this.create(prop.type, value, options);
|
|
315
320
|
}
|
|
316
321
|
const { newEntity, initialized, ...rest } = options;
|
|
317
|
-
const target = this.createReference(
|
|
318
|
-
return Reference.wrapReference(target,
|
|
322
|
+
const target = this.createReference(prop.type, nakedPk, rest);
|
|
323
|
+
return Reference.wrapReference(target, prop);
|
|
319
324
|
}
|
|
320
|
-
if (
|
|
325
|
+
if (prop?.kind === ReferenceKind.EMBEDDED && value) {
|
|
321
326
|
/* v8 ignore next 3 */
|
|
322
|
-
if (Utils.isEntity(
|
|
323
|
-
return
|
|
327
|
+
if (Utils.isEntity(value)) {
|
|
328
|
+
return value;
|
|
324
329
|
}
|
|
325
|
-
return this.createEmbeddable(
|
|
330
|
+
return this.createEmbeddable(prop.type, value, options);
|
|
326
331
|
}
|
|
327
|
-
if (!
|
|
332
|
+
if (!prop) {
|
|
328
333
|
const tmp = { ...data };
|
|
329
334
|
for (const prop of meta.props) {
|
|
330
335
|
if (!options.convertCustomTypes || !prop.customType || tmp[prop.name] == null) {
|
|
@@ -339,10 +344,10 @@ export class EntityFactory {
|
|
|
339
344
|
}
|
|
340
345
|
return tmp;
|
|
341
346
|
}
|
|
342
|
-
if (options.convertCustomTypes &&
|
|
343
|
-
return
|
|
347
|
+
if (options.convertCustomTypes && prop.customType && value != null) {
|
|
348
|
+
return prop.customType.convertToJSValue(value, this.platform);
|
|
344
349
|
}
|
|
345
|
-
return
|
|
350
|
+
return value;
|
|
346
351
|
});
|
|
347
352
|
}
|
|
348
353
|
get unitOfWork() {
|
package/entity/EntityHelper.js
CHANGED
|
@@ -32,7 +32,7 @@ export class EntityHelper {
|
|
|
32
32
|
const prototype = meta.prototype;
|
|
33
33
|
if (!prototype.toJSON) { // toJSON can be overridden
|
|
34
34
|
prototype.toJSON = function (...args) {
|
|
35
|
-
return EntityTransformer.toObject(this, ...args
|
|
35
|
+
return EntityTransformer.toObject(this, ...args);
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
}
|
package/metadata/EntitySchema.js
CHANGED
|
@@ -157,9 +157,7 @@ export class EntitySchema {
|
|
|
157
157
|
this._meta.prototype = proto.prototype;
|
|
158
158
|
this._meta.className = proto.name;
|
|
159
159
|
if (!sameClass || !this._meta.constructorParams) {
|
|
160
|
-
|
|
161
|
-
this._meta.constructorParams = Utils.getParamNames(tokens, 'constructor');
|
|
162
|
-
this._meta.toJsonParams = Utils.getParamNames(tokens, 'toJSON').filter(p => p !== '...args');
|
|
160
|
+
this._meta.constructorParams = Utils.getConstructorParams(proto);
|
|
163
161
|
}
|
|
164
162
|
if (!this.internal) {
|
|
165
163
|
EntitySchema.REGISTRY.set(proto, this);
|
|
@@ -731,12 +731,9 @@ export class MetadataDiscovery {
|
|
|
731
731
|
Utils.keys(base.hooks).forEach(type => {
|
|
732
732
|
meta.hooks[type] = Utils.unique([...base.hooks[type], ...(meta.hooks[type] || [])]);
|
|
733
733
|
});
|
|
734
|
-
if (meta.constructorParams
|
|
734
|
+
if ((meta.constructorParams?.length ?? 0) === 0 && (base.constructorParams?.length ?? 0) > 0) {
|
|
735
735
|
meta.constructorParams = [...base.constructorParams];
|
|
736
736
|
}
|
|
737
|
-
if (meta.toJsonParams.length === 0 && base.toJsonParams.length > 0) {
|
|
738
|
-
meta.toJsonParams = [...base.toJsonParams];
|
|
739
|
-
}
|
|
740
737
|
return order;
|
|
741
738
|
}
|
|
742
739
|
initPolyEmbeddables(embeddedProp, discovered, visited = new Set()) {
|
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.62",
|
|
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,9 +52,7 @@
|
|
|
52
52
|
"access": "public"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"
|
|
56
|
-
"esprima": "4.0.1",
|
|
57
|
-
"mikro-orm": "7.0.0-dev.60",
|
|
55
|
+
"mikro-orm": "7.0.0-dev.62",
|
|
58
56
|
"reflect-metadata": "0.2.2"
|
|
59
57
|
},
|
|
60
58
|
"peerDependencies": {
|
package/typings.d.ts
CHANGED
|
@@ -451,9 +451,8 @@ export interface EntityMetadata<T = any> {
|
|
|
451
451
|
discriminatorValue?: number | string;
|
|
452
452
|
discriminatorMap?: Dictionary<string>;
|
|
453
453
|
embeddable: boolean;
|
|
454
|
-
constructorParams
|
|
454
|
+
constructorParams?: (keyof T)[];
|
|
455
455
|
forceConstructor: boolean;
|
|
456
|
-
toJsonParams: string[];
|
|
457
456
|
extends: string;
|
|
458
457
|
collection: string;
|
|
459
458
|
path: string;
|
|
@@ -25,7 +25,6 @@ export declare class ConfigurationLoader {
|
|
|
25
25
|
* This method is used only in CLI context.
|
|
26
26
|
*/
|
|
27
27
|
static registerTypeScriptSupport(configPath?: string, tsLoader?: 'swc' | 'tsx' | 'jiti' | 'tsimp' | 'auto'): Promise<boolean>;
|
|
28
|
-
static registerDotenv<D extends IDatabaseDriver>(options: Options<D>): void;
|
|
29
28
|
static loadEnvironmentVars<D extends IDatabaseDriver>(): Promise<Partial<Options<D>>>;
|
|
30
29
|
static loadEnvironmentVarsSync<D extends IDatabaseDriver>(): Partial<Options<D>>;
|
|
31
30
|
static getORMPackages(): Set<string>;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import dotenv from 'dotenv';
|
|
2
1
|
import { realpathSync } from 'node:fs';
|
|
3
2
|
import { colors } from '../logging/colors.js';
|
|
4
3
|
import { Configuration } from './Configuration.js';
|
|
@@ -185,17 +184,6 @@ export class ConfigurationLoader {
|
|
|
185
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`.');
|
|
186
185
|
return false;
|
|
187
186
|
}
|
|
188
|
-
static registerDotenv(options) {
|
|
189
|
-
const path = process.env.MIKRO_ORM_ENV ?? ((options.baseDir ?? process.cwd()) + '/.env');
|
|
190
|
-
const env = {};
|
|
191
|
-
dotenv.config({ path, processEnv: env, quiet: true });
|
|
192
|
-
// only propagate known env vars
|
|
193
|
-
for (const key of Object.keys(env)) {
|
|
194
|
-
if (key.startsWith('MIKRO_ORM_')) {
|
|
195
|
-
process.env[key] ??= env[key]; // respect user provided values
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
187
|
static async loadEnvironmentVars() {
|
|
200
188
|
const ret = this.loadEnvironmentVarsSync();
|
|
201
189
|
// only to keep some sort of back compatibility with those using env vars only, to support `MIKRO_ORM_TYPE`
|
package/utils/Utils.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ import type { Dictionary, EntityData, EntityDictionary, EntityKey, EntityMetadat
|
|
|
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';
|
|
5
|
-
export declare const ObjectBindingPattern: unique symbol;
|
|
6
5
|
export declare function compareObjects(a: any, b: any): boolean;
|
|
7
6
|
export declare function compareArrays(a: any[] | string, b: any[] | string): boolean;
|
|
8
7
|
export declare function compareBooleans(a: unknown, b: unknown): boolean;
|
|
@@ -101,26 +100,11 @@ export declare class Utils {
|
|
|
101
100
|
*/
|
|
102
101
|
static renameKey<T>(payload: T, from: string | keyof T, to: string): void;
|
|
103
102
|
/**
|
|
104
|
-
* Returns array of functions argument names. Uses
|
|
103
|
+
* Returns array of functions argument names. Uses basic regex for source code analysis, might not work with advanced syntax.
|
|
105
104
|
*/
|
|
106
|
-
static
|
|
105
|
+
static getConstructorParams(func: {
|
|
107
106
|
toString(): string;
|
|
108
|
-
}
|
|
109
|
-
type: string;
|
|
110
|
-
value: string;
|
|
111
|
-
}[]): {
|
|
112
|
-
type: string;
|
|
113
|
-
value: string;
|
|
114
|
-
}[];
|
|
115
|
-
/**
|
|
116
|
-
* Returns array of functions argument names. Uses `esprima` for source code analysis.
|
|
117
|
-
*/
|
|
118
|
-
static getParamNames(func: {
|
|
119
|
-
toString(): string;
|
|
120
|
-
} | string | {
|
|
121
|
-
type: string;
|
|
122
|
-
value: string;
|
|
123
|
-
}[], methodName?: string): string[];
|
|
107
|
+
}): string[] | undefined;
|
|
124
108
|
/**
|
|
125
109
|
* Checks whether the argument looks like primary key (string, number or ObjectId).
|
|
126
110
|
*/
|
package/utils/Utils.js
CHANGED
|
@@ -3,11 +3,9 @@ import { extname, isAbsolute, join, normalize, relative, resolve } from 'node:pa
|
|
|
3
3
|
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
|
-
import { tokenize } from 'esprima';
|
|
7
6
|
import { clone } from './clone.js';
|
|
8
7
|
import { ARRAY_OPERATORS, GroupOperator, JSON_KEY_OPERATORS, PlainObject, QueryOperator, ReferenceKind, } from '../enums.js';
|
|
9
8
|
import { helper } from '../entity/wrap.js';
|
|
10
|
-
export const ObjectBindingPattern = Symbol('ObjectBindingPattern');
|
|
11
9
|
function compareConstructors(a, b) {
|
|
12
10
|
if (a.constructor === b.constructor) {
|
|
13
11
|
return true;
|
|
@@ -357,53 +355,37 @@ export class Utils {
|
|
|
357
355
|
}
|
|
358
356
|
}
|
|
359
357
|
/**
|
|
360
|
-
* Returns array of functions argument names. Uses
|
|
358
|
+
* Returns array of functions argument names. Uses basic regex for source code analysis, might not work with advanced syntax.
|
|
361
359
|
*/
|
|
362
|
-
static
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
static getParamNames(func, methodName) {
|
|
378
|
-
const ret = [];
|
|
379
|
-
const tokens = this.tokenize(func);
|
|
380
|
-
let inside = 0;
|
|
381
|
-
let currentBlockStart = 0;
|
|
382
|
-
for (let i = 0; i < tokens.length; i++) {
|
|
383
|
-
const token = tokens[i];
|
|
384
|
-
if (token.type === 'Identifier' && token.value === methodName) {
|
|
385
|
-
inside = 1;
|
|
386
|
-
currentBlockStart = i;
|
|
387
|
-
continue;
|
|
360
|
+
static getConstructorParams(func) {
|
|
361
|
+
const source = func.toString();
|
|
362
|
+
const i = source.indexOf('constructor');
|
|
363
|
+
if (i === -1) {
|
|
364
|
+
return undefined;
|
|
365
|
+
}
|
|
366
|
+
const start = source.indexOf('(', i);
|
|
367
|
+
if (start === -1) {
|
|
368
|
+
return undefined;
|
|
369
|
+
}
|
|
370
|
+
let depth = 0;
|
|
371
|
+
let end = start;
|
|
372
|
+
for (; end < source.length; end++) {
|
|
373
|
+
if (source[end] === '(') {
|
|
374
|
+
depth++;
|
|
388
375
|
}
|
|
389
|
-
if (
|
|
390
|
-
|
|
391
|
-
currentBlockStart = i;
|
|
392
|
-
continue;
|
|
376
|
+
if (source[end] === ')') {
|
|
377
|
+
depth--;
|
|
393
378
|
}
|
|
394
|
-
if (
|
|
379
|
+
if (depth === 0) {
|
|
395
380
|
break;
|
|
396
381
|
}
|
|
397
|
-
if (inside === 2 && token.type === 'Punctuator' && token.value === '{' && i === currentBlockStart + 1) {
|
|
398
|
-
ret.push(ObjectBindingPattern);
|
|
399
|
-
i = tokens.findIndex((t, idx) => idx > i + 2 && t.type === 'Punctuator' && t.value === '}');
|
|
400
|
-
continue;
|
|
401
|
-
}
|
|
402
|
-
if (inside === 2 && token.type === 'Identifier') {
|
|
403
|
-
ret.push(token.value);
|
|
404
|
-
}
|
|
405
382
|
}
|
|
406
|
-
|
|
383
|
+
const raw = source.slice(start + 1, end);
|
|
384
|
+
return raw
|
|
385
|
+
.split(',')
|
|
386
|
+
.map(s => s.trim().replace(/=.*$/, '').trim())
|
|
387
|
+
.filter(Boolean)
|
|
388
|
+
.map(raw => raw.startsWith('{') && raw.endsWith('}') ? '' : raw);
|
|
407
389
|
}
|
|
408
390
|
/**
|
|
409
391
|
* Checks whether the argument looks like primary key (string, number or ObjectId).
|