@mikro-orm/core 6.3.4-dev.0 → 6.3.4-dev.10
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 +8 -2
- package/EntityManager.js +7 -4
- package/drivers/IDatabaseDriver.d.ts +5 -3
- package/entity/Collection.d.ts +1 -0
- package/entity/Collection.js +9 -0
- package/entity/EntityLoader.d.ts +0 -5
- package/entity/EntityLoader.js +11 -48
- package/entity/EntityRepository.d.ts +7 -6
- package/entity/EntityRepository.js +1 -6
- package/entity/WrappedEntity.d.ts +7 -5
- package/entity/WrappedEntity.js +17 -0
- package/entity/utils.d.ts +5 -0
- package/entity/utils.js +59 -0
- package/metadata/MetadataDiscovery.js +7 -4
- package/package.json +2 -2
- package/typings.d.ts +3 -2
package/EntityManager.d.ts
CHANGED
|
@@ -308,7 +308,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
|
|
|
308
308
|
merge<Entity extends object>(entityName: EntityName<Entity>, data: EntityData<Entity> | EntityDTO<Entity>, options?: MergeOptions): Entity;
|
|
309
309
|
/**
|
|
310
310
|
* Creates new instance of given entity and populates it with given data.
|
|
311
|
-
* The entity constructor will be used unless you provide `{ managed: true }` in the options parameter.
|
|
311
|
+
* The entity constructor will be used unless you provide `{ managed: true }` in the `options` parameter.
|
|
312
312
|
* The constructor will be given parameters based on the defined constructor of the entity. If the constructor
|
|
313
313
|
* parameter matches a property name, its value will be extracted from `data`. If no matching property exists,
|
|
314
314
|
* the whole `data` parameter will be passed. This means we can also define `constructor(data: Partial<T>)` and
|
|
@@ -317,11 +317,14 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
|
|
|
317
317
|
* The parameters are strictly checked, you need to provide all required properties. You can use `OptionalProps`
|
|
318
318
|
* symbol to omit some properties from this check without making them optional. Alternatively, use `partial: true`
|
|
319
319
|
* in the options to disable the strict checks for required properties. This option has no effect on runtime.
|
|
320
|
+
*
|
|
321
|
+
* The newly created entity will be automatically marked for persistence via `em.persist` unless you disable this
|
|
322
|
+
* behavior, either locally via `persist: false` option, or globally via `persistOnCreate` ORM config option.
|
|
320
323
|
*/
|
|
321
324
|
create<Entity extends object, Convert extends boolean = false>(entityName: EntityName<Entity>, data: RequiredEntityData<Entity, never, Convert>, options?: CreateOptions<Convert>): Entity;
|
|
322
325
|
/**
|
|
323
326
|
* Creates new instance of given entity and populates it with given data.
|
|
324
|
-
* The entity constructor will be used unless you provide `{ managed: true }` in the options parameter.
|
|
327
|
+
* The entity constructor will be used unless you provide `{ managed: true }` in the `options` parameter.
|
|
325
328
|
* The constructor will be given parameters based on the defined constructor of the entity. If the constructor
|
|
326
329
|
* parameter matches a property name, its value will be extracted from `data`. If no matching property exists,
|
|
327
330
|
* the whole `data` parameter will be passed. This means we can also define `constructor(data: Partial<T>)` and
|
|
@@ -330,6 +333,9 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
|
|
|
330
333
|
* The parameters are strictly checked, you need to provide all required properties. You can use `OptionalProps`
|
|
331
334
|
* symbol to omit some properties from this check without making them optional. Alternatively, use `partial: true`
|
|
332
335
|
* in the options to disable the strict checks for required properties. This option has no effect on runtime.
|
|
336
|
+
*
|
|
337
|
+
* The newly created entity will be automatically marked for persistence via `em.persist` unless you disable this
|
|
338
|
+
* behavior, either locally via `persist: false` option, or globally via `persistOnCreate` ORM config option.
|
|
333
339
|
*/
|
|
334
340
|
create<Entity extends object, Convert extends boolean = false>(entityName: EntityName<Entity>, data: EntityData<Entity, Convert>, options: CreateOptions<Convert> & {
|
|
335
341
|
partial: true;
|
package/EntityManager.js
CHANGED
|
@@ -1158,15 +1158,18 @@ class EntityManager {
|
|
|
1158
1158
|
}
|
|
1159
1159
|
/**
|
|
1160
1160
|
* Creates new instance of given entity and populates it with given data.
|
|
1161
|
-
* The entity constructor will be used unless you provide `{ managed: true }` in the options parameter.
|
|
1161
|
+
* The entity constructor will be used unless you provide `{ managed: true }` in the `options` parameter.
|
|
1162
1162
|
* The constructor will be given parameters based on the defined constructor of the entity. If the constructor
|
|
1163
1163
|
* parameter matches a property name, its value will be extracted from `data`. If no matching property exists,
|
|
1164
1164
|
* the whole `data` parameter will be passed. This means we can also define `constructor(data: Partial<T>)` and
|
|
1165
1165
|
* `em.create()` will pass the data into it (unless we have a property named `data` too).
|
|
1166
1166
|
*
|
|
1167
|
-
The parameters are strictly checked, you need to provide all required properties. You can use `OptionalProps`
|
|
1168
|
-
symbol to omit some properties from this check without making them optional. Alternatively, use `partial: true`
|
|
1169
|
-
in the options to disable the strict checks for required properties. This option has no effect on runtime.
|
|
1167
|
+
* The parameters are strictly checked, you need to provide all required properties. You can use `OptionalProps`
|
|
1168
|
+
* symbol to omit some properties from this check without making them optional. Alternatively, use `partial: true`
|
|
1169
|
+
* in the options to disable the strict checks for required properties. This option has no effect on runtime.
|
|
1170
|
+
*
|
|
1171
|
+
* The newly created entity will be automatically marked for persistence via `em.persist` unless you disable this
|
|
1172
|
+
* behavior, either locally via `persist: false` option, or globally via `persistOnCreate` ORM config option.
|
|
1170
1173
|
*/
|
|
1171
1174
|
create(entityName, data, options = {}) {
|
|
1172
1175
|
const em = this.getContext();
|
|
@@ -68,12 +68,14 @@ export interface FindAllOptions<T, P extends string = never, F extends string =
|
|
|
68
68
|
where?: FilterQuery<T>;
|
|
69
69
|
}
|
|
70
70
|
export type FilterOptions = Dictionary<boolean | Dictionary> | string[] | boolean;
|
|
71
|
-
export interface
|
|
71
|
+
export interface LoadHint<Entity, Hint extends string = never, Fields extends string = PopulatePath.ALL, Excludes extends string = never> {
|
|
72
72
|
populate?: Populate<Entity, Hint>;
|
|
73
|
-
populateWhere?: ObjectQuery<Entity> | PopulateHint | `${PopulateHint}`;
|
|
74
|
-
populateOrderBy?: OrderDefinition<Entity>;
|
|
75
73
|
fields?: readonly AutoPath<Entity, Fields, `${PopulatePath.ALL}`>[];
|
|
76
74
|
exclude?: readonly AutoPath<Entity, Excludes>[];
|
|
75
|
+
}
|
|
76
|
+
export interface FindOptions<Entity, Hint extends string = never, Fields extends string = PopulatePath.ALL, Excludes extends string = never> extends LoadHint<Entity, Hint, Fields, Excludes> {
|
|
77
|
+
populateWhere?: ObjectQuery<Entity> | PopulateHint | `${PopulateHint}`;
|
|
78
|
+
populateOrderBy?: OrderDefinition<Entity>;
|
|
77
79
|
orderBy?: OrderDefinition<Entity>;
|
|
78
80
|
cache?: boolean | number | [string, number];
|
|
79
81
|
limit?: number;
|
package/entity/Collection.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export declare class Collection<T extends object, O extends object = object> ext
|
|
|
24
24
|
* Returns the Collection instance (itself), works the same as `Reference.load()`.
|
|
25
25
|
*/
|
|
26
26
|
load<TT extends T, P extends string = never>(options?: InitCollectionOptions<TT, P>): Promise<LoadedCollection<Loaded<TT, P>>>;
|
|
27
|
+
private setSerializationContext;
|
|
27
28
|
/**
|
|
28
29
|
* Initializes the collection and returns the items
|
|
29
30
|
*/
|
package/entity/Collection.js
CHANGED
|
@@ -37,12 +37,20 @@ class Collection extends ArrayCollection_1.ArrayCollection {
|
|
|
37
37
|
if (this.isInitialized(true) && !options.refresh) {
|
|
38
38
|
const em = this.getEntityManager(this.items, false);
|
|
39
39
|
await em?.populate(this.items, options.populate, options);
|
|
40
|
+
this.setSerializationContext(options);
|
|
40
41
|
}
|
|
41
42
|
else {
|
|
42
43
|
await this.init({ refresh: false, ...options });
|
|
43
44
|
}
|
|
44
45
|
return this;
|
|
45
46
|
}
|
|
47
|
+
setSerializationContext(options) {
|
|
48
|
+
(0, wrap_1.helper)(this.owner).setSerializationContext({
|
|
49
|
+
populate: Array.isArray(options.populate)
|
|
50
|
+
? options.populate.map(hint => `${this.property.name}.${hint}`)
|
|
51
|
+
: options.populate ?? [this.property.name],
|
|
52
|
+
});
|
|
53
|
+
}
|
|
46
54
|
/**
|
|
47
55
|
* Initializes the collection and returns the items
|
|
48
56
|
*/
|
|
@@ -86,6 +94,7 @@ class Collection extends ArrayCollection_1.ArrayCollection {
|
|
|
86
94
|
}
|
|
87
95
|
if (options.store) {
|
|
88
96
|
this.hydrate(items, true);
|
|
97
|
+
this.setSerializationContext(options);
|
|
89
98
|
this.populated();
|
|
90
99
|
this.readonly = true;
|
|
91
100
|
}
|
package/entity/EntityLoader.d.ts
CHANGED
|
@@ -33,16 +33,11 @@ export declare class EntityLoader {
|
|
|
33
33
|
populate<Entity extends object, Fields extends string = PopulatePath.ALL>(entityName: string, entities: Entity[], populate: PopulateOptions<Entity>[] | boolean, options: EntityLoaderOptions<Entity, Fields>): Promise<void>;
|
|
34
34
|
normalizePopulate<Entity>(entityName: string, populate: (PopulateOptions<Entity> | boolean)[] | PopulateOptions<Entity> | boolean, strategy?: LoadStrategy, lookup?: boolean): PopulateOptions<Entity>[];
|
|
35
35
|
private setSerializationContext;
|
|
36
|
-
private expandDotPaths;
|
|
37
36
|
/**
|
|
38
37
|
* Merge multiple populates for the same entity with different children. Also skips `*` fields, those can come from
|
|
39
38
|
* partial loading hints (`fields`) that are used to infer the `populate` hint if missing.
|
|
40
39
|
*/
|
|
41
40
|
private mergeNestedPopulate;
|
|
42
|
-
/**
|
|
43
|
-
* Expands `books.perex` like populate to use `children` array instead of the dot syntax
|
|
44
|
-
*/
|
|
45
|
-
private expandNestedPopulate;
|
|
46
41
|
/**
|
|
47
42
|
* preload everything in one call (this will update already existing references in IM)
|
|
48
43
|
*/
|
package/entity/EntityLoader.js
CHANGED
|
@@ -8,6 +8,7 @@ const enums_1 = require("../enums");
|
|
|
8
8
|
const Reference_1 = require("./Reference");
|
|
9
9
|
const wrap_1 = require("./wrap");
|
|
10
10
|
const RawQueryFragment_1 = require("../utils/RawQueryFragment");
|
|
11
|
+
const utils_1 = require("./utils");
|
|
11
12
|
class EntityLoader {
|
|
12
13
|
em;
|
|
13
14
|
metadata;
|
|
@@ -64,52 +65,24 @@ class EntityLoader {
|
|
|
64
65
|
normalized = this.lookupAllRelationships(entityName);
|
|
65
66
|
}
|
|
66
67
|
// convert nested `field` with dot syntax to PopulateOptions with `children` array
|
|
67
|
-
|
|
68
|
+
(0, utils_1.expandDotPaths)(meta, normalized, true);
|
|
68
69
|
if (lookup && populate !== false) {
|
|
69
70
|
normalized = this.lookupEagerLoadedRelationships(entityName, normalized, strategy);
|
|
70
71
|
// convert nested `field` with dot syntax produced by eager relations
|
|
71
|
-
|
|
72
|
+
(0, utils_1.expandDotPaths)(meta, normalized, true);
|
|
72
73
|
}
|
|
73
74
|
// merge same fields
|
|
74
75
|
return this.mergeNestedPopulate(normalized);
|
|
75
76
|
}
|
|
76
77
|
setSerializationContext(entities, populate, options) {
|
|
77
|
-
const exclude = options.exclude ?? [];
|
|
78
78
|
for (const entity of entities) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
else if (options.fields) {
|
|
86
|
-
context.fields = new Set(options.fields);
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
context.fields = new Set([enums_1.PopulatePath.ALL]);
|
|
90
|
-
}
|
|
79
|
+
(0, wrap_1.helper)(entity).setSerializationContext({
|
|
80
|
+
populate,
|
|
81
|
+
fields: options.fields,
|
|
82
|
+
exclude: options.exclude,
|
|
83
|
+
});
|
|
91
84
|
}
|
|
92
85
|
}
|
|
93
|
-
expandDotPaths(normalized, meta) {
|
|
94
|
-
normalized.forEach(p => {
|
|
95
|
-
if (!p.field.includes('.')) {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
const [f, ...parts] = p.field.split('.');
|
|
99
|
-
p.field = f;
|
|
100
|
-
p.children ??= [];
|
|
101
|
-
const prop = meta.properties[f];
|
|
102
|
-
p.strategy ??= prop.strategy;
|
|
103
|
-
if (parts[0] === enums_1.PopulatePath.ALL) {
|
|
104
|
-
prop.targetMeta.props
|
|
105
|
-
.filter(prop => prop.lazy || prop.kind !== enums_1.ReferenceKind.SCALAR)
|
|
106
|
-
.forEach(prop => p.children.push({ field: prop.name, strategy: p.strategy }));
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
p.children.push(this.expandNestedPopulate(prop.type, parts, p.strategy, p.all));
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
86
|
/**
|
|
114
87
|
* Merge multiple populates for the same entity with different children. Also skips `*` fields, those can come from
|
|
115
88
|
* partial loading hints (`fields`) that are used to infer the `populate` hint if missing.
|
|
@@ -138,19 +111,6 @@ class EntityLoader {
|
|
|
138
111
|
return item;
|
|
139
112
|
});
|
|
140
113
|
}
|
|
141
|
-
/**
|
|
142
|
-
* Expands `books.perex` like populate to use `children` array instead of the dot syntax
|
|
143
|
-
*/
|
|
144
|
-
expandNestedPopulate(entityName, parts, strategy, all) {
|
|
145
|
-
const meta = this.metadata.find(entityName);
|
|
146
|
-
const field = parts.shift();
|
|
147
|
-
const prop = meta.properties[field];
|
|
148
|
-
const ret = { field, strategy, all };
|
|
149
|
-
if (parts.length > 0) {
|
|
150
|
-
ret.children = [this.expandNestedPopulate(prop.type, parts, strategy)];
|
|
151
|
-
}
|
|
152
|
-
return ret;
|
|
153
|
-
}
|
|
154
114
|
/**
|
|
155
115
|
* preload everything in one call (this will update already existing references in IM)
|
|
156
116
|
*/
|
|
@@ -404,6 +364,9 @@ class EntityLoader {
|
|
|
404
364
|
const where = options.where;
|
|
405
365
|
const subCond = Utils_1.Utils.isPlainObject(where[prop.name]) ? where[prop.name] : {};
|
|
406
366
|
const meta2 = this.metadata.find(prop.type);
|
|
367
|
+
if (!meta2) {
|
|
368
|
+
return {};
|
|
369
|
+
}
|
|
407
370
|
const pk = Utils_1.Utils.getPrimaryKeyHash(meta2.primaryKeys);
|
|
408
371
|
['$and', '$or'].forEach(op => {
|
|
409
372
|
if (where[op]) {
|
|
@@ -132,14 +132,15 @@ export declare class EntityRepository<Entity extends object> {
|
|
|
132
132
|
*/
|
|
133
133
|
populate<Ent extends Entity | Entity[], Hint extends string = never, Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Fields extends string = '*', Excludes extends string = never>(entities: Ent, populate: AutoPath<Naked, Hint, PopulatePath.ALL>[] | false, options?: EntityLoaderOptions<Naked, Fields, Excludes>): Promise<Ent extends object[] ? MergeLoaded<ArrayElement<Ent>, Naked, Hint, Fields, Excludes>[] : MergeLoaded<Ent, Naked, Hint, Fields, Excludes>>;
|
|
134
134
|
/**
|
|
135
|
-
*
|
|
136
|
-
* The entity constructor will be used unless you provide `{ managed: true }` in the `options` parameter.
|
|
137
|
-
* The constructor will be given parameters based on the defined constructor of the entity. If the constructor
|
|
138
|
-
* parameter matches a property name, its value will be extracted from `data`. If no matching property exists,
|
|
139
|
-
* the whole `data` parameter will be passed. This means we can also define `constructor(data: Partial<Entity>)` and
|
|
140
|
-
* `em.create()` will pass the data into it (unless we have a property named `data` too).
|
|
135
|
+
* @inheritDoc EntityManager.create
|
|
141
136
|
*/
|
|
142
137
|
create<Convert extends boolean = false>(data: RequiredEntityData<Entity, never, Convert>, options?: CreateOptions<Convert>): Entity;
|
|
138
|
+
/**
|
|
139
|
+
* @inheritDoc EntityManager.create
|
|
140
|
+
*/
|
|
141
|
+
create<Convert extends boolean = false>(data: EntityData<Entity, Convert>, options: CreateOptions<Convert> & {
|
|
142
|
+
partial: true;
|
|
143
|
+
}): Entity;
|
|
143
144
|
/**
|
|
144
145
|
* Shortcut for `wrap(entity).assign(data, { em })`
|
|
145
146
|
*/
|
|
@@ -153,12 +153,7 @@ class EntityRepository {
|
|
|
153
153
|
return this.getEntityManager().populate(entities, populate, options);
|
|
154
154
|
}
|
|
155
155
|
/**
|
|
156
|
-
*
|
|
157
|
-
* The entity constructor will be used unless you provide `{ managed: true }` in the `options` parameter.
|
|
158
|
-
* The constructor will be given parameters based on the defined constructor of the entity. If the constructor
|
|
159
|
-
* parameter matches a property name, its value will be extracted from `data`. If no matching property exists,
|
|
160
|
-
* the whole `data` parameter will be passed. This means we can also define `constructor(data: Partial<Entity>)` and
|
|
161
|
-
* `em.create()` will pass the data into it (unless we have a property named `data` too).
|
|
156
|
+
* @inheritDoc EntityManager.create
|
|
162
157
|
*/
|
|
163
158
|
create(data, options) {
|
|
164
159
|
return this.getEntityManager().create(this.entityName, data, options);
|
|
@@ -8,7 +8,7 @@ import type { EntityLoaderOptions } from './EntityLoader';
|
|
|
8
8
|
import type { EntityIdentifier } from './EntityIdentifier';
|
|
9
9
|
import type { SerializationContext } from '../serialization/SerializationContext';
|
|
10
10
|
import { type SerializeOptions } from '../serialization/EntitySerializer';
|
|
11
|
-
import type { FindOneOptions } from '../drivers/IDatabaseDriver';
|
|
11
|
+
import type { FindOneOptions, LoadHint } from '../drivers/IDatabaseDriver';
|
|
12
12
|
export declare class WrappedEntity<Entity extends object> {
|
|
13
13
|
__initialized: boolean;
|
|
14
14
|
__touched: boolean;
|
|
@@ -17,14 +17,15 @@ export declare class WrappedEntity<Entity extends object> {
|
|
|
17
17
|
__onLoadFired?: boolean;
|
|
18
18
|
__schema?: string;
|
|
19
19
|
__em?: EntityManager;
|
|
20
|
+
__loadedProperties: Set<string>;
|
|
21
|
+
__data: Dictionary;
|
|
22
|
+
__processing: boolean;
|
|
20
23
|
__serializationContext: {
|
|
21
24
|
root?: SerializationContext<Entity>;
|
|
22
25
|
populate?: PopulateOptions<Entity>[];
|
|
23
|
-
fields?: string
|
|
26
|
+
fields?: Set<string>;
|
|
27
|
+
exclude?: readonly string[];
|
|
24
28
|
};
|
|
25
|
-
__loadedProperties: Set<string>;
|
|
26
|
-
__data: Dictionary;
|
|
27
|
-
__processing: boolean;
|
|
28
29
|
/** stores last known primary key, as its current state might be broken due to propagation/orphan removal, but we need to know the PK to be able t remove the entity */
|
|
29
30
|
__pk?: Primary<Entity>;
|
|
30
31
|
/** holds the reference wrapper instance (if created), so we can maintain the identity on reference wrappers too */
|
|
@@ -43,6 +44,7 @@ export declare class WrappedEntity<Entity extends object> {
|
|
|
43
44
|
isTouched(): boolean;
|
|
44
45
|
isManaged(): boolean;
|
|
45
46
|
populated(populated?: boolean | undefined): void;
|
|
47
|
+
setSerializationContext<Hint extends string = never, Fields extends string = '*', Exclude extends string = never>(options: LoadHint<Entity, Hint, Fields, Exclude>): void;
|
|
46
48
|
toReference(): Ref<Entity> & LoadedReference<Loaded<Entity, AddEager<Entity>>>;
|
|
47
49
|
toObject<Ignored extends EntityKey<Entity> = never>(ignoreFields?: Ignored[]): Omit<EntityDTO<Entity>, Ignored>;
|
|
48
50
|
serialize<Hint extends string = never, Exclude extends string = never>(options?: SerializeOptions<Entity, Hint, Exclude>): EntityDTO<Loaded<Entity, Hint>>;
|
package/entity/WrappedEntity.js
CHANGED
|
@@ -9,6 +9,7 @@ const Utils_1 = require("../utils/Utils");
|
|
|
9
9
|
const errors_1 = require("../errors");
|
|
10
10
|
const wrap_1 = require("./wrap");
|
|
11
11
|
const EntitySerializer_1 = require("../serialization/EntitySerializer");
|
|
12
|
+
const utils_1 = require("./utils");
|
|
12
13
|
class WrappedEntity {
|
|
13
14
|
constructor(entity, hydrator, pkGetter, pkSerializer, pkGetterConverted) {
|
|
14
15
|
this.entity = entity;
|
|
@@ -35,6 +36,22 @@ class WrappedEntity {
|
|
|
35
36
|
populated(populated = true) {
|
|
36
37
|
this.__populated = populated;
|
|
37
38
|
}
|
|
39
|
+
setSerializationContext(options) {
|
|
40
|
+
const exclude = options.exclude ?? [];
|
|
41
|
+
const context = this.__serializationContext;
|
|
42
|
+
const populate = (0, utils_1.expandDotPaths)(this.__meta, options.populate);
|
|
43
|
+
context.populate = context.populate ? context.populate.concat(populate) : populate;
|
|
44
|
+
context.exclude = context.exclude ? context.exclude.concat(exclude) : exclude;
|
|
45
|
+
if (context.fields && options.fields) {
|
|
46
|
+
options.fields.forEach(f => context.fields.add(f));
|
|
47
|
+
}
|
|
48
|
+
else if (options.fields) {
|
|
49
|
+
context.fields = new Set(options.fields);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
context.fields = new Set(['*']);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
38
55
|
toReference() {
|
|
39
56
|
this.__reference ??= new Reference_1.Reference(this.entity);
|
|
40
57
|
return this.__reference;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { EntityMetadata, PopulateOptions } from '../typings';
|
|
2
|
+
/**
|
|
3
|
+
* @internal
|
|
4
|
+
*/
|
|
5
|
+
export declare function expandDotPaths<Entity>(meta: EntityMetadata<Entity>, populate?: readonly (string | PopulateOptions<Entity>)[], normalized?: boolean): PopulateOptions<Entity>[];
|
package/entity/utils.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.expandDotPaths = expandDotPaths;
|
|
4
|
+
const enums_1 = require("../enums");
|
|
5
|
+
const core_1 = require("@mikro-orm/core");
|
|
6
|
+
/**
|
|
7
|
+
* Expands `books.perex` like populate to use `children` array instead of the dot syntax
|
|
8
|
+
*/
|
|
9
|
+
function expandNestedPopulate(parentProp, parts, strategy, all) {
|
|
10
|
+
const meta = parentProp.targetMeta;
|
|
11
|
+
const field = parts.shift();
|
|
12
|
+
const prop = meta.properties[field];
|
|
13
|
+
const ret = { field, strategy, all };
|
|
14
|
+
if (parts.length > 0) {
|
|
15
|
+
ret.children = [expandNestedPopulate(prop, parts, strategy)];
|
|
16
|
+
}
|
|
17
|
+
return ret;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
function expandDotPaths(meta, populate, normalized = false) {
|
|
23
|
+
const ret = normalized ? populate : core_1.Utils.asArray(populate).map(field => {
|
|
24
|
+
if (typeof field === 'string') {
|
|
25
|
+
return { field };
|
|
26
|
+
}
|
|
27
|
+
/* istanbul ignore next */
|
|
28
|
+
return typeof field === 'boolean' || field.field === enums_1.PopulatePath.ALL
|
|
29
|
+
? { all: !!field, field: meta.primaryKeys[0] }
|
|
30
|
+
: field;
|
|
31
|
+
});
|
|
32
|
+
for (const p of ret) {
|
|
33
|
+
if (!p.field.includes('.')) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const [f, ...parts] = p.field.split('.');
|
|
37
|
+
p.field = f;
|
|
38
|
+
p.children ??= [];
|
|
39
|
+
const prop = meta.properties[p.field];
|
|
40
|
+
p.strategy ??= prop.strategy;
|
|
41
|
+
if (parts[0] === enums_1.PopulatePath.ALL) {
|
|
42
|
+
prop.targetMeta.props
|
|
43
|
+
.filter(prop => prop.lazy || prop.kind !== enums_1.ReferenceKind.SCALAR)
|
|
44
|
+
.forEach(prop => p.children.push({ field: prop.name, strategy: p.strategy }));
|
|
45
|
+
}
|
|
46
|
+
else if (prop.kind === enums_1.ReferenceKind.EMBEDDED) {
|
|
47
|
+
ret.push({
|
|
48
|
+
...p,
|
|
49
|
+
field: Object.values(prop.embeddedProps).find(c => c.embedded[1] === parts[0])?.name,
|
|
50
|
+
children: [],
|
|
51
|
+
});
|
|
52
|
+
p.children.push(expandNestedPopulate(prop, parts, p.strategy, p.all));
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
p.children.push(expandNestedPopulate(prop, parts, p.strategy, p.all));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return ret;
|
|
59
|
+
}
|
|
@@ -896,10 +896,13 @@ class MetadataDiscovery {
|
|
|
896
896
|
prop.hydrate = false;
|
|
897
897
|
return;
|
|
898
898
|
}
|
|
899
|
-
|
|
900
|
-
prop.
|
|
901
|
-
|
|
902
|
-
|
|
899
|
+
const newProp = Utils_1.Utils.copy(prop, false);
|
|
900
|
+
if (prop.enum && prop.items && meta.root.properties[prop.name]?.items) {
|
|
901
|
+
newProp.items = Utils_1.Utils.unique([...meta.root.properties[prop.name].items, ...prop.items]);
|
|
902
|
+
}
|
|
903
|
+
newProp.nullable = true;
|
|
904
|
+
newProp.inherited = true;
|
|
905
|
+
meta.root.addProperty(newProp);
|
|
903
906
|
});
|
|
904
907
|
meta.collection = meta.root.collection;
|
|
905
908
|
meta.root.indexes = Utils_1.Utils.unique([...meta.root.indexes, ...meta.indexes]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/core",
|
|
3
|
-
"version": "6.3.4-dev.
|
|
3
|
+
"version": "6.3.4-dev.10",
|
|
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
|
"main": "index.js",
|
|
6
6
|
"module": "index.mjs",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"esprima": "4.0.1",
|
|
65
65
|
"fs-extra": "11.2.0",
|
|
66
66
|
"globby": "11.1.0",
|
|
67
|
-
"mikro-orm": "6.3.4-dev.
|
|
67
|
+
"mikro-orm": "6.3.4-dev.10",
|
|
68
68
|
"reflect-metadata": "0.2.2"
|
|
69
69
|
}
|
|
70
70
|
}
|
package/typings.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import type { Platform } from './platforms';
|
|
|
8
8
|
import type { Configuration } from './utils';
|
|
9
9
|
import type { EntityManager } from './EntityManager';
|
|
10
10
|
import type { EventSubscriber } from './events';
|
|
11
|
-
import type { FindOneOptions, FindOptions } from './drivers';
|
|
11
|
+
import type { FindOneOptions, FindOptions, LoadHint } from './drivers';
|
|
12
12
|
export type Constructor<T = unknown> = new (...args: any[]) => T;
|
|
13
13
|
export type Dictionary<T = any> = {
|
|
14
14
|
[k: string]: T;
|
|
@@ -135,7 +135,7 @@ export interface IWrappedEntity<Entity extends object> {
|
|
|
135
135
|
isManaged(): boolean;
|
|
136
136
|
populated(populated?: boolean): void;
|
|
137
137
|
populate<Hint extends string = never>(populate: AutoPath<Entity, Hint>[] | false, options?: EntityLoaderOptions<Entity>): Promise<Loaded<Entity, Hint>>;
|
|
138
|
-
init<Hint extends string = never, Fields extends string = '*',
|
|
138
|
+
init<Hint extends string = never, Fields extends string = '*', Exclude extends string = never>(options?: FindOneOptions<Entity, Hint, Fields, Exclude>): Promise<Loaded<Entity, Hint, Fields, Exclude> | null>;
|
|
139
139
|
toReference(): Ref<Entity> & LoadedReference<Loaded<Entity, AddEager<Entity>>>;
|
|
140
140
|
toObject(): EntityDTO<Entity>;
|
|
141
141
|
toObject(ignoreFields: never[]): EntityDTO<Entity>;
|
|
@@ -143,6 +143,7 @@ export interface IWrappedEntity<Entity extends object> {
|
|
|
143
143
|
toJSON(...args: any[]): EntityDTO<Entity>;
|
|
144
144
|
toPOJO(): EntityDTO<Entity>;
|
|
145
145
|
serialize<Hint extends string = never, Exclude extends string = never>(options?: SerializeOptions<Entity, Hint, Exclude>): EntityDTO<Loaded<Entity, Hint>>;
|
|
146
|
+
setSerializationContext<Hint extends string = never, Fields extends string = '*', Exclude extends string = never>(options: LoadHint<Entity, Hint, Fields, Exclude>): void;
|
|
146
147
|
assign<Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Convert extends boolean = false, Data extends EntityData<Naked, Convert> | Partial<EntityDTO<Naked>> = EntityData<Naked, Convert> | Partial<EntityDTO<Naked>>>(data: Data & IsSubset<EntityData<Naked, Convert>, Data>, options?: AssignOptions<Convert>): MergeSelected<Entity, Naked, keyof Data & string>;
|
|
147
148
|
getSchema(): string | undefined;
|
|
148
149
|
setSchema(schema?: string): void;
|