@mikro-orm/core 7.0.0-dev.215 → 7.0.0-dev.217

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.
@@ -7,7 +7,7 @@ import { EntityLoader, type EntityLoaderOptions } from './entity/EntityLoader.js
7
7
  import { Reference } from './entity/Reference.js';
8
8
  import { UnitOfWork } from './unit-of-work/UnitOfWork.js';
9
9
  import type { CountOptions, DeleteOptions, FilterOptions, FindAllOptions, FindByCursorOptions, FindOneOptions, FindOneOrFailOptions, FindOptions, GetReferenceOptions, IDatabaseDriver, LockOptions, NativeInsertUpdateOptions, StreamOptions, UpdateOptions, UpsertManyOptions, UpsertOptions } from './drivers/IDatabaseDriver.js';
10
- import type { AnyString, ArrayElement, AutoPath, ConnectionType, Dictionary, EntityClass, EntityData, EntityDictionary, EntityDTO, EntityMetadata, EntityName, FilterDef, FilterQuery, FromEntityType, GetRepository, IHydrator, IsSubset, Loaded, MergeLoaded, MergeSelected, NoInfer, ObjectQuery, PopulateOptions, Primary, Ref, RequiredEntityData, UnboxArray } from './typings.js';
10
+ import type { AnyString, ArrayElement, AutoPath, ConnectionType, Dictionary, EntityClass, EntityData, EntityDictionary, EntityDTO, EntityMetadata, EntityName, FilterDef, FilterQuery, FromEntityType, GetRepository, IHydrator, IsSubset, Loaded, MergeLoaded, MergeSelected, ObjectQuery, PopulateOptions, Primary, Ref, RequiredEntityData, UnboxArray } from './typings.js';
11
11
  import { FlushMode, LockMode, PopulatePath, type TransactionOptions } from './enums.js';
12
12
  import type { MetadataStorage } from './metadata/MetadataStorage.js';
13
13
  import type { Transaction } from './connections/Connection.js';
package/MikroORM.d.ts CHANGED
@@ -5,7 +5,7 @@ import { Configuration, type Options } from './utils/Configuration.js';
5
5
  import type { EntityManager } from './EntityManager.js';
6
6
  import type { AnyEntity, Constructor, EntityClass, EntityMetadata, EntityName, IEntityGenerator, IMigrator, ISeedManager } from './typings.js';
7
7
  /** @internal */
8
- export declare function lookupExtensions(options: Options): Promise<void>;
8
+ export declare function loadOptionalDependencies(options: Options): Promise<void>;
9
9
  /**
10
10
  * The main class used to configure and bootstrap the ORM.
11
11
  *
package/MikroORM.js CHANGED
@@ -4,31 +4,35 @@ import { Configuration } from './utils/Configuration.js';
4
4
  import { loadEnvironmentVars } from './utils/env-vars.js';
5
5
  import { Utils } from './utils/Utils.js';
6
6
  import { colors } from './logging/colors.js';
7
- async function registerExtension(name, mod, extensions) {
8
- /* v8 ignore next */
9
- const resolved = await mod.catch(() => null);
10
- const module = resolved?.[name];
11
- /* v8 ignore else */
12
- if (module) {
13
- extensions.push(module);
7
+ async function tryRegisterExtension(name, pkg, extensions) {
8
+ try {
9
+ const url = import.meta.resolve(pkg);
10
+ const mod = await import(url);
11
+ if (mod[name]) {
12
+ extensions.push(mod[name]);
13
+ }
14
+ }
15
+ catch {
16
+ // not installed
14
17
  }
15
18
  }
16
19
  /** @internal */
17
- export async function lookupExtensions(options) {
20
+ export async function loadOptionalDependencies(options) {
21
+ await import('@mikro-orm/core/fs-utils').then(m => m.fs.init()).catch(() => null);
18
22
  const extensions = options.extensions ?? [];
19
23
  const exists = (name) => extensions.some(ext => ext.name === name);
20
24
  if (!exists('SeedManager')) {
21
- await registerExtension('SeedManager', import((() => '@mikro-orm/seeder')()), extensions);
25
+ await tryRegisterExtension('SeedManager', '@mikro-orm/seeder', extensions);
22
26
  }
23
27
  if (!exists('Migrator')) {
24
- await registerExtension('Migrator', import((() => '@mikro-orm/migrations')()), extensions);
28
+ await tryRegisterExtension('Migrator', '@mikro-orm/migrations', extensions);
25
29
  }
26
30
  /* v8 ignore if */
27
31
  if (!exists('Migrator')) {
28
- await registerExtension('Migrator', import((() => '@mikro-orm/migrations-mongodb')()), extensions);
32
+ await tryRegisterExtension('Migrator', '@mikro-orm/migrations-mongodb', extensions);
29
33
  }
30
34
  if (!exists('EntityGenerator')) {
31
- await registerExtension('EntityGenerator', import((() => '@mikro-orm/entity-generator')()), extensions);
35
+ await tryRegisterExtension('EntityGenerator', '@mikro-orm/entity-generator', extensions);
32
36
  }
33
37
  options.extensions = extensions;
34
38
  const metadataCacheEnabled = options.metadataCache?.enabled || options.metadataProvider?.useCache?.();
@@ -85,7 +89,7 @@ export class MikroORM {
85
89
  options = { ...options };
86
90
  options.discovery ??= {};
87
91
  options.discovery.skipSyncDiscovery ??= true;
88
- await lookupExtensions(options);
92
+ await loadOptionalDependencies(options);
89
93
  const orm = new this(options);
90
94
  const preferTs = orm.config.get('preferTs', Utils.detectTypeScriptSupport());
91
95
  orm.metadata = await orm.discovery.discover(preferTs);
@@ -1,4 +1,4 @@
1
- import type { ConnectionType, EntityData, EntityMetadata, EntityProperty, FilterQuery, Primary, Dictionary, QBFilterQuery, IPrimaryKey, PopulateOptions, EntityDictionary, AutoPath, ObjectQuery, FilterObject, Populate, EntityName } from '../typings.js';
1
+ import type { ConnectionType, EntityData, EntityMetadata, EntityProperty, FilterQuery, Primary, Dictionary, IPrimaryKey, PopulateOptions, EntityDictionary, AutoPath, ObjectQuery, FilterObject, Populate, EntityName } from '../typings.js';
2
2
  import type { Connection, QueryResult, Transaction } from '../connections/Connection.js';
3
3
  import type { FlushMode, LockMode, QueryOrderMap, QueryFlag, LoadStrategy, PopulateHint, PopulatePath } from '../enums.js';
4
4
  import type { Platform } from '../platforms/Platform.js';
@@ -144,7 +144,7 @@ export interface FindOptions<Entity, Hint extends string = never, Fields extends
144
144
  flags?: QueryFlag[];
145
145
  /** sql only */
146
146
  groupBy?: string | string[];
147
- having?: QBFilterQuery<Entity>;
147
+ having?: FilterQuery<Entity>;
148
148
  /** sql only */
149
149
  strategy?: LoadStrategy | `${LoadStrategy}`;
150
150
  flushMode?: FlushMode | `${FlushMode}`;
@@ -203,7 +203,7 @@ export interface CountOptions<T extends object, P extends string = never> {
203
203
  filters?: FilterOptions;
204
204
  schema?: string;
205
205
  groupBy?: string | readonly string[];
206
- having?: QBFilterQuery<T>;
206
+ having?: FilterQuery<T>;
207
207
  cache?: boolean | number | [string, number];
208
208
  populate?: Populate<T, P>;
209
209
  populateWhere?: ObjectQuery<T> | PopulateHint | `${PopulateHint}`;
@@ -10,8 +10,67 @@ export declare abstract class BaseEntity {
10
10
  populated(populated?: boolean): void;
11
11
  populate<Entity extends this = this, Hint extends string = never>(populate: AutoPath<Entity, Hint, PopulatePath.ALL>[] | false, options?: EntityLoaderOptions<Entity>): Promise<Loaded<Entity, Hint>>;
12
12
  toReference<Entity extends this = this>(): Ref<Entity> & LoadedReference<Loaded<Entity, AddEager<Entity>>>;
13
+ /**
14
+ * Converts the entity to a plain object representation.
15
+ *
16
+ * **Note on typing with `Loaded` entities:** When called on a `Loaded<Entity, 'relation'>` type,
17
+ * the return type will be `EntityDTO<Entity>` (with relations as primary keys), not
18
+ * `EntityDTO<Loaded<Entity, 'relation'>>` (with loaded relations as nested objects).
19
+ * This is a TypeScript limitation - the `this` type resolves to the class, not the `Loaded` wrapper.
20
+ *
21
+ * For correct typing that reflects loaded relations, use `wrap()`:
22
+ * ```ts
23
+ * const result = await em.find(User, {}, { populate: ['profile'] });
24
+ * // Type: EntityDTO<User> (profile is number)
25
+ * const obj1 = result[0].toObject();
26
+ * // Type: EntityDTO<Loaded<User, 'profile'>> (profile is nested object)
27
+ * const obj2 = wrap(result[0]).toObject();
28
+ * ```
29
+ *
30
+ * Runtime values are correct in both cases - only the static types differ.
31
+ */
13
32
  toObject<Entity extends this = this>(): EntityDTO<Entity>;
33
+ /**
34
+ * Converts the entity to a plain object representation.
35
+ *
36
+ * **Note on typing with `Loaded` entities:** When called on a `Loaded<Entity, 'relation'>` type,
37
+ * the return type will be `EntityDTO<Entity>` (with relations as primary keys), not
38
+ * `EntityDTO<Loaded<Entity, 'relation'>>` (with loaded relations as nested objects).
39
+ * This is a TypeScript limitation - the `this` type resolves to the class, not the `Loaded` wrapper.
40
+ *
41
+ * For correct typing that reflects loaded relations, use `wrap()`:
42
+ * ```ts
43
+ * const result = await em.find(User, {}, { populate: ['profile'] });
44
+ * // Type: EntityDTO<User> (profile is number)
45
+ * const obj1 = result[0].toObject();
46
+ * // Type: EntityDTO<Loaded<User, 'profile'>> (profile is nested object)
47
+ * const obj2 = wrap(result[0]).toObject();
48
+ * ```
49
+ *
50
+ * Runtime values are correct in both cases - only the static types differ.
51
+ */
14
52
  toObject<Entity extends this = this>(ignoreFields: never[]): EntityDTO<Entity>;
53
+ /**
54
+ * Converts the entity to a plain object representation.
55
+ *
56
+ * **Note on typing with `Loaded` entities:** When called on a `Loaded<Entity, 'relation'>` type,
57
+ * the return type will be `EntityDTO<Entity>` (with relations as primary keys), not
58
+ * `EntityDTO<Loaded<Entity, 'relation'>>` (with loaded relations as nested objects).
59
+ * This is a TypeScript limitation - the `this` type resolves to the class, not the `Loaded` wrapper.
60
+ *
61
+ * For correct typing that reflects loaded relations, use `wrap()`:
62
+ * ```ts
63
+ * const result = await em.find(User, {}, { populate: ['profile'] });
64
+ * // Type: EntityDTO<User> (profile is number)
65
+ * const obj1 = result[0].toObject();
66
+ * // Type: EntityDTO<Loaded<User, 'profile'>> (profile is nested object)
67
+ * const obj2 = wrap(result[0]).toObject();
68
+ * ```
69
+ *
70
+ * Runtime values are correct in both cases - only the static types differ.
71
+ *
72
+ * @param ignoreFields - Array of field names to omit from the result.
73
+ */
15
74
  toObject<Entity extends this = this, Ignored extends EntityKey<Entity> = never>(ignoreFields: Ignored[]): Omit<EntityDTO<Entity>, Ignored>;
16
75
  toPOJO<Entity extends this = this>(): EntityDTO<Entity>;
17
76
  serialize<Entity extends this = this, Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Hint extends string = never, Exclude extends string = never>(options?: SerializeOptions<Naked, Hint, Exclude>): EntityDTO<Loaded<Naked, Hint>>;
@@ -58,7 +58,7 @@ export declare class WrappedEntity<Entity extends object> {
58
58
  setPrimaryKey(id: Primary<Entity> | null): void;
59
59
  getSerializedPrimaryKey(): string;
60
60
  get __meta(): EntityMetadata<Entity>;
61
- get __platform(): import("@mikro-orm/sql").Platform;
62
- get __config(): import("@mikro-orm/sql").Configuration<import("../drivers/IDatabaseDriver.js").IDatabaseDriver<import("@mikro-orm/sql").Connection>, EntityManager<import("../drivers/IDatabaseDriver.js").IDatabaseDriver<import("@mikro-orm/sql").Connection>>>;
61
+ get __platform(): import("../index.js").Platform;
62
+ get __config(): import("../index.js").Configuration<import("../drivers/IDatabaseDriver.js").IDatabaseDriver<import("../index.js").Connection>, EntityManager<import("../drivers/IDatabaseDriver.js").IDatabaseDriver<import("../index.js").Connection>>>;
63
63
  get __primaryKeys(): Primary<Entity>[];
64
64
  }
@@ -1,6 +1,7 @@
1
1
  import type { EntityManager } from '../EntityManager.js';
2
2
  import type { ColumnType, PropertyOptions, ReferenceOptions, EnumOptions, EmbeddedOptions, ManyToOneOptions, OneToManyOptions, OneToOneOptions, ManyToManyOptions } from '../metadata/types.js';
3
3
  import type { AnyString, GeneratedColumnCallback, Constructor, CheckCallback, FilterQuery, EntityName, Dictionary, EntityMetadata, PrimaryKeyProp, EntityRepositoryType, Hidden, Opt, Primary, EntityClass, EntitySchemaWithMeta, InferEntity, MaybeReturnType, Ref, IndexCallback, FormulaCallback, EntityCtor, IsNever } from '../typings.js';
4
+ import type { Raw } from '../utils/RawQueryFragment.js';
4
5
  import type { ScalarReference } from './Reference.js';
5
6
  import type { SerializeOptions } from '../serialization/EntitySerializer.js';
6
7
  import type { Cascade, DeferMode, EmbeddedPrefixMode, LoadStrategy, QueryOrderMap } from '../enums.js';
@@ -120,7 +121,7 @@ export declare class UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys
120
121
  * Specify default column value for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}.
121
122
  * This is a runtime value, assignable to the entity property. (SQL only)
122
123
  */
123
- default<T extends string | string[] | number | number[] | boolean | null>(defaultValue: T): Pick<UniversalPropertyOptionsBuilder<Value, Omit<Options, 'default'> & {
124
+ default<T extends string | string[] | number | number[] | boolean | null | Date | Raw>(defaultValue: T): Pick<UniversalPropertyOptionsBuilder<Value, Omit<Options, 'default'> & {
124
125
  default: T;
125
126
  }, IncludeKeys>, IncludeKeys>;
126
127
  /**
@@ -577,7 +578,7 @@ type MaybeOpt<Value, Options> = Options extends {
577
578
  } ? Opt<Value> : Options extends {
578
579
  onCreate: Function;
579
580
  } ? Opt<Value> : Options extends {
580
- default: string | string[] | number | number[] | boolean | null;
581
+ default: string | string[] | number | number[] | boolean | null | Date | Raw;
581
582
  } ? Opt<Value> : Options extends {
582
583
  defaultRaw: string;
583
584
  } ? Opt<Value> : Options extends {
package/enums.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Dictionary, EntityKey, ExpandProperty } from './typings.js';
1
+ import type { EntityKey, ExpandProperty } from './typings.js';
2
2
  import type { Transaction } from './connections/Connection.js';
3
3
  import type { LogContext } from './logging/Logger.js';
4
4
  export declare enum FlushMode {
@@ -72,7 +72,6 @@ export type QueryOrderKeys<T> = QueryOrderKeysFlat | QueryOrderMap<T>;
72
72
  export type QueryOrderMap<T> = {
73
73
  [K in EntityKey<T>]?: QueryOrderKeys<ExpandProperty<T[K]>>;
74
74
  };
75
- export type QBQueryOrderMap<T> = QueryOrderMap<T> | Dictionary;
76
75
  export interface FlatQueryOrderMap {
77
76
  [x: string]: QueryOrderKeysFlat;
78
77
  }
package/index.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * @module core
4
4
  */
5
5
  export { EntityMetadata, PrimaryKeyProp, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Config } from './typings.js';
6
- export type { Constructor, ConnectionType, Dictionary, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, EntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, QBFilterQuery, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, MigrationDiff, GenerateOptions, FilterObject, IEntityGenerator, ISeedManager, RequiredEntityData, CheckCallback, IndexCallback, FormulaCallback, FormulaTable, SimpleColumnMeta, Rel, Ref, ScalarRef, EntityRef, ISchemaGenerator, UmzugMigration, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, EntityDataValue, FilterKey, EntityType, FromEntityType, Selected, IsSubset, NoInfer, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, FilterValue, MergeLoaded, MergeSelected, TypeConfig, AnyString, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, RequiredNullable, DefineConfig, Opt, Hidden, EntitySchemaWithMeta, InferEntity, CheckConstraint, GeneratedColumnCallback, FilterDef, EntityCtor, } from './typings.js';
6
+ export type { Constructor, ConnectionType, Dictionary, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, EntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, MigrationDiff, GenerateOptions, FilterObject, IEntityGenerator, ISeedManager, RequiredEntityData, CheckCallback, IndexCallback, FormulaCallback, FormulaTable, SimpleColumnMeta, Rel, Ref, ScalarRef, EntityRef, ISchemaGenerator, UmzugMigration, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, EntityDataValue, FilterKey, EntityType, FromEntityType, Selected, IsSubset, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, FilterValue, MergeLoaded, MergeSelected, TypeConfig, AnyString, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, RequiredNullable, DefineConfig, Opt, Hidden, EntitySchemaWithMeta, InferEntity, CheckConstraint, GeneratedColumnCallback, FilterDef, EntityCtor, Subquery, } from './typings.js';
7
7
  export * from './enums.js';
8
8
  export * from './errors.js';
9
9
  export * from './exceptions.js';
@@ -4,6 +4,7 @@ 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
+ import type { Raw } from '../utils/RawQueryFragment.js';
7
8
  export type EntityOptions<T, E = T extends EntityClass<infer P> ? P : T> = {
8
9
  /** Override default collection/table name. Alias for `collection`. */
9
10
  tableName?: string;
@@ -126,12 +127,12 @@ export interface PropertyOptions<Owner> {
126
127
  * Specify default column value for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}.
127
128
  * This is a runtime value, assignable to the entity property. (SQL only)
128
129
  */
129
- default?: string | string[] | number | number[] | boolean | null;
130
+ default?: string | string[] | number | number[] | boolean | null | Date | Raw;
130
131
  /**
131
132
  * Specify SQL functions for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. (SQL only)
132
133
  * Since v4 you should use defaultRaw for SQL functions. e.g. now()
133
134
  */
134
- defaultRaw?: string;
135
+ defaultRaw?: string | Raw;
135
136
  /**
136
137
  * Set to map some SQL snippet for the entity.
137
138
  *
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mikro-orm/core",
3
3
  "type": "module",
4
- "version": "7.0.0-dev.215",
4
+ "version": "7.0.0-dev.217",
5
5
  "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.",
6
6
  "exports": {
7
7
  "./package.json": "./package.json",
@@ -8,6 +8,7 @@ import type { IDatabaseDriver } from '../drivers/IDatabaseDriver.js';
8
8
  import { Type } from '../types/index.js';
9
9
  import type { MikroORM } from '../MikroORM.js';
10
10
  import type { TransformContext } from '../types/Type.js';
11
+ import { Raw } from '../utils/RawQueryFragment.js';
11
12
  export declare const JsonProperty: unique symbol;
12
13
  export declare abstract class Platform {
13
14
  protected readonly exceptionConverter: ExceptionConverter;
@@ -142,8 +143,8 @@ export declare abstract class Platform {
142
143
  unmarshallArray(value: string): string[];
143
144
  getBlobDeclarationSQL(): string;
144
145
  getJsonDeclarationSQL(): string;
145
- getSearchJsonPropertySQL(path: string, type: string, aliased: boolean): string;
146
- getSearchJsonPropertyKey(path: string[], type: string, aliased: boolean, value?: unknown): string;
146
+ getSearchJsonPropertySQL(path: string, type: string, aliased: boolean): string | Raw;
147
+ getSearchJsonPropertyKey(path: string[], type: string, aliased: boolean, value?: unknown): string | Raw;
147
148
  getJsonIndexDefinition(index: {
148
149
  columnNames: string[];
149
150
  }): string[];
package/typings.d.ts CHANGED
@@ -40,7 +40,6 @@ export type IsUnknown<T> = T extends unknown ? unknown extends T ? true : never
40
40
  export type IsAny<T> = 0 extends (1 & T) ? true : false;
41
41
  export type IsNever<T, True = true, False = false> = [T] extends [never] ? True : False;
42
42
  export type MaybePromise<T> = T | Promise<T>;
43
- export type NoInfer<T> = [T][T extends any ? 0 : never];
44
43
  /**
45
44
  * Structural type for matching Collection without triggering full interface evaluation.
46
45
  * Using `T extends CollectionShape` instead of `T extends Collection<any, any>` avoids
@@ -80,8 +79,11 @@ type ReferenceShape<T = any> = {
80
79
  };
81
80
  /**
82
81
  * Structural type for matching LoadedReference (Reference with `$` property).
82
+ * Note: We don't parameterize ReferenceShape here because for loaded relations,
83
+ * the Reference unwrap() returns the base type while $ returns the Loaded type.
84
+ * We infer T from $ to get the full Loaded type for EntityDTO.
83
85
  */
84
- type LoadedReferenceShape<T = any> = ReferenceShape<T> & {
86
+ type LoadedReferenceShape<T = any> = ReferenceShape & {
85
87
  $: T;
86
88
  };
87
89
  /**
@@ -91,10 +93,11 @@ type LoadedReferenceShape<T = any> = ReferenceShape<T> & {
91
93
  */
92
94
  type LoadableShape = CollectionShape | ReferenceShape | readonly any[];
93
95
  export type UnionKeys<T> = T extends any ? keyof T : never;
94
- export type UnionPropertyType<T, K extends PropertyKey> = T extends any ? K extends keyof T ? T[K] : never : never;
95
- export type MergeUnion<T> = [T] extends [object] ? T extends Scalar ? T : {
96
+ export type UnionPropertyType<T, K extends PropertyKey> = T extends any ? (K extends keyof T ? T[K] : never) : never;
97
+ type IsUnion<T, U = T> = T extends any ? ([U] extends [T] ? false : true) : false;
98
+ export type MergeUnion<T> = [T] extends [object] ? (T extends Scalar ? T : IsUnion<T> extends true ? {
96
99
  [K in UnionKeys<T>]: UnionPropertyType<T, K>;
97
- } : T;
100
+ } : T) : T;
98
101
  export type DeepPartial<T> = T & {
99
102
  [P in keyof T]?: T[P] extends (infer U)[] ? DeepPartial<U>[] : T[P] extends Readonly<infer U>[] ? Readonly<DeepPartial<U>>[] : DeepPartial<T[P]>;
100
103
  };
@@ -181,13 +184,17 @@ export type Scalar = boolean | number | string | bigint | symbol | Date | RegExp
181
184
  };
182
185
  type Primitive = boolean | number | string | bigint | symbol;
183
186
  export type ExpandScalar<T> = null | (T extends string ? T | RegExp : T extends Date ? Date | string : T extends bigint ? bigint | string | number : T);
187
+ /** Marker interface for query builders that can be used as subqueries */
188
+ export interface Subquery {
189
+ readonly __subquery: true;
190
+ }
184
191
  export type OperatorMap<T> = {
185
192
  $and?: ExpandQuery<T>[];
186
193
  $or?: ExpandQuery<T>[];
187
- $eq?: ExpandScalar<T> | readonly ExpandScalar<T>[];
188
- $ne?: ExpandScalar<T>;
189
- $in?: readonly ExpandScalar<T>[];
190
- $nin?: readonly ExpandScalar<T>[];
194
+ $eq?: ExpandScalar<T> | readonly ExpandScalar<T>[] | Subquery;
195
+ $ne?: ExpandScalar<T> | readonly ExpandScalar<T>[] | Subquery;
196
+ $in?: readonly ExpandScalar<T>[] | readonly Primary<T>[] | Raw | Subquery;
197
+ $nin?: readonly ExpandScalar<T>[] | readonly Primary<T>[] | Raw | Subquery;
191
198
  $not?: ExpandQuery<T>;
192
199
  $none?: ExpandQuery<T>;
193
200
  $some?: ExpandQuery<T>;
@@ -200,10 +207,10 @@ export type OperatorMap<T> = {
200
207
  $lt?: number;
201
208
  $lte?: number;
202
209
  };
203
- $gt?: ExpandScalar<T>;
204
- $gte?: ExpandScalar<T>;
205
- $lt?: ExpandScalar<T>;
206
- $lte?: ExpandScalar<T>;
210
+ $gt?: ExpandScalar<T> | readonly ExpandScalar<T>[] | Subquery;
211
+ $gte?: ExpandScalar<T> | readonly ExpandScalar<T>[] | Subquery;
212
+ $lt?: ExpandScalar<T> | readonly ExpandScalar<T>[] | Subquery;
213
+ $lte?: ExpandScalar<T> | readonly ExpandScalar<T>[] | Subquery;
207
214
  $like?: string;
208
215
  $re?: string;
209
216
  $ilike?: string;
@@ -216,7 +223,7 @@ export type OperatorMap<T> = {
216
223
  $hasKeys?: readonly string[];
217
224
  $hasSomeKeys?: readonly string[];
218
225
  };
219
- export type FilterItemValue<T> = T | ExpandScalar<T> | Primary<T>;
226
+ export type FilterItemValue<T> = T | ExpandScalar<T> | Primary<T> | Raw;
220
227
  export type FilterValue<T> = OperatorMap<FilterItemValue<T>> | FilterItemValue<T> | FilterItemValue<T>[] | null;
221
228
  type FilterObjectProp<T, K extends PropertyKey> = K extends keyof MergeUnion<T> ? MergeUnion<T>[K] : K extends keyof T ? T[K] : never;
222
229
  type ExpandQueryMerged<T> = [T] extends [object] ? [T] extends [Scalar] ? never : FilterQuery<MergeUnion<T>> : FilterValue<T>;
@@ -229,7 +236,6 @@ export type EntityProps<T> = {
229
236
  };
230
237
  export type ObjectQuery<T> = OperatorMap<T> & FilterObject<T>;
231
238
  export type FilterQuery<T> = ObjectQuery<T> | NonNullable<ExpandScalar<Primary<T>>> | NonNullable<EntityProps<T> & OperatorMap<T>> | FilterQuery<T>[];
232
- export type QBFilterQuery<T = any> = ObjectQuery<T> | Dictionary;
233
239
  export interface IWrappedEntity<Entity extends object> {
234
240
  isInitialized(): boolean;
235
241
  isManaged(): boolean;
@@ -310,7 +316,7 @@ export type RequiredEntityDataProp<T, O, C extends boolean> = T extends Date ? s
310
316
  __raw?: infer Raw;
311
317
  } ? (C extends true ? Raw : Runtime) : T extends ReferenceShape<infer U> ? RequiredEntityDataNested<U, O, C> : T extends ScalarReference<infer U> ? RequiredEntityDataProp<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>;
312
318
  export type EntityDataNested<T, C extends boolean = false> = T extends undefined ? never : T extends any[] ? Readonly<T> : EntityData<T, C> | ExpandEntityProp<T, C>;
313
- type EntityDataItem<T, C extends boolean> = C extends false ? T | EntityDataProp<T, C> | null : EntityDataProp<T, C> | null;
319
+ type EntityDataItem<T, C extends boolean> = C extends false ? T | EntityDataProp<T, C> | Raw | null : EntityDataProp<T, C> | Raw | null;
314
320
  export type RequiredEntityDataNested<T, O, C extends boolean> = T extends any[] ? Readonly<T> : RequiredEntityData<T, O> | ExpandRequiredEntityProp<T, O, C>;
315
321
  type ExplicitlyOptionalProps<T> = (T extends {
316
322
  [OptionalProps]?: infer K;
@@ -331,9 +337,9 @@ export type EntityData<T, C extends boolean = false> = {
331
337
  [K in EntityKey<T>]?: EntityDataItem<T[K] & {}, C>;
332
338
  };
333
339
  export type RequiredEntityData<T, I = never, C extends boolean = false> = {
334
- [K in keyof T as RequiredKeys<T, K, I>]: T[K] | RequiredEntityDataProp<T[K], T, C> | Primary<T[K]>;
340
+ [K in keyof T as RequiredKeys<T, K, I>]: T[K] | RequiredEntityDataProp<T[K], T, C> | Primary<T[K]> | Raw;
335
341
  } & {
336
- [K in keyof T as OptionalKeys<T, K, I>]?: T[K] | RequiredEntityDataProp<T[K], T, C> | Primary<T[K]> | null;
342
+ [K in keyof T as OptionalKeys<T, K, I>]?: T[K] | RequiredEntityDataProp<T[K], T, C> | Primary<T[K]> | Raw | null;
337
343
  };
338
344
  export type EntityDictionary<T> = EntityData<T> & Record<any, any>;
339
345
  type ExtractEagerProps<T> = T extends {
@@ -399,12 +405,12 @@ export type FormulaTable = {
399
405
  };
400
406
  export type IndexCallback<T> = (table: TableName, columns: Record<PropertyName<T>, string>, indexName: string) => string | Raw;
401
407
  export type FormulaCallback<T> = (table: FormulaTable, columns: Record<PropertyName<T>, string>) => string;
402
- export type CheckCallback<T> = (columns: Record<PropertyName<T>, string>) => string;
408
+ export type CheckCallback<T> = (columns: Record<PropertyName<T>, string>) => string | Raw;
403
409
  export type GeneratedColumnCallback<T> = (columns: Record<keyof T, string>) => string;
404
410
  export interface CheckConstraint<T = any> {
405
411
  name?: string;
406
412
  property?: string;
407
- expression: string | CheckCallback<T>;
413
+ expression: string | Raw | CheckCallback<T>;
408
414
  }
409
415
  export type AnyString = string & {};
410
416
  export interface EntityProperty<Owner = any, Target = any> {
@@ -897,9 +903,7 @@ type LoadedEntityType<T> = {
897
903
  };
898
904
  export type EntityType<T> = T | LoadedEntityType<T>;
899
905
  export type FromEntityType<T> = T extends LoadedEntityType<infer U> ? U : T;
900
- type LoadedInternal<T, L extends string = never, F extends string = '*', E extends string = never> = [
901
- F
902
- ] extends ['*'] ? IsNever<E> extends true ? T & {
906
+ type LoadedInternal<T, L extends string = never, F extends string = '*', E extends string = never> = [F] extends ['*'] ? IsNever<E> extends true ? T & {
903
907
  [K in keyof T as IsPrefixed<T, K, ExpandHint<T, L>>]: LoadedProp<NonNullable<T[K]>, Suffix<K, L>, Suffix<K, F>, Suffix<K, E>> | AddOptional<T[K]>;
904
908
  } : {
905
909
  [K in keyof T as IsPrefixed<T, K, ExpandHint<T, L>, E>]: LoadedProp<NonNullable<T[K]>, Suffix<K, L>, Suffix<K, F>, Suffix<K, E>> | AddOptional<T[K]>;
@@ -35,7 +35,7 @@ declare const DEFAULTS: {
35
35
  readonly inferDefaultValues: true;
36
36
  };
37
37
  readonly validateRequired: true;
38
- readonly context: (name: string) => EntityManager<IDatabaseDriver<import("@mikro-orm/sql").Connection>> | undefined;
38
+ readonly context: (name: string) => EntityManager<IDatabaseDriver<import("../index.js").Connection>> | undefined;
39
39
  readonly contextName: "default";
40
40
  readonly allowGlobalContext: false;
41
41
  readonly logger: (message?: any, ...optionalParams: any[]) => void;
@@ -3,13 +3,15 @@ declare const rawFragmentSymbolBrand: unique symbol;
3
3
  export type RawQueryFragmentSymbol = symbol & {
4
4
  readonly [rawFragmentSymbolBrand]: true;
5
5
  };
6
- export declare class RawQueryFragment {
6
+ export declare class RawQueryFragment<Alias extends string = string> {
7
7
  #private;
8
8
  readonly sql: string;
9
9
  readonly params: unknown[];
10
+ /** @internal Type-level only - used to track the alias for type inference */
11
+ private readonly __alias?;
10
12
  constructor(sql: string, params?: unknown[]);
11
13
  get key(): RawQueryFragmentSymbol;
12
- as(alias: string): RawQueryFragment;
14
+ as<A extends string>(alias: A): RawQueryFragment<A>;
13
15
  [Symbol.toPrimitive](hint: 'string'): RawQueryFragmentSymbol;
14
16
  get [Symbol.toStringTag](): string;
15
17
  toJSON(): string;
@@ -17,7 +19,7 @@ export declare class RawQueryFragment {
17
19
  static isKnownFragmentSymbol(key: unknown): key is RawQueryFragmentSymbol;
18
20
  static hasObjectFragments(object: unknown): boolean;
19
21
  static isKnownFragment(key: unknown): key is RawQueryFragment | symbol;
20
- static getKnownFragment(key: unknown): RawQueryFragment | undefined;
22
+ static getKnownFragment(key: unknown): RawQueryFragment<any> | undefined;
21
23
  }
22
24
  export { RawQueryFragment as Raw };
23
25
  export declare function isRaw(value: unknown): value is RawQueryFragment;
@@ -80,7 +82,7 @@ export declare const ALIAS_REPLACEMENT_RE = "\\[::alias::\\]";
80
82
  * export class Author { ... }
81
83
  * ```
82
84
  */
83
- export declare function raw<T extends object = any, R = any>(sql: EntityKey<T> | EntityKey<T>[] | AnyString | ((alias: string) => string) | RawQueryFragment, params?: readonly unknown[] | Dictionary<unknown>): NoInfer<R>;
85
+ export declare function raw<R = RawQueryFragment & symbol, T extends object = any>(sql: EntityKey<T> | EntityKey<T>[] | AnyString | ((alias: string) => string) | RawQueryFragment, params?: readonly unknown[] | Dictionary<unknown>): R;
84
86
  /**
85
87
  * Alternative to the `raw()` helper allowing to use it as a tagged template function for the simple cases.
86
88
  *
@@ -93,16 +95,19 @@ export declare function raw<T extends object = any, R = any>(sql: EntityKey<T> |
93
95
  *
94
96
  * // value can be empty array
95
97
  * await em.find(User, { [sql`(select 1 = 1)`]: [] });
98
+ *
99
+ * // with type parameter for assignment without casting
100
+ * entity.date = sql<Date>`now()`;
96
101
  * ```
97
102
  */
98
- export declare function sql(sql: readonly string[], ...values: unknown[]): any;
103
+ export declare function sql<R = RawQueryFragment & symbol>(sql: readonly string[], ...values: unknown[]): R;
99
104
  export declare namespace sql {
100
- var ref: <T extends object>(...keys: string[]) => NoInfer<RawQueryFragment>;
101
- var now: (length?: number) => string;
102
- var lower: <T extends object>(key: string | ((alias: string) => string)) => string;
103
- var upper: <T extends object>(key: string | ((alias: string) => string)) => string;
105
+ var ref: <T extends object = any>(...keys: string[]) => RawQueryFragment<string> & symbol;
106
+ var now: (length?: number) => RawQueryFragment<string> & symbol;
107
+ var lower: <R = RawQueryFragment<string> & symbol, T extends object = any>(key: string | ((alias: string) => string)) => R;
108
+ var upper: <R = RawQueryFragment<string> & symbol, T extends object = any>(key: string | ((alias: string) => string)) => R;
104
109
  }
105
- export declare function createSqlFunction<T extends object, R = string>(func: string, key: string | ((alias: string) => string)): R;
110
+ export declare function createSqlFunction<R = RawQueryFragment & symbol, T extends object = any>(func: string, key: string | ((alias: string) => string)): R;
106
111
  /**
107
112
  * Tag function providing quoting of db identifiers (table name, columns names, index names, ...).
108
113
  *
@@ -111,11 +116,11 @@ export declare function createSqlFunction<T extends object, R = string>(func: st
111
116
  * ```ts
112
117
  * // On postgres, will produce: create index "index custom_idx_on_name" on "library.author" ("name")
113
118
  * // On mysql, will produce: create index `index custom_idx_on_name` on `library.author` (`name`)
114
- * @Index({ name: 'custom_idx_on_name', expression: (table, columns) => quote`create index ${'custom_idx_on_name'} on ${table} (${columns.name})` })
119
+ * @Index({ name: 'custom_idx_on_name', expression: (table, columns, indexName) => quote`create index ${indexName} on ${table} (${columns.name})` })
115
120
  * @Entity({ schema: 'library' })
116
121
  * export class Author { ... }
117
122
  * ```
118
123
  */
119
124
  export declare function quote(expParts: readonly string[], ...values: (string | {
120
125
  toString(): string;
121
- })[]): any;
126
+ })[]): RawQueryFragment<string> & symbol;
@@ -2,7 +2,6 @@ import { Utils } from './Utils.js';
2
2
  export class RawQueryFragment {
3
3
  sql;
4
4
  params;
5
- // holds a weak reference to fragments used as object keys
6
5
  static #rawQueryReferences = new WeakMap();
7
6
  #key;
8
7
  constructor(sql, params = []) {
@@ -170,6 +169,9 @@ export function raw(sql, params) {
170
169
  *
171
170
  * // value can be empty array
172
171
  * await em.find(User, { [sql`(select 1 = 1)`]: [] });
172
+ *
173
+ * // with type parameter for assignment without casting
174
+ * entity.date = sql<Date>`now()`;
173
175
  * ```
174
176
  */
175
177
  export function sql(sql, ...values) {
@@ -193,7 +195,7 @@ sql.upper = (key) => createSqlFunction('upper', key);
193
195
  * ```ts
194
196
  * // On postgres, will produce: create index "index custom_idx_on_name" on "library.author" ("name")
195
197
  * // On mysql, will produce: create index `index custom_idx_on_name` on `library.author` (`name`)
196
- * @Index({ name: 'custom_idx_on_name', expression: (table, columns) => quote`create index ${'custom_idx_on_name'} on ${table} (${columns.name})` })
198
+ * @Index({ name: 'custom_idx_on_name', expression: (table, columns, indexName) => quote`create index ${indexName} on ${table} (${columns.name})` })
197
199
  * @Entity({ schema: 'library' })
198
200
  * export class Author { ... }
199
201
  * ```
package/utils/Utils.js CHANGED
@@ -123,7 +123,7 @@ export function parseJsonSafe(value) {
123
123
  }
124
124
  export class Utils {
125
125
  static PK_SEPARATOR = '~~~';
126
- static #ORM_VERSION = '7.0.0-dev.215';
126
+ static #ORM_VERSION = '7.0.0-dev.217';
127
127
  /**
128
128
  * Checks if the argument is instance of `Object`. Returns false for arrays.
129
129
  */
@@ -1,5 +1,6 @@
1
1
  import { type Dictionary } from '../typings.js';
2
2
  export declare const fs: {
3
+ init(): Promise<void>;
3
4
  pathExists(path: string): boolean;
4
5
  ensureDir(path: string): void;
5
6
  readJSONSync<T = Dictionary>(path: string): T;
package/utils/fs-utils.js CHANGED
@@ -1,9 +1,25 @@
1
- import { existsSync, globSync, mkdirSync, readFileSync, realpathSync, statSync } from 'node:fs';
1
+ import { existsSync, globSync as nodeGlobSync, mkdirSync, readFileSync, realpathSync, statSync } from 'node:fs';
2
2
  import { isAbsolute, join, normalize, relative } from 'node:path';
3
3
  import { fileURLToPath, pathToFileURL } from 'node:url';
4
4
  import { Utils } from './Utils.js';
5
5
  import { colors } from '../logging/colors.js';
6
+ let globSync = (patterns, options) => {
7
+ const files = nodeGlobSync(patterns, { ...options, withFileTypes: true });
8
+ return files.filter(f => f.isFile()).map(f => join(f.parentPath, f.name));
9
+ };
6
10
  export const fs = {
11
+ async init() {
12
+ const tinyGlobby = await import('tinyglobby').catch(() => null);
13
+ if (tinyGlobby) {
14
+ globSync = (patterns, options) => {
15
+ patterns = Utils.asArray(patterns).map(p => p.replace(/\\/g, '/'));
16
+ if (options?.cwd) {
17
+ options = { ...options, cwd: options.cwd.replace(/\\/g, '/') };
18
+ }
19
+ return tinyGlobby.globSync(patterns, { ...options, expandDirectories: false });
20
+ };
21
+ }
22
+ },
7
23
  pathExists(path) {
8
24
  if (/[*?[\]]/.test(path)) {
9
25
  return globSync(path).length > 0;
@@ -49,16 +65,14 @@ export const fs = {
49
65
  try {
50
66
  const s = statSync(cwd ? this.normalizePath(cwd, input) : input);
51
67
  if (s.isDirectory()) {
52
- const files = globSync(join(input, '**'), { cwd, withFileTypes: true });
53
- return files.filter(f => f.isFile()).map(f => join(f.parentPath, f.name));
68
+ return globSync(join(input, '**'), { cwd });
54
69
  }
55
70
  }
56
71
  catch {
57
72
  // ignore
58
73
  }
59
74
  }
60
- const files = globSync(input, { cwd, withFileTypes: true });
61
- return files.filter(f => f.isFile()).map(f => join(f.parentPath, f.name));
75
+ return globSync(input, { cwd });
62
76
  },
63
77
  getPackageConfig(basePath = process.cwd()) {
64
78
  if (this.pathExists(`${basePath}/package.json`)) {