@mikro-orm/core 7.0.0-dev.2 → 7.0.0-dev.200
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 +111 -61
- package/EntityManager.js +346 -300
- package/MikroORM.d.ts +44 -35
- package/MikroORM.js +103 -143
- package/README.md +3 -2
- package/cache/FileCacheAdapter.d.ts +1 -1
- package/cache/FileCacheAdapter.js +8 -7
- package/cache/GeneratedCacheAdapter.d.ts +0 -1
- package/cache/GeneratedCacheAdapter.js +0 -2
- package/cache/index.d.ts +0 -1
- package/cache/index.js +0 -1
- package/connections/Connection.d.ts +16 -7
- package/connections/Connection.js +23 -14
- package/drivers/DatabaseDriver.d.ts +25 -16
- package/drivers/DatabaseDriver.js +80 -35
- package/drivers/IDatabaseDriver.d.ts +47 -17
- package/entity/BaseEntity.d.ts +2 -2
- package/entity/BaseEntity.js +0 -3
- package/entity/Collection.d.ts +95 -31
- package/entity/Collection.js +444 -102
- package/entity/EntityAssigner.d.ts +1 -1
- package/entity/EntityAssigner.js +26 -18
- package/entity/EntityFactory.d.ts +13 -1
- package/entity/EntityFactory.js +88 -54
- package/entity/EntityHelper.d.ts +2 -2
- package/entity/EntityHelper.js +38 -15
- package/entity/EntityLoader.d.ts +8 -7
- package/entity/EntityLoader.js +134 -80
- package/entity/EntityRepository.d.ts +24 -4
- package/entity/EntityRepository.js +8 -2
- package/entity/Reference.d.ts +9 -12
- package/entity/Reference.js +34 -9
- package/entity/WrappedEntity.d.ts +2 -7
- package/entity/WrappedEntity.js +3 -8
- package/entity/defineEntity.d.ts +585 -0
- package/entity/defineEntity.js +533 -0
- package/entity/index.d.ts +3 -2
- package/entity/index.js +3 -2
- package/entity/utils.d.ts +7 -0
- package/entity/utils.js +16 -4
- package/entity/validators.d.ts +11 -0
- package/entity/validators.js +65 -0
- package/enums.d.ts +22 -6
- package/enums.js +15 -1
- package/errors.d.ts +23 -9
- package/errors.js +59 -21
- package/events/EventManager.d.ts +2 -1
- package/events/EventManager.js +19 -11
- package/events/EventSubscriber.d.ts +3 -1
- package/hydration/Hydrator.js +1 -2
- package/hydration/ObjectHydrator.d.ts +4 -4
- package/hydration/ObjectHydrator.js +53 -33
- package/index.d.ts +2 -2
- package/index.js +1 -2
- package/logging/DefaultLogger.d.ts +1 -1
- package/logging/DefaultLogger.js +1 -0
- package/logging/SimpleLogger.d.ts +1 -1
- package/logging/colors.d.ts +1 -1
- package/logging/colors.js +7 -6
- package/logging/index.d.ts +1 -0
- package/logging/index.js +1 -0
- package/logging/inspect.d.ts +2 -0
- package/logging/inspect.js +11 -0
- package/metadata/EntitySchema.d.ts +26 -26
- package/metadata/EntitySchema.js +82 -51
- package/metadata/MetadataDiscovery.d.ts +7 -10
- package/metadata/MetadataDiscovery.js +408 -335
- package/metadata/MetadataProvider.d.ts +11 -2
- package/metadata/MetadataProvider.js +46 -2
- package/metadata/MetadataStorage.d.ts +13 -11
- package/metadata/MetadataStorage.js +70 -37
- package/metadata/MetadataValidator.d.ts +17 -9
- package/metadata/MetadataValidator.js +100 -42
- package/metadata/discover-entities.d.ts +5 -0
- package/metadata/discover-entities.js +40 -0
- package/metadata/index.d.ts +1 -1
- package/metadata/index.js +1 -1
- package/metadata/types.d.ts +502 -0
- package/metadata/types.js +1 -0
- package/naming-strategy/AbstractNamingStrategy.d.ts +12 -4
- package/naming-strategy/AbstractNamingStrategy.js +14 -2
- package/naming-strategy/EntityCaseNamingStrategy.d.ts +3 -3
- package/naming-strategy/EntityCaseNamingStrategy.js +6 -5
- package/naming-strategy/MongoNamingStrategy.d.ts +3 -3
- package/naming-strategy/MongoNamingStrategy.js +6 -6
- package/naming-strategy/NamingStrategy.d.ts +24 -4
- package/naming-strategy/UnderscoreNamingStrategy.d.ts +3 -3
- package/naming-strategy/UnderscoreNamingStrategy.js +6 -6
- package/not-supported.d.ts +2 -0
- package/not-supported.js +4 -0
- package/package.json +19 -11
- package/platforms/ExceptionConverter.js +1 -1
- package/platforms/Platform.d.ts +7 -13
- package/platforms/Platform.js +20 -43
- package/serialization/EntitySerializer.d.ts +5 -0
- package/serialization/EntitySerializer.js +47 -27
- package/serialization/EntityTransformer.js +28 -18
- package/serialization/SerializationContext.d.ts +6 -6
- package/serialization/SerializationContext.js +16 -13
- package/types/ArrayType.d.ts +1 -1
- package/types/ArrayType.js +2 -3
- package/types/BigIntType.d.ts +9 -6
- package/types/BigIntType.js +4 -1
- package/types/BlobType.d.ts +0 -1
- package/types/BlobType.js +0 -3
- package/types/BooleanType.d.ts +2 -1
- package/types/BooleanType.js +3 -0
- package/types/DecimalType.d.ts +6 -4
- package/types/DecimalType.js +3 -3
- package/types/DoubleType.js +2 -2
- package/types/EnumArrayType.js +1 -2
- package/types/JsonType.d.ts +1 -1
- package/types/JsonType.js +7 -2
- package/types/TinyIntType.js +1 -1
- package/types/Type.d.ts +2 -4
- package/types/Type.js +3 -3
- package/types/Uint8ArrayType.d.ts +0 -1
- package/types/Uint8ArrayType.js +1 -4
- package/types/index.d.ts +1 -1
- package/typings.d.ts +300 -140
- package/typings.js +62 -44
- package/unit-of-work/ChangeSet.d.ts +2 -6
- package/unit-of-work/ChangeSet.js +4 -5
- package/unit-of-work/ChangeSetComputer.d.ts +1 -3
- package/unit-of-work/ChangeSetComputer.js +26 -13
- package/unit-of-work/ChangeSetPersister.d.ts +5 -4
- package/unit-of-work/ChangeSetPersister.js +77 -35
- package/unit-of-work/CommitOrderCalculator.d.ts +12 -10
- package/unit-of-work/CommitOrderCalculator.js +13 -13
- package/unit-of-work/IdentityMap.d.ts +12 -0
- package/unit-of-work/IdentityMap.js +39 -1
- package/unit-of-work/UnitOfWork.d.ts +23 -3
- package/unit-of-work/UnitOfWork.js +199 -106
- package/utils/AbstractSchemaGenerator.d.ts +5 -5
- package/utils/AbstractSchemaGenerator.js +22 -17
- package/utils/AsyncContext.d.ts +6 -0
- package/utils/AsyncContext.js +42 -0
- package/utils/Configuration.d.ts +779 -207
- package/utils/Configuration.js +146 -190
- package/utils/ConfigurationLoader.d.ts +1 -54
- package/utils/ConfigurationLoader.js +1 -352
- package/utils/Cursor.d.ts +3 -6
- package/utils/Cursor.js +27 -11
- package/utils/DataloaderUtils.d.ts +15 -5
- package/utils/DataloaderUtils.js +65 -17
- package/utils/EntityComparator.d.ts +13 -9
- package/utils/EntityComparator.js +164 -89
- package/utils/QueryHelper.d.ts +14 -6
- package/utils/QueryHelper.js +88 -26
- package/utils/RawQueryFragment.d.ts +48 -25
- package/utils/RawQueryFragment.js +67 -66
- package/utils/RequestContext.js +2 -2
- package/utils/TransactionContext.js +2 -2
- package/utils/TransactionManager.d.ts +65 -0
- package/utils/TransactionManager.js +223 -0
- package/utils/Utils.d.ts +13 -120
- package/utils/Utils.js +104 -375
- package/utils/clone.js +8 -23
- package/utils/env-vars.d.ts +7 -0
- package/utils/env-vars.js +97 -0
- package/utils/fs-utils.d.ts +32 -0
- package/utils/fs-utils.js +178 -0
- package/utils/index.d.ts +2 -1
- package/utils/index.js +2 -1
- package/utils/upsert-utils.d.ts +9 -4
- package/utils/upsert-utils.js +55 -4
- package/decorators/Check.d.ts +0 -3
- package/decorators/Check.js +0 -13
- package/decorators/CreateRequestContext.d.ts +0 -3
- package/decorators/CreateRequestContext.js +0 -29
- package/decorators/Embeddable.d.ts +0 -8
- package/decorators/Embeddable.js +0 -11
- package/decorators/Embedded.d.ts +0 -18
- package/decorators/Embedded.js +0 -18
- package/decorators/Entity.d.ts +0 -18
- package/decorators/Entity.js +0 -13
- package/decorators/Enum.d.ts +0 -9
- package/decorators/Enum.js +0 -16
- package/decorators/Filter.d.ts +0 -2
- package/decorators/Filter.js +0 -8
- package/decorators/Formula.d.ts +0 -5
- package/decorators/Formula.js +0 -15
- package/decorators/Indexed.d.ts +0 -17
- package/decorators/Indexed.js +0 -20
- package/decorators/ManyToMany.d.ts +0 -40
- package/decorators/ManyToMany.js +0 -14
- package/decorators/ManyToOne.d.ts +0 -30
- package/decorators/ManyToOne.js +0 -14
- package/decorators/OneToMany.d.ts +0 -28
- package/decorators/OneToMany.js +0 -17
- package/decorators/OneToOne.d.ts +0 -24
- package/decorators/OneToOne.js +0 -7
- package/decorators/PrimaryKey.d.ts +0 -9
- package/decorators/PrimaryKey.js +0 -20
- package/decorators/Property.d.ts +0 -250
- package/decorators/Property.js +0 -32
- package/decorators/Transactional.d.ts +0 -13
- package/decorators/Transactional.js +0 -28
- package/decorators/hooks.d.ts +0 -16
- package/decorators/hooks.js +0 -47
- package/decorators/index.d.ts +0 -17
- package/decorators/index.js +0 -17
- package/entity/ArrayCollection.d.ts +0 -116
- package/entity/ArrayCollection.js +0 -395
- package/entity/EntityValidator.d.ts +0 -19
- package/entity/EntityValidator.js +0 -150
- package/metadata/ReflectMetadataProvider.d.ts +0 -8
- package/metadata/ReflectMetadataProvider.js +0 -44
- package/utils/resolveContextProvider.d.ts +0 -10
- package/utils/resolveContextProvider.js +0 -28
package/entity/EntityLoader.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { ConnectionType,
|
|
1
|
+
import type { AnyEntity, ConnectionType, EntityName, EntityProperty, FilterQuery, PopulateOptions } from '../typings.js';
|
|
2
2
|
import type { EntityManager } from '../EntityManager.js';
|
|
3
3
|
import { LoadStrategy, type LockMode, type PopulateHint, PopulatePath, type QueryOrderMap } from '../enums.js';
|
|
4
|
-
import type { EntityField } from '../drivers/IDatabaseDriver.js';
|
|
4
|
+
import type { EntityField, FilterOptions } from '../drivers/IDatabaseDriver.js';
|
|
5
5
|
import type { LoggingOptions } from '../logging/Logger.js';
|
|
6
6
|
export type EntityLoaderOptions<Entity, Fields extends string = PopulatePath.ALL, Excludes extends string = never> = {
|
|
7
7
|
where?: FilterQuery<Entity>;
|
|
@@ -14,8 +14,8 @@ export type EntityLoaderOptions<Entity, Fields extends string = PopulatePath.ALL
|
|
|
14
14
|
lookup?: boolean;
|
|
15
15
|
convertCustomTypes?: boolean;
|
|
16
16
|
ignoreLazyScalarProperties?: boolean;
|
|
17
|
-
filters?:
|
|
18
|
-
strategy?: LoadStrategy
|
|
17
|
+
filters?: FilterOptions;
|
|
18
|
+
strategy?: LoadStrategy | `${LoadStrategy}`;
|
|
19
19
|
lockMode?: Exclude<LockMode, LockMode.OPTIMISTIC>;
|
|
20
20
|
schema?: string;
|
|
21
21
|
connectionType?: ConnectionType;
|
|
@@ -30,8 +30,8 @@ export declare class EntityLoader {
|
|
|
30
30
|
* Loads specified relations in batch.
|
|
31
31
|
* This will execute one query for each relation, that will populate it on all the specified entities.
|
|
32
32
|
*/
|
|
33
|
-
populate<Entity extends object, Fields extends string = PopulatePath.ALL>(entityName:
|
|
34
|
-
normalizePopulate<Entity>(entityName:
|
|
33
|
+
populate<Entity extends object, Fields extends string = PopulatePath.ALL>(entityName: EntityName<Entity>, entities: Entity[], populate: PopulateOptions<Entity>[] | boolean, options: EntityLoaderOptions<Entity, Fields>): Promise<void>;
|
|
34
|
+
normalizePopulate<Entity>(entityName: EntityName<Entity>, populate: (PopulateOptions<Entity> | boolean)[] | PopulateOptions<Entity> | boolean, strategy?: LoadStrategy, lookup?: boolean, exclude?: string[]): PopulateOptions<Entity>[];
|
|
35
35
|
private setSerializationContext;
|
|
36
36
|
/**
|
|
37
37
|
* Merge multiple populates for the same entity with different children. Also skips `*` fields, those can come from
|
|
@@ -49,7 +49,8 @@ export declare class EntityLoader {
|
|
|
49
49
|
private findChildren;
|
|
50
50
|
private mergePrimaryCondition;
|
|
51
51
|
private populateField;
|
|
52
|
-
|
|
52
|
+
/** @internal */
|
|
53
|
+
findChildrenFromPivotTable<Entity extends object>(filtered: Entity[], prop: EntityProperty<Entity>, options: Required<EntityLoaderOptions<Entity>>, orderBy?: QueryOrderMap<Entity>[], populate?: PopulateOptions<Entity>, pivotJoin?: boolean): Promise<AnyEntity[][]>;
|
|
53
54
|
private extractChildCondition;
|
|
54
55
|
private buildFields;
|
|
55
56
|
private getChildReferences;
|
package/entity/EntityLoader.js
CHANGED
|
@@ -4,8 +4,8 @@ import { ValidationError } from '../errors.js';
|
|
|
4
4
|
import { LoadStrategy, PopulatePath, ReferenceKind, } from '../enums.js';
|
|
5
5
|
import { Reference } from './Reference.js';
|
|
6
6
|
import { helper } from './wrap.js';
|
|
7
|
-
import { raw, RawQueryFragment } from '../utils/RawQueryFragment.js';
|
|
8
7
|
import { expandDotPaths } from './utils.js';
|
|
8
|
+
import { Raw } from '../utils/RawQueryFragment.js';
|
|
9
9
|
export class EntityLoader {
|
|
10
10
|
em;
|
|
11
11
|
metadata;
|
|
@@ -32,17 +32,16 @@ export class EntityLoader {
|
|
|
32
32
|
const visited = options.visited ??= new Set();
|
|
33
33
|
options.where ??= {};
|
|
34
34
|
options.orderBy ??= {};
|
|
35
|
-
options.filters ??= {};
|
|
36
35
|
options.lookup ??= true;
|
|
37
36
|
options.validate ??= true;
|
|
38
37
|
options.refresh ??= false;
|
|
39
38
|
options.convertCustomTypes ??= true;
|
|
40
39
|
if (references.length > 0) {
|
|
41
|
-
await this.populateScalar(meta, references, options);
|
|
40
|
+
await this.populateScalar(meta, references, { ...options, populateWhere: undefined });
|
|
42
41
|
}
|
|
43
|
-
populate = this.normalizePopulate(entityName, populate, options.strategy, options.lookup);
|
|
42
|
+
populate = this.normalizePopulate(entityName, populate, options.strategy, options.lookup, options.exclude);
|
|
44
43
|
const invalid = populate.find(({ field }) => !this.em.canPopulate(entityName, field));
|
|
45
|
-
/* v8 ignore next
|
|
44
|
+
/* v8 ignore next */
|
|
46
45
|
if (options.validate && invalid) {
|
|
47
46
|
throw ValidationError.invalidPropertyName(entityName, invalid.field);
|
|
48
47
|
}
|
|
@@ -57,7 +56,7 @@ export class EntityLoader {
|
|
|
57
56
|
visited.delete(entity);
|
|
58
57
|
}
|
|
59
58
|
}
|
|
60
|
-
normalizePopulate(entityName, populate, strategy, lookup = true) {
|
|
59
|
+
normalizePopulate(entityName, populate, strategy, lookup = true, exclude) {
|
|
61
60
|
const meta = this.metadata.find(entityName);
|
|
62
61
|
let normalized = Utils.asArray(populate).map(field => {
|
|
63
62
|
return typeof field === 'boolean' || field.field === PopulatePath.ALL ? { all: !!field, field: meta.primaryKeys[0] } : field;
|
|
@@ -68,7 +67,7 @@ export class EntityLoader {
|
|
|
68
67
|
// convert nested `field` with dot syntax to PopulateOptions with `children` array
|
|
69
68
|
expandDotPaths(meta, normalized, true);
|
|
70
69
|
if (lookup && populate !== false) {
|
|
71
|
-
normalized = this.lookupEagerLoadedRelationships(entityName, normalized, strategy);
|
|
70
|
+
normalized = this.lookupEagerLoadedRelationships(entityName, normalized, strategy, '', [], exclude);
|
|
72
71
|
// convert nested `field` with dot syntax produced by eager relations
|
|
73
72
|
expandDotPaths(meta, normalized, true);
|
|
74
73
|
}
|
|
@@ -140,34 +139,39 @@ export class EntityLoader {
|
|
|
140
139
|
const innerOrderBy = Utils.asArray(options.orderBy)
|
|
141
140
|
.filter(orderBy => (Array.isArray(orderBy[prop.name]) && orderBy[prop.name].length > 0) || Utils.isObject(orderBy[prop.name]))
|
|
142
141
|
.flatMap(orderBy => orderBy[prop.name]);
|
|
142
|
+
const where = await this.extractChildCondition(options, prop);
|
|
143
143
|
if (prop.kind === ReferenceKind.MANY_TO_MANY && this.driver.getPlatform().usesPivotTable()) {
|
|
144
|
-
|
|
144
|
+
const res = await this.findChildrenFromPivotTable(filtered, prop, options, innerOrderBy, populate, !!ref);
|
|
145
|
+
return Utils.flatten(res);
|
|
145
146
|
}
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
147
|
+
const { items, partial } = await this.findChildren(options.filtered ?? entities, prop, populate, {
|
|
148
|
+
...options,
|
|
149
|
+
where,
|
|
150
|
+
orderBy: innerOrderBy,
|
|
151
|
+
}, !!(ref || prop.mapToPk));
|
|
152
|
+
this.initializeCollections(filtered, prop, field, items, innerOrderBy.length > 0, partial);
|
|
153
|
+
return items;
|
|
150
154
|
}
|
|
151
155
|
async populateScalar(meta, filtered, options) {
|
|
152
156
|
const pk = Utils.getPrimaryKeyHash(meta.primaryKeys);
|
|
153
|
-
const ids = Utils.unique(filtered.map(e => Utils.getPrimaryKeyValues(e, meta
|
|
157
|
+
const ids = Utils.unique(filtered.map(e => Utils.getPrimaryKeyValues(e, meta, true)));
|
|
154
158
|
const where = this.mergePrimaryCondition(ids, pk, options, meta, this.metadata, this.driver.getPlatform());
|
|
155
159
|
const { filters, convertCustomTypes, lockMode, strategy, populateWhere, connectionType, logging, fields } = options;
|
|
156
|
-
await this.em.find(meta.
|
|
160
|
+
await this.em.find(meta.class, where, {
|
|
157
161
|
filters, convertCustomTypes, lockMode, strategy, populateWhere, connectionType, logging,
|
|
158
162
|
fields: fields,
|
|
159
163
|
populate: [],
|
|
160
164
|
});
|
|
161
165
|
}
|
|
162
|
-
initializeCollections(filtered, prop, field, children, customOrder) {
|
|
166
|
+
initializeCollections(filtered, prop, field, children, customOrder, partial) {
|
|
163
167
|
if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
164
|
-
this.initializeOneToMany(filtered, children, prop, field);
|
|
168
|
+
this.initializeOneToMany(filtered, children, prop, field, partial);
|
|
165
169
|
}
|
|
166
170
|
if (prop.kind === ReferenceKind.MANY_TO_MANY && !this.driver.getPlatform().usesPivotTable()) {
|
|
167
|
-
this.initializeManyToMany(filtered, children, prop, field, customOrder);
|
|
171
|
+
this.initializeManyToMany(filtered, children, prop, field, customOrder, partial);
|
|
168
172
|
}
|
|
169
173
|
}
|
|
170
|
-
initializeOneToMany(filtered, children, prop, field) {
|
|
174
|
+
initializeOneToMany(filtered, children, prop, field, partial) {
|
|
171
175
|
const mapToPk = prop.targetMeta.properties[prop.mappedBy].mapToPk;
|
|
172
176
|
const map = {};
|
|
173
177
|
for (const entity of filtered) {
|
|
@@ -177,20 +181,20 @@ export class EntityLoader {
|
|
|
177
181
|
for (const child of children) {
|
|
178
182
|
const pk = child.__helper.__data[prop.mappedBy] ?? child[prop.mappedBy];
|
|
179
183
|
if (pk) {
|
|
180
|
-
const key = helper(mapToPk ? this.em.getReference(prop.
|
|
184
|
+
const key = helper(mapToPk ? this.em.getReference(prop.targetMeta.class, pk) : pk).getSerializedPrimaryKey();
|
|
181
185
|
map[key]?.push(child);
|
|
182
186
|
}
|
|
183
187
|
}
|
|
184
188
|
for (const entity of filtered) {
|
|
185
189
|
const key = helper(entity).getSerializedPrimaryKey();
|
|
186
|
-
entity[field].hydrate(map[key]);
|
|
190
|
+
entity[field].hydrate(map[key], undefined, partial);
|
|
187
191
|
}
|
|
188
192
|
}
|
|
189
|
-
initializeManyToMany(filtered, children, prop, field, customOrder) {
|
|
193
|
+
initializeManyToMany(filtered, children, prop, field, customOrder, partial) {
|
|
190
194
|
if (prop.mappedBy) {
|
|
191
195
|
for (const entity of filtered) {
|
|
192
196
|
const items = children.filter(child => child[prop.mappedBy].contains(entity, false));
|
|
193
|
-
entity[field].hydrate(items, true);
|
|
197
|
+
entity[field].hydrate(items, true, partial);
|
|
194
198
|
}
|
|
195
199
|
}
|
|
196
200
|
else { // owning side of M:N without pivot table needs to be reordered
|
|
@@ -200,15 +204,17 @@ export class EntityLoader {
|
|
|
200
204
|
if (!customOrder) {
|
|
201
205
|
items.sort((a, b) => order.indexOf(a) - order.indexOf(b));
|
|
202
206
|
}
|
|
203
|
-
entity[field].hydrate(items, true);
|
|
207
|
+
entity[field].hydrate(items, true, partial);
|
|
204
208
|
}
|
|
205
209
|
}
|
|
206
210
|
}
|
|
207
211
|
async findChildren(entities, prop, populate, options, ref) {
|
|
208
|
-
const children = this.getChildReferences(entities, prop, options, ref);
|
|
212
|
+
const children = Utils.unique(this.getChildReferences(entities, prop, options, ref));
|
|
209
213
|
const meta = prop.targetMeta;
|
|
210
|
-
|
|
214
|
+
// When targetKey is set, use it for FK lookup instead of the PK
|
|
215
|
+
let fk = prop.targetKey ?? Utils.getPrimaryKeyHash(meta.primaryKeys);
|
|
211
216
|
let schema = options.schema;
|
|
217
|
+
const partial = !Utils.isEmpty(prop.where) || !Utils.isEmpty(options.where);
|
|
212
218
|
if (prop.kind === ReferenceKind.ONE_TO_MANY || (prop.kind === ReferenceKind.MANY_TO_MANY && !prop.owner)) {
|
|
213
219
|
fk = meta.properties[prop.mappedBy].name;
|
|
214
220
|
}
|
|
@@ -218,40 +224,31 @@ export class EntityLoader {
|
|
|
218
224
|
children.push(...this.filterByReferences(entities, prop.name, options.refresh));
|
|
219
225
|
}
|
|
220
226
|
if (children.length === 0) {
|
|
221
|
-
return [];
|
|
227
|
+
return { items: [], partial };
|
|
222
228
|
}
|
|
223
229
|
if (!schema && [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind)) {
|
|
224
230
|
schema = children.find(e => e.__helper.__schema)?.__helper.__schema;
|
|
225
231
|
}
|
|
226
|
-
|
|
232
|
+
// When targetKey is set, get the targetKey value instead of PK
|
|
233
|
+
const ids = Utils.unique(children.map(e => prop.targetKey ? e[prop.targetKey] : e.__helper.getPrimaryKey()));
|
|
227
234
|
let where = this.mergePrimaryCondition(ids, fk, options, meta, this.metadata, this.driver.getPlatform());
|
|
228
235
|
const fields = this.buildFields(options.fields, prop, ref);
|
|
229
236
|
/* eslint-disable prefer-const */
|
|
230
|
-
let { refresh, filters, convertCustomTypes, lockMode, strategy, populateWhere, connectionType, logging, } = options;
|
|
237
|
+
let { refresh, filters, convertCustomTypes, lockMode, strategy, populateWhere = 'infer', connectionType, logging, } = options;
|
|
231
238
|
/* eslint-enable prefer-const */
|
|
232
239
|
if (typeof populateWhere === 'object') {
|
|
233
240
|
populateWhere = await this.extractChildCondition({ where: populateWhere }, prop);
|
|
234
241
|
}
|
|
235
|
-
if (!Utils.isEmpty(prop.where)) {
|
|
242
|
+
if (!Utils.isEmpty(prop.where) || Raw.hasObjectFragments(prop.where)) {
|
|
236
243
|
where = { $and: [where, prop.where] };
|
|
237
244
|
}
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
if (rawField) {
|
|
244
|
-
const raw2 = raw(rawField.sql, rawField.params);
|
|
245
|
-
propOrderBy.push({ [raw2.toString()]: item[field] });
|
|
246
|
-
continue;
|
|
247
|
-
}
|
|
248
|
-
propOrderBy.push({ [field]: item[field] });
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
const items = await this.em.find(prop.type, where, {
|
|
245
|
+
const orderBy = [...Utils.asArray(options.orderBy), ...Utils.asArray(prop.orderBy)].filter((order, idx, array) => {
|
|
246
|
+
// skip consecutive ordering with the same key to get around mongo issues
|
|
247
|
+
return idx === 0 || !Utils.equals(Utils.getObjectQueryKeys(array[idx - 1]), Utils.getObjectQueryKeys(order));
|
|
248
|
+
});
|
|
249
|
+
const items = await this.em.find(meta.class, where, {
|
|
253
250
|
filters, convertCustomTypes, lockMode, populateWhere, logging,
|
|
254
|
-
orderBy
|
|
251
|
+
orderBy,
|
|
255
252
|
populate: populate.children ?? populate.all ?? [],
|
|
256
253
|
exclude: Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop.name) : options.exclude,
|
|
257
254
|
strategy, fields, schema, connectionType,
|
|
@@ -260,6 +257,49 @@ export class EntityLoader {
|
|
|
260
257
|
// @ts-ignore not a public option, will be propagated to the populate call
|
|
261
258
|
visited: options.visited,
|
|
262
259
|
});
|
|
260
|
+
// For targetKey relations, wire up loaded entities to parent references
|
|
261
|
+
// This is needed because the references were created under alternate key,
|
|
262
|
+
// but loaded entities are stored under PK, so they don't automatically merge
|
|
263
|
+
if (prop.targetKey && [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind)) {
|
|
264
|
+
const itemsByKey = new Map();
|
|
265
|
+
for (const item of items) {
|
|
266
|
+
itemsByKey.set('' + item[prop.targetKey], item);
|
|
267
|
+
}
|
|
268
|
+
for (const entity of entities) {
|
|
269
|
+
const ref = entity[prop.name];
|
|
270
|
+
/* v8 ignore next */
|
|
271
|
+
if (!ref) {
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
const keyValue = '' + (Reference.isReference(ref) ? ref.unwrap()[prop.targetKey] : ref[prop.targetKey]);
|
|
275
|
+
const loadedItem = itemsByKey.get(keyValue);
|
|
276
|
+
if (loadedItem) {
|
|
277
|
+
entity[prop.name] = (Reference.isReference(ref) ? Reference.create(loadedItem) : loadedItem);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if ([ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind) && items.length !== children.length) {
|
|
282
|
+
const nullVal = this.em.config.get('forceUndefined') ? undefined : null;
|
|
283
|
+
const itemsMap = new Set();
|
|
284
|
+
const childrenMap = new Set();
|
|
285
|
+
// Use targetKey value if set, otherwise use serialized PK
|
|
286
|
+
const getKey = (e) => prop.targetKey ? '' + e[prop.targetKey] : helper(e).getSerializedPrimaryKey();
|
|
287
|
+
for (const item of items) {
|
|
288
|
+
/* v8 ignore next */
|
|
289
|
+
itemsMap.add(getKey(item));
|
|
290
|
+
}
|
|
291
|
+
for (const child of children) {
|
|
292
|
+
childrenMap.add(getKey(child));
|
|
293
|
+
}
|
|
294
|
+
for (const entity of entities) {
|
|
295
|
+
const ref = entity[prop.name] ?? {};
|
|
296
|
+
const key = helper(ref) ? getKey(ref) : undefined;
|
|
297
|
+
if (key && childrenMap.has(key) && !itemsMap.has(key)) {
|
|
298
|
+
entity[prop.name] = nullVal;
|
|
299
|
+
helper(entity).__originalEntityData[prop.name] = null;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
263
303
|
for (const item of items) {
|
|
264
304
|
if (ref && !helper(item).__onLoadFired) {
|
|
265
305
|
helper(item).__initialized = false;
|
|
@@ -267,10 +307,10 @@ export class EntityLoader {
|
|
|
267
307
|
this.em.getUnitOfWork()['loadedEntities'].delete(item);
|
|
268
308
|
}
|
|
269
309
|
}
|
|
270
|
-
return items;
|
|
310
|
+
return { items, partial };
|
|
271
311
|
}
|
|
272
312
|
mergePrimaryCondition(ids, pk, options, meta, metadata, platform) {
|
|
273
|
-
const cond1 = QueryHelper.processWhere({ where: { [pk]: { $in: ids } }, entityName: meta.
|
|
313
|
+
const cond1 = QueryHelper.processWhere({ where: { [pk]: { $in: ids } }, entityName: meta.class, metadata, platform, convertCustomTypes: !options.convertCustomTypes });
|
|
274
314
|
const where = { ...options.where };
|
|
275
315
|
Utils.dropUndefinedProperties(where);
|
|
276
316
|
return where[pk]
|
|
@@ -283,6 +323,7 @@ export class EntityLoader {
|
|
|
283
323
|
if (prop.kind === ReferenceKind.SCALAR && !prop.lazy) {
|
|
284
324
|
return;
|
|
285
325
|
}
|
|
326
|
+
options = { ...options, filters: QueryHelper.mergePropertyFilters(prop.filters, options.filters) };
|
|
286
327
|
const populated = await this.populateMany(entityName, entities, populate, options);
|
|
287
328
|
if (!populate.children && !populate.all) {
|
|
288
329
|
return;
|
|
@@ -310,10 +351,22 @@ export class EntityLoader {
|
|
|
310
351
|
const innerOrderBy = Utils.asArray(options.orderBy)
|
|
311
352
|
.filter(orderBy => Utils.isObject(orderBy[prop.name]))
|
|
312
353
|
.map(orderBy => orderBy[prop.name]);
|
|
313
|
-
const { refresh, filters, ignoreLazyScalarProperties, populateWhere, connectionType, logging } = options;
|
|
354
|
+
const { refresh, filters, ignoreLazyScalarProperties, populateWhere, connectionType, logging, schema } = options;
|
|
314
355
|
const exclude = Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop.name) : options.exclude;
|
|
315
|
-
const
|
|
316
|
-
|
|
356
|
+
const visited = options.visited;
|
|
357
|
+
for (const entity of entities) {
|
|
358
|
+
visited.delete(entity);
|
|
359
|
+
}
|
|
360
|
+
const unique = Utils.unique(children);
|
|
361
|
+
const filtered = unique.filter(e => !visited.has(e));
|
|
362
|
+
for (const entity of entities) {
|
|
363
|
+
visited.add(entity);
|
|
364
|
+
}
|
|
365
|
+
// skip lazy scalar properties
|
|
366
|
+
if (!prop.targetMeta) {
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
await this.populate(prop.targetMeta.class, unique, populate.children ?? populate.all, {
|
|
317
370
|
where: await this.extractChildCondition(options, prop, false),
|
|
318
371
|
orderBy: innerOrderBy,
|
|
319
372
|
fields,
|
|
@@ -325,12 +378,16 @@ export class EntityLoader {
|
|
|
325
378
|
populateWhere,
|
|
326
379
|
connectionType,
|
|
327
380
|
logging,
|
|
381
|
+
schema,
|
|
328
382
|
// @ts-ignore not a public option, will be propagated to the populate call
|
|
329
383
|
refresh: refresh && !filtered.every(item => options.visited.has(item)),
|
|
330
384
|
// @ts-ignore not a public option, will be propagated to the populate call
|
|
331
385
|
visited: options.visited,
|
|
386
|
+
// @ts-ignore not a public option
|
|
387
|
+
filtered,
|
|
332
388
|
});
|
|
333
389
|
}
|
|
390
|
+
/** @internal */
|
|
334
391
|
async findChildrenFromPivotTable(filtered, prop, options, orderBy, populate, pivotJoin) {
|
|
335
392
|
const ids = filtered.map(e => e.__helper.__primaryKeys);
|
|
336
393
|
const refresh = options.refresh;
|
|
@@ -354,12 +411,12 @@ export class EntityLoader {
|
|
|
354
411
|
for (const entity of filtered) {
|
|
355
412
|
const items = map[entity.__helper.getSerializedPrimaryKey()].map(item => {
|
|
356
413
|
if (pivotJoin) {
|
|
357
|
-
return this.em.getReference(prop.
|
|
414
|
+
return this.em.getReference(prop.targetMeta.class, item, {
|
|
358
415
|
convertCustomTypes: true,
|
|
359
416
|
schema: options.schema ?? this.em.config.get('schema'),
|
|
360
417
|
});
|
|
361
418
|
}
|
|
362
|
-
const entity = this.em.getEntityFactory().create(prop.
|
|
419
|
+
const entity = this.em.getEntityFactory().create(prop.targetMeta.class, item, {
|
|
363
420
|
refresh,
|
|
364
421
|
merge: true,
|
|
365
422
|
convertCustomTypes: true,
|
|
@@ -368,23 +425,20 @@ export class EntityLoader {
|
|
|
368
425
|
return this.em.getUnitOfWork().register(entity, item, { refresh, loaded: true });
|
|
369
426
|
});
|
|
370
427
|
entity[prop.name].hydrate(items, true);
|
|
371
|
-
children.push(
|
|
428
|
+
children.push(items);
|
|
372
429
|
}
|
|
373
430
|
return children;
|
|
374
431
|
}
|
|
375
432
|
async extractChildCondition(options, prop, filters = false) {
|
|
376
433
|
const where = options.where;
|
|
377
434
|
const subCond = Utils.isPlainObject(where[prop.name]) ? where[prop.name] : {};
|
|
378
|
-
const meta2 =
|
|
379
|
-
if (!meta2) {
|
|
380
|
-
return {};
|
|
381
|
-
}
|
|
435
|
+
const meta2 = prop.targetMeta;
|
|
382
436
|
const pk = Utils.getPrimaryKeyHash(meta2.primaryKeys);
|
|
383
437
|
['$and', '$or'].forEach(op => {
|
|
384
438
|
if (where[op]) {
|
|
385
439
|
const child = where[op]
|
|
386
440
|
.map((cond) => cond[prop.name])
|
|
387
|
-
.filter((sub) => sub != null && !(Utils.isPlainObject(sub) &&
|
|
441
|
+
.filter((sub) => sub != null && !(Utils.isPlainObject(sub) && Utils.getObjectQueryKeys(sub).every(key => Utils.isOperator(key, false))))
|
|
388
442
|
.map((cond) => {
|
|
389
443
|
if (Utils.isPrimaryKey(cond)) {
|
|
390
444
|
return { [pk]: cond };
|
|
@@ -405,7 +459,7 @@ export class EntityLoader {
|
|
|
405
459
|
});
|
|
406
460
|
}
|
|
407
461
|
if (filters) {
|
|
408
|
-
return this.em.applyFilters(
|
|
462
|
+
return this.em.applyFilters(meta2.class, subCond, options.filters, 'read', options);
|
|
409
463
|
}
|
|
410
464
|
return subCond;
|
|
411
465
|
}
|
|
@@ -423,7 +477,7 @@ export class EntityLoader {
|
|
|
423
477
|
const parts = f.toString().split('.');
|
|
424
478
|
const propName = parts.shift();
|
|
425
479
|
const childPropName = parts.join('.');
|
|
426
|
-
/* v8 ignore next
|
|
480
|
+
/* v8 ignore next */
|
|
427
481
|
if (propName === prop.name) {
|
|
428
482
|
ret.push(childPropName);
|
|
429
483
|
}
|
|
@@ -444,23 +498,20 @@ export class EntityLoader {
|
|
|
444
498
|
}
|
|
445
499
|
getChildReferences(entities, prop, options, ref) {
|
|
446
500
|
const filtered = this.filterCollections(entities, prop.name, options, ref);
|
|
447
|
-
const children = [];
|
|
448
501
|
if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
449
|
-
|
|
502
|
+
return filtered.map(e => e[prop.name].owner);
|
|
450
503
|
}
|
|
451
|
-
|
|
452
|
-
|
|
504
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY && prop.owner) {
|
|
505
|
+
return filtered.reduce((a, b) => {
|
|
453
506
|
a.push(...b[prop.name].getItems());
|
|
454
507
|
return a;
|
|
455
|
-
}, [])
|
|
508
|
+
}, []);
|
|
456
509
|
}
|
|
457
|
-
|
|
458
|
-
|
|
510
|
+
if (prop.kind === ReferenceKind.MANY_TO_MANY) { // inverse side
|
|
511
|
+
return filtered;
|
|
459
512
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
}
|
|
463
|
-
return children;
|
|
513
|
+
// MANY_TO_ONE or ONE_TO_ONE
|
|
514
|
+
return this.filterReferences(entities, prop.name, options, ref);
|
|
464
515
|
}
|
|
465
516
|
filterCollections(entities, field, options, ref) {
|
|
466
517
|
if (options.refresh) {
|
|
@@ -477,7 +528,7 @@ export class EntityLoader {
|
|
|
477
528
|
return wrapped.__loadedProperties.has(field);
|
|
478
529
|
}
|
|
479
530
|
const [f, ...r] = field.split('.');
|
|
480
|
-
/* v8 ignore next
|
|
531
|
+
/* v8 ignore next */
|
|
481
532
|
if (!wrapped.__loadedProperties.has(f) || !wrapped.__meta.properties[f]?.targetMeta) {
|
|
482
533
|
return false;
|
|
483
534
|
}
|
|
@@ -510,11 +561,11 @@ export class EntityLoader {
|
|
|
510
561
|
.map(e => Reference.unwrapReference(e[field]));
|
|
511
562
|
}
|
|
512
563
|
filterByReferences(entities, field, refresh) {
|
|
513
|
-
/* v8 ignore next
|
|
564
|
+
/* v8 ignore next */
|
|
514
565
|
if (refresh) {
|
|
515
566
|
return entities;
|
|
516
567
|
}
|
|
517
|
-
return entities.filter(e => !e[field]?.__helper?.__initialized);
|
|
568
|
+
return entities.filter(e => e[field] !== null && !e[field]?.__helper?.__initialized);
|
|
518
569
|
}
|
|
519
570
|
lookupAllRelationships(entityName) {
|
|
520
571
|
const ret = [];
|
|
@@ -536,33 +587,36 @@ export class EntityLoader {
|
|
|
536
587
|
}
|
|
537
588
|
return `${this.getRelationName(meta, meta.properties[prop.embedded[0]])}.${prop.embedded[1]}`;
|
|
538
589
|
}
|
|
539
|
-
lookupEagerLoadedRelationships(entityName, populate, strategy, prefix = '', visited = []) {
|
|
590
|
+
lookupEagerLoadedRelationships(entityName, populate, strategy, prefix = '', visited = [], exclude) {
|
|
540
591
|
const meta = this.metadata.find(entityName);
|
|
541
592
|
if (!meta && !prefix) {
|
|
542
593
|
return populate;
|
|
543
594
|
}
|
|
544
|
-
if (visited.includes(
|
|
595
|
+
if (!meta || visited.includes(meta)) {
|
|
545
596
|
return [];
|
|
546
597
|
}
|
|
547
|
-
visited.push(
|
|
598
|
+
visited.push(meta);
|
|
548
599
|
const ret = prefix === '' ? [...populate] : [];
|
|
549
600
|
meta.relations
|
|
550
601
|
.filter(prop => {
|
|
602
|
+
const field = this.getRelationName(meta, prop);
|
|
603
|
+
const prefixed = prefix ? `${prefix}.${field}` : field;
|
|
604
|
+
const isExcluded = exclude?.includes(prefixed);
|
|
551
605
|
const eager = prop.eager && !populate.some(p => p.field === `${prop.name}:ref`);
|
|
552
606
|
const populated = populate.some(p => p.field === prop.name);
|
|
553
607
|
const disabled = populate.some(p => p.field === prop.name && p.all === false);
|
|
554
|
-
return !disabled && (eager || populated);
|
|
608
|
+
return !disabled && !isExcluded && (eager || populated);
|
|
555
609
|
})
|
|
556
610
|
.forEach(prop => {
|
|
557
611
|
const field = this.getRelationName(meta, prop);
|
|
558
612
|
const prefixed = prefix ? `${prefix}.${field}` : field;
|
|
559
613
|
const nestedPopulate = populate.filter(p => p.field === prop.name).flatMap(p => p.children).filter(Boolean);
|
|
560
|
-
const nested = this.lookupEagerLoadedRelationships(prop.
|
|
614
|
+
const nested = this.lookupEagerLoadedRelationships(prop.targetMeta.class, nestedPopulate, strategy, prefixed, visited.slice(), exclude);
|
|
561
615
|
if (nested.length > 0) {
|
|
562
616
|
ret.push(...nested);
|
|
563
617
|
}
|
|
564
618
|
else {
|
|
565
|
-
const selfReferencing = [meta.
|
|
619
|
+
const selfReferencing = [meta.tableName, ...visited.map(m => m.tableName)].includes(prop.targetMeta.tableName) && prop.eager;
|
|
566
620
|
ret.push({
|
|
567
621
|
field: prefixed,
|
|
568
622
|
// enforce select-in strategy for self-referencing relations
|
|
@@ -2,7 +2,7 @@ import type { PopulatePath } from '../enums.js';
|
|
|
2
2
|
import type { CreateOptions, EntityManager, MergeOptions } from '../EntityManager.js';
|
|
3
3
|
import type { AssignOptions } from './EntityAssigner.js';
|
|
4
4
|
import type { EntityData, EntityName, Primary, Loaded, FilterQuery, EntityDictionary, AutoPath, RequiredEntityData, Ref, EntityType, EntityDTO, MergeSelected, FromEntityType, IsSubset, MergeLoaded, ArrayElement } from '../typings.js';
|
|
5
|
-
import type { CountOptions, DeleteOptions, FindAllOptions, FindByCursorOptions, FindOneOptions, FindOneOrFailOptions, FindOptions, GetReferenceOptions, NativeInsertUpdateOptions, UpdateOptions, UpsertManyOptions, UpsertOptions } from '../drivers/IDatabaseDriver.js';
|
|
5
|
+
import type { CountOptions, DeleteOptions, FindAllOptions, FindByCursorOptions, FindOneOptions, FindOneOrFailOptions, FindOptions, GetReferenceOptions, NativeInsertUpdateOptions, StreamOptions, UpdateOptions, UpsertManyOptions, UpsertOptions } from '../drivers/IDatabaseDriver.js';
|
|
6
6
|
import type { EntityLoaderOptions } from './EntityLoader.js';
|
|
7
7
|
import type { Cursor } from '../utils/Cursor.js';
|
|
8
8
|
export declare class EntityRepository<Entity extends object> {
|
|
@@ -80,11 +80,15 @@ export declare class EntityRepository<Entity extends object> {
|
|
|
80
80
|
/**
|
|
81
81
|
* @inheritDoc EntityManager.findByCursor
|
|
82
82
|
*/
|
|
83
|
-
findByCursor<Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(
|
|
83
|
+
findByCursor<Hint extends string = never, Fields extends string = '*', Excludes extends string = never, IncludeCount extends boolean = true>(options: FindByCursorOptions<Entity, Hint, Fields, Excludes, IncludeCount>): Promise<Cursor<Entity, Hint, Fields, Excludes, IncludeCount>>;
|
|
84
84
|
/**
|
|
85
85
|
* Finds all entities of given type. You can pass additional options via the `options` parameter.
|
|
86
86
|
*/
|
|
87
87
|
findAll<Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(options?: FindAllOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
|
|
88
|
+
/**
|
|
89
|
+
* @inheritDoc EntityManager.stream
|
|
90
|
+
*/
|
|
91
|
+
stream<Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(options?: StreamOptions<Entity, Hint, Fields, Excludes>): AsyncIterableIterator<Loaded<Entity, Hint, Fields, Excludes>>;
|
|
88
92
|
/**
|
|
89
93
|
* @inheritDoc EntityManager.insert
|
|
90
94
|
*/
|
|
@@ -107,10 +111,26 @@ export declare class EntityRepository<Entity extends object> {
|
|
|
107
111
|
map(result: EntityDictionary<Entity>, options?: {
|
|
108
112
|
schema?: string;
|
|
109
113
|
}): Entity;
|
|
114
|
+
/**
|
|
115
|
+
* Gets a reference to the entity identified by the given type and alternate key property without actually loading it.
|
|
116
|
+
* The key option specifies which property to use for identity map lookup instead of the primary key.
|
|
117
|
+
*/
|
|
118
|
+
getReference<K extends string & keyof Entity>(id: Entity[K], options: Omit<GetReferenceOptions, 'key' | 'wrapped'> & {
|
|
119
|
+
key: K;
|
|
120
|
+
wrapped: true;
|
|
121
|
+
}): Ref<Entity>;
|
|
122
|
+
/**
|
|
123
|
+
* Gets a reference to the entity identified by the given type and alternate key property without actually loading it.
|
|
124
|
+
* The key option specifies which property to use for identity map lookup instead of the primary key.
|
|
125
|
+
*/
|
|
126
|
+
getReference<K extends string & keyof Entity>(id: Entity[K], options: Omit<GetReferenceOptions, 'key'> & {
|
|
127
|
+
key: K;
|
|
128
|
+
wrapped?: false;
|
|
129
|
+
}): Entity;
|
|
110
130
|
/**
|
|
111
131
|
* Gets a reference to the entity identified by the given type and identifier without actually loading it, if the entity is not yet loaded
|
|
112
132
|
*/
|
|
113
|
-
getReference(id: Primary<Entity>, options: Omit<GetReferenceOptions, 'wrapped'> & {
|
|
133
|
+
getReference(id: Primary<Entity>, options: Omit<GetReferenceOptions, 'wrapped' | 'key'> & {
|
|
114
134
|
wrapped: true;
|
|
115
135
|
}): Ref<Entity>;
|
|
116
136
|
/**
|
|
@@ -120,7 +140,7 @@ export declare class EntityRepository<Entity extends object> {
|
|
|
120
140
|
/**
|
|
121
141
|
* Gets a reference to the entity identified by the given type and identifier without actually loading it, if the entity is not yet loaded
|
|
122
142
|
*/
|
|
123
|
-
getReference(id: Primary<Entity>, options: Omit<GetReferenceOptions, 'wrapped'> & {
|
|
143
|
+
getReference(id: Primary<Entity>, options: Omit<GetReferenceOptions, 'wrapped' | 'key'> & {
|
|
124
144
|
wrapped: false;
|
|
125
145
|
}): Entity;
|
|
126
146
|
/**
|
|
@@ -90,8 +90,8 @@ export class EntityRepository {
|
|
|
90
90
|
/**
|
|
91
91
|
* @inheritDoc EntityManager.findByCursor
|
|
92
92
|
*/
|
|
93
|
-
async findByCursor(
|
|
94
|
-
return this.getEntityManager().findByCursor(this.entityName,
|
|
93
|
+
async findByCursor(options) {
|
|
94
|
+
return this.getEntityManager().findByCursor(this.entityName, options);
|
|
95
95
|
}
|
|
96
96
|
/**
|
|
97
97
|
* Finds all entities of given type. You can pass additional options via the `options` parameter.
|
|
@@ -99,6 +99,12 @@ export class EntityRepository {
|
|
|
99
99
|
async findAll(options) {
|
|
100
100
|
return this.getEntityManager().findAll(this.entityName, options);
|
|
101
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* @inheritDoc EntityManager.stream
|
|
104
|
+
*/
|
|
105
|
+
async *stream(options) {
|
|
106
|
+
yield* this.getEntityManager().stream(this.entityName, options);
|
|
107
|
+
}
|
|
102
108
|
/**
|
|
103
109
|
* @inheritDoc EntityManager.insert
|
|
104
110
|
*/
|
package/entity/Reference.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { AddEager, Dictionary, EntityClass, EntityKey, EntityProperty, Loaded, LoadedReference, Primary, Ref } from '../typings.js';
|
|
1
|
+
import type { AddEager, AddOptional, Dictionary, EntityClass, EntityKey, EntityProperty, Loaded, LoadedReference, Primary, Ref } from '../typings.js';
|
|
3
2
|
import type { FindOneOptions, FindOneOrFailOptions } from '../drivers/IDatabaseDriver.js';
|
|
4
3
|
export declare class Reference<T extends object> {
|
|
5
4
|
private entity;
|
|
5
|
+
private property?;
|
|
6
6
|
constructor(entity: T);
|
|
7
7
|
static create<T extends object>(entity: T | Ref<T>): Ref<T>;
|
|
8
8
|
static createFromPK<T extends object>(entityType: EntityClass<T>, pk: Primary<T>, options?: {
|
|
@@ -42,8 +42,6 @@ export declare class Reference<T extends object> {
|
|
|
42
42
|
isInitialized(): boolean;
|
|
43
43
|
populated(populated?: boolean): void;
|
|
44
44
|
toJSON(...args: any[]): Dictionary;
|
|
45
|
-
/** @ignore */
|
|
46
|
-
[inspect.custom](depth?: number): string;
|
|
47
45
|
}
|
|
48
46
|
export declare class ScalarReference<Value> {
|
|
49
47
|
private value?;
|
|
@@ -56,12 +54,15 @@ export declare class ScalarReference<Value> {
|
|
|
56
54
|
* Returns either the whole entity, or the requested property.
|
|
57
55
|
*/
|
|
58
56
|
load(options?: Omit<LoadReferenceOptions<any, any>, 'populate' | 'fields' | 'exclude'>): Promise<Value | undefined>;
|
|
57
|
+
/**
|
|
58
|
+
* Ensures the underlying entity is loaded first (without reloading it if it already is loaded).
|
|
59
|
+
* Returns the entity or throws an error just like `em.findOneOrFail()` (and respects the same config options).
|
|
60
|
+
*/
|
|
61
|
+
loadOrFail(options?: Omit<LoadReferenceOrFailOptions<any, any>, 'populate' | 'fields' | 'exclude'>): Promise<Value>;
|
|
59
62
|
set(value: Value): void;
|
|
60
63
|
bind<Entity extends object>(entity: Entity, property: EntityKey<Entity>): void;
|
|
61
64
|
unwrap(): Value | undefined;
|
|
62
65
|
isInitialized(): boolean;
|
|
63
|
-
/** @ignore */
|
|
64
|
-
[inspect.custom](): string;
|
|
65
66
|
}
|
|
66
67
|
export interface LoadReferenceOptions<T extends object, P extends string = never, F extends string = '*', E extends string = never> extends FindOneOptions<T, P, F, E> {
|
|
67
68
|
dataloader?: boolean;
|
|
@@ -72,15 +73,11 @@ export interface LoadReferenceOrFailOptions<T extends object, P extends string =
|
|
|
72
73
|
/**
|
|
73
74
|
* shortcut for `wrap(entity).toReference()`
|
|
74
75
|
*/
|
|
75
|
-
export declare function ref<
|
|
76
|
+
export declare function ref<I extends unknown | Ref<unknown> | undefined | null, T extends I & {}>(entity: I): Ref<T> & LoadedReference<Loaded<T, AddEager<T>>> | AddOptional<typeof entity>;
|
|
76
77
|
/**
|
|
77
78
|
* shortcut for `Reference.createFromPK(entityType, pk)`
|
|
78
79
|
*/
|
|
79
|
-
export declare function ref<T, PKV extends Primary<T> = Primary<T>>(entityType: EntityClass<T>, pk
|
|
80
|
-
/**
|
|
81
|
-
* shortcut for `wrap(entity).toReference()`
|
|
82
|
-
*/
|
|
83
|
-
export declare function ref<T>(value: T | Ref<T>): Ref<T> & LoadedReference<Loaded<T, AddEager<T>>>;
|
|
80
|
+
export declare function ref<I extends unknown | undefined | null, T, PKV extends Primary<T> = Primary<T>>(entityType: EntityClass<T>, pk: I): Ref<T> | AddOptional<typeof pk>;
|
|
84
81
|
/**
|
|
85
82
|
* shortcut for `Reference.createNakedFromPK(entityType, pk)`
|
|
86
83
|
*/
|