@mikro-orm/core 7.1.0-dev.2 → 7.1.0-dev.21
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 +63 -11
- package/EntityManager.js +180 -21
- package/drivers/DatabaseDriver.d.ts +1 -0
- package/drivers/DatabaseDriver.js +3 -0
- package/drivers/IDatabaseDriver.d.ts +44 -1
- package/entity/BaseEntity.d.ts +68 -1
- package/entity/BaseEntity.js +18 -0
- package/entity/Collection.d.ts +6 -3
- package/entity/Collection.js +15 -4
- package/entity/EntityFactory.js +20 -1
- package/entity/EntityLoader.d.ts +3 -1
- package/entity/EntityLoader.js +39 -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/defineEntity.d.ts +84 -15
- package/entity/defineEntity.js +10 -6
- package/entity/utils.js +4 -5
- 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 +12 -0
- package/metadata/MetadataDiscovery.js +165 -15
- package/metadata/MetadataValidator.d.ts +24 -0
- package/metadata/MetadataValidator.js +202 -1
- package/metadata/types.d.ts +71 -3
- 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 +8 -1
- package/platforms/Platform.js +38 -3
- package/typings.d.ts +139 -10
- package/typings.js +21 -4
- package/utils/AbstractMigrator.d.ts +11 -1
- package/utils/AbstractMigrator.js +203 -0
- package/utils/Configuration.d.ts +7 -0
- package/utils/Configuration.js +1 -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/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/metadata/types.d.ts
CHANGED
|
@@ -1,9 +1,52 @@
|
|
|
1
|
-
import type { AnyEntity, Constructor, EntityName, AnyString, CheckCallback, GeneratedColumnCallback, FormulaCallback, FilterQuery, Dictionary, AutoPath, EntityClass, IndexCallback, ObjectQuery, Raw } from '../typings.js';
|
|
1
|
+
import type { AnyEntity, Constructor, EntityName, AnyString, CheckCallback, GeneratedColumnCallback, FormulaCallback, FilterQuery, Dictionary, AutoPath, EntityClass, IndexCallback, ObjectQuery, Raw, SchemaColumns, TriggerDef } from '../typings.js';
|
|
2
2
|
import type { Cascade, LoadStrategy, DeferMode, QueryOrderMap, EmbeddedPrefixMode } from '../enums.js';
|
|
3
3
|
import type { Type, types } from '../types/index.js';
|
|
4
4
|
import type { EntityManager } from '../EntityManager.js';
|
|
5
5
|
import type { FilterOptions, FindOptions } from '../drivers/IDatabaseDriver.js';
|
|
6
6
|
import type { SerializeOptions } from '../serialization/EntitySerializer.js';
|
|
7
|
+
/** Supported PostgreSQL partitioning strategies. */
|
|
8
|
+
export type EntityPartitionType = 'hash' | 'list' | 'range';
|
|
9
|
+
/**
|
|
10
|
+
* Partition key expression for PostgreSQL partitioned tables.
|
|
11
|
+
*
|
|
12
|
+
* You can use:
|
|
13
|
+
* - a property name, e.g. `'type'`
|
|
14
|
+
* - a list of property names for composite expressions, e.g. `['tenant', 'createdAt']`
|
|
15
|
+
* - a raw SQL expression string, e.g. `"date_trunc('month', created_at)"`
|
|
16
|
+
* - a callback that receives schema column mappings and returns SQL
|
|
17
|
+
*/
|
|
18
|
+
export type EntityPartitionExpression<E = AnyEntity> = (keyof E & string) | readonly (keyof E & string)[] | AnyString | ((columns: SchemaColumns<E>) => string);
|
|
19
|
+
/** Explicit child partition definition for PostgreSQL `list` and `range` partitioning. */
|
|
20
|
+
export interface EntityPartition<E = AnyEntity> {
|
|
21
|
+
/**
|
|
22
|
+
* Optional child table name. Defaults to `<tableName>_<index>`. A single `.` is treated as a
|
|
23
|
+
* `schema.table` separator; names with more than one `.` are rejected to avoid ambiguity.
|
|
24
|
+
*/
|
|
25
|
+
name?: string;
|
|
26
|
+
/** Partition bound clause, either as `for values ...` or the trailing part such as `in (...)`, `from ... to ...`, or `default`. */
|
|
27
|
+
values: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* PostgreSQL table partitioning definition.
|
|
31
|
+
*
|
|
32
|
+
* - `hash` partitions generate child tables automatically from the partition count
|
|
33
|
+
* - `list` and `range` partitions require explicit child partition definitions
|
|
34
|
+
*/
|
|
35
|
+
export type EntityPartitionBy<E = AnyEntity> = {
|
|
36
|
+
type: Extract<EntityPartitionType, 'hash'>;
|
|
37
|
+
expression: EntityPartitionExpression<E>;
|
|
38
|
+
/**
|
|
39
|
+
* Hash partition fan-out: either a number (auto-named as `${tableName}_N`) or an array of
|
|
40
|
+
* explicit partition names in remainder order. Names may be `schema.name` to create the
|
|
41
|
+
* child in a non-default schema.
|
|
42
|
+
*/
|
|
43
|
+
partitions: number | readonly string[];
|
|
44
|
+
} | {
|
|
45
|
+
type: Exclude<EntityPartitionType, 'hash'>;
|
|
46
|
+
expression: EntityPartitionExpression<E>;
|
|
47
|
+
/** Explicit child partitions created in the order provided. */
|
|
48
|
+
partitions: EntityPartition<E>[];
|
|
49
|
+
};
|
|
7
50
|
export type EntityOptions<T, E = T extends EntityClass<infer P> ? P : T> = {
|
|
8
51
|
/** Override default collection/table name. Alias for `collection`. */
|
|
9
52
|
tableName?: string;
|
|
@@ -57,6 +100,15 @@ export type EntityOptions<T, E = T extends EntityClass<infer P> ? P : T> = {
|
|
|
57
100
|
};
|
|
58
101
|
/** Used to make ORM aware of externally defined triggers. This is needed for MS SQL Server multi inserts, ignored in other dialects. */
|
|
59
102
|
hasTriggers?: boolean;
|
|
103
|
+
/** Database triggers to create for this entity's table. (SQL drivers only) */
|
|
104
|
+
triggers?: TriggerDef<E>[];
|
|
105
|
+
/**
|
|
106
|
+
* PostgreSQL partitioning definition for this table.
|
|
107
|
+
*
|
|
108
|
+
* Partitioned tables are tracked by the schema generator and introspected back from PostgreSQL.
|
|
109
|
+
* Changing an existing partition layout still requires a manual migration.
|
|
110
|
+
*/
|
|
111
|
+
partitionBy?: EntityPartitionBy<E>;
|
|
60
112
|
/** SQL query that maps to a {@doclink virtual-entities | virtual entity}, or for view entities, the view definition. */
|
|
61
113
|
expression?: string | ((em: any, where: ObjectQuery<E>, options: FindOptions<E, any, any, any>, stream?: boolean) => object);
|
|
62
114
|
/** Set {@doclink repositories#custom-repository | custom repository class}. */
|
|
@@ -202,6 +254,12 @@ export interface PropertyOptions<Owner> {
|
|
|
202
254
|
* @see https://mikro-orm.io/docs/defining-entities#lazy-scalar-properties
|
|
203
255
|
*/
|
|
204
256
|
lazy?: boolean;
|
|
257
|
+
/**
|
|
258
|
+
* Marks this property as an array. When used with a custom type, the type is automatically
|
|
259
|
+
* wrapped in an `ArrayType` that delegates element conversion to the inner type.
|
|
260
|
+
* The column type is inferred as `innerType[]` (e.g. `int[]`, `time[]`).
|
|
261
|
+
*/
|
|
262
|
+
array?: boolean;
|
|
205
263
|
/**
|
|
206
264
|
* Set true to define entity's unique primary key identifier.
|
|
207
265
|
* Alias for `@PrimaryKey()` decorator
|
|
@@ -334,7 +392,7 @@ export interface PropertyOptions<Owner> {
|
|
|
334
392
|
}
|
|
335
393
|
export interface ReferenceOptions<Owner, Target> extends PropertyOptions<Owner> {
|
|
336
394
|
/** Set target entity type. For polymorphic relations, pass an array of entity types. */
|
|
337
|
-
entity?: () => EntityName<Target> | EntityName
|
|
395
|
+
entity?: () => EntityName<Target> | EntityName[];
|
|
338
396
|
/** Set what actions on owning entity should be cascaded to the relationship. Defaults to [Cascade.PERSIST, Cascade.MERGE] (see {@doclink cascading}). */
|
|
339
397
|
cascade?: Cascade[];
|
|
340
398
|
/** Always load the relationship. Discouraged for use with to-many relations for performance reasons. */
|
|
@@ -499,7 +557,7 @@ export interface EmbeddableOptions<Owner> {
|
|
|
499
557
|
abstract?: boolean;
|
|
500
558
|
}
|
|
501
559
|
export interface EnumOptions<T> extends PropertyOptions<T> {
|
|
502
|
-
items?: readonly (number | string)[] | (() => Dictionary);
|
|
560
|
+
items?: readonly (number | string)[] | Dictionary | (() => Dictionary);
|
|
503
561
|
array?: boolean;
|
|
504
562
|
/** for postgres, by default it uses text column with check constraint */
|
|
505
563
|
nativeEnumName?: string;
|
|
@@ -543,6 +601,16 @@ interface BaseOptions<T, H extends string> {
|
|
|
543
601
|
include?: T extends EntityClass<infer P> ? Properties<P, H> : Properties<T, H>;
|
|
544
602
|
/** Fill factor for the index as a percentage 0-100 (PostgreSQL, MSSQL). */
|
|
545
603
|
fillFactor?: number;
|
|
604
|
+
/**
|
|
605
|
+
* Predicate for partial indexes. Object form is a `FilterQuery` and is portable across
|
|
606
|
+
* SQL drivers and MongoDB; string form is a raw SQL fragment (SQL drivers only).
|
|
607
|
+
*
|
|
608
|
+
* Native support: PostgreSQL, SQLite, MSSQL (`WHERE`), MongoDB (`partialFilterExpression`).
|
|
609
|
+
* MySQL 8.0.13+ / Oracle: emulated via `CASE WHEN` functional index (uniqueness only enforced
|
|
610
|
+
* where the predicate holds). MariaDB is not supported — it has no inline expression indexes;
|
|
611
|
+
* define a virtual generated column and index that instead.
|
|
612
|
+
*/
|
|
613
|
+
where?: string | FilterQuery<NoInfer<T> extends EntityClass<infer P> ? P : NoInfer<T>>;
|
|
546
614
|
}
|
|
547
615
|
export interface UniqueOptions<T, H extends string = string> extends BaseOptions<T, H> {
|
|
548
616
|
deferMode?: DeferMode | `${DeferMode}`;
|
|
@@ -4,7 +4,7 @@ import { type ReferenceKind } from '../enums.js';
|
|
|
4
4
|
export declare abstract class AbstractNamingStrategy implements NamingStrategy {
|
|
5
5
|
getClassName(file: string, separator?: string): string;
|
|
6
6
|
classToMigrationName(timestamp: string, customMigrationName?: string): string;
|
|
7
|
-
indexName(tableName: string, columns: string[], type: 'primary' | 'foreign' | 'unique' | 'index' | 'sequence' | 'check' | 'default'): string;
|
|
7
|
+
indexName(tableName: string, columns: string[], type: 'primary' | 'foreign' | 'unique' | 'index' | 'sequence' | 'check' | 'default' | 'trigger'): string;
|
|
8
8
|
/**
|
|
9
9
|
* @inheritDoc
|
|
10
10
|
*/
|
|
@@ -75,7 +75,7 @@ export interface NamingStrategy {
|
|
|
75
75
|
/**
|
|
76
76
|
* Returns key/constraint name for the given type. Some drivers might not support all the types (e.g. mysql and sqlite enforce the PK name).
|
|
77
77
|
*/
|
|
78
|
-
indexName(tableName: string, columns: string[], type: 'primary' | 'foreign' | 'unique' | 'index' | 'sequence' | 'check' | 'default'): string;
|
|
78
|
+
indexName(tableName: string, columns: string[], type: 'primary' | 'foreign' | 'unique' | 'index' | 'sequence' | 'check' | 'default' | 'trigger'): string;
|
|
79
79
|
/**
|
|
80
80
|
* Returns alias name for given entity. The alias needs to be unique across the query, which is by default
|
|
81
81
|
* ensured via appended index parameter. It is optional to use it as long as you ensure it will be unique.
|
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.21",
|
|
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
|
@@ -43,6 +43,8 @@ export declare abstract class Platform {
|
|
|
43
43
|
getEnumArrayCheckConstraintExpression(column: string, items: string[]): string | null;
|
|
44
44
|
/** Whether this platform supports materialized views. */
|
|
45
45
|
supportsMaterializedViews(): boolean;
|
|
46
|
+
/** Whether this platform supports declarative table partitioning in schema generation. */
|
|
47
|
+
supportsPartitionedTables(): boolean;
|
|
46
48
|
/** Returns the schema helper instance for this platform, or undefined if not supported. */
|
|
47
49
|
getSchemaHelper(): unknown;
|
|
48
50
|
/** Whether the platform automatically creates indexes on foreign key columns. */
|
|
@@ -168,7 +170,7 @@ export declare abstract class Platform {
|
|
|
168
170
|
getUuidTypeDeclarationSQL(column: {
|
|
169
171
|
length?: number;
|
|
170
172
|
}): string;
|
|
171
|
-
/** Extracts the base type name from a full SQL type declaration (e.g.
|
|
173
|
+
/** Extracts the base type name from a full SQL type declaration (e.g. `varchar(255)` -> `varchar`). */
|
|
172
174
|
extractSimpleType(type: string): string;
|
|
173
175
|
/**
|
|
174
176
|
* This should be used only to compare types, it can strip some information like the length.
|
|
@@ -211,6 +213,11 @@ export declare abstract class Platform {
|
|
|
211
213
|
getFullTextWhereClause(prop: EntityProperty): string;
|
|
212
214
|
supportsCreatingFullTextIndex(): boolean;
|
|
213
215
|
getFullTextIndexExpression(indexName: string, schemaName: string | undefined, tableName: string, columns: SimpleColumnMeta[]): string;
|
|
216
|
+
/**
|
|
217
|
+
* Generates the SQL index hint clause for the given index names.
|
|
218
|
+
* Returns `undefined` when the platform does not support index hints (e.g. PostgreSQL, SQLite).
|
|
219
|
+
*/
|
|
220
|
+
formatIndexHint(indexNames: string[]): string | undefined;
|
|
214
221
|
/** Whether the driver automatically parses JSON columns into JS objects. */
|
|
215
222
|
convertsJsonAutomatically(): boolean;
|
|
216
223
|
/** Converts a JS value to its JSON database representation (typically JSON.stringify). */
|
package/platforms/Platform.js
CHANGED
|
@@ -2,12 +2,22 @@ import { clone } from '../utils/clone.js';
|
|
|
2
2
|
import { EntityRepository } from '../entity/EntityRepository.js';
|
|
3
3
|
import { UnderscoreNamingStrategy } from '../naming-strategy/UnderscoreNamingStrategy.js';
|
|
4
4
|
import { ExceptionConverter } from './ExceptionConverter.js';
|
|
5
|
+
import { MetadataError } from '../errors.js';
|
|
5
6
|
import { ArrayType, BigIntType, BlobType, BooleanType, CharacterType, DateTimeType, DateType, DecimalType, DoubleType, EnumType, FloatType, IntegerType, IntervalType, JsonType, MediumIntType, SmallIntType, StringType, TextType, TimeType, TinyIntType, Type, Uint8ArrayType, UnknownType, UuidType, } from '../types/index.js';
|
|
6
7
|
import { parseJsonSafe, Utils } from '../utils/Utils.js';
|
|
7
8
|
import { ReferenceKind } from '../enums.js';
|
|
8
9
|
import { Raw } from '../utils/RawQueryFragment.js';
|
|
9
10
|
/** Symbol used to tag cloned embeddable data for JSON serialization handling. */
|
|
10
11
|
export const JsonProperty = Symbol('JsonProperty');
|
|
12
|
+
const MULTI_WORD_SQL_TYPES = [
|
|
13
|
+
'timestamp with time zone',
|
|
14
|
+
'timestamp without time zone',
|
|
15
|
+
'time with time zone',
|
|
16
|
+
'time without time zone',
|
|
17
|
+
'character varying',
|
|
18
|
+
'double precision',
|
|
19
|
+
'bit varying',
|
|
20
|
+
];
|
|
11
21
|
/** Abstract base class providing database-specific behavior and SQL dialect differences. */
|
|
12
22
|
export class Platform {
|
|
13
23
|
exceptionConverter = new ExceptionConverter();
|
|
@@ -62,6 +72,10 @@ export class Platform {
|
|
|
62
72
|
supportsMaterializedViews() {
|
|
63
73
|
return false;
|
|
64
74
|
}
|
|
75
|
+
/** Whether this platform supports declarative table partitioning in schema generation. */
|
|
76
|
+
supportsPartitionedTables() {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
65
79
|
/** Returns the schema helper instance for this platform, or undefined if not supported. */
|
|
66
80
|
getSchemaHelper() {
|
|
67
81
|
return undefined;
|
|
@@ -222,9 +236,15 @@ export class Platform {
|
|
|
222
236
|
column.length ??= 36;
|
|
223
237
|
return this.getVarcharTypeDeclarationSQL(column);
|
|
224
238
|
}
|
|
225
|
-
/** Extracts the base type name from a full SQL type declaration (e.g.
|
|
239
|
+
/** Extracts the base type name from a full SQL type declaration (e.g. `varchar(255)` -> `varchar`). */
|
|
226
240
|
extractSimpleType(type) {
|
|
227
|
-
|
|
241
|
+
const lower = type.toLowerCase();
|
|
242
|
+
for (const multiWord of MULTI_WORD_SQL_TYPES) {
|
|
243
|
+
if (lower.startsWith(multiWord)) {
|
|
244
|
+
return multiWord;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return /[^(), ]+/.exec(lower)[0];
|
|
228
248
|
}
|
|
229
249
|
/**
|
|
230
250
|
* This should be used only to compare types, it can strip some information like the length.
|
|
@@ -248,6 +268,7 @@ export class Platform {
|
|
|
248
268
|
return Type.getType(CharacterType);
|
|
249
269
|
case 'string':
|
|
250
270
|
case 'varchar':
|
|
271
|
+
case 'character varying':
|
|
251
272
|
return Type.getType(StringType);
|
|
252
273
|
case 'interval':
|
|
253
274
|
return Type.getType(IntervalType);
|
|
@@ -267,6 +288,7 @@ export class Platform {
|
|
|
267
288
|
case 'float':
|
|
268
289
|
return Type.getType(FloatType);
|
|
269
290
|
case 'double':
|
|
291
|
+
case 'double precision':
|
|
270
292
|
return Type.getType(DoubleType);
|
|
271
293
|
case 'integer':
|
|
272
294
|
return Type.getType(IntegerType);
|
|
@@ -286,8 +308,12 @@ export class Platform {
|
|
|
286
308
|
return Type.getType(DateType);
|
|
287
309
|
case 'datetime':
|
|
288
310
|
case 'timestamp':
|
|
311
|
+
case 'timestamp with time zone':
|
|
312
|
+
case 'timestamp without time zone':
|
|
289
313
|
return Type.getType(DateTimeType);
|
|
290
314
|
case 'time':
|
|
315
|
+
case 'time with time zone':
|
|
316
|
+
case 'time without time zone':
|
|
291
317
|
return Type.getType(TimeType);
|
|
292
318
|
case 'object':
|
|
293
319
|
case 'json':
|
|
@@ -415,6 +441,13 @@ export class Platform {
|
|
|
415
441
|
getFullTextIndexExpression(indexName, schemaName, tableName, columns) {
|
|
416
442
|
throw new Error('Full text searching is not supported by this driver.');
|
|
417
443
|
}
|
|
444
|
+
/**
|
|
445
|
+
* Generates the SQL index hint clause for the given index names.
|
|
446
|
+
* Returns `undefined` when the platform does not support index hints (e.g. PostgreSQL, SQLite).
|
|
447
|
+
*/
|
|
448
|
+
formatIndexHint(indexNames) {
|
|
449
|
+
return undefined;
|
|
450
|
+
}
|
|
418
451
|
/** Whether the driver automatically parses JSON columns into JS objects. */
|
|
419
452
|
convertsJsonAutomatically() {
|
|
420
453
|
return true;
|
|
@@ -651,7 +684,9 @@ export class Platform {
|
|
|
651
684
|
}
|
|
652
685
|
/** Platform-specific validation of entity metadata. */
|
|
653
686
|
validateMetadata(meta) {
|
|
654
|
-
|
|
687
|
+
if (meta.partitionBy && !this.supportsPartitionedTables()) {
|
|
688
|
+
throw new MetadataError(`Entity ${meta.className} uses partitionBy, but ${this.constructor.name} does not support partitioned tables`);
|
|
689
|
+
}
|
|
655
690
|
}
|
|
656
691
|
/**
|
|
657
692
|
* Generates a custom order by statement given a set of in order values, eg.
|
package/typings.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import type { SerializationContext } from './serialization/SerializationContext.
|
|
|
11
11
|
import type { SerializeOptions } from './serialization/EntitySerializer.js';
|
|
12
12
|
import type { MetadataStorage } from './metadata/MetadataStorage.js';
|
|
13
13
|
import type { EntitySchema } from './metadata/EntitySchema.js';
|
|
14
|
-
import type { IndexColumnOptions } from './metadata/types.js';
|
|
14
|
+
import type { EntityPartitionBy, IndexColumnOptions } from './metadata/types.js';
|
|
15
15
|
import type { Type, types } from './types/index.js';
|
|
16
16
|
import type { Platform } from './platforms/Platform.js';
|
|
17
17
|
import type { Configuration } from './utils/Configuration.js';
|
|
@@ -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. */
|
|
@@ -113,7 +113,7 @@ type LoadedReferenceShape<T = any> = ReferenceShape & {
|
|
|
113
113
|
* Using this instead of `Loadable<any>` in conditional type checks prevents
|
|
114
114
|
* TypeScript from evaluating the full Collection/Reference interfaces.
|
|
115
115
|
*/
|
|
116
|
-
type LoadableShape = CollectionShape | ReferenceShape | readonly any[];
|
|
116
|
+
type LoadableShape = CollectionShape | ReferenceShape | LazyRef.Brand<any> | readonly any[];
|
|
117
117
|
/** Gets all keys from all members of a union type (distributes over the union). */
|
|
118
118
|
export type UnionKeys<T> = T extends any ? keyof T : never;
|
|
119
119
|
/** Gets the type of a property from all union members that have it (distributes over the union). */
|
|
@@ -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;
|
|
@@ -417,12 +467,12 @@ type NonArrayObject = object & {
|
|
|
417
467
|
export type EntityDataProp<T, C extends boolean> = T extends Date ? string | Date : T extends Scalar ? T : T extends ScalarReference<infer U> ? EntityDataProp<U, C> : T extends {
|
|
418
468
|
__runtime?: infer Runtime;
|
|
419
469
|
__raw?: infer Raw;
|
|
420
|
-
} ? C extends true ? Raw : Runtime : T extends ReferenceShape<infer U> ? EntityDataNested<U, C> : T extends CollectionShape<infer U> ? U | U[] | EntityDataNested<U & object, C> | EntityDataNested<U & object, C>[] : T extends readonly (infer U)[] ? U extends NonArrayObject ? U | U[] | EntityDataNested<U, C> | EntityDataNested<U, C>[] : U[] | EntityDataNested<U, C>[] : EntityDataNested<T, C>;
|
|
470
|
+
} ? C extends true ? Raw : Runtime : T extends LazyRef.Brand<infer U> ? EntityDataNested<U, C> : T extends ReferenceShape<infer U> ? EntityDataNested<U, C> : T extends CollectionShape<infer U> ? U | U[] | EntityDataNested<U & object, C> | EntityDataNested<U & object, C>[] : T extends readonly (infer U)[] ? U extends NonArrayObject ? U | U[] | EntityDataNested<U, C> | EntityDataNested<U, C>[] : U[] | EntityDataNested<U, C>[] : EntityDataNested<T, C>;
|
|
421
471
|
/** Like `EntityDataProp` but used in `RequiredEntityData` context with required/optional key distinction. */
|
|
422
472
|
export type RequiredEntityDataProp<T, O, C extends boolean> = T extends Date ? string | Date : Exclude<T, null> extends RequiredNullable.Brand ? T | null : T extends Scalar ? T : T extends ScalarReference<infer U> ? RequiredEntityDataProp<U, O, C> : T extends {
|
|
423
473
|
__runtime?: infer Runtime;
|
|
424
474
|
__raw?: infer Raw;
|
|
425
|
-
} ? C extends true ? Raw : Runtime : T extends ReferenceShape<infer U> ? RequiredEntityDataNested<U, O, C> : T extends CollectionShape<infer U> ? U | U[] | RequiredEntityDataNested<U & object, O, C> | RequiredEntityDataNested<U & object, O, C>[] : T extends readonly (infer U)[] ? U extends NonArrayObject ? U | U[] | RequiredEntityDataNested<U, O, C> | RequiredEntityDataNested<U, O, C>[] : U[] | RequiredEntityDataNested<U, O, C>[] : RequiredEntityDataNested<T, O, C>;
|
|
475
|
+
} ? C extends true ? Raw : Runtime : T extends LazyRef.Brand<infer U> ? RequiredEntityDataNested<U, O, C> : T extends ReferenceShape<infer U> ? RequiredEntityDataNested<U, O, C> : T extends CollectionShape<infer U> ? U | U[] | RequiredEntityDataNested<U & object, O, C> | RequiredEntityDataNested<U & object, O, C>[] : T extends readonly (infer U)[] ? U extends NonArrayObject ? U | U[] | RequiredEntityDataNested<U, O, C> | RequiredEntityDataNested<U, O, C>[] : U[] | RequiredEntityDataNested<U, O, C>[] : RequiredEntityDataNested<T, O, C>;
|
|
426
476
|
/** Nested entity data shape for embedded or related entities within `EntityData`. */
|
|
427
477
|
export type EntityDataNested<T, C extends boolean = false> = T extends undefined ? never : T extends any[] ? Readonly<T> : EntityData<T, C> | ExpandEntityProp<T, C>;
|
|
428
478
|
type UnwrapScalarRef<T> = T extends ScalarReference<infer U> ? U : T;
|
|
@@ -471,6 +521,35 @@ type Relation<T> = {
|
|
|
471
521
|
export type Rel<T> = T;
|
|
472
522
|
/** Alias for `ScalarReference` (see {@apilink Ref}). */
|
|
473
523
|
export type ScalarRef<T> = ScalarReference<T>;
|
|
524
|
+
/**
|
|
525
|
+
* Type-level marker for a to-one relation that is **direct at runtime** (no `Reference` wrapper) but
|
|
526
|
+
* **restricted at compile time** until narrowed via `Loaded<>`.
|
|
527
|
+
*
|
|
528
|
+
* Use as the property type on a `@ManyToOne`/`@OneToOne` relation that does **not** have `ref: true`:
|
|
529
|
+
*
|
|
530
|
+
* ```ts
|
|
531
|
+
* @ManyToOne(() => User)
|
|
532
|
+
* author!: LazyRef<User>;
|
|
533
|
+
* ```
|
|
534
|
+
*
|
|
535
|
+
* Semantics:
|
|
536
|
+
* - **Runtime**: identical to a plain direct relation — `article.author` is a `User` instance (stub or hydrated),
|
|
537
|
+
* `article.author instanceof User` is `true`, no `Reference` object is created.
|
|
538
|
+
* - **Type (unloaded view)**: only the primary key is accessible. Accessing other properties is a compile error.
|
|
539
|
+
* - **Type (loaded view)**: once the relation is in the populate hint of a `Loaded<Entity, 'author'>`, it narrows
|
|
540
|
+
* back to the full entity — no `.$` or `.get()` indirection needed.
|
|
541
|
+
*
|
|
542
|
+
* Note: the safety is purely compile-time. JS code or `as any` casts bypass it.
|
|
543
|
+
*/
|
|
544
|
+
export type LazyRef<T extends object> = IsAny<T> extends true ? LazyRef.Brand<T> : {
|
|
545
|
+
[K in PrimaryProperty<T> & keyof T]: T[K];
|
|
546
|
+
} & LazyRef.Brand<T>;
|
|
547
|
+
export declare namespace LazyRef {
|
|
548
|
+
const __lazyRef: unique symbol;
|
|
549
|
+
interface Brand<T> {
|
|
550
|
+
[__lazyRef]?: (arg: T) => T;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
474
553
|
/** Alias for `Reference<T> & { id: number }` (see {@apilink Ref}). */
|
|
475
554
|
export type EntityRef<T extends object> = true extends IsUnknown<PrimaryProperty<T>> ? Reference<T> : IsAny<T> extends true ? Reference<T> : {
|
|
476
555
|
[K in PrimaryProperty<T> & keyof T]: T[K];
|
|
@@ -606,6 +685,8 @@ export type IndexCallback<T> = (columns: Record<PropertyName<T>, string>, table:
|
|
|
606
685
|
export type FormulaCallback<T> = (columns: FormulaColumns<T>, table: FormulaTable) => string | Raw;
|
|
607
686
|
/** Callback for CHECK constraint expressions. Receives column mappings and table info. */
|
|
608
687
|
export type CheckCallback<T> = (columns: Record<PropertyName<T>, string>, table: SchemaTable) => string | Raw;
|
|
688
|
+
/** Callback for trigger body expressions. Receives column mappings and table info. */
|
|
689
|
+
export type TriggerCallback<T> = (columns: Record<PropertyName<T>, string>, table: SchemaTable) => string | Raw;
|
|
609
690
|
/** Callback for generated (computed) column expressions. Receives column mappings and table info. */
|
|
610
691
|
export type GeneratedColumnCallback<T> = (columns: Record<PropertyName<T>, string>, table: SchemaTable) => string | Raw;
|
|
611
692
|
/** Definition of a CHECK constraint on a table or property. */
|
|
@@ -614,6 +695,23 @@ export interface CheckConstraint<T = any> {
|
|
|
614
695
|
property?: string;
|
|
615
696
|
expression: string | Raw | CheckCallback<T>;
|
|
616
697
|
}
|
|
698
|
+
/** Definition of a database trigger on a table. */
|
|
699
|
+
export interface TriggerDef<T = any> {
|
|
700
|
+
/** Trigger name. Auto-generated if omitted. */
|
|
701
|
+
name?: string;
|
|
702
|
+
/** When the trigger fires relative to the event. */
|
|
703
|
+
timing: 'before' | 'after' | 'instead of';
|
|
704
|
+
/** Which DML events activate the trigger. */
|
|
705
|
+
events: ('insert' | 'update' | 'delete' | 'truncate')[];
|
|
706
|
+
/** Whether the trigger fires once per row or per statement. Defaults to `'row'`. */
|
|
707
|
+
forEach?: 'row' | 'statement';
|
|
708
|
+
/** SQL body of the trigger. Can be a string, Raw query, or callback receiving column name mappings. */
|
|
709
|
+
body?: string | Raw | TriggerCallback<T>;
|
|
710
|
+
/** Optional SQL WHEN condition for the trigger. */
|
|
711
|
+
when?: string;
|
|
712
|
+
/** Raw DDL escape hatch — full CREATE TRIGGER statement. Mutually exclusive with `body`. */
|
|
713
|
+
expression?: string;
|
|
714
|
+
}
|
|
617
715
|
/** Branded string that accepts any string value while preserving autocompletion for known literals. */
|
|
618
716
|
export type AnyString = string & {};
|
|
619
717
|
/** Describes a single property (column, relation, or embedded) within an entity's metadata. */
|
|
@@ -776,6 +874,8 @@ export interface EntityMetadata<Entity = any, Class extends EntityCtor<Entity> =
|
|
|
776
874
|
materialized?: boolean;
|
|
777
875
|
/** For materialized views, whether data is populated on creation. Defaults to true. */
|
|
778
876
|
withData?: boolean;
|
|
877
|
+
/** PostgreSQL partitioning definition for this table. */
|
|
878
|
+
partitionBy?: EntityPartitionBy<Entity>;
|
|
779
879
|
expression?: string | ((em: any, where: ObjectQuery<Entity>, options: FindOptions<Entity, any, any, any>, stream?: boolean) => MaybePromise<Raw | object | string>);
|
|
780
880
|
discriminatorColumn?: EntityKey<Entity> | AnyString;
|
|
781
881
|
discriminatorValue?: number | string;
|
|
@@ -814,6 +914,7 @@ export interface EntityMetadata<Entity = any, Class extends EntityCtor<Entity> =
|
|
|
814
914
|
type?: string;
|
|
815
915
|
options?: Dictionary;
|
|
816
916
|
expression?: string | IndexCallback<Entity>;
|
|
917
|
+
where?: string | FilterQuery<Entity>;
|
|
817
918
|
columns?: IndexColumnOptions[];
|
|
818
919
|
include?: EntityKey<Entity> | EntityKey<Entity>[];
|
|
819
920
|
fillFactor?: number;
|
|
@@ -826,6 +927,7 @@ export interface EntityMetadata<Entity = any, Class extends EntityCtor<Entity> =
|
|
|
826
927
|
name?: string;
|
|
827
928
|
options?: Dictionary;
|
|
828
929
|
expression?: string | IndexCallback<Entity>;
|
|
930
|
+
where?: string | FilterQuery<Entity>;
|
|
829
931
|
deferMode?: DeferMode | `${DeferMode}`;
|
|
830
932
|
columns?: IndexColumnOptions[];
|
|
831
933
|
include?: EntityKey<Entity> | EntityKey<Entity>[];
|
|
@@ -833,6 +935,7 @@ export interface EntityMetadata<Entity = any, Class extends EntityCtor<Entity> =
|
|
|
833
935
|
disabled?: boolean;
|
|
834
936
|
}[];
|
|
835
937
|
checks: CheckConstraint<Entity>[];
|
|
938
|
+
triggers: TriggerDef<Entity>[];
|
|
836
939
|
repositoryClass?: string;
|
|
837
940
|
repository: () => EntityClass<EntityRepository<any>>;
|
|
838
941
|
hooks: {
|
|
@@ -853,6 +956,8 @@ export interface EntityMetadata<Entity = any, Class extends EntityCtor<Entity> =
|
|
|
853
956
|
polymorphicDiscriminatorMap?: Dictionary<EntityClass>;
|
|
854
957
|
/** Inheritance type: 'sti' (Single Table Inheritance) or 'tpt' (Table-Per-Type). Only set on root entities. */
|
|
855
958
|
inheritanceType?: 'sti' | 'tpt';
|
|
959
|
+
/** Legacy alias populated from `EntityOptions.inheritance`; mirrored to `inheritanceType` during discovery. */
|
|
960
|
+
inheritance?: 'tpt';
|
|
856
961
|
/** For TPT: direct parent entity metadata (the entity this one extends). */
|
|
857
962
|
tptParent?: EntityMetadata;
|
|
858
963
|
/** For TPT: direct child entities (entities that extend this one). */
|
|
@@ -1060,6 +1165,11 @@ export interface IMigrator {
|
|
|
1060
1165
|
* Executes down migrations to the given point. Without parameter it will migrate one version down.
|
|
1061
1166
|
*/
|
|
1062
1167
|
down(options?: string | string[] | Omit<MigrateOptions, 'from'>): Promise<MigrationInfo[]>;
|
|
1168
|
+
/**
|
|
1169
|
+
* Combines multiple executed migrations into a single migration file.
|
|
1170
|
+
* Concatenates source code without touching the database schema.
|
|
1171
|
+
*/
|
|
1172
|
+
rollup(migrations?: string[]): Promise<MigrationResult>;
|
|
1063
1173
|
/**
|
|
1064
1174
|
* Registers event handler.
|
|
1065
1175
|
*/
|
|
@@ -1142,13 +1252,32 @@ export type PopulateOptions<T> = {
|
|
|
1142
1252
|
children?: PopulateOptions<T[keyof T]>[];
|
|
1143
1253
|
/** When true, ignores `mapToPk` on the property and returns full entity data instead of just PKs. */
|
|
1144
1254
|
dataOnly?: boolean;
|
|
1255
|
+
/** Limit the number of items loaded per parent entity. Collections will be marked as partial and readonly. */
|
|
1256
|
+
limit?: number;
|
|
1257
|
+
/** Offset for per-parent limiting (used with `limit`). */
|
|
1258
|
+
offset?: number;
|
|
1259
|
+
/** Order by clause for per-parent limiting. Takes precedence over nested `FindOptions.orderBy`. */
|
|
1260
|
+
orderBy?: QueryOrderMap<T[keyof T]>;
|
|
1145
1261
|
};
|
|
1146
1262
|
/** Inline options that can be appended to populate hint strings (e.g., strategy, join type). */
|
|
1147
1263
|
export type PopulateHintOptions = {
|
|
1148
1264
|
strategy?: LoadStrategy.JOINED | LoadStrategy.SELECT_IN | 'joined' | 'select-in';
|
|
1149
1265
|
joinType?: 'inner join' | 'left join';
|
|
1266
|
+
/** Limit the number of items loaded per parent entity. Collections will be marked as partial and readonly. */
|
|
1267
|
+
limit?: number;
|
|
1268
|
+
/** Offset for per-parent limiting (used with `limit`). */
|
|
1269
|
+
offset?: number;
|
|
1270
|
+
/** Order by clause for per-parent limiting. Takes precedence over nested `FindOptions.orderBy`. */
|
|
1271
|
+
orderBy?: QueryOrderMap<any>;
|
|
1150
1272
|
};
|
|
1151
1273
|
type ExtractType<T> = T extends CollectionShape<infer U> ? U : T extends ReferenceShape<infer U> ? U : T extends Ref<infer U> ? U : T extends readonly (infer U)[] ? U : T;
|
|
1274
|
+
/**
|
|
1275
|
+
* Like {@link ExtractType} but also unwraps {@link LazyRef}. Kept separate so {@link ExtractType}'s
|
|
1276
|
+
* hot path (used by `IsOptional`, `EntityData`, `RequiredEntityData`) doesn't pay the cost of the
|
|
1277
|
+
* extra branch — those contexts handle `LazyRef` in their own earlier branches (see
|
|
1278
|
+
* `EntityDataProp` / `RequiredEntityDataProp`) before delegating to `ExtractType`.
|
|
1279
|
+
*/
|
|
1280
|
+
type ExtractTypeWithLazyRef<T> = T extends LazyRef.Brand<infer U> ? U : ExtractType<T>;
|
|
1152
1281
|
type ExtractStringKeys<T> = {
|
|
1153
1282
|
[K in keyof T]-?: CleanKeys<T, K>;
|
|
1154
1283
|
}[keyof T] & {};
|
|
@@ -1156,8 +1285,8 @@ type ExtractStringKeys<T> = {
|
|
|
1156
1285
|
* Extracts string keys from an entity type, handling Collection/Reference wrappers.
|
|
1157
1286
|
* Simplified to just check `T extends object` since ExtractType handles the unwrapping.
|
|
1158
1287
|
*/
|
|
1159
|
-
type StringKeys<T, E extends string = never> = T extends object ? ExtractStringKeys<
|
|
1160
|
-
type GetStringKey<T, K extends StringKeys<T, string>, E extends string> = K extends keyof T ?
|
|
1288
|
+
type StringKeys<T, E extends string = never> = T extends object ? ExtractStringKeys<ExtractTypeWithLazyRef<T>> | E : never;
|
|
1289
|
+
type GetStringKey<T, K extends StringKeys<T, string>, E extends string> = K extends keyof T ? ExtractTypeWithLazyRef<T[K]> : K extends E ? keyof T : never;
|
|
1161
1290
|
type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
1162
1291
|
type RelationKeys<T> = T extends object ? {
|
|
1163
1292
|
[K in keyof T]-?: CleanKeys<T, K, true>;
|
|
@@ -1172,8 +1301,8 @@ export type UnboxArray<T> = T extends any[] ? ArrayElement<T> : T;
|
|
|
1172
1301
|
/** Extracts the element type from an array type. */
|
|
1173
1302
|
export type ArrayElement<ArrayType extends unknown[]> = ArrayType extends (infer ElementType)[] ? ElementType : never;
|
|
1174
1303
|
/** Unwraps a property type from its wrapper (Reference, Collection, or array) to the inner entity type. */
|
|
1175
|
-
export type ExpandProperty<T> = T extends ReferenceShape<infer U> ? NonNullable<U> : T extends CollectionShape<infer U> ? NonNullable<U> : T extends (infer U)[] ? NonNullable<U> : NonNullable<T>;
|
|
1176
|
-
type LoadedLoadable<T, E extends object> = T extends CollectionShape ? LoadedCollection<E> : T extends ScalarReference<infer U> ? LoadedScalarReference<U> : T extends ReferenceShape ? T & LoadedReference<E> : T extends Scalar ? T : T extends (infer U)[] ? U extends Scalar ? T : E[] : E;
|
|
1304
|
+
export type ExpandProperty<T> = T extends LazyRef.Brand<infer U> ? NonNullable<U> : T extends ReferenceShape<infer U> ? NonNullable<U> : T extends CollectionShape<infer U> ? NonNullable<U> : T extends (infer U)[] ? NonNullable<U> : NonNullable<T>;
|
|
1305
|
+
type LoadedLoadable<T, E extends object> = T extends CollectionShape ? LoadedCollection<E> : T extends ScalarReference<infer U> ? LoadedScalarReference<U> : T extends LazyRef.Brand<any> ? E : T extends ReferenceShape ? T & LoadedReference<E> : T extends Scalar ? T : T extends (infer U)[] ? U extends Scalar ? T : E[] : E;
|
|
1177
1306
|
type IsTrue<T> = IsNever<T> extends true ? false : T extends boolean ? (T extends true ? true : false) : false;
|
|
1178
1307
|
type StringLiteral<T> = T extends string ? (string extends T ? never : T) : never;
|
|
1179
1308
|
type Prefix<T, K> = K extends `${infer S}.${string}` ? S : K extends '*' ? keyof T : K;
|
|
@@ -1207,7 +1336,7 @@ export type MergeSelected<T, U, F extends string> = IsLoadedType<T> extends true
|
|
|
1207
1336
|
export type MergeLoaded<T, U, P extends string, F extends string, E extends string, R extends boolean = false> = IsLoadedType<T> extends true ? T & Loaded<U, P, F, E> : Loaded<T, P, F, E>;
|
|
1208
1337
|
/** Extracts the nullability modifiers (`null`, `undefined`, or both) from a type `T`. */
|
|
1209
1338
|
export type AddOptional<T> = undefined | null extends T ? null | undefined : null extends T ? null : undefined extends T ? undefined : never;
|
|
1210
|
-
type LoadedProp<T, L extends string = never, F extends string = '*', E extends string = never> = LoadedLoadable<T, Loaded<
|
|
1339
|
+
type LoadedProp<T, L extends string = never, F extends string = '*', E extends string = never> = LoadedLoadable<T, Loaded<ExtractTypeWithLazyRef<T>, L, F, E>>;
|
|
1211
1340
|
/** Extracts the eager-loaded property names declared via `[EagerProps]` as a string union. */
|
|
1212
1341
|
export type AddEager<T> = ExtractEagerProps<T> & string;
|
|
1213
1342
|
/** Combines an explicit populate hint `L` with the entity's eagerly loaded properties. */
|
package/typings.js
CHANGED
|
@@ -4,7 +4,6 @@ import { EntityHelper } from './entity/EntityHelper.js';
|
|
|
4
4
|
import { helper } from './entity/wrap.js';
|
|
5
5
|
import { Utils } from './utils/Utils.js';
|
|
6
6
|
import { EntityComparator } from './utils/EntityComparator.js';
|
|
7
|
-
import { BaseEntity } from './entity/BaseEntity.js';
|
|
8
7
|
/** Symbol used to declare a custom repository type on an entity class (e.g., `[EntityRepositoryType]?: BookRepository`). */
|
|
9
8
|
export const EntityRepositoryType = Symbol('EntityRepositoryType');
|
|
10
9
|
/** Symbol used to declare the primary key property name(s) on an entity (e.g., `[PrimaryKeyProp]?: 'id'`). */
|
|
@@ -22,6 +21,16 @@ export const Config = Symbol('Config');
|
|
|
22
21
|
/** Symbol used to declare the entity name as a string literal type (used by `defineEntity`). */
|
|
23
22
|
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
24
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');
|
|
25
34
|
/**
|
|
26
35
|
* Runtime metadata for an entity, holding its properties, relations, indexes, hooks, and more.
|
|
27
36
|
* Created during metadata discovery and used throughout the ORM lifecycle.
|
|
@@ -39,12 +48,20 @@ export class EntityMetadata {
|
|
|
39
48
|
this.indexes = [];
|
|
40
49
|
this.uniques = [];
|
|
41
50
|
this.checks = [];
|
|
51
|
+
this.triggers = [];
|
|
42
52
|
this.referencingProperties = [];
|
|
43
53
|
this.concurrencyCheckKeys = new Set();
|
|
44
54
|
Object.assign(this, meta);
|
|
45
55
|
const name = meta.className ?? meta.name;
|
|
46
56
|
if (!this.class && name) {
|
|
47
|
-
|
|
57
|
+
let Parent;
|
|
58
|
+
if (typeof this.extends === 'function') {
|
|
59
|
+
Parent = this.extends;
|
|
60
|
+
}
|
|
61
|
+
else if (this.extends != null && typeof this.extends.class === 'function') {
|
|
62
|
+
Parent = this.extends.class;
|
|
63
|
+
}
|
|
64
|
+
const Class = Parent ? { [name]: class extends Parent {
|
|
48
65
|
} }[name] : { [name]: class {
|
|
49
66
|
} }[name];
|
|
50
67
|
this.class = Class;
|
|
@@ -244,8 +261,8 @@ export class EntityMetadata {
|
|
|
244
261
|
}, { __gettersDefined: { value: true, enumerable: false } });
|
|
245
262
|
}
|
|
246
263
|
initIndexes(prop) {
|
|
247
|
-
const simpleIndex = this.indexes.find(index => index.properties === prop.name && !index.options && !index.type && !index.expression);
|
|
248
|
-
const simpleUnique = this.uniques.find(index => index.properties === prop.name && !index.options);
|
|
264
|
+
const simpleIndex = this.indexes.find(index => index.properties === prop.name && !index.options && !index.type && !index.expression && index.where == null);
|
|
265
|
+
const simpleUnique = this.uniques.find(index => index.properties === prop.name && !index.options && !index.expression && index.where == null);
|
|
249
266
|
const owner = prop.kind === ReferenceKind.MANY_TO_ONE;
|
|
250
267
|
if (!prop.index && simpleIndex) {
|
|
251
268
|
Utils.defaultValue(simpleIndex, 'name', true);
|