@mikro-orm/core 7.1.0-dev.5 → 7.1.0-dev.6
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 +18 -8
- package/EntityManager.js +77 -17
- package/drivers/IDatabaseDriver.d.ts +15 -1
- package/entity/EntityRepository.d.ts +16 -8
- package/entity/defineEntity.d.ts +24 -6
- package/entity/defineEntity.js +0 -6
- package/index.d.ts +2 -2
- package/index.js +1 -1
- package/package.json +1 -1
- package/platforms/Platform.d.ts +5 -0
- package/platforms/Platform.js +7 -0
- package/typings.d.ts +51 -1
- package/typings.js +10 -0
- package/utils/Utils.js +1 -1
package/EntityManager.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { EntityLoader, type EntityLoaderOptions } from './entity/EntityLoader.js
|
|
|
7
7
|
import { Reference } from './entity/Reference.js';
|
|
8
8
|
import { UnitOfWork } from './unit-of-work/UnitOfWork.js';
|
|
9
9
|
import type { CountOptions, DeleteOptions, FilterOptions, FindAllOptions, FindByCursorOptions, FindOneOptions, FindOneOrFailOptions, FindOptions, GetReferenceOptions, IDatabaseDriver, LockOptions, NativeInsertUpdateOptions, StreamOptions, UpdateOptions, UpsertManyOptions, UpsertOptions } from './drivers/IDatabaseDriver.js';
|
|
10
|
-
import type { AnyString, ArrayElement, AutoPath, ConnectionType, Dictionary, EntityClass, EntityData, EntityDictionary, EntityDTO, EntityMetadata, EntityName, FilterDef, FilterQuery, FromEntityType, GetRepository, IHydrator, IsSubset, Loaded, MergeLoaded, MergeSelected, ObjectQuery, PopulateOptions, Primary, Ref, RequiredEntityData, UnboxArray } from './typings.js';
|
|
10
|
+
import type { AnyString, ArrayElement, AutoPath, ConnectionType, Dictionary, EntityClass, EntityData, EntityDictionary, EntityDTO, EntityMetadata, EntityName, FilterDef, FilterQuery, FromEntityType, GetRepository, IHydrator, IsSubset, Loaded, MergeLoaded, MergeSelected, ObjectQuery, PopulateOptions, Primary, Ref, RequiredEntityData, UnboxArray, IndexFilterQuery, WithUsingOptions } from './typings.js';
|
|
11
11
|
import { FlushMode, LockMode, PopulatePath, type TransactionOptions } from './enums.js';
|
|
12
12
|
import type { MetadataStorage } from './metadata/MetadataStorage.js';
|
|
13
13
|
import type { Transaction } from './connections/Connection.js';
|
|
@@ -61,7 +61,9 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
|
|
|
61
61
|
/**
|
|
62
62
|
* Finds all entities matching your `where` query. You can pass additional options via the `options` parameter.
|
|
63
63
|
*/
|
|
64
|
-
find<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<NoInfer<Entity
|
|
64
|
+
find<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(entityName: EntityName<Entity>, where: [Using] extends [never] ? FilterQuery<NoInfer<Entity>> : IndexFilterQuery<NoInfer<Entity>, Using>, options?: FindOptions<Entity, Hint, Fields, Excludes> & {
|
|
65
|
+
using?: Using | Using[];
|
|
66
|
+
}): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
|
|
65
67
|
/**
|
|
66
68
|
* Finds all entities and returns an async iterable (async generator) that yields results one by one.
|
|
67
69
|
* The results are merged and mapped to entity instances, without adding them to the identity map.
|
|
@@ -79,11 +81,11 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
|
|
|
79
81
|
* }
|
|
80
82
|
* ```
|
|
81
83
|
*/
|
|
82
|
-
stream<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, options?: StreamOptions<NoInfer<Entity>, Hint, Fields, Excludes>): AsyncIterableIterator<Loaded<Entity, Hint, Fields, Excludes>>;
|
|
84
|
+
stream<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(entityName: EntityName<Entity>, options?: WithUsingOptions<StreamOptions<NoInfer<Entity>, Hint, Fields, Excludes>, NoInfer<Entity>, Using>): AsyncIterableIterator<Loaded<Entity, Hint, Fields, Excludes>>;
|
|
83
85
|
/**
|
|
84
86
|
* Finds all entities of given type, optionally matching the `where` condition provided in the `options` parameter.
|
|
85
87
|
*/
|
|
86
|
-
findAll<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, options?: FindAllOptions<NoInfer<Entity>, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
|
|
88
|
+
findAll<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(entityName: EntityName<Entity>, options?: WithUsingOptions<FindAllOptions<NoInfer<Entity>, Hint, Fields, Excludes>, NoInfer<Entity>, Using>): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
|
|
87
89
|
private getPopulateWhere;
|
|
88
90
|
/**
|
|
89
91
|
* Registers global filter to this entity manager. Global filters are enabled by default (unless disabled via last parameter).
|
|
@@ -130,7 +132,9 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
|
|
|
130
132
|
* Calls `em.find()` and `em.count()` with the same arguments (where applicable) and returns the results as tuple
|
|
131
133
|
* where the first element is the array of entities, and the second is the count.
|
|
132
134
|
*/
|
|
133
|
-
findAndCount<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<NoInfer<Entity
|
|
135
|
+
findAndCount<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(entityName: EntityName<Entity>, where: [Using] extends [never] ? FilterQuery<NoInfer<Entity>> : IndexFilterQuery<NoInfer<Entity>, Using>, options?: FindOptions<Entity, Hint, Fields, Excludes> & {
|
|
136
|
+
using?: Using | Using[];
|
|
137
|
+
}): Promise<[Loaded<Entity, Hint, Fields, Excludes>[], number]>;
|
|
134
138
|
/**
|
|
135
139
|
* Calls `em.find()` and `em.count()` with the same arguments (where applicable) and returns the results as {@apilink Cursor} object.
|
|
136
140
|
* Supports `before`, `after`, `first` and `last` options while disallowing `limit` and `offset`. Explicit `orderBy` option
|
|
@@ -187,7 +191,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
|
|
|
187
191
|
* }
|
|
188
192
|
* ```
|
|
189
193
|
*/
|
|
190
|
-
findByCursor<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, IncludeCount extends boolean = true>(entityName: EntityName<Entity>, options: FindByCursorOptions<Entity, Hint, Fields, Excludes, IncludeCount>): Promise<Cursor<Entity, Hint, Fields, Excludes, IncludeCount>>;
|
|
194
|
+
findByCursor<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, IncludeCount extends boolean = true, Using extends string = never>(entityName: EntityName<Entity>, options: WithUsingOptions<FindByCursorOptions<Entity, Hint, Fields, Excludes, IncludeCount>, Entity, Using>): Promise<Cursor<Entity, Hint, Fields, Excludes, IncludeCount>>;
|
|
191
195
|
/**
|
|
192
196
|
* Refreshes the persistent state of an entity from the database, overriding any local changes that have not yet been
|
|
193
197
|
* persisted. Returns the same entity instance (same object reference), but re-hydrated. If the entity is no longer
|
|
@@ -203,14 +207,18 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
|
|
|
203
207
|
/**
|
|
204
208
|
* Finds first entity matching your `where` query.
|
|
205
209
|
*/
|
|
206
|
-
findOne<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<NoInfer<Entity
|
|
210
|
+
findOne<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(entityName: EntityName<Entity>, where: [Using] extends [never] ? FilterQuery<NoInfer<Entity>> : IndexFilterQuery<NoInfer<Entity>, Using>, options?: FindOneOptions<Entity, Hint, Fields, Excludes> & {
|
|
211
|
+
using?: Using | Using[];
|
|
212
|
+
}): Promise<Loaded<Entity, Hint, Fields, Excludes> | null>;
|
|
207
213
|
/**
|
|
208
214
|
* Finds first entity matching your `where` query. If nothing found, it will throw an error.
|
|
209
215
|
* If the `strict` option is specified and nothing is found or more than one matching entity is found, it will throw an error.
|
|
210
216
|
* You can override the factory for creating this method via `options.failHandler` locally
|
|
211
217
|
* or via `Configuration.findOneOrFailHandler` (`findExactlyOneOrFailHandler` when specifying `strict`) globally.
|
|
212
218
|
*/
|
|
213
|
-
findOneOrFail<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<NoInfer<Entity
|
|
219
|
+
findOneOrFail<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, Using extends string = never>(entityName: EntityName<Entity>, where: [Using] extends [never] ? FilterQuery<NoInfer<Entity>> : IndexFilterQuery<NoInfer<Entity>, Using>, options?: FindOneOrFailOptions<Entity, Hint, Fields, Excludes> & {
|
|
220
|
+
using?: Using | Using[];
|
|
221
|
+
}): Promise<Loaded<Entity, Hint, Fields, Excludes>>;
|
|
214
222
|
/**
|
|
215
223
|
* Creates or updates the entity, based on whether it is already present in the database.
|
|
216
224
|
* This method performs an `insert on conflict merge` query ensuring the database is in sync, returning a managed
|
|
@@ -524,6 +532,8 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
|
|
|
524
532
|
*/
|
|
525
533
|
getComparator(): EntityComparator;
|
|
526
534
|
private checkLockRequirements;
|
|
535
|
+
private validateIndexUsage;
|
|
536
|
+
private validateWhereKeysForIndex;
|
|
527
537
|
private lockAndPopulate;
|
|
528
538
|
private buildFields;
|
|
529
539
|
/** @internal */
|
package/EntityManager.js
CHANGED
|
@@ -103,9 +103,6 @@ export class EntityManager {
|
|
|
103
103
|
repo(entityName) {
|
|
104
104
|
return this.getRepository(entityName);
|
|
105
105
|
}
|
|
106
|
-
/**
|
|
107
|
-
* Finds all entities matching your `where` query. You can pass additional options via the `options` parameter.
|
|
108
|
-
*/
|
|
109
106
|
async find(entityName, where, options = {}) {
|
|
110
107
|
if (options.disableIdentityMap ?? this.config.get('disableIdentityMap')) {
|
|
111
108
|
const em = this.getContext(false);
|
|
@@ -116,10 +113,11 @@ export class EntityManager {
|
|
|
116
113
|
}
|
|
117
114
|
const em = this.getContext();
|
|
118
115
|
em.prepareOptions(options);
|
|
116
|
+
const meta = this.metadata.get(entityName);
|
|
117
|
+
em.validateIndexUsage(meta, where, options);
|
|
119
118
|
await em.tryFlush(entityName, options);
|
|
120
119
|
where = await em.processWhere(entityName, where, options, 'read');
|
|
121
120
|
validateParams(where);
|
|
122
|
-
const meta = this.metadata.get(entityName);
|
|
123
121
|
if (meta.orderBy) {
|
|
124
122
|
options.orderBy = QueryHelper.mergeOrderBy(options.orderBy, meta.orderBy);
|
|
125
123
|
}
|
|
@@ -203,6 +201,7 @@ export class EntityManager {
|
|
|
203
201
|
options.orderBy = options.orderBy || {};
|
|
204
202
|
options.populate = (await em.preparePopulate(entityName, options));
|
|
205
203
|
const meta = this.metadata.get(entityName);
|
|
204
|
+
em.validateIndexUsage(meta, options.where ?? {}, options);
|
|
206
205
|
options = { ...options };
|
|
207
206
|
// save the original hint value so we know it was infer/all
|
|
208
207
|
options._populateWhere = options.populateWhere ?? this.config.get('populateWhere');
|
|
@@ -494,10 +493,6 @@ export class EntityManager {
|
|
|
494
493
|
const conds = [...ret, where].filter(c => Utils.hasObjectKeys(c) || Raw.hasObjectFragments(c));
|
|
495
494
|
return conds.length > 1 ? { $and: conds } : conds[0];
|
|
496
495
|
}
|
|
497
|
-
/**
|
|
498
|
-
* Calls `em.find()` and `em.count()` with the same arguments (where applicable) and returns the results as tuple
|
|
499
|
-
* where the first element is the array of entities, and the second is the count.
|
|
500
|
-
*/
|
|
501
496
|
async findAndCount(entityName, where, options = {}) {
|
|
502
497
|
const em = this.getContext(false);
|
|
503
498
|
await em.tryFlush(entityName, options);
|
|
@@ -631,9 +626,6 @@ export class EntityManager {
|
|
|
631
626
|
}
|
|
632
627
|
return entity;
|
|
633
628
|
}
|
|
634
|
-
/**
|
|
635
|
-
* Finds first entity matching your `where` query.
|
|
636
|
-
*/
|
|
637
629
|
async findOne(entityName, where, options = {}) {
|
|
638
630
|
if (options.disableIdentityMap ?? this.config.get('disableIdentityMap')) {
|
|
639
631
|
const em = this.getContext(false);
|
|
@@ -653,6 +645,7 @@ export class EntityManager {
|
|
|
653
645
|
}
|
|
654
646
|
await em.tryFlush(entityName, options);
|
|
655
647
|
const meta = em.metadata.get(entityName);
|
|
648
|
+
em.validateIndexUsage(meta, where, options);
|
|
656
649
|
where = await em.processWhere(entityName, where, options, 'read');
|
|
657
650
|
validateEmptyWhere(where);
|
|
658
651
|
em.checkLockRequirements(options.lockMode, meta);
|
|
@@ -701,12 +694,6 @@ export class EntityManager {
|
|
|
701
694
|
await em.storeCache(options.cache, cached, () => helper(entity).toPOJO());
|
|
702
695
|
return entity;
|
|
703
696
|
}
|
|
704
|
-
/**
|
|
705
|
-
* Finds first entity matching your `where` query. If nothing found, it will throw an error.
|
|
706
|
-
* If the `strict` option is specified and nothing is found or more than one matching entity is found, it will throw an error.
|
|
707
|
-
* You can override the factory for creating this method via `options.failHandler` locally
|
|
708
|
-
* or via `Configuration.findOneOrFailHandler` (`findExactlyOneOrFailHandler` when specifying `strict`) globally.
|
|
709
|
-
*/
|
|
710
697
|
async findOneOrFail(entityName, where, options = {}) {
|
|
711
698
|
let entity;
|
|
712
699
|
let isStrictViolation = false;
|
|
@@ -1727,6 +1714,79 @@ export class EntityManager {
|
|
|
1727
1714
|
throw ValidationError.transactionRequired();
|
|
1728
1715
|
}
|
|
1729
1716
|
}
|
|
1717
|
+
validateIndexUsage(meta, where, options) {
|
|
1718
|
+
if (!options.using) {
|
|
1719
|
+
return;
|
|
1720
|
+
}
|
|
1721
|
+
const indexNames = Utils.asArray(options.using);
|
|
1722
|
+
const allIndexes = [...meta.indexes, ...meta.uniques];
|
|
1723
|
+
const indexMap = new Map();
|
|
1724
|
+
for (const idx of allIndexes) {
|
|
1725
|
+
if (idx.name) {
|
|
1726
|
+
indexMap.set(idx.name, Utils.asArray(idx.properties ?? []));
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
for (const prop of meta.props) {
|
|
1730
|
+
if (typeof prop.index === 'string') {
|
|
1731
|
+
indexMap.set(prop.index, [prop.name]);
|
|
1732
|
+
}
|
|
1733
|
+
if (typeof prop.unique === 'string') {
|
|
1734
|
+
indexMap.set(prop.unique, [prop.name]);
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
const allowedProps = new Set();
|
|
1738
|
+
for (const name of indexNames) {
|
|
1739
|
+
const props = indexMap.get(name);
|
|
1740
|
+
if (!props) {
|
|
1741
|
+
const available = [...indexMap.keys()];
|
|
1742
|
+
throw new Error(`Index '${name}' not found on entity '${meta.className}'. ` +
|
|
1743
|
+
(available.length > 0 ? `Available indexes: ${available.join(', ')}` : 'No named indexes defined.'));
|
|
1744
|
+
}
|
|
1745
|
+
for (const prop of props) {
|
|
1746
|
+
allowedProps.add(prop);
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
this.validateWhereKeysForIndex(where, allowedProps, indexNames);
|
|
1750
|
+
if (options.orderBy) {
|
|
1751
|
+
const orderMaps = Array.isArray(options.orderBy) ? options.orderBy : [options.orderBy];
|
|
1752
|
+
for (const orderMap of orderMaps) {
|
|
1753
|
+
for (const key of Object.keys(orderMap)) {
|
|
1754
|
+
if (!allowedProps.has(key)) {
|
|
1755
|
+
throw new Error(`Property '${key}' in orderBy is not covered by index '${indexNames.join("', '")}'. ` +
|
|
1756
|
+
`Allowed properties: ${[...allowedProps].join(', ')}`);
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
validateWhereKeysForIndex(where, allowedProps, indexNames) {
|
|
1763
|
+
if (typeof where !== 'object' || where === null) {
|
|
1764
|
+
return;
|
|
1765
|
+
}
|
|
1766
|
+
if (Array.isArray(where)) {
|
|
1767
|
+
for (const item of where) {
|
|
1768
|
+
this.validateWhereKeysForIndex(item, allowedProps, indexNames);
|
|
1769
|
+
}
|
|
1770
|
+
return;
|
|
1771
|
+
}
|
|
1772
|
+
for (const key of Object.keys(where)) {
|
|
1773
|
+
if (key === '$and' || key === '$or') {
|
|
1774
|
+
for (const item of Utils.asArray(where[key])) {
|
|
1775
|
+
this.validateWhereKeysForIndex(item, allowedProps, indexNames);
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
else if (key === '$not') {
|
|
1779
|
+
this.validateWhereKeysForIndex(where[key], allowedProps, indexNames);
|
|
1780
|
+
}
|
|
1781
|
+
else if (key.startsWith('$')) {
|
|
1782
|
+
continue;
|
|
1783
|
+
}
|
|
1784
|
+
else if (!allowedProps.has(key)) {
|
|
1785
|
+
throw new Error(`Property '${key}' in where clause is not covered by index '${indexNames.join("', '")}'. ` +
|
|
1786
|
+
`Allowed properties: ${[...allowedProps].join(', ')}`);
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1730
1790
|
async lockAndPopulate(meta, entity, where, options) {
|
|
1731
1791
|
if (!meta.virtual && options.lockMode === LockMode.OPTIMISTIC) {
|
|
1732
1792
|
await this.lock(entity, options.lockMode, {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ConnectionType, Constructor, EntityData, EntityMetadata, EntityProperty, FilterQuery, Primary, Dictionary, IPrimaryKey, PopulateOptions, EntityDictionary, AutoPath, ObjectQuery, FilterObject, Populate, EntityName, PopulateHintOptions, Prefixes } from '../typings.js';
|
|
1
|
+
import type { ConnectionType, Constructor, EntityData, EntityMetadata, EntityProperty, FilterQuery, Primary, Dictionary, IPrimaryKey, PopulateOptions, EntityDictionary, AutoPath, ObjectQuery, FilterObject, Populate, EntityName, PopulateHintOptions, Prefixes, IndexName } from '../typings.js';
|
|
2
2
|
import type { Connection, QueryResult, Transaction } from '../connections/Connection.js';
|
|
3
3
|
import type { FlushMode, LockMode, QueryOrderMap, QueryFlag, LoadStrategy, PopulateHint, PopulatePath } from '../enums.js';
|
|
4
4
|
import type { Platform } from '../platforms/Platform.js';
|
|
@@ -216,6 +216,20 @@ export interface FindOptions<Entity, Hint extends string = never, Fields extends
|
|
|
216
216
|
connectionType?: ConnectionType;
|
|
217
217
|
/** SQL: appended to FROM clause (e.g. `'force index(my_index)'`); MongoDB: index name or spec passed as `hint`. */
|
|
218
218
|
indexHint?: string | Dictionary;
|
|
219
|
+
/**
|
|
220
|
+
* Named index(es) for this query. When provided:
|
|
221
|
+
* - Validates that `where` and `orderBy` only reference columns covered by the specified index(es).
|
|
222
|
+
* - Emits SQL index hints where supported (MySQL/MariaDB: `USE INDEX`, MSSQL: `WITH (INDEX(...))`).
|
|
223
|
+
* - If `indexHint` is also set, `indexHint` takes precedence for SQL generation.
|
|
224
|
+
*
|
|
225
|
+
* Accepts a single index name or an array. For `defineEntity` entities with named indexes
|
|
226
|
+
* and decorator entities with `[IndexHints]`, index names are autocompleted.
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* await em.find(Book, { title: 'foo' }, { using: 'idx_book_title' });
|
|
230
|
+
* await em.find(Book, { title: 'foo', author: 1 }, { using: ['idx_book_title', 'idx_book_author'] });
|
|
231
|
+
*/
|
|
232
|
+
using?: IndexName<Entity> | IndexName<Entity>[];
|
|
219
233
|
/** sql only */
|
|
220
234
|
comments?: string | string[];
|
|
221
235
|
/** sql only */
|
|
@@ -1,7 +1,7 @@
|
|
|
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, EntityName, Primary, Loaded, FilterQuery, EntityDictionary, AutoPath, RequiredEntityData, Ref, EntityType, EntityDTO, MergeSelected, FromEntityType, IsSubset, MergeLoaded, ArrayElement } from '../typings.js';
|
|
4
|
+
import type { EntityData, EntityName, Primary, Loaded, FilterQuery, EntityDictionary, AutoPath, RequiredEntityData, Ref, EntityType, EntityDTO, MergeSelected, FromEntityType, IsSubset, MergeLoaded, ArrayElement, IndexFilterQuery, WithUsingOptions } from '../typings.js';
|
|
5
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';
|
|
@@ -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
|
*/
|
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, IndexCallback, 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';
|
|
@@ -104,8 +104,16 @@ export interface PropertyChain<Value, Options> {
|
|
|
104
104
|
customOrder(...customOrder: string[] | number[] | boolean[]): PropertyChain<Value, Options>;
|
|
105
105
|
extra(extra: string): PropertyChain<Value, Options>;
|
|
106
106
|
ignoreSchemaChanges(...ignoreSchemaChanges: ('type' | 'extra' | 'default')[]): PropertyChain<Value, Options>;
|
|
107
|
-
index
|
|
108
|
-
|
|
107
|
+
/** Explicitly specify index on a property. When a string name is passed, it enables type-safe `using` in `FindOptions`. */
|
|
108
|
+
index<N extends string>(name: N): PropertyChain<Value, Omit<Options, 'index'> & {
|
|
109
|
+
index: N;
|
|
110
|
+
}>;
|
|
111
|
+
index(index?: boolean): PropertyChain<Value, Options>;
|
|
112
|
+
/** Set column as unique. When a string name is passed, it enables type-safe `using` in `FindOptions`. (SQL only) */
|
|
113
|
+
unique<N extends string>(name: N): PropertyChain<Value, Omit<Options, 'unique'> & {
|
|
114
|
+
unique: N;
|
|
115
|
+
}>;
|
|
116
|
+
unique(unique?: boolean): PropertyChain<Value, Options>;
|
|
109
117
|
comment(comment: string): PropertyChain<Value, Options>;
|
|
110
118
|
accessor(accessor?: string | boolean): PropertyChain<Value, Options>;
|
|
111
119
|
eager(eager?: boolean): HasKind<Options, 'm:1' | '1:m' | '1:1' | 'm:n'> extends true ? PropertyChain<Value, Options> : never;
|
|
@@ -338,12 +346,20 @@ export declare class UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys
|
|
|
338
346
|
concurrencyCheck(concurrencyCheck?: boolean): Pick<UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys>, IncludeKeys>;
|
|
339
347
|
/**
|
|
340
348
|
* Explicitly specify index on a property.
|
|
349
|
+
* When a string name is passed, it is captured as a literal type for use with the `using` option in `FindOptions`.
|
|
341
350
|
*/
|
|
342
|
-
index
|
|
351
|
+
index<N extends string>(name: N): Pick<UniversalPropertyOptionsBuilder<Value, Omit<Options, 'index'> & {
|
|
352
|
+
index: N;
|
|
353
|
+
}, IncludeKeys>, IncludeKeys>;
|
|
354
|
+
index(index?: boolean): Pick<UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys>, IncludeKeys>;
|
|
343
355
|
/**
|
|
344
356
|
* Set column as unique for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. (SQL only)
|
|
357
|
+
* When a string name is passed, it is captured as a literal type for use with the `using` option in `FindOptions`.
|
|
345
358
|
*/
|
|
346
|
-
unique
|
|
359
|
+
unique<N extends string>(name: N): Pick<UniversalPropertyOptionsBuilder<Value, Omit<Options, 'unique'> & {
|
|
360
|
+
unique: N;
|
|
361
|
+
}, IncludeKeys>, IncludeKeys>;
|
|
362
|
+
unique(unique?: boolean): Pick<UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys>, IncludeKeys>;
|
|
347
363
|
/**
|
|
348
364
|
* Specify column with check constraints. (Postgres driver only)
|
|
349
365
|
*
|
|
@@ -669,7 +685,9 @@ export type InferEntityFromProperties<Properties extends Record<string, any>, PK
|
|
|
669
685
|
[Config]?: DefineConfig<{
|
|
670
686
|
forceObject: true;
|
|
671
687
|
}>;
|
|
672
|
-
} : {})
|
|
688
|
+
} : {}) & {
|
|
689
|
+
[IndexHints]?: [Properties];
|
|
690
|
+
};
|
|
673
691
|
type InferCombinedPrimaryKey<Properties extends Record<string, any>, PK, Base> = PK extends undefined ? CombinePrimaryKeys<InferPrimaryKey<Properties>, ExtractBasePrimaryKey<Base>> : PK;
|
|
674
692
|
type ExtractBasePrimaryKey<Base> = Base extends {
|
|
675
693
|
[PrimaryKeyProp]?: infer BasePK;
|
package/entity/defineEntity.js
CHANGED
|
@@ -191,15 +191,9 @@ export class UniversalPropertyOptionsBuilder {
|
|
|
191
191
|
concurrencyCheck(concurrencyCheck = true) {
|
|
192
192
|
return this.assignOptions({ concurrencyCheck });
|
|
193
193
|
}
|
|
194
|
-
/**
|
|
195
|
-
* Explicitly specify index on a property.
|
|
196
|
-
*/
|
|
197
194
|
index(index = true) {
|
|
198
195
|
return this.assignOptions({ index });
|
|
199
196
|
}
|
|
200
|
-
/**
|
|
201
|
-
* Set column as unique for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. (SQL only)
|
|
202
|
-
*/
|
|
203
197
|
unique(unique = true) {
|
|
204
198
|
return this.assignOptions({ unique });
|
|
205
199
|
}
|
package/index.d.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* @packageDocumentation
|
|
3
3
|
* @module core
|
|
4
4
|
*/
|
|
5
|
-
export { EntityMetadata, PrimaryKeyProp, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Config, EntityName, } from './typings.js';
|
|
6
|
-
export type { CompiledFunctions, Constructor, ConnectionType, Dictionary, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, InferEntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, EntityDTOFlat, EntityDTOProp, SerializeDTO, MigrationDiff, GenerateOptions, FilterObject, IMigrationRunner, IEntityGenerator, ISeedManager, SeederObject, IMigratorStorage, RequiredEntityData, CheckCallback, IndexCallback, FormulaCallback, FormulaTable, SchemaTable, SchemaColumns, SimpleColumnMeta, Rel, Ref, ScalarRef, EntityRef, ISchemaGenerator, MigrationInfo, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, EntityDataValue, FilterKey, EntityType, FromEntityType, Selected, IsSubset, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, FilterValue, MergeLoaded, MergeSelected, TypeConfig, AnyString, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, RequiredNullable, DefineConfig, Opt, Hidden, EntitySchemaWithMeta, InferEntity, CheckConstraint, GeneratedColumnCallback, FilterDef, EntityCtor, Subquery, PopulateHintOptions, Prefixes, } from './typings.js';
|
|
5
|
+
export { EntityMetadata, PrimaryKeyProp, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Config, EntityName, IndexHints, } from './typings.js';
|
|
6
|
+
export type { CompiledFunctions, Constructor, ConnectionType, Dictionary, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, InferEntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, EntityDTOFlat, EntityDTOProp, SerializeDTO, MigrationDiff, GenerateOptions, FilterObject, IndexFilterQuery, ExtractIndexHints, IndexName, IndexColumns, WithUsingOptions, IMigrationRunner, IEntityGenerator, ISeedManager, SeederObject, IMigratorStorage, RequiredEntityData, CheckCallback, IndexCallback, FormulaCallback, FormulaTable, SchemaTable, SchemaColumns, SimpleColumnMeta, Rel, Ref, ScalarRef, EntityRef, ISchemaGenerator, MigrationInfo, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, EntityDataValue, FilterKey, EntityType, FromEntityType, Selected, IsSubset, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, FilterValue, MergeLoaded, MergeSelected, TypeConfig, AnyString, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, RequiredNullable, DefineConfig, Opt, Hidden, EntitySchemaWithMeta, InferEntity, CheckConstraint, GeneratedColumnCallback, FilterDef, EntityCtor, Subquery, PopulateHintOptions, Prefixes, } from './typings.js';
|
|
7
7
|
export * from './enums.js';
|
|
8
8
|
export * from './errors.js';
|
|
9
9
|
export * from './exceptions.js';
|
package/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @packageDocumentation
|
|
3
3
|
* @module core
|
|
4
4
|
*/
|
|
5
|
-
export { EntityMetadata, PrimaryKeyProp, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Config, EntityName, } from './typings.js';
|
|
5
|
+
export { EntityMetadata, PrimaryKeyProp, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Config, EntityName, IndexHints, } from './typings.js';
|
|
6
6
|
export * from './enums.js';
|
|
7
7
|
export * from './errors.js';
|
|
8
8
|
export * from './exceptions.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/core",
|
|
3
|
-
"version": "7.1.0-dev.
|
|
3
|
+
"version": "7.1.0-dev.6",
|
|
4
4
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"data-mapper",
|
package/platforms/Platform.d.ts
CHANGED
|
@@ -211,6 +211,11 @@ export declare abstract class Platform {
|
|
|
211
211
|
getFullTextWhereClause(prop: EntityProperty): string;
|
|
212
212
|
supportsCreatingFullTextIndex(): boolean;
|
|
213
213
|
getFullTextIndexExpression(indexName: string, schemaName: string | undefined, tableName: string, columns: SimpleColumnMeta[]): string;
|
|
214
|
+
/**
|
|
215
|
+
* Generates the SQL index hint clause for the given index names.
|
|
216
|
+
* Returns `undefined` when the platform does not support index hints (e.g. PostgreSQL, SQLite).
|
|
217
|
+
*/
|
|
218
|
+
formatIndexHint(indexNames: string[]): string | undefined;
|
|
214
219
|
/** Whether the driver automatically parses JSON columns into JS objects. */
|
|
215
220
|
convertsJsonAutomatically(): boolean;
|
|
216
221
|
/** Converts a JS value to its JSON database representation (typically JSON.stringify). */
|
package/platforms/Platform.js
CHANGED
|
@@ -415,6 +415,13 @@ export class Platform {
|
|
|
415
415
|
getFullTextIndexExpression(indexName, schemaName, tableName, columns) {
|
|
416
416
|
throw new Error('Full text searching is not supported by this driver.');
|
|
417
417
|
}
|
|
418
|
+
/**
|
|
419
|
+
* Generates the SQL index hint clause for the given index names.
|
|
420
|
+
* Returns `undefined` when the platform does not support index hints (e.g. PostgreSQL, SQLite).
|
|
421
|
+
*/
|
|
422
|
+
formatIndexHint(indexNames) {
|
|
423
|
+
return undefined;
|
|
424
|
+
}
|
|
418
425
|
/** Whether the driver automatically parses JSON columns into JS objects. */
|
|
419
426
|
convertsJsonAutomatically() {
|
|
420
427
|
return true;
|
package/typings.d.ts
CHANGED
|
@@ -47,7 +47,7 @@ export type AsyncFunction<R = any, T = Dictionary> = (args: T) => Promise<T>;
|
|
|
47
47
|
export type Compute<T> = {
|
|
48
48
|
[K in keyof T]: T[K];
|
|
49
49
|
} & {};
|
|
50
|
-
type InternalKeys = 'EntityRepositoryType' | 'PrimaryKeyProp' | 'OptionalProps' | 'EagerProps' | 'HiddenProps' | '__selectedType' | '__loadedType';
|
|
50
|
+
type InternalKeys = 'EntityRepositoryType' | 'PrimaryKeyProp' | 'OptionalProps' | 'EagerProps' | 'HiddenProps' | 'IndexHints' | '__selectedType' | '__loadedType';
|
|
51
51
|
/** Filters out function, symbol, and internal keys from an entity type. When `B = true`, also excludes scalar keys. */
|
|
52
52
|
export type CleanKeys<T, K extends keyof T, B extends boolean = false> = T[K] & {} extends Function ? never : K extends symbol | InternalKeys ? never : B extends true ? T[K] & {} extends Scalar ? never : K : K;
|
|
53
53
|
/** Extracts keys of `T` whose values are functions. */
|
|
@@ -150,6 +150,44 @@ export declare const EntityName: unique symbol;
|
|
|
150
150
|
export type InferEntityName<T> = T extends {
|
|
151
151
|
[EntityName]?: infer Name;
|
|
152
152
|
} ? (Name extends string ? Name : never) : never;
|
|
153
|
+
/**
|
|
154
|
+
* Symbol used to declare index-to-column mappings on an entity type.
|
|
155
|
+
* For decorator entities, declare as a phantom property:
|
|
156
|
+
* ```typescript
|
|
157
|
+
* [IndexHints]?: { idx_email: 'email'; idx_name_age: 'name' | 'age' };
|
|
158
|
+
* ```
|
|
159
|
+
* For `defineEntity` entities, index hints are inferred automatically from
|
|
160
|
+
* named indexes (property-level `.index('name')` and entity-level `indexes`/`uniques`).
|
|
161
|
+
*/
|
|
162
|
+
export declare const IndexHints: unique symbol;
|
|
163
|
+
/**
|
|
164
|
+
* Extracts the index hints map from an entity type. Returns `never` when no hints are declared.
|
|
165
|
+
* For decorator entities, `[IndexHints]` contains a pre-computed `{ idxName: 'prop' }` map.
|
|
166
|
+
* For `defineEntity` entities, `[IndexHints]` contains `[Properties]` (a tuple wrapping the
|
|
167
|
+
* raw property builders), which is lazily converted to the index map when first accessed.
|
|
168
|
+
*/
|
|
169
|
+
export type ExtractIndexHints<T> = T extends {
|
|
170
|
+
[IndexHints]?: infer H;
|
|
171
|
+
} ? H extends [infer P extends Record<string, any>] ? InferPropertyIndexMap<P> : H : never;
|
|
172
|
+
/**
|
|
173
|
+
* Extracts `{ indexName: propertyKey }` from property builder options.
|
|
174
|
+
* Checks `.index('name')` and `.unique('name')` on each property in a single pass.
|
|
175
|
+
*/
|
|
176
|
+
export type InferPropertyIndexMap<Properties extends Record<string, any>> = {
|
|
177
|
+
[K in keyof Properties as MaybeReturnType<Properties[K]> extends {
|
|
178
|
+
'~options': {
|
|
179
|
+
index: infer N extends string;
|
|
180
|
+
};
|
|
181
|
+
} ? N : MaybeReturnType<Properties[K]> extends {
|
|
182
|
+
'~options': {
|
|
183
|
+
unique: infer N extends string;
|
|
184
|
+
};
|
|
185
|
+
} ? N : never]: K & string;
|
|
186
|
+
};
|
|
187
|
+
/** Union of declared index names on an entity. Falls back to `string` when no `[IndexHints]` are declared. */
|
|
188
|
+
export type IndexName<T> = [ExtractIndexHints<T>] extends [never] ? string : (keyof ExtractIndexHints<T> & string) | (string & {});
|
|
189
|
+
/** Properties covered by the named index on entity T. Falls back to all entity keys when the index is unknown. */
|
|
190
|
+
export type IndexColumns<T, Name extends string> = ExtractIndexHints<T> extends Record<Name, infer Cols> ? Cols & string : EntityKey<T>;
|
|
153
191
|
/**
|
|
154
192
|
* Branded type that marks a property as optional in `em.create()`.
|
|
155
193
|
* Use as a property type wrapper: `createdAt: Opt<Date>` instead of listing in `[OptionalProps]`.
|
|
@@ -328,6 +366,18 @@ export type ObjectQuery<T> = OperatorMap<T> & FilterObject<T>;
|
|
|
328
366
|
* Accepts an object query, a primary key value, entity props with operators, or an array of filters.
|
|
329
367
|
*/
|
|
330
368
|
export type FilterQuery<T> = ObjectQuery<T> | NonNullable<ExpandScalar<Primary<T>>> | NonNullable<EntityProps<T> & OperatorMap<T>> | FilterQuery<T>[];
|
|
369
|
+
/**
|
|
370
|
+
* `FilterQuery` restricted to only properties covered by the specified index(es).
|
|
371
|
+
* Used when `using` option is set in `FindOptions` to enforce type-safe index usage.
|
|
372
|
+
*/
|
|
373
|
+
export type IndexFilterQuery<T, Using extends string> = [Using] extends [never] ? FilterQuery<T> : (OperatorMap<T> & {
|
|
374
|
+
-readonly [K in Extract<EntityKey<T>, IndexColumns<T, Using>>]?: ExpandQuery<ExpandProperty<FilterObjectProp<T, K>>> | ExpandQueryMerged<ExpandProperty<FilterObjectProp<T, K>>> | FilterValue<ExpandProperty<FilterObjectProp<T, K>>> | ElemMatchFilter<FilterObjectProp<T, K>> | null;
|
|
375
|
+
}) | NonNullable<ExpandScalar<Primary<T>>> | IndexFilterQuery<T, Using>[];
|
|
376
|
+
/** Replaces `where` and `using` on an options type with index-aware variants when `Using` is specified. */
|
|
377
|
+
export type WithUsingOptions<Opts, Entity, Using extends string> = Omit<Opts, 'where' | 'using'> & {
|
|
378
|
+
using?: Using | Using[];
|
|
379
|
+
where?: [Using] extends [never] ? FilterQuery<Entity> : IndexFilterQuery<Entity, Using>;
|
|
380
|
+
};
|
|
331
381
|
/** Public interface for the entity wrapper, accessible via `wrap(entity)`. Provides helper methods for entity state management. */
|
|
332
382
|
export interface IWrappedEntity<Entity extends object> {
|
|
333
383
|
isInitialized(): boolean;
|
package/typings.js
CHANGED
|
@@ -21,6 +21,16 @@ export const Config = Symbol('Config');
|
|
|
21
21
|
/** Symbol used to declare the entity name as a string literal type (used by `defineEntity`). */
|
|
22
22
|
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
23
23
|
export const EntityName = Symbol('EntityName');
|
|
24
|
+
/**
|
|
25
|
+
* Symbol used to declare index-to-column mappings on an entity type.
|
|
26
|
+
* For decorator entities, declare as a phantom property:
|
|
27
|
+
* ```typescript
|
|
28
|
+
* [IndexHints]?: { idx_email: 'email'; idx_name_age: 'name' | 'age' };
|
|
29
|
+
* ```
|
|
30
|
+
* For `defineEntity` entities, index hints are inferred automatically from
|
|
31
|
+
* named indexes (property-level `.index('name')` and entity-level `indexes`/`uniques`).
|
|
32
|
+
*/
|
|
33
|
+
export const IndexHints = Symbol('IndexHints');
|
|
24
34
|
/**
|
|
25
35
|
* Runtime metadata for an entity, holding its properties, relations, indexes, hooks, and more.
|
|
26
36
|
* Created during metadata discovery and used throughout the ORM lifecycle.
|
package/utils/Utils.js
CHANGED
|
@@ -141,7 +141,7 @@ export function parseJsonSafe(value) {
|
|
|
141
141
|
/** Collection of general-purpose utility methods used throughout the ORM. */
|
|
142
142
|
export class Utils {
|
|
143
143
|
static PK_SEPARATOR = '~~~';
|
|
144
|
-
static #ORM_VERSION = '7.1.0-dev.
|
|
144
|
+
static #ORM_VERSION = '7.1.0-dev.6';
|
|
145
145
|
/**
|
|
146
146
|
* Checks if the argument is instance of `Object`. Returns false for arrays.
|
|
147
147
|
*/
|