@mikro-orm/core 7.0.17-dev.9 → 7.0.18-dev.0
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 +106 -12
- package/EntityManager.js +228 -19
- package/MikroORM.d.ts +3 -3
- package/README.md +2 -1
- package/connections/Connection.d.ts +67 -1
- package/connections/Connection.js +64 -0
- package/drivers/DatabaseDriver.d.ts +1 -0
- package/drivers/DatabaseDriver.js +3 -0
- package/drivers/IDatabaseDriver.d.ts +50 -7
- package/entity/BaseEntity.d.ts +70 -3
- package/entity/BaseEntity.js +18 -0
- package/entity/Collection.d.ts +6 -3
- package/entity/Collection.js +15 -4
- package/entity/EntityAssigner.js +8 -0
- package/entity/EntityFactory.js +25 -4
- package/entity/EntityLoader.d.ts +8 -1
- package/entity/EntityLoader.js +41 -16
- package/entity/EntityRepository.d.ts +27 -9
- package/entity/EntityRepository.js +12 -0
- package/entity/Reference.d.ts +42 -1
- package/entity/Reference.js +9 -0
- package/entity/WrappedEntity.d.ts +2 -2
- package/entity/defineEntity.d.ts +92 -17
- package/entity/defineEntity.js +17 -6
- package/entity/utils.js +4 -5
- package/enums.d.ts +8 -1
- package/errors.d.ts +2 -0
- package/errors.js +4 -0
- package/index.d.ts +2 -2
- package/index.js +1 -1
- package/metadata/EntitySchema.js +3 -0
- package/metadata/MetadataDiscovery.d.ts +11 -0
- package/metadata/MetadataDiscovery.js +135 -10
- package/metadata/MetadataValidator.d.ts +26 -0
- package/metadata/MetadataValidator.js +236 -0
- package/metadata/Routine.d.ts +74 -0
- package/metadata/Routine.js +140 -0
- package/metadata/index.d.ts +1 -0
- package/metadata/index.js +1 -0
- package/metadata/types.d.ts +77 -4
- package/naming-strategy/AbstractNamingStrategy.d.ts +1 -1
- package/naming-strategy/NamingStrategy.d.ts +1 -1
- package/package.json +1 -1
- package/platforms/Platform.d.ts +7 -0
- package/platforms/Platform.js +15 -1
- package/serialization/EntitySerializer.d.ts +18 -6
- package/serialization/EntitySerializer.js +33 -6
- package/typings.d.ts +389 -18
- package/typings.js +21 -4
- package/unit-of-work/UnitOfWork.js +11 -3
- package/utils/AbstractMigrator.d.ts +26 -3
- package/utils/AbstractMigrator.js +264 -15
- package/utils/AbstractSchemaGenerator.d.ts +1 -1
- package/utils/AbstractSchemaGenerator.js +4 -1
- package/utils/Configuration.d.ts +40 -3
- package/utils/Configuration.js +46 -0
- package/utils/DataloaderUtils.d.ts +10 -1
- package/utils/DataloaderUtils.js +78 -0
- package/utils/QueryHelper.d.ts +16 -0
- package/utils/QueryHelper.js +15 -0
- package/utils/TransactionManager.js +2 -0
- package/utils/Utils.d.ts +1 -1
- package/utils/Utils.js +1 -1
- package/utils/fs-utils.d.ts +2 -0
- package/utils/fs-utils.js +7 -1
- package/utils/index.d.ts +1 -0
- package/utils/index.js +1 -0
- package/utils/partition-utils.d.ts +17 -0
- package/utils/partition-utils.js +79 -0
package/entity/EntityLoader.js
CHANGED
|
@@ -177,8 +177,9 @@ export class EntityLoader {
|
|
|
177
177
|
Utils.isObject(orderBy[prop.name]))
|
|
178
178
|
.flatMap(orderBy => orderBy[prop.name]);
|
|
179
179
|
const where = await this.extractChildCondition(options, prop);
|
|
180
|
+
const mergedOrderBy = populate.orderBy ? Utils.asArray(populate.orderBy) : innerOrderBy;
|
|
180
181
|
if (prop.kind === ReferenceKind.MANY_TO_MANY && this.#driver.getPlatform().usesPivotTable()) {
|
|
181
|
-
const pivotOrderBy = QueryHelper.mergeOrderBy(
|
|
182
|
+
const pivotOrderBy = QueryHelper.mergeOrderBy(mergedOrderBy, prop.orderBy, prop.targetMeta?.orderBy);
|
|
182
183
|
const res = await this.findChildrenFromPivotTable(filtered, prop, options, pivotOrderBy, populate, !!ref);
|
|
183
184
|
return Utils.flatten(res);
|
|
184
185
|
}
|
|
@@ -188,10 +189,12 @@ export class EntityLoader {
|
|
|
188
189
|
const { items, partial } = await this.findChildren(options.filtered ?? entities, prop, populate, {
|
|
189
190
|
...options,
|
|
190
191
|
where,
|
|
191
|
-
orderBy:
|
|
192
|
+
orderBy: mergedOrderBy,
|
|
192
193
|
}, !!(ref || prop.mapToPk));
|
|
193
|
-
const
|
|
194
|
-
|
|
194
|
+
const hasLimit = populate.limit != null;
|
|
195
|
+
const isPartial = partial || hasLimit;
|
|
196
|
+
const customOrder = mergedOrderBy.length > 0 || !!prop.orderBy || !!prop.targetMeta?.orderBy;
|
|
197
|
+
this.initializeCollections(filtered, prop, field, items, customOrder, isPartial, hasLimit);
|
|
195
198
|
return items;
|
|
196
199
|
}
|
|
197
200
|
async populateScalar(meta, filtered, options) {
|
|
@@ -269,15 +272,15 @@ export class EntityLoader {
|
|
|
269
272
|
}));
|
|
270
273
|
return allItems;
|
|
271
274
|
}
|
|
272
|
-
initializeCollections(filtered, prop, field, children, customOrder, partial) {
|
|
275
|
+
initializeCollections(filtered, prop, field, children, customOrder, partial, readonly) {
|
|
273
276
|
if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
274
|
-
this.initializeOneToMany(filtered, children, prop, field, partial);
|
|
277
|
+
this.initializeOneToMany(filtered, children, prop, field, partial, readonly);
|
|
275
278
|
}
|
|
276
279
|
if (prop.kind === ReferenceKind.MANY_TO_MANY && !this.#driver.getPlatform().usesPivotTable()) {
|
|
277
|
-
this.initializeManyToMany(filtered, children, prop, field, customOrder, partial);
|
|
280
|
+
this.initializeManyToMany(filtered, children, prop, field, customOrder, partial, readonly);
|
|
278
281
|
}
|
|
279
282
|
}
|
|
280
|
-
initializeOneToMany(filtered, children, prop, field, partial) {
|
|
283
|
+
initializeOneToMany(filtered, children, prop, field, partial, readonly) {
|
|
281
284
|
const mapToPk = prop.targetMeta.properties[prop.mappedBy].mapToPk;
|
|
282
285
|
const map = {};
|
|
283
286
|
for (const entity of filtered) {
|
|
@@ -293,14 +296,14 @@ export class EntityLoader {
|
|
|
293
296
|
}
|
|
294
297
|
for (const entity of filtered) {
|
|
295
298
|
const key = helper(entity).getSerializedPrimaryKey();
|
|
296
|
-
entity[field].hydrate(map[key], undefined, partial);
|
|
299
|
+
entity[field].hydrate(map[key], undefined, partial, readonly);
|
|
297
300
|
}
|
|
298
301
|
}
|
|
299
|
-
initializeManyToMany(filtered, children, prop, field, customOrder, partial) {
|
|
302
|
+
initializeManyToMany(filtered, children, prop, field, customOrder, partial, readonly) {
|
|
300
303
|
if (prop.mappedBy) {
|
|
301
304
|
for (const entity of filtered) {
|
|
302
305
|
const items = children.filter(child => child[prop.mappedBy].contains(entity, false));
|
|
303
|
-
entity[field].hydrate(items, true, partial);
|
|
306
|
+
entity[field].hydrate(items, true, partial, readonly);
|
|
304
307
|
}
|
|
305
308
|
}
|
|
306
309
|
else {
|
|
@@ -311,7 +314,7 @@ export class EntityLoader {
|
|
|
311
314
|
if (!customOrder) {
|
|
312
315
|
items.sort((a, b) => order.indexOf(a) - order.indexOf(b));
|
|
313
316
|
}
|
|
314
|
-
entity[field].hydrate(items, true, partial);
|
|
317
|
+
entity[field].hydrate(items, true, partial, readonly);
|
|
315
318
|
}
|
|
316
319
|
}
|
|
317
320
|
}
|
|
@@ -375,7 +378,7 @@ export class EntityLoader {
|
|
|
375
378
|
where = { $and: [where, prop.where] };
|
|
376
379
|
}
|
|
377
380
|
const orderBy = QueryHelper.mergeOrderBy(options.orderBy, prop.orderBy);
|
|
378
|
-
const
|
|
381
|
+
const findOptions = {
|
|
379
382
|
filters,
|
|
380
383
|
convertCustomTypes,
|
|
381
384
|
lockMode,
|
|
@@ -390,11 +393,21 @@ export class EntityLoader {
|
|
|
390
393
|
fields,
|
|
391
394
|
schema,
|
|
392
395
|
connectionType,
|
|
396
|
+
signal: options.signal,
|
|
397
|
+
inflightQueryAbortStrategy: options.inflightQueryAbortStrategy,
|
|
393
398
|
// @ts-ignore not a public option, will be propagated to the populate call
|
|
394
399
|
refresh: refresh && !children.every(item => options.visited.has(item)),
|
|
395
400
|
// @ts-ignore not a public option, will be propagated to the populate call
|
|
396
401
|
visited: options.visited,
|
|
397
|
-
}
|
|
402
|
+
};
|
|
403
|
+
if (populate.limit != null) {
|
|
404
|
+
findOptions._partitionLimit = {
|
|
405
|
+
partitionBy: fk,
|
|
406
|
+
limit: populate.limit,
|
|
407
|
+
offset: populate.offset,
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
const items = await this.#em.find(meta.class, where, findOptions);
|
|
398
411
|
// For targetKey relations, wire up loaded entities to parent references
|
|
399
412
|
// This is needed because the references were created under alternate key,
|
|
400
413
|
// but loaded entities are stored under PK, so they don't automatically merge
|
|
@@ -582,11 +595,18 @@ export class EntityLoader {
|
|
|
582
595
|
const options2 = { ...options, fields, exclude, populateFilter };
|
|
583
596
|
['limit', 'offset', 'first', 'last', 'before', 'after', 'overfetch'].forEach(prop => delete options2[prop]);
|
|
584
597
|
options2.populate = populate?.children ?? [];
|
|
598
|
+
if (populate?.limit != null) {
|
|
599
|
+
options2._partitionLimit = {
|
|
600
|
+
limit: populate.limit,
|
|
601
|
+
offset: populate.offset,
|
|
602
|
+
};
|
|
603
|
+
}
|
|
585
604
|
if (!Utils.isEmpty(prop.where)) {
|
|
586
605
|
where = { $and: [where, prop.where] };
|
|
587
606
|
}
|
|
588
607
|
const map = await this.#driver.loadFromPivotTable(prop, ids, where, orderBy, this.#em.getTransactionContext(), options2, pivotJoin);
|
|
589
608
|
const children = [];
|
|
609
|
+
const isUnionTargetMN = QueryHelper.isUnionTargetPolymorphic(prop);
|
|
590
610
|
for (let i = 0; i < filtered.length; i++) {
|
|
591
611
|
const entity = filtered[i];
|
|
592
612
|
const items = map[Utils.getPrimaryKeyHash(ids[i])].map(item => {
|
|
@@ -596,7 +616,11 @@ export class EntityLoader {
|
|
|
596
616
|
schema: options.schema ?? this.#em.config.get('schema'),
|
|
597
617
|
});
|
|
598
618
|
}
|
|
599
|
-
|
|
619
|
+
// Union-target items carry their concrete class via `constructor` — dispatch to the right factory call.
|
|
620
|
+
const targetClass = isUnionTargetMN && item.constructor !== Object
|
|
621
|
+
? item.constructor
|
|
622
|
+
: prop.targetMeta.class;
|
|
623
|
+
const entity = this.#em.getEntityFactory().create(targetClass, item, {
|
|
600
624
|
refresh,
|
|
601
625
|
merge: true,
|
|
602
626
|
convertCustomTypes: true,
|
|
@@ -604,7 +628,8 @@ export class EntityLoader {
|
|
|
604
628
|
});
|
|
605
629
|
return this.#em.getUnitOfWork().register(entity, item, { refresh, loaded: true });
|
|
606
630
|
});
|
|
607
|
-
|
|
631
|
+
const hasLimit = populate?.limit != null;
|
|
632
|
+
entity[prop.name].hydrate(items, true, hasLimit, hasLimit);
|
|
608
633
|
children.push(items);
|
|
609
634
|
}
|
|
610
635
|
return children;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
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
|
-
import type { EntityData,
|
|
5
|
-
import type { CountOptions, DeleteOptions, FindAllOptions, FindByCursorOptions, FindOneOptions, FindOneOrFailOptions, FindOptions, GetReferenceOptions, NativeInsertUpdateOptions, StreamOptions, UpdateOptions, UpsertManyOptions, UpsertOptions } from '../drivers/IDatabaseDriver.js';
|
|
4
|
+
import type { Dictionary, EntityData, EntityDictionary, EntityKey, EntityName, FilterQuery, Loaded, Primary, AutoPath, RequiredEntityData, Ref, EntityType, EntityDTO, MergeSelected, FromEntityType, IsSubset, MergeLoaded, ArrayElement, IndexFilterQuery, WithUsingOptions } from '../typings.js';
|
|
5
|
+
import type { CountByOptions, 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
|
/** Repository class providing a type-safe API for querying and persisting a specific entity type. */
|
|
@@ -13,13 +13,17 @@ export declare class EntityRepository<Entity extends object> {
|
|
|
13
13
|
/**
|
|
14
14
|
* Finds first entity matching your `where` query.
|
|
15
15
|
*/
|
|
16
|
-
findOne<Hint extends string = never, Fields extends string = never, Excludes extends string = never>(where: FilterQuery<Entity
|
|
16
|
+
findOne<Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(where: [Using] extends [never] ? FilterQuery<Entity> : IndexFilterQuery<Entity, Using>, options?: FindOneOptions<Entity, Hint, Fields, Excludes> & {
|
|
17
|
+
using?: Using | Using[];
|
|
18
|
+
}): Promise<Loaded<Entity, Hint, Fields, Excludes> | null>;
|
|
17
19
|
/**
|
|
18
20
|
* Finds first entity matching your `where` query. If nothing is found, it will throw an error.
|
|
19
21
|
* You can override the factory for creating this method via `options.failHandler` locally
|
|
20
22
|
* or via `Configuration.findOneOrFailHandler` globally.
|
|
21
23
|
*/
|
|
22
|
-
findOneOrFail<Hint extends string = never, Fields extends string = never, Excludes extends string = never>(where: FilterQuery<Entity>, options?: FindOneOrFailOptions<Entity, Hint, Fields, Excludes>
|
|
24
|
+
findOneOrFail<Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(where: [Using] extends [never] ? FilterQuery<Entity> : IndexFilterQuery<Entity, Using>, options?: FindOneOrFailOptions<Entity, Hint, Fields, Excludes> & {
|
|
25
|
+
using?: Using | Using[];
|
|
26
|
+
}): Promise<Loaded<Entity, Hint, Fields, Excludes>>;
|
|
23
27
|
/**
|
|
24
28
|
* Creates or updates the entity, based on whether it is already present in the database.
|
|
25
29
|
* This method performs an `insert on conflict merge` query ensuring the database is in sync, returning a managed
|
|
@@ -72,24 +76,28 @@ export declare class EntityRepository<Entity extends object> {
|
|
|
72
76
|
/**
|
|
73
77
|
* Finds all entities matching your `where` query. You can pass additional options via the `options` parameter.
|
|
74
78
|
*/
|
|
75
|
-
find<Hint extends string = never, Fields extends string = never, Excludes extends string = never>(where: FilterQuery<Entity>, options?: FindOptions<Entity, Hint, Fields, Excludes>
|
|
79
|
+
find<Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(where: [Using] extends [never] ? FilterQuery<Entity> : IndexFilterQuery<Entity, Using>, options?: FindOptions<Entity, Hint, Fields, Excludes> & {
|
|
80
|
+
using?: Using | Using[];
|
|
81
|
+
}): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
|
|
76
82
|
/**
|
|
77
83
|
* Calls `em.find()` and `em.count()` with the same arguments (where applicable) and returns the results as tuple
|
|
78
84
|
* where first element is the array of entities, and the second is the count.
|
|
79
85
|
*/
|
|
80
|
-
findAndCount<Hint extends string = never, Fields extends string = never, Excludes extends string = never>(where: FilterQuery<Entity
|
|
86
|
+
findAndCount<Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(where: [Using] extends [never] ? FilterQuery<Entity> : IndexFilterQuery<Entity, Using>, options?: FindOptions<Entity, Hint, Fields, Excludes> & {
|
|
87
|
+
using?: Using | Using[];
|
|
88
|
+
}): Promise<[Loaded<Entity, Hint, Fields, Excludes>[], number]>;
|
|
81
89
|
/**
|
|
82
90
|
* @inheritDoc EntityManager.findByCursor
|
|
83
91
|
*/
|
|
84
|
-
findByCursor<Hint extends string = never, Fields extends string = never, Excludes extends string = never, IncludeCount extends boolean = true>(options: FindByCursorOptions<Entity, Hint, Fields, Excludes, IncludeCount>): Promise<Cursor<Entity, Hint, Fields, Excludes, IncludeCount>>;
|
|
92
|
+
findByCursor<Hint extends string = never, Fields extends string = never, Excludes extends string = never, IncludeCount extends boolean = true, Using extends string = never>(options: WithUsingOptions<FindByCursorOptions<Entity, Hint, Fields, Excludes, IncludeCount>, Entity, Using>): Promise<Cursor<Entity, Hint, Fields, Excludes, IncludeCount>>;
|
|
85
93
|
/**
|
|
86
94
|
* Finds all entities of given type. You can pass additional options via the `options` parameter.
|
|
87
95
|
*/
|
|
88
|
-
findAll<Hint extends string = never, Fields extends string = never, Excludes extends string = never>(options?: FindAllOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
|
|
96
|
+
findAll<Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(options?: WithUsingOptions<FindAllOptions<Entity, Hint, Fields, Excludes>, Entity, Using>): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
|
|
89
97
|
/**
|
|
90
98
|
* @inheritDoc EntityManager.stream
|
|
91
99
|
*/
|
|
92
|
-
stream<Hint extends string = never, Fields extends string = never, Excludes extends string = never>(options?: StreamOptions<Entity, Hint, Fields, Excludes>): AsyncIterableIterator<Loaded<Entity, Hint, Fields, Excludes>>;
|
|
100
|
+
stream<Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(options?: WithUsingOptions<StreamOptions<Entity, Hint, Fields, Excludes>, Entity, Using>): AsyncIterableIterator<Loaded<Entity, Hint, Fields, Excludes>>;
|
|
93
101
|
/**
|
|
94
102
|
* @inheritDoc EntityManager.insert
|
|
95
103
|
*/
|
|
@@ -199,6 +207,16 @@ export declare class EntityRepository<Entity extends object> {
|
|
|
199
207
|
* Returns total number of entities matching your `where` query.
|
|
200
208
|
*/
|
|
201
209
|
count<Hint extends string = never>(where?: FilterQuery<Entity>, options?: CountOptions<Entity, Hint>): Promise<number>;
|
|
210
|
+
/**
|
|
211
|
+
* Counts entities grouped by one or more properties.
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```ts
|
|
215
|
+
* const counts = await repo.countBy('status');
|
|
216
|
+
* // { 'active': 5, 'inactive': 2 }
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
219
|
+
countBy(groupBy: EntityKey<Entity> | readonly EntityKey<Entity>[], options?: CountByOptions<Entity>): Promise<Dictionary<number>>;
|
|
202
220
|
/** Returns the entity class name associated with this repository. */
|
|
203
221
|
getEntityName(): string;
|
|
204
222
|
/**
|
|
@@ -194,6 +194,18 @@ export class EntityRepository {
|
|
|
194
194
|
async count(where = {}, options = {}) {
|
|
195
195
|
return this.getEntityManager().count(this.entityName, where, options);
|
|
196
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* Counts entities grouped by one or more properties.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```ts
|
|
202
|
+
* const counts = await repo.countBy('status');
|
|
203
|
+
* // { 'active': 5, 'inactive': 2 }
|
|
204
|
+
* ```
|
|
205
|
+
*/
|
|
206
|
+
async countBy(groupBy, options) {
|
|
207
|
+
return this.getEntityManager().countBy(this.entityName, groupBy, options);
|
|
208
|
+
}
|
|
197
209
|
/** Returns the entity class name associated with this repository. */
|
|
198
210
|
getEntityName() {
|
|
199
211
|
return Utils.className(this.entityName);
|
package/entity/Reference.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AddEager, AddOptional, Dictionary, EntityClass, EntityKey, EntityProperty, Loaded, LoadedReference, Primary, Ref } from '../typings.js';
|
|
1
|
+
import type { AddEager, AddOptional, Dictionary, EntityClass, EntityKey, EntityProperty, LazyRef, Loaded, LoadedReference, Primary, Ref } from '../typings.js';
|
|
2
2
|
import type { FindOneOptions, FindOneOrFailOptions } from '../drivers/IDatabaseDriver.js';
|
|
3
3
|
/** Wrapper around an entity that provides lazy loading capabilities and identity-preserving reference semantics. */
|
|
4
4
|
export declare class Reference<T extends object> {
|
|
@@ -98,6 +98,47 @@ export declare function ref<I extends unknown | Ref<unknown> | undefined | null,
|
|
|
98
98
|
* shortcut for `Reference.createFromPK(entityType, pk)`
|
|
99
99
|
*/
|
|
100
100
|
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>;
|
|
101
|
+
/**
|
|
102
|
+
* Unwraps a reference to its underlying value, returning the entity or scalar. Works on any of:
|
|
103
|
+
*
|
|
104
|
+
* - `Ref<T>` / `Reference<T>` (entity) — calls `.unwrap()` to extract the wrapped entity, returns `T`.
|
|
105
|
+
* - `LazyRef<T>` — type-only marker; runtime value is already `T`, so returned as-is.
|
|
106
|
+
* - plain entity `T` — returned as-is.
|
|
107
|
+
* - `ScalarReference<V>` / `ScalarRef<V>` — calls `.unwrap()` to extract the scalar value, returns `V | undefined`
|
|
108
|
+
* (a scalar reference may be bound without an initial value).
|
|
109
|
+
*
|
|
110
|
+
* Inverse of the {@link ref} helper. Use as a typed escape hatch when you know a relation is populated
|
|
111
|
+
* but don't want to (or can't) thread `Loaded<T, 'relation'>` through a function signature.
|
|
112
|
+
*
|
|
113
|
+
* ```ts
|
|
114
|
+
* function logAuthor(book: Book) {
|
|
115
|
+
* // `book.author` is typed as `LazyRef<Author>`, so `.name` is not directly accessible
|
|
116
|
+
* console.log(unref(book.author).name);
|
|
117
|
+
* }
|
|
118
|
+
*
|
|
119
|
+
* // Scalar reference:
|
|
120
|
+
* const scalar = ref('hello');
|
|
121
|
+
* unref(scalar); // 'hello' (type: string | undefined)
|
|
122
|
+
* ```
|
|
123
|
+
*
|
|
124
|
+
* Note: `unref` is a compile-time narrowing only for entity refs. On a `LazyRef<T>` or plain entity
|
|
125
|
+
* relation that is a stub (PK only, never populated), reads of non-PK properties will still return
|
|
126
|
+
* `undefined` at runtime — same footgun as a plain non-`Ref` relation.
|
|
127
|
+
*/
|
|
128
|
+
export declare function unref<V>(value: ScalarReference<V>): V | undefined;
|
|
129
|
+
export declare function unref<T extends object>(value: Ref<T> | LazyRef<T> | T): T;
|
|
130
|
+
/**
|
|
131
|
+
* Unwraps a reference to its underlying value. Nullable variant — returns `null` unchanged.
|
|
132
|
+
*/
|
|
133
|
+
export declare function unref<T extends object>(value: Ref<T> | LazyRef<T> | T | null): T | null;
|
|
134
|
+
/**
|
|
135
|
+
* Unwraps a reference to its underlying value. Optional variant — returns `undefined` unchanged.
|
|
136
|
+
*/
|
|
137
|
+
export declare function unref<T extends object>(value: Ref<T> | LazyRef<T> | T | undefined): T | undefined;
|
|
138
|
+
/**
|
|
139
|
+
* Unwraps a reference to its underlying value. Nullable variant — returns `null`/`undefined` unchanged.
|
|
140
|
+
*/
|
|
141
|
+
export declare function unref<T extends object>(value: Ref<T> | LazyRef<T> | T | null | undefined): T | null | undefined;
|
|
101
142
|
/**
|
|
102
143
|
* shortcut for `Reference.createNakedFromPK(entityType, pk)`
|
|
103
144
|
*/
|
package/entity/Reference.js
CHANGED
|
@@ -303,6 +303,15 @@ export function ref(entityOrType, pk) {
|
|
|
303
303
|
}
|
|
304
304
|
return Reference.createFromPK(entityOrType, pk);
|
|
305
305
|
}
|
|
306
|
+
export function unref(value) {
|
|
307
|
+
if (value == null) {
|
|
308
|
+
return value;
|
|
309
|
+
}
|
|
310
|
+
if (ScalarReference.isScalarReference(value)) {
|
|
311
|
+
return value.unwrap();
|
|
312
|
+
}
|
|
313
|
+
return Reference.unwrapReference(value);
|
|
314
|
+
}
|
|
306
315
|
/**
|
|
307
316
|
* shortcut for `Reference.createNakedFromPK(entityType, pk)`
|
|
308
317
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PopulatePath } from '../enums.js';
|
|
2
2
|
import type { EntityManager } from '../EntityManager.js';
|
|
3
|
-
import type { Dictionary, EntityData, EntityDictionary, EntityMetadata, IHydrator, EntityKey, PopulateOptions, Primary, AutoPath, Ref, AddEager, LoadedReference, EntityDTO, Loaded, SerializeDTO, FromEntityType, IsSubset, MergeSelected } from '../typings.js';
|
|
3
|
+
import type { Dictionary, EntityData, EntityDictionary, EntityMetadata, IHydrator, EntityKey, PopulateOptions, Primary, AutoPath, Ref, AddEager, LoadedReference, EntityDTO, Loaded, ExtractFieldsHint, ResolveSerializeFields, SerializeDTO, SerializeFieldsKeepPK, FromEntityType, IsSubset, MergeSelected } from '../typings.js';
|
|
4
4
|
import { Reference } from './Reference.js';
|
|
5
5
|
import { type AssignOptions } from './EntityAssigner.js';
|
|
6
6
|
import type { EntityLoaderOptions } from './EntityLoader.js';
|
|
@@ -54,7 +54,7 @@ export declare class WrappedEntity<Entity extends object> {
|
|
|
54
54
|
/** Converts the entity to a plain object representation, optionally excluding specified fields. */
|
|
55
55
|
toObject<Ignored extends EntityKey<Entity> = never>(ignoreFields?: Ignored[]): Omit<EntityDTO<Entity>, Ignored>;
|
|
56
56
|
/** Serializes the entity with control over which relations and fields to include or exclude. */
|
|
57
|
-
serialize<Hint extends string = never, Exclude extends string = never>(options?: SerializeOptions<Entity
|
|
57
|
+
serialize<Hint extends string = never, Exclude extends string = never, Fields extends string = never>(options?: SerializeOptions<FromEntityType<Entity>, Hint, Exclude, Fields>): SerializeDTO<FromEntityType<Entity>, Hint, Exclude, never, ResolveSerializeFields<Fields, ExtractFieldsHint<Entity>>, SerializeFieldsKeepPK<Fields>>;
|
|
58
58
|
/** Converts the entity to a plain object, including all properties regardless of serialization rules. */
|
|
59
59
|
toPOJO(): EntityDTO<Entity>;
|
|
60
60
|
/** Serializes the entity using its `toJSON` method (supports `JSON.stringify`). */
|
package/entity/defineEntity.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EntityManager } from '../EntityManager.js';
|
|
2
2
|
import type { ColumnType, PropertyOptions, ReferenceOptions, EnumOptions, EmbeddedOptions, ManyToOneOptions, OneToManyOptions, OneToOneOptions, ManyToManyOptions, IndexColumnOptions } from '../metadata/types.js';
|
|
3
|
-
import type { AnyString, GeneratedColumnCallback, Constructor, CheckCallback, FilterQuery, EntityName, Dictionary, EntityMetadata, PrimaryKeyProp, EntityRepositoryType, Hidden, Opt, Primary, EntityClass, EntitySchemaWithMeta, InferEntity, MaybeReturnType, Ref, IndexCallback, FormulaCallback, EntityCtor, IsNever, IWrappedEntity, DefineConfig, Config, MaybePromise } from '../typings.js';
|
|
3
|
+
import type { AnyString, GeneratedColumnCallback, Constructor, CheckCallback, FilterQuery, EntityName, Dictionary, EntityMetadata, PrimaryKeyProp, EntityRepositoryType, Hidden, Opt, Primary, EntityClass, EntitySchemaWithMeta, InferEntity, MaybeReturnType, Ref, LazyRef, IndexCallback, TriggerCallback, FormulaCallback, EntityCtor, IsNever, IWrappedEntity, DefineConfig, Config, MaybePromise, IndexHints } from '../typings.js';
|
|
4
4
|
import type { Raw } from '../utils/RawQueryFragment.js';
|
|
5
5
|
import type { ScalarReference } from './Reference.js';
|
|
6
6
|
import type { SerializeOptions } from '../serialization/EntitySerializer.js';
|
|
@@ -12,7 +12,7 @@ import type { Collection } from './Collection.js';
|
|
|
12
12
|
import type { FilterOptions, FindOptions, FindOneOptions } from '../drivers/IDatabaseDriver.js';
|
|
13
13
|
/** Union of all option keys supported across all property definition types (scalar, enum, embedded, relations). */
|
|
14
14
|
export type UniversalPropertyKeys = keyof PropertyOptions<any> | keyof EnumOptions<any> | keyof EmbeddedOptions<any, any> | keyof ReferenceOptions<any, any> | keyof ManyToOneOptions<any, any> | keyof OneToManyOptions<any, any> | keyof OneToOneOptions<any, any> | keyof ManyToManyOptions<any, any>;
|
|
15
|
-
type BuilderExtraKeys = '~options' | '~type' | '$type' | 'strictNullable';
|
|
15
|
+
type BuilderExtraKeys = '~options' | '~type' | '$type' | 'strictNullable' | 'lazyRef';
|
|
16
16
|
type ExcludeKeys = 'entity' | 'items';
|
|
17
17
|
type BuilderKeys = Exclude<UniversalPropertyKeys, ExcludeKeys> | BuilderExtraKeys;
|
|
18
18
|
type IncludeKeysForProperty = Exclude<keyof PropertyOptions<any>, ExcludeKeys> | BuilderExtraKeys;
|
|
@@ -36,9 +36,23 @@ export interface PropertyChain<Value, Options> {
|
|
|
36
36
|
nullable: true;
|
|
37
37
|
strictNullable: true;
|
|
38
38
|
}>;
|
|
39
|
-
ref():
|
|
39
|
+
ref(): Options extends {
|
|
40
|
+
lazyRef: true;
|
|
41
|
+
} ? never : PropertyChain<Value, Omit<Options, 'ref'> & {
|
|
40
42
|
ref: true;
|
|
41
43
|
}>;
|
|
44
|
+
/**
|
|
45
|
+
* Mark a to-one relation (`m:1`/`1:1`) as a {@apilink LazyRef} — direct entity at runtime, type-restricted
|
|
46
|
+
* until `Loaded<>` narrows it. Type-level only, no `ref: true` wrapping. Not compatible with `.ref()` or
|
|
47
|
+
* `.mapToPk()` — those chains are rejected in both directions at compile time.
|
|
48
|
+
*/
|
|
49
|
+
lazyRef(): HasKind<Options, 'm:1' | '1:1'> extends true ? Options extends {
|
|
50
|
+
ref: true;
|
|
51
|
+
} | {
|
|
52
|
+
mapToPk: true;
|
|
53
|
+
} ? never : PropertyChain<Value, Omit<Options, 'lazyRef'> & {
|
|
54
|
+
lazyRef: true;
|
|
55
|
+
}> : never;
|
|
42
56
|
primary(): PropertyChain<Value, Omit<Options, 'primary'> & {
|
|
43
57
|
primary: true;
|
|
44
58
|
}>;
|
|
@@ -103,10 +117,19 @@ export interface PropertyChain<Value, Options> {
|
|
|
103
117
|
groups(...groups: string[]): PropertyChain<Value, Options>;
|
|
104
118
|
customOrder(...customOrder: string[] | number[] | boolean[]): PropertyChain<Value, Options>;
|
|
105
119
|
extra(extra: string): PropertyChain<Value, Options>;
|
|
106
|
-
ignoreSchemaChanges(...ignoreSchemaChanges: ('type' | 'extra' | 'default')[]): PropertyChain<Value, Options>;
|
|
107
|
-
index
|
|
108
|
-
|
|
120
|
+
ignoreSchemaChanges(...ignoreSchemaChanges: ('type' | 'extra' | 'default' | 'collation')[]): PropertyChain<Value, Options>;
|
|
121
|
+
/** Explicitly specify index on a property. When a string name is passed, it enables type-safe `using` in `FindOptions`. */
|
|
122
|
+
index<N extends string>(name: N): PropertyChain<Value, Omit<Options, 'index'> & {
|
|
123
|
+
index: N;
|
|
124
|
+
}>;
|
|
125
|
+
index(index?: boolean): PropertyChain<Value, Options>;
|
|
126
|
+
/** Set column as unique. When a string name is passed, it enables type-safe `using` in `FindOptions`. (SQL only) */
|
|
127
|
+
unique<N extends string>(name: N): PropertyChain<Value, Omit<Options, 'unique'> & {
|
|
128
|
+
unique: N;
|
|
129
|
+
}>;
|
|
130
|
+
unique(unique?: boolean): PropertyChain<Value, Options>;
|
|
109
131
|
comment(comment: string): PropertyChain<Value, Options>;
|
|
132
|
+
collation(collation: string): PropertyChain<Value, Options>;
|
|
110
133
|
accessor(accessor?: string | boolean): PropertyChain<Value, Options>;
|
|
111
134
|
eager(eager?: boolean): HasKind<Options, 'm:1' | '1:m' | '1:1' | 'm:n'> extends true ? PropertyChain<Value, Options> : never;
|
|
112
135
|
cascade(...cascade: Cascade[]): HasKind<Options, 'm:1' | '1:m' | '1:1' | 'm:n'> extends true ? PropertyChain<Value, Options> : never;
|
|
@@ -117,7 +140,9 @@ export interface PropertyChain<Value, Options> {
|
|
|
117
140
|
owner(): HasKind<Options, '1:1' | 'm:n'> extends true ? PropertyChain<Value, Omit<Options, 'owner'> & {
|
|
118
141
|
owner: true;
|
|
119
142
|
}> : never;
|
|
120
|
-
mapToPk(): HasKind<Options, 'm:1' | '1:1'> extends true ?
|
|
143
|
+
mapToPk(): HasKind<Options, 'm:1' | '1:1'> extends true ? Options extends {
|
|
144
|
+
lazyRef: true;
|
|
145
|
+
} ? never : PropertyChain<Value, Omit<Options, 'mapToPk'> & {
|
|
121
146
|
mapToPk: true;
|
|
122
147
|
}> : never;
|
|
123
148
|
orphanRemoval(orphanRemoval?: boolean): HasKind<Options, '1:m' | '1:1'> extends true ? PropertyChain<Value, Options> : never;
|
|
@@ -127,9 +152,13 @@ export interface PropertyChain<Value, Options> {
|
|
|
127
152
|
pivotEntity(pivotEntity: () => EntityName): HasKind<Options, 'm:n'> extends true ? PropertyChain<Value, Options> : never;
|
|
128
153
|
fixedOrder(fixedOrder?: boolean): HasKind<Options, 'm:n'> extends true ? PropertyChain<Value, Options> : never;
|
|
129
154
|
fixedOrderColumn(fixedOrderColumn: string): HasKind<Options, 'm:n'> extends true ? PropertyChain<Value, Options> : never;
|
|
130
|
-
array():
|
|
155
|
+
array(): Options extends {
|
|
156
|
+
kind: infer K extends string;
|
|
157
|
+
} ? K extends 'embedded' | 'enum' ? PropertyChain<Value, Omit<Options, 'array'> & {
|
|
131
158
|
array: true;
|
|
132
|
-
}> : never
|
|
159
|
+
}> : never : PropertyChain<Value, Omit<Options, 'array'> & {
|
|
160
|
+
array: true;
|
|
161
|
+
}>;
|
|
133
162
|
prefix(prefix: string | boolean): HasKind<Options, 'embedded'> extends true ? PropertyChain<Value, Options> : never;
|
|
134
163
|
prefixMode(prefixMode: EmbeddedPrefixMode): HasKind<Options, 'embedded'> extends true ? PropertyChain<Value, Options> : never;
|
|
135
164
|
object(object?: boolean): HasKind<Options, 'embedded'> extends true ? PropertyChain<Value, Options> : never;
|
|
@@ -313,9 +342,24 @@ export declare class UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys
|
|
|
313
342
|
/**
|
|
314
343
|
* Enable `ScalarReference` wrapper for lazy values. Use this in combination with `lazy: true` to have a type-safe accessor object in place of the value.
|
|
315
344
|
*/
|
|
316
|
-
ref():
|
|
345
|
+
ref(): Options extends {
|
|
346
|
+
lazyRef: true;
|
|
347
|
+
} ? never : UniversalPropertyOptionsBuilder<Value, Omit<Options, 'ref'> & {
|
|
317
348
|
ref: true;
|
|
318
349
|
}, IncludeKeys>;
|
|
350
|
+
/**
|
|
351
|
+
* Mark a to-one relation (`m:1`/`1:1`) as a {@apilink LazyRef} — the runtime value stays a plain entity
|
|
352
|
+
* (no `Reference` wrapper) but the TypeScript type restricts access to the primary key until `Loaded<>`
|
|
353
|
+
* narrows it. Type-level only; does not set `ref: true`. Not compatible with `.ref()` or `.mapToPk()` —
|
|
354
|
+
* those chains are rejected in both directions at compile time.
|
|
355
|
+
*/
|
|
356
|
+
lazyRef(): HasKind<Options, 'm:1' | '1:1'> extends true ? Options extends {
|
|
357
|
+
ref: true;
|
|
358
|
+
} | {
|
|
359
|
+
mapToPk: true;
|
|
360
|
+
} ? never : UniversalPropertyOptionsBuilder<Value, Omit<Options, 'lazyRef'> & {
|
|
361
|
+
lazyRef: true;
|
|
362
|
+
}, IncludeKeys> : never;
|
|
319
363
|
/**
|
|
320
364
|
* Set to true to omit the property when {@link https://mikro-orm.io/docs/serializing Serializing}.
|
|
321
365
|
*/
|
|
@@ -334,12 +378,20 @@ export declare class UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys
|
|
|
334
378
|
concurrencyCheck(concurrencyCheck?: boolean): Pick<UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys>, IncludeKeys>;
|
|
335
379
|
/**
|
|
336
380
|
* Explicitly specify index on a property.
|
|
381
|
+
* When a string name is passed, it is captured as a literal type for use with the `using` option in `FindOptions`.
|
|
337
382
|
*/
|
|
338
|
-
index
|
|
383
|
+
index<N extends string>(name: N): Pick<UniversalPropertyOptionsBuilder<Value, Omit<Options, 'index'> & {
|
|
384
|
+
index: N;
|
|
385
|
+
}, IncludeKeys>, IncludeKeys>;
|
|
386
|
+
index(index?: boolean): Pick<UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys>, IncludeKeys>;
|
|
339
387
|
/**
|
|
340
388
|
* Set column as unique for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. (SQL only)
|
|
389
|
+
* When a string name is passed, it is captured as a literal type for use with the `using` option in `FindOptions`.
|
|
341
390
|
*/
|
|
342
|
-
unique
|
|
391
|
+
unique<N extends string>(name: N): Pick<UniversalPropertyOptionsBuilder<Value, Omit<Options, 'unique'> & {
|
|
392
|
+
unique: N;
|
|
393
|
+
}, IncludeKeys>, IncludeKeys>;
|
|
394
|
+
unique(unique?: boolean): Pick<UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys>, IncludeKeys>;
|
|
343
395
|
/**
|
|
344
396
|
* Specify column with check constraints. (Postgres driver only)
|
|
345
397
|
*
|
|
@@ -427,6 +479,11 @@ export declare class UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys
|
|
|
427
479
|
* Specify comment of column for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. (SQL only)
|
|
428
480
|
*/
|
|
429
481
|
comment(comment: string): Pick<UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys>, IncludeKeys>;
|
|
482
|
+
/**
|
|
483
|
+
* Specify column-level collation for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. (SQL only)
|
|
484
|
+
* Emits a `COLLATE` clause on the column definition; the accepted collation names are dialect-specific.
|
|
485
|
+
*/
|
|
486
|
+
collation(collation: string): Pick<UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys>, IncludeKeys>;
|
|
430
487
|
/** mysql only */
|
|
431
488
|
extra(extra: string): Pick<UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys>, IncludeKeys>;
|
|
432
489
|
/**
|
|
@@ -434,7 +491,7 @@ export declare class UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys
|
|
|
434
491
|
*
|
|
435
492
|
* @see https://mikro-orm.io/docs/defining-entities#sql-generated-columns
|
|
436
493
|
*/
|
|
437
|
-
ignoreSchemaChanges(...ignoreSchemaChanges: ('type' | 'extra' | 'default')[]): Pick<UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys>, IncludeKeys>;
|
|
494
|
+
ignoreSchemaChanges(...ignoreSchemaChanges: ('type' | 'extra' | 'default' | 'collation')[]): Pick<UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys>, IncludeKeys>;
|
|
438
495
|
array(): Pick<UniversalPropertyOptionsBuilder<Value, Omit<Options, 'array'> & {
|
|
439
496
|
array: true;
|
|
440
497
|
}, IncludeKeys>, IncludeKeys>;
|
|
@@ -492,7 +549,9 @@ export declare class UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys
|
|
|
492
549
|
/** What to do when the reference to the target entity gets updated. */
|
|
493
550
|
updateRule(updateRule: 'cascade' | 'no action' | 'set null' | 'set default' | AnyString): Pick<UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys>, IncludeKeys>;
|
|
494
551
|
/** Map this relation to the primary key value instead of an entity. */
|
|
495
|
-
mapToPk():
|
|
552
|
+
mapToPk(): Options extends {
|
|
553
|
+
lazyRef: true;
|
|
554
|
+
} ? never : Pick<UniversalPropertyOptionsBuilder<Value, Omit<Options, 'mapToPk'> & {
|
|
496
555
|
mapToPk: true;
|
|
497
556
|
}, IncludeKeys>, IncludeKeys>;
|
|
498
557
|
/** Set the constraint type. Immediate constraints are checked for each statement, while deferred ones are only checked at the end of the transaction. Only for postgres unique constraints. */
|
|
@@ -536,7 +595,7 @@ export type PropertyBuilders = {
|
|
|
536
595
|
datetime: (length?: number) => UniversalPropertyOptionsBuilder<InferPropertyValueType<typeof types.datetime>, EmptyOptions, IncludeKeysForProperty>;
|
|
537
596
|
time: (length?: number) => UniversalPropertyOptionsBuilder<InferPropertyValueType<typeof types.time>, EmptyOptions, IncludeKeysForProperty>;
|
|
538
597
|
type: <T extends PropertyValueType>(type: T) => UniversalPropertyOptionsBuilder<InferPropertyValueType<T>, EmptyOptions, IncludeKeysForProperty>;
|
|
539
|
-
enum: <const T extends readonly (number | string)[] | (() => Dictionary)>(items?: T) => UniversalPropertyOptionsBuilder<T extends () => Dictionary ? ValueOf<ReturnType<T>> : T extends readonly (infer Value)[] ? Value : T, EmptyOptions, IncludeKeysForEnumOptions>;
|
|
598
|
+
enum: <const T extends readonly (number | string)[] | Dictionary | (() => Dictionary)>(items?: T) => UniversalPropertyOptionsBuilder<T extends () => Dictionary ? ValueOf<ReturnType<T>> : T extends readonly (infer Value)[] ? Value : T extends Dictionary ? ValueOf<T> : T, EmptyOptions, IncludeKeysForEnumOptions>;
|
|
540
599
|
embedded: <Target extends EntityTarget | EntityTarget[]>(target: Target) => PropertyChain<InferEntity<Target extends (infer T)[] ? T : Target>, EmptyOptions & {
|
|
541
600
|
kind: 'embedded';
|
|
542
601
|
}>;
|
|
@@ -556,7 +615,7 @@ export type PropertyBuilders = {
|
|
|
556
615
|
/** Own keys + base entity keys (when TBase is not `never`). Guards against `keyof never = string | number | symbol`. */
|
|
557
616
|
type AllKeys<TProperties, TBase> = keyof TProperties | (IsNever<TBase> extends true ? never : keyof TBase);
|
|
558
617
|
/** Metadata descriptor for `defineEntity()`, combining entity options with property definitions. */
|
|
559
|
-
export interface EntityMetadataWithProperties<TName extends string, TTableName extends string, TProperties extends Record<string, any>, TPK extends (keyof TProperties)[] | undefined = undefined, TBase = never, TRepository = never, TForceObject extends boolean = false, TDiscriminatorColumn extends string | undefined = undefined, TDiscriminatorValue extends string | number | undefined = undefined, TBaseDiscriminatorColumn extends string | undefined = undefined> extends Omit<Partial<EntityMetadata<InferEntityFromProperties<TProperties, TPK, TBase, TRepository>>>, 'properties' | 'extends' | 'primaryKeys' | 'hooks' | 'discriminatorColumn' | 'discriminatorValue' | 'versionProperty' | 'concurrencyCheckKeys' | 'serializedPrimaryKey' | 'indexes' | 'uniques' | 'repository' | 'filters' | 'orderBy'> {
|
|
618
|
+
export interface EntityMetadataWithProperties<TName extends string, TTableName extends string, TProperties extends Record<string, any>, TPK extends (keyof TProperties)[] | undefined = undefined, TBase = never, TRepository = never, TForceObject extends boolean = false, TDiscriminatorColumn extends string | undefined = undefined, TDiscriminatorValue extends string | number | undefined = undefined, TBaseDiscriminatorColumn extends string | undefined = undefined> extends Omit<Partial<EntityMetadata<InferEntityFromProperties<TProperties, TPK, TBase, TRepository>>>, 'properties' | 'extends' | 'primaryKeys' | 'hooks' | 'discriminatorColumn' | 'discriminatorValue' | 'versionProperty' | 'concurrencyCheckKeys' | 'serializedPrimaryKey' | 'indexes' | 'uniques' | 'triggers' | 'repository' | 'filters' | 'orderBy'> {
|
|
560
619
|
name: TName;
|
|
561
620
|
tableName?: TTableName;
|
|
562
621
|
extends?: {
|
|
@@ -595,6 +654,7 @@ export interface EntityMetadataWithProperties<TName extends string, TTableName e
|
|
|
595
654
|
type?: string;
|
|
596
655
|
options?: Dictionary;
|
|
597
656
|
expression?: string | IndexCallback<InferEntityFromProperties<TProperties, TPK, TBase>>;
|
|
657
|
+
where?: string | FilterQuery<InferEntityFromProperties<TProperties, TPK, TBase>>;
|
|
598
658
|
columns?: IndexColumnOptions[];
|
|
599
659
|
include?: NoInfer<AllKeys<TProperties, TBase>> | NoInfer<AllKeys<TProperties, TBase>>[];
|
|
600
660
|
fillFactor?: number;
|
|
@@ -607,12 +667,22 @@ export interface EntityMetadataWithProperties<TName extends string, TTableName e
|
|
|
607
667
|
name?: string;
|
|
608
668
|
options?: Dictionary;
|
|
609
669
|
expression?: string | IndexCallback<InferEntityFromProperties<TProperties, TPK, TBase>>;
|
|
670
|
+
where?: string | FilterQuery<InferEntityFromProperties<TProperties, TPK, TBase>>;
|
|
610
671
|
deferMode?: DeferMode | `${DeferMode}`;
|
|
611
672
|
columns?: IndexColumnOptions[];
|
|
612
673
|
include?: NoInfer<AllKeys<TProperties, TBase>> | NoInfer<AllKeys<TProperties, TBase>>[];
|
|
613
674
|
fillFactor?: number;
|
|
614
675
|
disabled?: boolean;
|
|
615
676
|
}[];
|
|
677
|
+
triggers?: {
|
|
678
|
+
name?: string;
|
|
679
|
+
timing: 'before' | 'after' | 'instead of';
|
|
680
|
+
events: ('insert' | 'update' | 'delete' | 'truncate')[];
|
|
681
|
+
forEach?: 'row' | 'statement';
|
|
682
|
+
body?: string | Raw | TriggerCallback<InferEntityFromProperties<TProperties, TPK, TBase>>;
|
|
683
|
+
when?: string;
|
|
684
|
+
expression?: string;
|
|
685
|
+
}[];
|
|
616
686
|
}
|
|
617
687
|
/** Defines an entity schema using property builders, with full type inference from the property definitions. */
|
|
618
688
|
export declare function defineEntity<const TName extends string, const TTableName extends string, const TProperties extends Record<string, any>, const TPK extends (keyof TProperties)[] | undefined = undefined, const TBase = never, const TRepository = never, const TForceObject extends boolean = false, const TDiscriminatorColumn extends string | undefined = undefined, const TDiscriminatorValue extends string | number | undefined = undefined, const TBaseDiscriminatorColumn extends string | undefined = undefined>(meta: EntityMetadataWithProperties<TName, TTableName, TProperties, TPK, TBase, TRepository, TForceObject, TDiscriminatorColumn, TDiscriminatorValue, TBaseDiscriminatorColumn>): EntitySchemaWithMeta<TName, TTableName, InferEntityFromProperties<TProperties, TPK, TBase, TRepository, TForceObject, TBaseDiscriminatorColumn, TDiscriminatorValue>, TBase, TProperties, EntityCtor<InferEntityFromProperties<TProperties, TPK, TBase, TRepository, TForceObject, TBaseDiscriminatorColumn, TDiscriminatorValue>>, TDiscriminatorColumn>;
|
|
@@ -669,7 +739,9 @@ export type InferEntityFromProperties<Properties extends Record<string, any>, PK
|
|
|
669
739
|
[Config]?: DefineConfig<{
|
|
670
740
|
forceObject: true;
|
|
671
741
|
}>;
|
|
672
|
-
} : {})
|
|
742
|
+
} : {}) & {
|
|
743
|
+
[IndexHints]?: [Properties];
|
|
744
|
+
};
|
|
673
745
|
type NarrowDiscriminator<Base, DiscColumn extends string | undefined, DiscValue> = DiscColumn extends string ? DiscColumn extends keyof Base ? DiscValue extends string | number ? Omit<Base, DiscColumn> & {
|
|
674
746
|
[K in DiscColumn]: DiscValue;
|
|
675
747
|
} : Base : Base : Base;
|
|
@@ -714,6 +786,9 @@ type MaybeNullable<Value, Options> = Options extends {
|
|
|
714
786
|
type MaybeRelationRef<Value, Options> = Options extends {
|
|
715
787
|
mapToPk: true;
|
|
716
788
|
} ? Value : Options extends {
|
|
789
|
+
lazyRef: true;
|
|
790
|
+
kind: '1:1' | 'm:1';
|
|
791
|
+
} ? Value extends object ? LazyRef<Value> : never : Options extends {
|
|
717
792
|
ref: true;
|
|
718
793
|
kind: '1:1';
|
|
719
794
|
} ? Value extends object ? Ref<Value> : never : Options extends {
|
package/entity/defineEntity.js
CHANGED
|
@@ -173,6 +173,16 @@ export class UniversalPropertyOptionsBuilder {
|
|
|
173
173
|
ref() {
|
|
174
174
|
return this.assignOptions({ ref: true });
|
|
175
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Mark a to-one relation (`m:1`/`1:1`) as a {@apilink LazyRef} — the runtime value stays a plain entity
|
|
178
|
+
* (no `Reference` wrapper) but the TypeScript type restricts access to the primary key until `Loaded<>`
|
|
179
|
+
* narrows it. Type-level only; does not set `ref: true`. Not compatible with `.ref()` or `.mapToPk()` —
|
|
180
|
+
* those chains are rejected in both directions at compile time.
|
|
181
|
+
*/
|
|
182
|
+
lazyRef() {
|
|
183
|
+
// purely type-level — no runtime metadata change
|
|
184
|
+
return this;
|
|
185
|
+
}
|
|
176
186
|
/**
|
|
177
187
|
* Set to true to omit the property when {@link https://mikro-orm.io/docs/serializing Serializing}.
|
|
178
188
|
*/
|
|
@@ -191,15 +201,9 @@ export class UniversalPropertyOptionsBuilder {
|
|
|
191
201
|
concurrencyCheck(concurrencyCheck = true) {
|
|
192
202
|
return this.assignOptions({ concurrencyCheck });
|
|
193
203
|
}
|
|
194
|
-
/**
|
|
195
|
-
* Explicitly specify index on a property.
|
|
196
|
-
*/
|
|
197
204
|
index(index = true) {
|
|
198
205
|
return this.assignOptions({ index });
|
|
199
206
|
}
|
|
200
|
-
/**
|
|
201
|
-
* Set column as unique for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. (SQL only)
|
|
202
|
-
*/
|
|
203
207
|
unique(unique = true) {
|
|
204
208
|
return this.assignOptions({ unique });
|
|
205
209
|
}
|
|
@@ -312,6 +316,13 @@ export class UniversalPropertyOptionsBuilder {
|
|
|
312
316
|
comment(comment) {
|
|
313
317
|
return this.assignOptions({ comment });
|
|
314
318
|
}
|
|
319
|
+
/**
|
|
320
|
+
* Specify column-level collation for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. (SQL only)
|
|
321
|
+
* Emits a `COLLATE` clause on the column definition; the accepted collation names are dialect-specific.
|
|
322
|
+
*/
|
|
323
|
+
collation(collation) {
|
|
324
|
+
return this.assignOptions({ collation });
|
|
325
|
+
}
|
|
315
326
|
/** mysql only */
|
|
316
327
|
extra(extra) {
|
|
317
328
|
return this.assignOptions({ extra });
|