@mikro-orm/core 7.1.0-dev.9 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/EntityManager.d.ts +47 -3
- package/EntityManager.js +150 -23
- package/README.md +2 -1
- package/connections/Connection.d.ts +67 -1
- package/connections/Connection.js +64 -0
- package/drivers/IDatabaseDriver.d.ts +20 -6
- package/entity/BaseEntity.d.ts +68 -1
- package/entity/BaseEntity.js +18 -0
- package/entity/Collection.d.ts +1 -1
- package/entity/Collection.js +4 -1
- package/entity/EntityAssigner.js +8 -0
- package/entity/EntityFactory.js +5 -3
- package/entity/EntityLoader.d.ts +8 -1
- package/entity/EntityLoader.js +97 -29
- package/entity/Reference.d.ts +42 -1
- package/entity/Reference.js +9 -0
- package/entity/defineEntity.d.ts +69 -16
- package/entity/defineEntity.js +17 -0
- package/entity/utils.js +4 -5
- package/enums.d.ts +8 -1
- package/index.d.ts +1 -1
- package/metadata/EntitySchema.js +18 -0
- package/metadata/MetadataDiscovery.d.ts +1 -0
- package/metadata/MetadataDiscovery.js +79 -15
- package/metadata/MetadataValidator.d.ts +26 -0
- package/metadata/MetadataValidator.js +228 -1
- package/metadata/Routine.d.ts +74 -0
- package/metadata/Routine.js +140 -0
- package/metadata/index.d.ts +1 -0
- package/metadata/index.js +1 -0
- package/metadata/types.d.ts +75 -8
- package/package.json +1 -1
- package/platforms/Platform.d.ts +13 -3
- package/platforms/Platform.js +51 -6
- package/serialization/EntitySerializer.js +4 -3
- package/typings.d.ts +323 -21
- package/typings.js +32 -12
- package/unit-of-work/UnitOfWork.js +43 -5
- package/utils/AbstractMigrator.d.ts +9 -4
- package/utils/AbstractMigrator.js +60 -28
- package/utils/AbstractSchemaGenerator.d.ts +1 -1
- package/utils/AbstractSchemaGenerator.js +4 -1
- package/utils/Configuration.d.ts +30 -0
- package/utils/Configuration.js +45 -0
- package/utils/EntityComparator.js +1 -1
- package/utils/TransactionManager.js +2 -0
- package/utils/Utils.js +1 -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/utils/upsert-utils.d.ts +2 -0
- package/utils/upsert-utils.js +26 -1
package/typings.d.ts
CHANGED
|
@@ -10,8 +10,9 @@ import { Reference, type ScalarReference } from './entity/Reference.js';
|
|
|
10
10
|
import type { SerializationContext } from './serialization/SerializationContext.js';
|
|
11
11
|
import type { SerializeOptions } from './serialization/EntitySerializer.js';
|
|
12
12
|
import type { MetadataStorage } from './metadata/MetadataStorage.js';
|
|
13
|
+
import type { Routine } from './metadata/Routine.js';
|
|
13
14
|
import type { EntitySchema } from './metadata/EntitySchema.js';
|
|
14
|
-
import type { IndexColumnOptions } from './metadata/types.js';
|
|
15
|
+
import type { EntityPartitionBy, IndexColumnOptions } from './metadata/types.js';
|
|
15
16
|
import type { Type, types } from './types/index.js';
|
|
16
17
|
import type { Platform } from './platforms/Platform.js';
|
|
17
18
|
import type { Configuration } from './utils/Configuration.js';
|
|
@@ -113,7 +114,7 @@ type LoadedReferenceShape<T = any> = ReferenceShape & {
|
|
|
113
114
|
* Using this instead of `Loadable<any>` in conditional type checks prevents
|
|
114
115
|
* TypeScript from evaluating the full Collection/Reference interfaces.
|
|
115
116
|
*/
|
|
116
|
-
type LoadableShape = CollectionShape | ReferenceShape | readonly any[];
|
|
117
|
+
type LoadableShape = CollectionShape | ReferenceShape | LazyRef.Brand<any> | readonly any[];
|
|
117
118
|
/** Gets all keys from all members of a union type (distributes over the union). */
|
|
118
119
|
export type UnionKeys<T> = T extends any ? keyof T : never;
|
|
119
120
|
/** Gets the type of a property from all union members that have it (distributes over the union). */
|
|
@@ -467,12 +468,12 @@ type NonArrayObject = object & {
|
|
|
467
468
|
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 {
|
|
468
469
|
__runtime?: infer Runtime;
|
|
469
470
|
__raw?: infer Raw;
|
|
470
|
-
} ? 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>;
|
|
471
|
+
} ? 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>;
|
|
471
472
|
/** Like `EntityDataProp` but used in `RequiredEntityData` context with required/optional key distinction. */
|
|
472
473
|
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 {
|
|
473
474
|
__runtime?: infer Runtime;
|
|
474
475
|
__raw?: infer Raw;
|
|
475
|
-
} ? 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>;
|
|
476
|
+
} ? 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>;
|
|
476
477
|
/** Nested entity data shape for embedded or related entities within `EntityData`. */
|
|
477
478
|
export type EntityDataNested<T, C extends boolean = false> = T extends undefined ? never : T extends any[] ? Readonly<T> : EntityData<T, C> | ExpandEntityProp<T, C>;
|
|
478
479
|
type UnwrapScalarRef<T> = T extends ScalarReference<infer U> ? U : T;
|
|
@@ -521,6 +522,35 @@ type Relation<T> = {
|
|
|
521
522
|
export type Rel<T> = T;
|
|
522
523
|
/** Alias for `ScalarReference` (see {@apilink Ref}). */
|
|
523
524
|
export type ScalarRef<T> = ScalarReference<T>;
|
|
525
|
+
/**
|
|
526
|
+
* Type-level marker for a to-one relation that is **direct at runtime** (no `Reference` wrapper) but
|
|
527
|
+
* **restricted at compile time** until narrowed via `Loaded<>`.
|
|
528
|
+
*
|
|
529
|
+
* Use as the property type on a `@ManyToOne`/`@OneToOne` relation that does **not** have `ref: true`:
|
|
530
|
+
*
|
|
531
|
+
* ```ts
|
|
532
|
+
* @ManyToOne(() => User)
|
|
533
|
+
* author!: LazyRef<User>;
|
|
534
|
+
* ```
|
|
535
|
+
*
|
|
536
|
+
* Semantics:
|
|
537
|
+
* - **Runtime**: identical to a plain direct relation — `article.author` is a `User` instance (stub or hydrated),
|
|
538
|
+
* `article.author instanceof User` is `true`, no `Reference` object is created.
|
|
539
|
+
* - **Type (unloaded view)**: only the primary key is accessible. Accessing other properties is a compile error.
|
|
540
|
+
* - **Type (loaded view)**: once the relation is in the populate hint of a `Loaded<Entity, 'author'>`, it narrows
|
|
541
|
+
* back to the full entity — no `.$` or `.get()` indirection needed.
|
|
542
|
+
*
|
|
543
|
+
* Note: the safety is purely compile-time. JS code or `as any` casts bypass it.
|
|
544
|
+
*/
|
|
545
|
+
export type LazyRef<T extends object> = IsAny<T> extends true ? LazyRef.Brand<T> : {
|
|
546
|
+
[K in PrimaryProperty<T> & keyof T]: T[K];
|
|
547
|
+
} & LazyRef.Brand<T>;
|
|
548
|
+
export declare namespace LazyRef {
|
|
549
|
+
const __lazyRef: unique symbol;
|
|
550
|
+
interface Brand<T> {
|
|
551
|
+
[__lazyRef]?: (arg: T) => T;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
524
554
|
/** Alias for `Reference<T> & { id: number }` (see {@apilink Ref}). */
|
|
525
555
|
export type EntityRef<T extends object> = true extends IsUnknown<PrimaryProperty<T>> ? Reference<T> : IsAny<T> extends true ? Reference<T> : {
|
|
526
556
|
[K in PrimaryProperty<T> & keyof T]: T[K];
|
|
@@ -644,21 +674,39 @@ export type SchemaTable = {
|
|
|
644
674
|
export type FormulaColumns<T> = Record<PropertyName<T>, string> & {
|
|
645
675
|
toString(): string;
|
|
646
676
|
};
|
|
677
|
+
/**
|
|
678
|
+
* Column reference for schema callbacks. Behaves like a string (coercible via `toString()`),
|
|
679
|
+
* with arbitrary nested property access for embedded sub-columns (e.g. `cols.address.city`).
|
|
680
|
+
*/
|
|
681
|
+
export type SchemaColumnRef = string & {
|
|
682
|
+
readonly [key: string]: SchemaColumnRef;
|
|
683
|
+
};
|
|
647
684
|
/**
|
|
648
685
|
* Column mapping for schema callbacks (indexes, checks, generated columns).
|
|
649
686
|
* Maps property names to field names. For TPT entities, only includes properties
|
|
650
687
|
* that belong to the current table (not inherited properties from parent tables).
|
|
688
|
+
* Embedded properties expose their sub-columns via nested access (e.g. `cols.address.city`),
|
|
689
|
+
* while coercing to the embedded property's own column name via `toString()` (matches the
|
|
690
|
+
* pre-7712 behaviour, regardless of any custom `prefix`).
|
|
691
|
+
*/
|
|
692
|
+
export type SchemaColumns<T> = Record<PropertyName<T>, SchemaColumnRef>;
|
|
693
|
+
/**
|
|
694
|
+
* Callback for custom index expressions. Receives column mappings, table info, and the index name.
|
|
695
|
+
* The runtime `columns` object includes nested entries for embedded properties (see `SchemaColumnRef`);
|
|
696
|
+
* cast to `SchemaColumns<T>` if you need typed nested access.
|
|
651
697
|
*/
|
|
652
|
-
export type SchemaColumns<T> = Record<PropertyName<T>, string>;
|
|
653
|
-
/** Callback for custom index expressions. Receives column mappings, table info, and the index name. */
|
|
654
698
|
export type IndexCallback<T> = (columns: Record<PropertyName<T>, string>, table: SchemaTable, indexName: string) => string | Raw;
|
|
655
699
|
/** Callback for computed (formula) properties. Receives column mappings and table info, returns a SQL expression. */
|
|
656
700
|
export type FormulaCallback<T> = (columns: FormulaColumns<T>, table: FormulaTable) => string | Raw;
|
|
657
701
|
/** Callback for CHECK constraint expressions. Receives column mappings and table info. */
|
|
658
|
-
export type CheckCallback<T> = (columns:
|
|
702
|
+
export type CheckCallback<T> = (columns: SchemaColumns<T>, table: SchemaTable) => string | Raw;
|
|
659
703
|
/** Callback for trigger body expressions. Receives column mappings and table info. */
|
|
660
704
|
export type TriggerCallback<T> = (columns: Record<PropertyName<T>, string>, table: SchemaTable) => string | Raw;
|
|
661
|
-
/**
|
|
705
|
+
/**
|
|
706
|
+
* Callback for generated (computed) column expressions. Receives column mappings and table info.
|
|
707
|
+
* The runtime `columns` object includes nested entries for embedded properties (see `SchemaColumnRef`);
|
|
708
|
+
* cast to `SchemaColumns<T>` if you need typed nested access.
|
|
709
|
+
*/
|
|
662
710
|
export type GeneratedColumnCallback<T> = (columns: Record<PropertyName<T>, string>, table: SchemaTable) => string | Raw;
|
|
663
711
|
/** Definition of a CHECK constraint on a table or property. */
|
|
664
712
|
export interface CheckConstraint<T = any> {
|
|
@@ -683,6 +731,197 @@ export interface TriggerDef<T = any> {
|
|
|
683
731
|
/** Raw DDL escape hatch — full CREATE TRIGGER statement. Mutually exclusive with `body`. */
|
|
684
732
|
expression?: string;
|
|
685
733
|
}
|
|
734
|
+
export type RoutineParamDirection = 'in' | 'out' | 'inout';
|
|
735
|
+
/** Mirrors MySQL/MariaDB's `SQL DATA ACCESS` clause; ignored by other dialects. */
|
|
736
|
+
export type RoutineDataAccess = 'contains-sql' | 'no-sql' | 'reads-sql-data' | 'modifies-sql-data';
|
|
737
|
+
export type RoutineSecurity = 'invoker' | 'definer';
|
|
738
|
+
export type RoutineKind = 'procedure' | 'function';
|
|
739
|
+
export type RoutineIgnoreField = 'body' | 'comment' | 'security' | 'deterministic' | 'definer';
|
|
740
|
+
export type RoutineParamMap<T> = Record<PropertyName<T>, string>;
|
|
741
|
+
export type RoutineBodyCallback<T> = (params: RoutineParamMap<T>, em: any) => string | Raw;
|
|
742
|
+
/**
|
|
743
|
+
* Routine return shape:
|
|
744
|
+
* - omitted/`void`: procedures with no result set
|
|
745
|
+
* - `() => Entity` (single or tuple): hydrated row arrays, one per result set
|
|
746
|
+
* - `{ type: Type<...> }`: scalar function return — runtime/column types both inferred
|
|
747
|
+
* from the {@link Type} generics
|
|
748
|
+
* - `{ runtimeType, columnType }`: scalar function return with explicit SQL+TS types
|
|
749
|
+
* - `{ hydrate }`: fully custom row mapping
|
|
750
|
+
*/
|
|
751
|
+
export type RoutineReturns<T = unknown> = (() => EntityName<any>) | (() => EntityName<any>)[] | {
|
|
752
|
+
type: Type<unknown> | Constructor<Type<unknown>>;
|
|
753
|
+
nullable?: boolean;
|
|
754
|
+
} | {
|
|
755
|
+
runtimeType: RoutineRuntimeType;
|
|
756
|
+
columnType?: string;
|
|
757
|
+
nullable?: boolean;
|
|
758
|
+
customType?: Type<unknown> | Constructor<Type<unknown>>;
|
|
759
|
+
} | {
|
|
760
|
+
hydrate: (rows: Dictionary[][], args: T, em: any) => unknown;
|
|
761
|
+
};
|
|
762
|
+
/** JS fallback registered as a UDF on SQLite (better-sqlite3). Functions only. */
|
|
763
|
+
export type RoutineJsBody<T> = (params: T) => unknown;
|
|
764
|
+
export interface RoutineDef<T = any> {
|
|
765
|
+
type: RoutineKind;
|
|
766
|
+
name?: string;
|
|
767
|
+
schema?: string;
|
|
768
|
+
comment?: string;
|
|
769
|
+
security?: RoutineSecurity;
|
|
770
|
+
/** User the routine runs as when `security: 'definer'`. */
|
|
771
|
+
definer?: string;
|
|
772
|
+
deterministic?: boolean;
|
|
773
|
+
/** MySQL/MariaDB only. */
|
|
774
|
+
dataAccess?: RoutineDataAccess;
|
|
775
|
+
language?: 'sql' | 'plpgsql' | 'tsql' | 'plsql' | AnyString;
|
|
776
|
+
/** Mutually exclusive with `expression`. */
|
|
777
|
+
body?: string | Raw | RoutineBodyCallback<T>;
|
|
778
|
+
/** Raw `CREATE PROCEDURE`/`FUNCTION` escape hatch — schema diff can't detect changes. Prefer `body`. */
|
|
779
|
+
expression?: string;
|
|
780
|
+
/** JS fallback registered as a UDF on SQLite (better-sqlite3). Functions only. */
|
|
781
|
+
bodyJs?: RoutineJsBody<T>;
|
|
782
|
+
returns?: RoutineReturns<T>;
|
|
783
|
+
/** Skip selected fields in schema diff; useful when the engine normalises the body differently. */
|
|
784
|
+
ignoreSchemaChanges?: RoutineIgnoreField[];
|
|
785
|
+
}
|
|
786
|
+
export interface RoutineProperty<Owner = any> {
|
|
787
|
+
name: EntityKey<Owner>;
|
|
788
|
+
/** SQL string, or a `Type` instance (resolved to the dialect column type at schema-gen time via `getColumnType`). */
|
|
789
|
+
type: keyof typeof types | AnyString | Type<unknown>;
|
|
790
|
+
runtimeType: EntityProperty['runtimeType'];
|
|
791
|
+
/** Singleton array to align with EntityProperty's `columnTypes`/Type API surface. */
|
|
792
|
+
columnTypes: string[];
|
|
793
|
+
customType?: Type<unknown>;
|
|
794
|
+
direction: RoutineParamDirection;
|
|
795
|
+
/** Required for OUT/INOUT params — wraps the JS-side value in `ScalarReference`. */
|
|
796
|
+
ref?: boolean;
|
|
797
|
+
length?: number;
|
|
798
|
+
precision?: number;
|
|
799
|
+
scale?: number;
|
|
800
|
+
nullable?: boolean;
|
|
801
|
+
/** Default expression used when the caller omits the parameter, where the dialect supports it. */
|
|
802
|
+
defaultRaw?: string;
|
|
803
|
+
/** Original declaration order, used to rebuild positional argument lists. */
|
|
804
|
+
index: number;
|
|
805
|
+
}
|
|
806
|
+
export interface RoutineParamConfig {
|
|
807
|
+
runtimeType?: RoutineRuntimeType;
|
|
808
|
+
type?: keyof typeof types | AnyString | Type<any> | Constructor<Type<any>>;
|
|
809
|
+
direction?: RoutineParamDirection;
|
|
810
|
+
ref?: boolean;
|
|
811
|
+
length?: number;
|
|
812
|
+
precision?: number;
|
|
813
|
+
scale?: number;
|
|
814
|
+
nullable?: boolean;
|
|
815
|
+
defaultRaw?: string;
|
|
816
|
+
/** Marshals the param via `Type.convertToDatabaseValue` inbound and `convertToJSValue` outbound. */
|
|
817
|
+
customType?: Type<unknown> | Constructor<Type<unknown>>;
|
|
818
|
+
}
|
|
819
|
+
/** Routine declaration shape accepted by the {@link Routine} class. */
|
|
820
|
+
export interface RoutineConfig<T = any> extends Omit<RoutineDef<T>, 'name'> {
|
|
821
|
+
name: string;
|
|
822
|
+
/** Order is preserved from `Object.keys`. */
|
|
823
|
+
params?: Record<string, RoutineParamConfig>;
|
|
824
|
+
}
|
|
825
|
+
export type RoutineRuntimeTypeMap = {
|
|
826
|
+
string: string;
|
|
827
|
+
number: number;
|
|
828
|
+
boolean: boolean;
|
|
829
|
+
bigint: bigint;
|
|
830
|
+
Buffer: Buffer;
|
|
831
|
+
Date: Date;
|
|
832
|
+
object: Dictionary;
|
|
833
|
+
any: any;
|
|
834
|
+
};
|
|
835
|
+
/** Narrow union (vs `EntityProperty['runtimeType']`) so literals survive `const` inference and feed args/return inference. */
|
|
836
|
+
export type RoutineRuntimeType = keyof RoutineRuntimeTypeMap;
|
|
837
|
+
type RoutineRuntimeOf<R> = R extends keyof RoutineRuntimeTypeMap ? RoutineRuntimeTypeMap[R] : unknown;
|
|
838
|
+
type Nullify<P, V> = P extends {
|
|
839
|
+
nullable: true;
|
|
840
|
+
} ? V | null : V;
|
|
841
|
+
type StripSqlTypeArgs<S extends string> = S extends `${infer Base}(${string}` ? Base : S;
|
|
842
|
+
type SqlStringTypes = 'varchar' | 'char' | 'character' | 'nvarchar' | 'nchar' | 'text' | 'mediumtext' | 'longtext' | 'tinytext' | 'ntext' | 'clob' | 'nclob' | 'citext' | 'xml' | 'uuid' | 'string' | 'decimal' | 'numeric' | 'money' | 'bigint' | 'int8' | 'bigserial';
|
|
843
|
+
type SqlNumberTypes = 'int' | 'integer' | 'smallint' | 'tinyint' | 'mediumint' | 'int2' | 'int4' | 'serial' | 'smallserial' | 'real' | 'float' | 'float4' | 'float8' | 'double';
|
|
844
|
+
type SqlBooleanTypes = 'boolean' | 'bool' | 'bit';
|
|
845
|
+
type SqlDateTypes = 'date' | 'datetime' | 'datetime2' | 'smalldatetime' | 'timestamp' | 'timestamptz' | 'time' | 'timetz';
|
|
846
|
+
type SqlJsonTypes = 'json' | 'jsonb';
|
|
847
|
+
type SqlBufferTypes = 'blob' | 'tinyblob' | 'mediumblob' | 'longblob' | 'binary' | 'varbinary' | 'bytea' | 'bytes' | 'image' | 'raw';
|
|
848
|
+
type SqlTypeMap = {
|
|
849
|
+
[K in SqlStringTypes]: string;
|
|
850
|
+
} & {
|
|
851
|
+
[K in SqlNumberTypes]: number;
|
|
852
|
+
} & {
|
|
853
|
+
[K in SqlBooleanTypes]: boolean;
|
|
854
|
+
} & {
|
|
855
|
+
[K in SqlDateTypes]: Date;
|
|
856
|
+
} & {
|
|
857
|
+
[K in SqlJsonTypes]: Dictionary;
|
|
858
|
+
} & {
|
|
859
|
+
[K in SqlBufferTypes]: Buffer;
|
|
860
|
+
} & {
|
|
861
|
+
'character varying': string;
|
|
862
|
+
'double precision': number;
|
|
863
|
+
'time with time zone': Date;
|
|
864
|
+
'timestamp with time zone': Date;
|
|
865
|
+
'long raw': Buffer;
|
|
866
|
+
};
|
|
867
|
+
type LookupSqlType<K> = K extends keyof SqlTypeMap ? SqlTypeMap[K] : any;
|
|
868
|
+
/**
|
|
869
|
+
* Maps a SQL-flavoured `type` string (e.g. `'varchar(255)'`, `'int'`, `'timestamp'`) to a TS
|
|
870
|
+
* runtime type, used as a fallback when {@link RoutineParamConfig} does not declare an explicit
|
|
871
|
+
* `runtimeType`. Length/precision arguments are stripped, the lowercase token is matched
|
|
872
|
+
* against {@link SqlTypeMap}. `decimal`/`numeric`/`money`/`bigint` default to `string` since
|
|
873
|
+
* drivers typically return them as strings to preserve precision; opt in to `number` or
|
|
874
|
+
* `bigint` via `runtimeType` when the value range is safe. Unrecognised or genuinely
|
|
875
|
+
* ambiguous types (`refcursor`, `sys_refcursor`, …) fall through to `any`.
|
|
876
|
+
*/
|
|
877
|
+
export type SqlTypeToTs<S> = S extends string ? Lowercase<S> extends `tinyint(1)${string}` ? boolean : LookupSqlType<StripSqlTypeArgs<Lowercase<S>>> : any;
|
|
878
|
+
/** Strips `null | undefined` from a `Type<JSType, _>` JSType, so e.g. `StringType extends Type<string | null | undefined>` resolves to `string`. */
|
|
879
|
+
type TypeJsType<T> = T extends Type<infer J, any> ? Exclude<J, null | undefined> : T extends new (...args: any[]) => Type<infer J, any> ? Exclude<J, null | undefined> : never;
|
|
880
|
+
/**
|
|
881
|
+
* TS value type for a single routine parameter. Resolution order:
|
|
882
|
+
*
|
|
883
|
+
* 1. explicit `runtimeType`
|
|
884
|
+
* 2. `type` set to a {@link Type} class or instance — JSType is extracted from the Type generic
|
|
885
|
+
* 3. `type` set to a SQL string — mapped via {@link SqlTypeToTs}
|
|
886
|
+
* 4. fallback `any`
|
|
887
|
+
*
|
|
888
|
+
* `ref: true` wraps the result in `ScalarReference`; `nullable: true` adds `| null`.
|
|
889
|
+
*/
|
|
890
|
+
export type RoutineParamValue<P> = P extends {
|
|
891
|
+
runtimeType: infer R;
|
|
892
|
+
} ? P extends {
|
|
893
|
+
ref: true;
|
|
894
|
+
} ? ScalarReference<Nullify<P, RoutineRuntimeOf<R>>> : Nullify<P, RoutineRuntimeOf<R>> : P extends {
|
|
895
|
+
type: infer T;
|
|
896
|
+
} ? [TypeJsType<T>] extends [never] ? T extends string ? P extends {
|
|
897
|
+
ref: true;
|
|
898
|
+
} ? ScalarReference<Nullify<P, SqlTypeToTs<T>>> : Nullify<P, SqlTypeToTs<T>> : P extends {
|
|
899
|
+
ref: true;
|
|
900
|
+
} ? ScalarReference<any> : any : P extends {
|
|
901
|
+
ref: true;
|
|
902
|
+
} ? ScalarReference<Nullify<P, TypeJsType<T>>> : Nullify<P, TypeJsType<T>> : P extends {
|
|
903
|
+
ref: true;
|
|
904
|
+
} ? ScalarReference<any> : any;
|
|
905
|
+
/** Default `TArgs` for {@link Routine}; consumers use {@link RoutineArgs}, which honours overrides from {@link Routine.create}. */
|
|
906
|
+
export type RoutineArgsOf<Config> = Config extends {
|
|
907
|
+
params: infer P;
|
|
908
|
+
} ? P extends Record<string, RoutineParamConfig> ? {
|
|
909
|
+
[K in keyof P]: RoutineParamValue<P[K]>;
|
|
910
|
+
} : Record<string, unknown> : Record<string, unknown>;
|
|
911
|
+
/** Default `TReturn` for {@link Routine}; consumers use {@link RoutineReturn}, which honours overrides from {@link Routine.create}. */
|
|
912
|
+
export type RoutineReturnOf<Config> = Config extends {
|
|
913
|
+
returns: infer R;
|
|
914
|
+
} ? R extends {
|
|
915
|
+
runtimeType: infer RT;
|
|
916
|
+
} ? Nullify<R, RoutineRuntimeOf<RT>> : R extends {
|
|
917
|
+
type: infer T;
|
|
918
|
+
} ? [TypeJsType<T>] extends [never] ? unknown : Nullify<R, TypeJsType<T>> : R extends readonly (() => EntityName<any>)[] ? {
|
|
919
|
+
[K in keyof R]: R[K] extends () => EntityName<infer E> ? E[] : never;
|
|
920
|
+
} : R extends () => EntityName<infer E> ? E[] : R extends {
|
|
921
|
+
hydrate: (...args: any[]) => infer H;
|
|
922
|
+
} ? Awaited<H> : void : void;
|
|
923
|
+
export type RoutineArgs<R> = R extends Routine<any, infer A, any> ? A : Record<string, unknown>;
|
|
924
|
+
export type RoutineReturn<R> = R extends Routine<any, any, infer Re> ? Re : unknown;
|
|
686
925
|
/** Branded string that accepts any string value while preserving autocompletion for known literals. */
|
|
687
926
|
export type AnyString = string & {};
|
|
688
927
|
/** Describes a single property (column, relation, or embedded) within an entity's metadata. */
|
|
@@ -780,11 +1019,12 @@ export interface EntityProperty<Owner = any, Target = any> {
|
|
|
780
1019
|
serializer?: (value: any, options?: SerializeOptions<any>) => any;
|
|
781
1020
|
serializedName?: string;
|
|
782
1021
|
comment?: string;
|
|
1022
|
+
collation?: string;
|
|
783
1023
|
/** mysql only */
|
|
784
1024
|
extra?: string;
|
|
785
1025
|
userDefined?: boolean;
|
|
786
1026
|
optional?: boolean;
|
|
787
|
-
ignoreSchemaChanges?: ('type' | 'extra' | 'default')[];
|
|
1027
|
+
ignoreSchemaChanges?: ('type' | 'extra' | 'default' | 'collation')[];
|
|
788
1028
|
deferMode?: DeferMode;
|
|
789
1029
|
createForeignKeyConstraint: boolean;
|
|
790
1030
|
foreignKeyName?: string;
|
|
@@ -812,8 +1052,12 @@ export declare class EntityMetadata<Entity = any, Class extends EntityCtor<Entit
|
|
|
812
1052
|
/**
|
|
813
1053
|
* Creates a column mapping for schema callbacks (indexes, checks, generated columns).
|
|
814
1054
|
* For TPT entities, only includes properties that belong to the current table (ownProps).
|
|
1055
|
+
* Embedded properties expose their sub-columns via nested access (e.g. `cols.address.city`),
|
|
1056
|
+
* while still coercing to the embedded column prefix when used as a string (GH #7712).
|
|
815
1057
|
*/
|
|
816
1058
|
createSchemaColumnMappingObject(): SchemaColumns<Entity>;
|
|
1059
|
+
/** @internal Recursively builds a column mapping for an embedded property's sub-columns. */
|
|
1060
|
+
private static buildEmbeddedColumnMapping;
|
|
817
1061
|
get tableName(): string;
|
|
818
1062
|
set tableName(name: string);
|
|
819
1063
|
get uniqueName(): string;
|
|
@@ -832,7 +1076,6 @@ export type EntityCtor<T = any> = abstract new (...args: any[]) => T;
|
|
|
832
1076
|
export interface EntityMetadata<Entity = any, Class extends EntityCtor<Entity> = EntityCtor<Entity>> {
|
|
833
1077
|
name?: string;
|
|
834
1078
|
className: string;
|
|
835
|
-
tableName: string;
|
|
836
1079
|
schema?: string;
|
|
837
1080
|
pivotTable?: boolean;
|
|
838
1081
|
virtual?: boolean;
|
|
@@ -845,8 +1088,15 @@ export interface EntityMetadata<Entity = any, Class extends EntityCtor<Entity> =
|
|
|
845
1088
|
materialized?: boolean;
|
|
846
1089
|
/** For materialized views, whether data is populated on creation. Defaults to true. */
|
|
847
1090
|
withData?: boolean;
|
|
1091
|
+
/** PostgreSQL partitioning definition for this table. */
|
|
1092
|
+
partitionBy?: EntityPartitionBy<Entity>;
|
|
848
1093
|
expression?: string | ((em: any, where: ObjectQuery<Entity>, options: FindOptions<Entity, any, any, any>, stream?: boolean) => MaybePromise<Raw | object | string>);
|
|
1094
|
+
/** Property name on the entity that stores the discriminator value. */
|
|
1095
|
+
discriminator?: EntityKey<Entity> | AnyString;
|
|
1096
|
+
/** Internally holds the discriminator property name (legacy) or a column-name override (when different from `discriminator`); normalized in `EntitySchema.init()`. */
|
|
849
1097
|
discriminatorColumn?: EntityKey<Entity> | AnyString;
|
|
1098
|
+
/** Explicit column-name override for the auto-managed discriminator property. Set when both `discriminator` and `discriminatorColumn` are provided and differ. */
|
|
1099
|
+
discriminatorFieldName?: string;
|
|
850
1100
|
discriminatorValue?: number | string;
|
|
851
1101
|
discriminatorMap?: Dictionary<EntityClass>;
|
|
852
1102
|
embeddable: boolean;
|
|
@@ -883,6 +1133,7 @@ export interface EntityMetadata<Entity = any, Class extends EntityCtor<Entity> =
|
|
|
883
1133
|
type?: string;
|
|
884
1134
|
options?: Dictionary;
|
|
885
1135
|
expression?: string | IndexCallback<Entity>;
|
|
1136
|
+
where?: string | FilterQuery<Entity>;
|
|
886
1137
|
columns?: IndexColumnOptions[];
|
|
887
1138
|
include?: EntityKey<Entity> | EntityKey<Entity>[];
|
|
888
1139
|
fillFactor?: number;
|
|
@@ -895,6 +1146,7 @@ export interface EntityMetadata<Entity = any, Class extends EntityCtor<Entity> =
|
|
|
895
1146
|
name?: string;
|
|
896
1147
|
options?: Dictionary;
|
|
897
1148
|
expression?: string | IndexCallback<Entity>;
|
|
1149
|
+
where?: string | FilterQuery<Entity>;
|
|
898
1150
|
deferMode?: DeferMode | `${DeferMode}`;
|
|
899
1151
|
columns?: IndexColumnOptions[];
|
|
900
1152
|
include?: EntityKey<Entity> | EntityKey<Entity>[];
|
|
@@ -923,6 +1175,8 @@ export interface EntityMetadata<Entity = any, Class extends EntityCtor<Entity> =
|
|
|
923
1175
|
polymorphicDiscriminatorMap?: Dictionary<EntityClass>;
|
|
924
1176
|
/** Inheritance type: 'sti' (Single Table Inheritance) or 'tpt' (Table-Per-Type). Only set on root entities. */
|
|
925
1177
|
inheritanceType?: 'sti' | 'tpt';
|
|
1178
|
+
/** Legacy alias populated from `EntityOptions.inheritance`; mirrored to `inheritanceType` during discovery. */
|
|
1179
|
+
inheritance?: 'tpt';
|
|
926
1180
|
/** For TPT: direct parent entity metadata (the entity this one extends). */
|
|
927
1181
|
tptParent?: EntityMetadata;
|
|
928
1182
|
/** For TPT: direct child entities (entities that extend this one). */
|
|
@@ -950,6 +1204,11 @@ export interface EntityMetadata<Entity = any, Class extends EntityCtor<Entity> =
|
|
|
950
1204
|
export interface CreateSchemaOptions {
|
|
951
1205
|
wrap?: boolean;
|
|
952
1206
|
schema?: string;
|
|
1207
|
+
/**
|
|
1208
|
+
* When true, entities with a wildcard schema (`schema: '*'`) are included in the generated DDL.
|
|
1209
|
+
* Without this, wildcard tables are skipped.
|
|
1210
|
+
*/
|
|
1211
|
+
includeWildcardSchema?: boolean;
|
|
953
1212
|
}
|
|
954
1213
|
/** Options for `ISchemaGenerator.clear()` to truncate/clear database tables. */
|
|
955
1214
|
export interface ClearDatabaseOptions {
|
|
@@ -979,6 +1238,13 @@ export interface UpdateSchemaOptions<DatabaseSchema = unknown> {
|
|
|
979
1238
|
dropTables?: boolean;
|
|
980
1239
|
schema?: string;
|
|
981
1240
|
fromSchema?: DatabaseSchema;
|
|
1241
|
+
/**
|
|
1242
|
+
* When true, entities with a wildcard schema (`schema: '*'`) are included in the diff so migrations
|
|
1243
|
+
* can be generated for them. The emitted SQL is unqualified — and therefore safe to apply against
|
|
1244
|
+
* any schema at runtime — only when neither `options.schema` nor `config.schema` is set; otherwise
|
|
1245
|
+
* wildcard tables inherit that schema qualifier.
|
|
1246
|
+
*/
|
|
1247
|
+
includeWildcardSchema?: boolean;
|
|
982
1248
|
}
|
|
983
1249
|
/** Options for `ISchemaGenerator.refresh()` which drops and recreates the schema. */
|
|
984
1250
|
export interface RefreshDatabaseOptions extends CreateSchemaOptions {
|
|
@@ -1059,6 +1325,12 @@ export type MigrateOptions = {
|
|
|
1059
1325
|
to?: string | number;
|
|
1060
1326
|
migrations?: string[];
|
|
1061
1327
|
transaction?: Transaction;
|
|
1328
|
+
/**
|
|
1329
|
+
* Target schema to run migrations against. Issues a driver-specific "set current schema"
|
|
1330
|
+
* statement (e.g. `SET search_path` on PostgreSQL) before each migration, and places the
|
|
1331
|
+
* tracking table in this schema. Overrides `migrations.schema` from config. Not supported on MSSQL.
|
|
1332
|
+
*/
|
|
1333
|
+
schema?: string;
|
|
1062
1334
|
};
|
|
1063
1335
|
/** Result of creating a new migration file, including the generated code and schema diff. */
|
|
1064
1336
|
export type MigrationResult = {
|
|
@@ -1076,21 +1348,25 @@ export type MigrationRow = {
|
|
|
1076
1348
|
* @internal
|
|
1077
1349
|
*/
|
|
1078
1350
|
export interface IMigrationRunner {
|
|
1079
|
-
run(migration: Migration, method: 'up' | 'down'): Promise<void>;
|
|
1351
|
+
run(migration: Migration, method: 'up' | 'down', afterRun?: (tx?: Transaction) => Promise<void>): Promise<void>;
|
|
1080
1352
|
setMasterMigration(trx: Transaction): void;
|
|
1081
1353
|
unsetMasterMigration(): void;
|
|
1354
|
+
setRunSchema?(schema?: string): void;
|
|
1355
|
+
unsetRunSchema?(): void;
|
|
1082
1356
|
}
|
|
1083
1357
|
/**
|
|
1084
1358
|
* @internal
|
|
1085
1359
|
*/
|
|
1086
1360
|
export interface IMigratorStorage {
|
|
1087
1361
|
executed(): Promise<string[]>;
|
|
1088
|
-
logMigration(params: Dictionary): Promise<void>;
|
|
1089
|
-
unlogMigration(params: Dictionary): Promise<void>;
|
|
1362
|
+
logMigration(params: Dictionary, tx?: Transaction): Promise<void>;
|
|
1363
|
+
unlogMigration(params: Dictionary, tx?: Transaction): Promise<void>;
|
|
1090
1364
|
getExecutedMigrations(): Promise<MigrationRow[]>;
|
|
1091
1365
|
ensureTable?(): Promise<void>;
|
|
1092
1366
|
setMasterMigration(trx: Transaction): void;
|
|
1093
1367
|
unsetMasterMigration(): void;
|
|
1368
|
+
setRunSchema?(schema?: string): void;
|
|
1369
|
+
unsetRunSchema?(): void;
|
|
1094
1370
|
getMigrationName(name: string): string;
|
|
1095
1371
|
getTableName?(): {
|
|
1096
1372
|
schemaName?: string;
|
|
@@ -1117,11 +1393,15 @@ export interface IMigrator {
|
|
|
1117
1393
|
/**
|
|
1118
1394
|
* Returns list of already executed migrations.
|
|
1119
1395
|
*/
|
|
1120
|
-
getExecuted(
|
|
1396
|
+
getExecuted(options?: {
|
|
1397
|
+
schema?: string;
|
|
1398
|
+
}): Promise<MigrationRow[]>;
|
|
1121
1399
|
/**
|
|
1122
1400
|
* Returns list of pending (not yet executed) migrations found in the migration directory.
|
|
1123
1401
|
*/
|
|
1124
|
-
getPending(
|
|
1402
|
+
getPending(options?: {
|
|
1403
|
+
schema?: string;
|
|
1404
|
+
}): Promise<MigrationInfo[]>;
|
|
1125
1405
|
/**
|
|
1126
1406
|
* Executes specified migrations. Without parameter it will migrate up to the latest version.
|
|
1127
1407
|
*/
|
|
@@ -1217,13 +1497,32 @@ export type PopulateOptions<T> = {
|
|
|
1217
1497
|
children?: PopulateOptions<T[keyof T]>[];
|
|
1218
1498
|
/** When true, ignores `mapToPk` on the property and returns full entity data instead of just PKs. */
|
|
1219
1499
|
dataOnly?: boolean;
|
|
1500
|
+
/** Limit the number of items loaded per parent entity. Collections will be marked as partial and readonly. */
|
|
1501
|
+
limit?: number;
|
|
1502
|
+
/** Offset for per-parent limiting (used with `limit`). */
|
|
1503
|
+
offset?: number;
|
|
1504
|
+
/** Order by clause for per-parent limiting. Takes precedence over nested `FindOptions.orderBy`. */
|
|
1505
|
+
orderBy?: QueryOrderMap<T[keyof T]>;
|
|
1220
1506
|
};
|
|
1221
1507
|
/** Inline options that can be appended to populate hint strings (e.g., strategy, join type). */
|
|
1222
1508
|
export type PopulateHintOptions = {
|
|
1223
1509
|
strategy?: LoadStrategy.JOINED | LoadStrategy.SELECT_IN | 'joined' | 'select-in';
|
|
1224
1510
|
joinType?: 'inner join' | 'left join';
|
|
1511
|
+
/** Limit the number of items loaded per parent entity. Collections will be marked as partial and readonly. */
|
|
1512
|
+
limit?: number;
|
|
1513
|
+
/** Offset for per-parent limiting (used with `limit`). */
|
|
1514
|
+
offset?: number;
|
|
1515
|
+
/** Order by clause for per-parent limiting. Takes precedence over nested `FindOptions.orderBy`. */
|
|
1516
|
+
orderBy?: QueryOrderMap<any>;
|
|
1225
1517
|
};
|
|
1226
1518
|
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;
|
|
1519
|
+
/**
|
|
1520
|
+
* Like {@link ExtractType} but also unwraps {@link LazyRef}. Kept separate so {@link ExtractType}'s
|
|
1521
|
+
* hot path (used by `IsOptional`, `EntityData`, `RequiredEntityData`) doesn't pay the cost of the
|
|
1522
|
+
* extra branch — those contexts handle `LazyRef` in their own earlier branches (see
|
|
1523
|
+
* `EntityDataProp` / `RequiredEntityDataProp`) before delegating to `ExtractType`.
|
|
1524
|
+
*/
|
|
1525
|
+
type ExtractTypeWithLazyRef<T> = T extends LazyRef.Brand<infer U> ? U : ExtractType<T>;
|
|
1227
1526
|
type ExtractStringKeys<T> = {
|
|
1228
1527
|
[K in keyof T]-?: CleanKeys<T, K>;
|
|
1229
1528
|
}[keyof T] & {};
|
|
@@ -1231,8 +1530,8 @@ type ExtractStringKeys<T> = {
|
|
|
1231
1530
|
* Extracts string keys from an entity type, handling Collection/Reference wrappers.
|
|
1232
1531
|
* Simplified to just check `T extends object` since ExtractType handles the unwrapping.
|
|
1233
1532
|
*/
|
|
1234
|
-
type StringKeys<T, E extends string = never> = T extends object ? ExtractStringKeys<
|
|
1235
|
-
type GetStringKey<T, K extends StringKeys<T, string>, E extends string> = K extends keyof T ?
|
|
1533
|
+
type StringKeys<T, E extends string = never> = T extends object ? ExtractStringKeys<ExtractTypeWithLazyRef<T>> | E : never;
|
|
1534
|
+
type GetStringKey<T, K extends StringKeys<T, string>, E extends string> = K extends keyof T ? ExtractTypeWithLazyRef<T[K]> : K extends E ? keyof T : never;
|
|
1236
1535
|
type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
1237
1536
|
type RelationKeys<T> = T extends object ? {
|
|
1238
1537
|
[K in keyof T]-?: CleanKeys<T, K, true>;
|
|
@@ -1247,8 +1546,8 @@ export type UnboxArray<T> = T extends any[] ? ArrayElement<T> : T;
|
|
|
1247
1546
|
/** Extracts the element type from an array type. */
|
|
1248
1547
|
export type ArrayElement<ArrayType extends unknown[]> = ArrayType extends (infer ElementType)[] ? ElementType : never;
|
|
1249
1548
|
/** Unwraps a property type from its wrapper (Reference, Collection, or array) to the inner entity type. */
|
|
1250
|
-
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>;
|
|
1251
|
-
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;
|
|
1549
|
+
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>;
|
|
1550
|
+
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;
|
|
1252
1551
|
type IsTrue<T> = IsNever<T> extends true ? false : T extends boolean ? (T extends true ? true : false) : false;
|
|
1253
1552
|
type StringLiteral<T> = T extends string ? (string extends T ? never : T) : never;
|
|
1254
1553
|
type Prefix<T, K> = K extends `${infer S}.${string}` ? S : K extends '*' ? keyof T : K;
|
|
@@ -1282,7 +1581,7 @@ export type MergeSelected<T, U, F extends string> = IsLoadedType<T> extends true
|
|
|
1282
1581
|
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>;
|
|
1283
1582
|
/** Extracts the nullability modifiers (`null`, `undefined`, or both) from a type `T`. */
|
|
1284
1583
|
export type AddOptional<T> = undefined | null extends T ? null | undefined : null extends T ? null : undefined extends T ? undefined : never;
|
|
1285
|
-
type LoadedProp<T, L extends string = never, F extends string = '*', E extends string = never> = LoadedLoadable<T, Loaded<
|
|
1584
|
+
type LoadedProp<T, L extends string = never, F extends string = '*', E extends string = never> = LoadedLoadable<T, Loaded<ExtractTypeWithLazyRef<T>, L, F, E>>;
|
|
1286
1585
|
/** Extracts the eager-loaded property names declared via `[EagerProps]` as a string union. */
|
|
1287
1586
|
export type AddEager<T> = ExtractEagerProps<T> & string;
|
|
1288
1587
|
/** Combines an explicit populate hint `L` with the entity's eagerly loaded properties. */
|
|
@@ -1397,15 +1696,18 @@ export type MaybeReturnType<T> = T extends (...args: any[]) => infer R ? R : T;
|
|
|
1397
1696
|
* Extended `EntitySchema` interface that carries additional type-level metadata (entity name, properties, table name).
|
|
1398
1697
|
* Returned by `defineEntity()` to provide strong type inference without explicit generics.
|
|
1399
1698
|
*/
|
|
1400
|
-
export interface EntitySchemaWithMeta<TName extends string = string, TTableName extends string = string, TEntity = any, TBase = never, TProperties extends Record<string, any> = Record<string, any>, TClass extends EntityCtor = EntityCtor<TEntity
|
|
1699
|
+
export interface EntitySchemaWithMeta<TName extends string = string, TTableName extends string = string, TEntity = any, TBase = never, TProperties extends Record<string, any> = Record<string, any>, TClass extends EntityCtor = EntityCtor<TEntity>, TDiscriminatorColumn extends string | undefined = undefined> extends EntitySchema<TEntity, TBase, TClass> {
|
|
1401
1700
|
readonly name: TName;
|
|
1402
1701
|
readonly properties: TProperties;
|
|
1403
1702
|
readonly tableName: TTableName;
|
|
1404
1703
|
/** @internal Direct entity type access - avoids expensive pattern matching */
|
|
1405
1704
|
readonly '~entity': TEntity;
|
|
1705
|
+
/** @internal Type-level marker carrying the discriminator column name, used by `defineEntity()` to narrow inherited discriminator properties to the literal `discriminatorValue` of each child schema. */
|
|
1706
|
+
readonly '~discriminatorColumn'?: TDiscriminatorColumn;
|
|
1406
1707
|
/** @internal */
|
|
1407
1708
|
readonly class: TClass & {
|
|
1408
1709
|
'~entityName'?: TName;
|
|
1710
|
+
'~discriminatorColumn'?: TDiscriminatorColumn;
|
|
1409
1711
|
};
|
|
1410
1712
|
}
|
|
1411
1713
|
/**
|
package/typings.js
CHANGED
|
@@ -133,16 +133,37 @@ export class EntityMetadata {
|
|
|
133
133
|
/**
|
|
134
134
|
* Creates a column mapping for schema callbacks (indexes, checks, generated columns).
|
|
135
135
|
* For TPT entities, only includes properties that belong to the current table (ownProps).
|
|
136
|
+
* Embedded properties expose their sub-columns via nested access (e.g. `cols.address.city`),
|
|
137
|
+
* while still coercing to the embedded column prefix when used as a string (GH #7712).
|
|
136
138
|
*/
|
|
137
139
|
createSchemaColumnMappingObject() {
|
|
138
140
|
// For TPT entities, only include properties that belong to this entity's table
|
|
139
141
|
const props = this.inheritanceType === 'tpt' && this.ownProps ? this.ownProps : Object.values(this.properties);
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
142
|
+
const result = {};
|
|
143
|
+
for (const prop of props) {
|
|
144
|
+
if (!prop.fieldNames) {
|
|
145
|
+
continue;
|
|
143
146
|
}
|
|
144
|
-
|
|
145
|
-
|
|
147
|
+
if (prop.kind === ReferenceKind.EMBEDDED && prop.embeddedProps) {
|
|
148
|
+
result[prop.name] = EntityMetadata.buildEmbeddedColumnMapping(prop);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
result[prop.name] = prop.fieldNames[0];
|
|
152
|
+
}
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
/** @internal Recursively builds a column mapping for an embedded property's sub-columns. */
|
|
156
|
+
static buildEmbeddedColumnMapping(embeddedProp) {
|
|
157
|
+
const result = {};
|
|
158
|
+
for (const [name, sub] of Object.entries(embeddedProp.embeddedProps)) {
|
|
159
|
+
result[name] =
|
|
160
|
+
sub.kind === ReferenceKind.EMBEDDED && sub.embeddedProps
|
|
161
|
+
? EntityMetadata.buildEmbeddedColumnMapping(sub)
|
|
162
|
+
: sub.fieldNames[0];
|
|
163
|
+
}
|
|
164
|
+
const prefix = embeddedProp.fieldNames[0];
|
|
165
|
+
Object.defineProperty(result, 'toString', { value: () => prefix, enumerable: false });
|
|
166
|
+
return result;
|
|
146
167
|
}
|
|
147
168
|
get tableName() {
|
|
148
169
|
return this.collection;
|
|
@@ -166,7 +187,7 @@ export class EntityMetadata {
|
|
|
166
187
|
if (prop.inherited || (prop.persist === false && prop.userDefined !== false)) {
|
|
167
188
|
return false;
|
|
168
189
|
}
|
|
169
|
-
return prop.kind === ReferenceKind.SCALAR && ['string', 'number', 'boolean', 'Date'].includes(prop.type);
|
|
190
|
+
return (prop.kind === ReferenceKind.SCALAR && !prop.array && ['string', 'number', 'boolean', 'Date'].includes(prop.type));
|
|
170
191
|
});
|
|
171
192
|
this.hydrateProps = this.props.filter(prop => {
|
|
172
193
|
// `prop.userDefined` is either `undefined` or `false`
|
|
@@ -193,9 +214,10 @@ export class EntityMetadata {
|
|
|
193
214
|
// Virtual entities evaluate expressions at query time, view entities create actual database views.
|
|
194
215
|
this.virtual = !!this.expression && !this.view;
|
|
195
216
|
if (config) {
|
|
217
|
+
const platform = config.getPlatform();
|
|
196
218
|
for (const prop of this.props) {
|
|
197
219
|
if (prop.enum && !prop.nativeEnumName && prop.items?.every(item => typeof item === 'string')) {
|
|
198
|
-
const name =
|
|
220
|
+
const name = platform.getIndexName(this.tableName, prop.fieldNames, 'check');
|
|
199
221
|
const exists = this.checks.findIndex(check => check.name === name);
|
|
200
222
|
if (exists !== -1) {
|
|
201
223
|
this.checks.splice(exists, 1);
|
|
@@ -203,9 +225,7 @@ export class EntityMetadata {
|
|
|
203
225
|
this.checks.push({
|
|
204
226
|
name,
|
|
205
227
|
property: prop.name,
|
|
206
|
-
expression:
|
|
207
|
-
.getPlatform()
|
|
208
|
-
.getEnumCheckConstraintExpression(prop.fieldNames[0], prop.items),
|
|
228
|
+
expression: platform.getEnumCheckConstraintExpression(prop.fieldNames[0], prop.items),
|
|
209
229
|
});
|
|
210
230
|
}
|
|
211
231
|
}
|
|
@@ -261,8 +281,8 @@ export class EntityMetadata {
|
|
|
261
281
|
}, { __gettersDefined: { value: true, enumerable: false } });
|
|
262
282
|
}
|
|
263
283
|
initIndexes(prop) {
|
|
264
|
-
const simpleIndex = this.indexes.find(index => index.properties === prop.name && !index.options && !index.type && !index.expression);
|
|
265
|
-
const simpleUnique = this.uniques.find(index => index.properties === prop.name && !index.options);
|
|
284
|
+
const simpleIndex = this.indexes.find(index => index.properties === prop.name && !index.options && !index.type && !index.expression && index.where == null);
|
|
285
|
+
const simpleUnique = this.uniques.find(index => index.properties === prop.name && !index.options && !index.expression && index.where == null);
|
|
266
286
|
const owner = prop.kind === ReferenceKind.MANY_TO_ONE;
|
|
267
287
|
if (!prop.index && simpleIndex) {
|
|
268
288
|
Utils.defaultValue(simpleIndex, 'name', true);
|