@mikro-orm/decorators 7.0.2-dev.8 → 7.0.2

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.
Files changed (74) hide show
  1. package/README.md +128 -294
  2. package/es/Check.d.ts +4 -1
  3. package/es/Check.js +7 -6
  4. package/es/CreateRequestContext.d.ts +15 -2
  5. package/es/CreateRequestContext.js +26 -22
  6. package/es/Embeddable.d.ts +4 -1
  7. package/es/Embeddable.js +10 -9
  8. package/es/Embedded.d.ts +5 -1
  9. package/es/Embedded.js +11 -10
  10. package/es/Entity.d.ts +4 -1
  11. package/es/Entity.js +10 -9
  12. package/es/Enum.d.ts +4 -1
  13. package/es/Enum.js +11 -10
  14. package/es/Filter.d.ts +1 -0
  15. package/es/Filter.js +5 -4
  16. package/es/Formula.d.ts +5 -1
  17. package/es/Formula.js +10 -9
  18. package/es/Indexed.d.ts +8 -2
  19. package/es/Indexed.js +13 -11
  20. package/es/ManyToMany.d.ts +6 -1
  21. package/es/ManyToMany.js +9 -8
  22. package/es/ManyToOne.d.ts +5 -1
  23. package/es/ManyToOne.js +8 -7
  24. package/es/OneToMany.d.ts +9 -2
  25. package/es/OneToMany.js +8 -8
  26. package/es/OneToOne.d.ts +6 -1
  27. package/es/OneToOne.js +10 -9
  28. package/es/PrimaryKey.d.ts +8 -2
  29. package/es/PrimaryKey.js +14 -12
  30. package/es/Property.d.ts +12 -1
  31. package/es/Property.js +38 -41
  32. package/es/Transactional.d.ts +8 -3
  33. package/es/Transactional.js +18 -15
  34. package/es/hooks.d.ts +40 -8
  35. package/es/hooks.js +25 -17
  36. package/legacy/Check.d.ts +4 -1
  37. package/legacy/Check.js +10 -9
  38. package/legacy/CreateRequestContext.d.ts +6 -1
  39. package/legacy/CreateRequestContext.js +28 -24
  40. package/legacy/Embeddable.d.ts +1 -0
  41. package/legacy/Embeddable.js +9 -8
  42. package/legacy/Embedded.d.ts +5 -1
  43. package/legacy/Embedded.js +12 -11
  44. package/legacy/Entity.d.ts +1 -0
  45. package/legacy/Entity.js +9 -8
  46. package/legacy/Enum.d.ts +4 -1
  47. package/legacy/Enum.js +11 -10
  48. package/legacy/Filter.d.ts +1 -0
  49. package/legacy/Filter.js +5 -4
  50. package/legacy/Formula.d.ts +5 -1
  51. package/legacy/Formula.js +10 -9
  52. package/legacy/Indexed.d.ts +8 -2
  53. package/legacy/Indexed.js +14 -12
  54. package/legacy/ManyToMany.d.ts +9 -2
  55. package/legacy/ManyToMany.js +8 -8
  56. package/legacy/ManyToOne.d.ts +8 -2
  57. package/legacy/ManyToOne.js +8 -8
  58. package/legacy/OneToMany.d.ts +9 -2
  59. package/legacy/OneToMany.js +8 -8
  60. package/legacy/OneToOne.d.ts +9 -2
  61. package/legacy/OneToOne.js +10 -10
  62. package/legacy/PrimaryKey.d.ts +8 -2
  63. package/legacy/PrimaryKey.js +15 -13
  64. package/legacy/Property.d.ts +4 -1
  65. package/legacy/Property.js +26 -25
  66. package/legacy/ReflectMetadataProvider.d.ts +3 -2
  67. package/legacy/ReflectMetadataProvider.js +49 -44
  68. package/legacy/Transactional.d.ts +2 -2
  69. package/legacy/Transactional.js +20 -17
  70. package/legacy/hooks.d.ts +8 -0
  71. package/legacy/hooks.js +23 -15
  72. package/package.json +3 -3
  73. package/utils.d.ts +41 -10
  74. package/utils.js +91 -85
@@ -1,29 +1,30 @@
1
1
  import { Utils, ReferenceKind } from '@mikro-orm/core';
2
2
  import { validateSingleDecorator, getMetadataFromDecorator } from '../utils.js';
3
+ /** Defines a scalar property on an entity (legacy TypeScript decorator). */
3
4
  export function Property(options = {}) {
4
- return function (target, propertyName) {
5
- const meta = getMetadataFromDecorator(target.constructor);
6
- const desc = Object.getOwnPropertyDescriptor(target, propertyName) || {};
7
- validateSingleDecorator(meta, propertyName, ReferenceKind.SCALAR);
8
- const name = options.name || propertyName;
9
- if (propertyName !== name && !(desc.value instanceof Function)) {
10
- Utils.renameKey(options, 'name', 'fieldName');
11
- }
12
- options.name = propertyName;
13
- const { check, ...opts } = options;
14
- const prop = { kind: ReferenceKind.SCALAR, ...opts };
15
- prop.getter = !!desc.get;
16
- prop.setter = !!desc.set;
17
- if (desc.value instanceof Function) {
18
- prop.getter = true;
19
- prop.persist = false;
20
- prop.type = 'method';
21
- prop.getterName = propertyName;
22
- prop.name = name;
23
- }
24
- if (check) {
25
- meta.checks.push({ property: prop.name, expression: check });
26
- }
27
- meta.properties[prop.name] = prop;
28
- };
5
+ return function (target, propertyName) {
6
+ const meta = getMetadataFromDecorator(target.constructor);
7
+ const desc = Object.getOwnPropertyDescriptor(target, propertyName) || {};
8
+ validateSingleDecorator(meta, propertyName, ReferenceKind.SCALAR);
9
+ const name = options.name || propertyName;
10
+ if (propertyName !== name && !(desc.value instanceof Function)) {
11
+ Utils.renameKey(options, 'name', 'fieldName');
12
+ }
13
+ options.name = propertyName;
14
+ const { check, ...opts } = options;
15
+ const prop = { kind: ReferenceKind.SCALAR, ...opts };
16
+ prop.getter = !!desc.get;
17
+ prop.setter = !!desc.set;
18
+ if (desc.value instanceof Function) {
19
+ prop.getter = true;
20
+ prop.persist = false;
21
+ prop.type = 'method';
22
+ prop.getterName = propertyName;
23
+ prop.name = name;
24
+ }
25
+ if (check) {
26
+ meta.checks.push({ property: prop.name, expression: check });
27
+ }
28
+ meta.properties[prop.name] = prop;
29
+ };
29
30
  }
@@ -1,6 +1,7 @@
1
1
  import 'reflect-metadata';
2
2
  import { type EntityMetadata, type EntityProperty, MetadataProvider } from '@mikro-orm/core';
3
+ /** Metadata provider that uses `reflect-metadata` to infer property types from TypeScript's emitted design:type metadata. */
3
4
  export declare class ReflectMetadataProvider extends MetadataProvider {
4
- loadEntityMetadata(meta: EntityMetadata): void;
5
- protected initPropertyType(meta: EntityMetadata, prop: EntityProperty): void;
5
+ loadEntityMetadata(meta: EntityMetadata): void;
6
+ protected initPropertyType(meta: EntityMetadata, prop: EntityProperty): void;
6
7
  }
@@ -1,49 +1,54 @@
1
1
  import 'reflect-metadata';
2
- import { EntitySchema, MetadataProvider, ReferenceKind, Utils, } from '@mikro-orm/core';
2
+ import { EntitySchema, MetadataProvider, ReferenceKind, Utils } from '@mikro-orm/core';
3
+ /** Metadata provider that uses `reflect-metadata` to infer property types from TypeScript's emitted design:type metadata. */
3
4
  export class ReflectMetadataProvider extends MetadataProvider {
4
- loadEntityMetadata(meta) {
5
- // load types and column names
6
- for (const prop of meta.props) {
7
- /* v8 ignore next */
8
- if (typeof prop.entity === 'string') {
9
- throw new Error(`Relation target needs to be an entity class or EntitySchema instance, '${prop.entity}' given instead for ${meta.className}.${prop.name}.`);
10
- }
11
- else if (prop.entity) {
12
- const tmp = prop.entity();
13
- prop.type = Array.isArray(tmp)
14
- ? tmp
15
- .map(t => Utils.className(t))
16
- .sort()
17
- .join(' | ')
18
- : Utils.className(tmp);
19
- prop.target = tmp instanceof EntitySchema ? tmp.meta.class : tmp;
20
- }
21
- else {
22
- this.initPropertyType(meta, prop);
23
- }
24
- }
5
+ loadEntityMetadata(meta) {
6
+ // load types and column names
7
+ for (const prop of meta.props) {
8
+ /* v8 ignore next */
9
+ if (typeof prop.entity === 'string') {
10
+ throw new Error(
11
+ `Relation target needs to be an entity class or EntitySchema instance, '${prop.entity}' given instead for ${meta.className}.${prop.name}.`,
12
+ );
13
+ } else if (prop.entity) {
14
+ const tmp = prop.entity();
15
+ prop.type = Array.isArray(tmp)
16
+ ? tmp
17
+ .map(t => Utils.className(t))
18
+ .sort()
19
+ .join(' | ')
20
+ : Utils.className(tmp);
21
+ prop.target = EntitySchema.is(tmp) ? tmp.meta.class : tmp;
22
+ } else {
23
+ this.initPropertyType(meta, prop);
24
+ }
25
25
  }
26
- initPropertyType(meta, prop) {
27
- const type = Reflect.getMetadata('design:type', meta.prototype, prop.name);
28
- if (!prop.type &&
29
- (!type || (type === Object && prop.kind !== ReferenceKind.SCALAR)) &&
30
- !(prop.enum && (prop.items?.length ?? 0) > 0)) {
31
- throw new Error(`Please provide either 'type' or 'entity' attribute in ${meta.className}.${prop.name}. Make sure you have 'emitDecoratorMetadata' enabled in your tsconfig.json.`);
32
- }
33
- // Force mapping to UnknownType which is a string when we see just `Object`, as that often means failed inference.
34
- // This is to prevent defaulting to JSON column type, which can often be hard to revert and cause hard to understand issues with PKs.
35
- // If there are explicitly provided `columnTypes`, we use those instead for the inference, this way
36
- // we can have things like `columnType: 'timestamp'` be respected as `type: 'Date'`.
37
- if (prop.kind === ReferenceKind.SCALAR && type === Object && !prop.columnTypes) {
38
- prop.type ??= 'any';
39
- return;
40
- }
41
- let typeName = type?.name;
42
- if (typeName && ['string', 'number', 'boolean', 'array', 'object'].includes(typeName.toLowerCase())) {
43
- typeName = typeName.toLowerCase();
44
- }
45
- prop.type ??= typeName;
46
- prop.runtimeType ??= typeName;
47
- prop.target = type;
26
+ }
27
+ initPropertyType(meta, prop) {
28
+ const type = Reflect.getMetadata('design:type', meta.prototype, prop.name);
29
+ if (
30
+ !prop.type &&
31
+ (!type || (type === Object && prop.kind !== ReferenceKind.SCALAR)) &&
32
+ !(prop.enum && (prop.items?.length ?? 0) > 0)
33
+ ) {
34
+ throw new Error(
35
+ `Please provide either 'type' or 'entity' attribute in ${meta.className}.${prop.name}. Make sure you have 'emitDecoratorMetadata' enabled in your tsconfig.json.`,
36
+ );
48
37
  }
38
+ // Force mapping to UnknownType which is a string when we see just `Object`, as that often means failed inference.
39
+ // This is to prevent defaulting to JSON column type, which can often be hard to revert and cause hard to understand issues with PKs.
40
+ // If there are explicitly provided `columnTypes`, we use those instead for the inference, this way
41
+ // we can have things like `columnType: 'timestamp'` be respected as `type: 'Date'`.
42
+ if (prop.kind === ReferenceKind.SCALAR && type === Object && !prop.columnTypes) {
43
+ prop.type ??= 'any';
44
+ return;
45
+ }
46
+ let typeName = type?.name;
47
+ if (typeName && ['string', 'number', 'boolean', 'array', 'object'].includes(typeName.toLowerCase())) {
48
+ typeName = typeName.toLowerCase();
49
+ }
50
+ prop.type ??= typeName;
51
+ prop.runtimeType ??= typeName;
52
+ prop.target = type;
53
+ }
49
54
  }
@@ -1,8 +1,8 @@
1
1
  import { type TransactionOptions } from '@mikro-orm/core';
2
2
  import { type ContextProvider } from '../utils.js';
3
3
  type TransactionalOptions<T> = TransactionOptions & {
4
- context?: ContextProvider<T>;
5
- contextName?: string;
4
+ context?: ContextProvider<T>;
5
+ contextName?: string;
6
6
  };
7
7
  /**
8
8
  * This decorator wraps the method with `em.transactional()`, so you can provide `TransactionOptions` just like with `em.transactional()`.
@@ -8,22 +8,25 @@ import { resolveContextProvider } from '../utils.js';
8
8
  * Unlike `em.transactional()`, this decorator uses `REQUIRED` propagation by default, which means it will join existing transactions.
9
9
  */
10
10
  export function Transactional(options = {}) {
11
- return function (target, propertyKey, descriptor) {
12
- const originalMethod = descriptor.value;
13
- if (originalMethod.constructor.name !== 'AsyncFunction') {
14
- throw new Error('@Transactional() should be use with async functions');
15
- }
16
- descriptor.value = async function (...args) {
17
- const { context, contextName, ...txOptions } = options;
18
- txOptions.propagation ??= TransactionPropagation.REQUIRED;
19
- const em = (await resolveContextProvider(this, context)) ||
20
- TransactionContext.getEntityManager(contextName) ||
21
- RequestContext.getEntityManager(contextName);
22
- if (!em) {
23
- throw new Error(`@Transactional() decorator can only be applied to methods of classes with \`orm: MikroORM\` property, \`em: EntityManager\` property, or with a callback parameter like \`@Transactional(() => orm)\` that returns one of those types. The parameter will contain a reference to current \`this\`. Returning an EntityRepository from it is also supported.`);
24
- }
25
- return em.transactional(() => originalMethod.apply(this, args), txOptions);
26
- };
27
- return descriptor;
11
+ return function (target, propertyKey, descriptor) {
12
+ const originalMethod = descriptor.value;
13
+ if (originalMethod.constructor.name !== 'AsyncFunction') {
14
+ throw new Error('@Transactional() should be use with async functions');
15
+ }
16
+ descriptor.value = async function (...args) {
17
+ const { context, contextName, ...txOptions } = options;
18
+ txOptions.propagation ??= TransactionPropagation.REQUIRED;
19
+ const em =
20
+ (await resolveContextProvider(this, context)) ||
21
+ TransactionContext.getEntityManager(contextName) ||
22
+ RequestContext.getEntityManager(contextName);
23
+ if (!em) {
24
+ throw new Error(
25
+ `@Transactional() decorator can only be applied to methods of classes with \`orm: MikroORM\` property, \`em: EntityManager\` property, or with a callback parameter like \`@Transactional(() => orm)\` that returns one of those types. The parameter will contain a reference to current \`this\`. Returning an EntityRepository from it is also supported.`,
26
+ );
27
+ }
28
+ return em.transactional(() => originalMethod.apply(this, args), txOptions);
28
29
  };
30
+ return descriptor;
31
+ };
29
32
  }
package/legacy/hooks.d.ts CHANGED
@@ -1,10 +1,18 @@
1
+ /** Called before a new entity is persisted to the database (legacy TypeScript decorator). */
1
2
  export declare function BeforeCreate(): (target: any, method: string) => void;
3
+ /** Called after a new entity has been persisted to the database (legacy TypeScript decorator). */
2
4
  export declare function AfterCreate(): (target: any, method: string) => void;
5
+ /** Called before an existing entity is updated in the database (legacy TypeScript decorator). */
3
6
  export declare function BeforeUpdate(): (target: any, method: string) => void;
7
+ /** Called after an existing entity has been updated in the database (legacy TypeScript decorator). */
4
8
  export declare function AfterUpdate(): (target: any, method: string) => void;
9
+ /** Called before an entity is upserted (legacy TypeScript decorator). */
5
10
  export declare function BeforeUpsert(): (target: any, method: string) => void;
11
+ /** Called after an entity has been upserted (legacy TypeScript decorator). */
6
12
  export declare function AfterUpsert(): (target: any, method: string) => void;
13
+ /** Called when an entity is instantiated by the EntityManager (legacy TypeScript decorator). */
7
14
  export declare function OnInit(): (target: any, method: string) => void;
15
+ /** Called after an entity is loaded from the database (legacy TypeScript decorator). */
8
16
  export declare function OnLoad(): (target: any, method: string) => void;
9
17
  /**
10
18
  * Called before deleting entity, but only when providing initialized entity to EM#remove()
package/legacy/hooks.js CHANGED
@@ -1,45 +1,53 @@
1
1
  import { EventType } from '@mikro-orm/core';
2
2
  import { getMetadataFromDecorator } from '../utils.js';
3
3
  function hook(type) {
4
- return function (target, method) {
5
- const meta = getMetadataFromDecorator(target.constructor);
6
- meta.hooks[type] ??= [];
7
- meta.hooks[type].push(method);
8
- };
4
+ return function (target, method) {
5
+ const meta = getMetadataFromDecorator(target.constructor);
6
+ meta.hooks[type] ??= [];
7
+ meta.hooks[type].push(method);
8
+ };
9
9
  }
10
+ /** Called before a new entity is persisted to the database (legacy TypeScript decorator). */
10
11
  export function BeforeCreate() {
11
- return hook(EventType.beforeCreate);
12
+ return hook(EventType.beforeCreate);
12
13
  }
14
+ /** Called after a new entity has been persisted to the database (legacy TypeScript decorator). */
13
15
  export function AfterCreate() {
14
- return hook(EventType.afterCreate);
16
+ return hook(EventType.afterCreate);
15
17
  }
18
+ /** Called before an existing entity is updated in the database (legacy TypeScript decorator). */
16
19
  export function BeforeUpdate() {
17
- return hook(EventType.beforeUpdate);
20
+ return hook(EventType.beforeUpdate);
18
21
  }
22
+ /** Called after an existing entity has been updated in the database (legacy TypeScript decorator). */
19
23
  export function AfterUpdate() {
20
- return hook(EventType.afterUpdate);
24
+ return hook(EventType.afterUpdate);
21
25
  }
26
+ /** Called before an entity is upserted (legacy TypeScript decorator). */
22
27
  export function BeforeUpsert() {
23
- return hook(EventType.beforeUpsert);
28
+ return hook(EventType.beforeUpsert);
24
29
  }
30
+ /** Called after an entity has been upserted (legacy TypeScript decorator). */
25
31
  export function AfterUpsert() {
26
- return hook(EventType.afterUpsert);
32
+ return hook(EventType.afterUpsert);
27
33
  }
34
+ /** Called when an entity is instantiated by the EntityManager (legacy TypeScript decorator). */
28
35
  export function OnInit() {
29
- return hook(EventType.onInit);
36
+ return hook(EventType.onInit);
30
37
  }
38
+ /** Called after an entity is loaded from the database (legacy TypeScript decorator). */
31
39
  export function OnLoad() {
32
- return hook(EventType.onLoad);
40
+ return hook(EventType.onLoad);
33
41
  }
34
42
  /**
35
43
  * Called before deleting entity, but only when providing initialized entity to EM#remove()
36
44
  */
37
45
  export function BeforeDelete() {
38
- return hook(EventType.beforeDelete);
46
+ return hook(EventType.beforeDelete);
39
47
  }
40
48
  /**
41
49
  * Called after deleting entity, but only when providing initialized entity to EM#remove()
42
50
  */
43
51
  export function AfterDelete() {
44
- return hook(EventType.afterDelete);
52
+ return hook(EventType.afterDelete);
45
53
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/decorators",
3
- "version": "7.0.2-dev.8",
3
+ "version": "7.0.2",
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",
@@ -49,10 +49,10 @@
49
49
  "copy": "node ../../scripts/copy.mjs"
50
50
  },
51
51
  "devDependencies": {
52
- "@mikro-orm/core": "^7.0.1"
52
+ "@mikro-orm/core": "^7.0.2"
53
53
  },
54
54
  "peerDependencies": {
55
- "@mikro-orm/core": "7.0.2-dev.8",
55
+ "@mikro-orm/core": "7.0.2",
56
56
  "reflect-metadata": "^0.1.0 || ^0.2.0"
57
57
  },
58
58
  "peerDependenciesMeta": {
package/utils.d.ts CHANGED
@@ -1,17 +1,36 @@
1
- import { type Dictionary, EntityManager, type EntityMetadata, EntityRepository, type MaybePromise, MetadataStorage, MikroORM, type ReferenceKind } from '@mikro-orm/core';
1
+ import {
2
+ type Dictionary,
3
+ EntityManager,
4
+ type EntityMetadata,
5
+ EntityRepository,
6
+ type MaybePromise,
7
+ MetadataStorage,
8
+ MikroORM,
9
+ type ReferenceKind,
10
+ } from '@mikro-orm/core';
2
11
  /**
3
12
  * The type of context that the user intends to inject.
4
13
  */
5
- export type ContextProvider<T> = MaybePromise<MikroORM> | ((type: T) => MaybePromise<MikroORM | EntityManager | EntityRepository<any> | {
6
- getEntityManager(): EntityManager;
7
- }>);
14
+ export type ContextProvider<T> =
15
+ | MaybePromise<MikroORM>
16
+ | ((type: T) => MaybePromise<
17
+ | MikroORM
18
+ | EntityManager
19
+ | EntityRepository<any>
20
+ | {
21
+ getEntityManager(): EntityManager;
22
+ }
23
+ >);
8
24
  /**
9
25
  * Find `EntityManager` in provided context, or else in instance's `orm` or `em` properties.
10
26
  */
11
- export declare function resolveContextProvider<T>(caller: T & {
27
+ export declare function resolveContextProvider<T>(
28
+ caller: T & {
12
29
  orm?: MaybePromise<MikroORM>;
13
30
  em?: MaybePromise<EntityManager>;
14
- }, provider?: ContextProvider<T>): Promise<EntityManager | undefined>;
31
+ },
32
+ provider?: ContextProvider<T>,
33
+ ): Promise<EntityManager | undefined>;
15
34
  /**
16
35
  * Relation decorators allow using two signatures
17
36
  * - using first parameter as options object
@@ -33,12 +52,24 @@ export declare function validateSingleDecorator(meta: EntityMetadata, propertyNa
33
52
  * We need to use the `Object.hasOwn` here, since the metadata object respects inheritance, and the `properties` object might already
34
53
  * exist for some base entity.
35
54
  */
36
- export declare function prepareMetadataContext<T>(context: ClassFieldDecoratorContext<T> | ClassGetterDecoratorContext<T> | ClassSetterDecoratorContext<T> | ClassAccessorDecoratorContext<T> | ClassMethodDecoratorContext<T>, kind?: ReferenceKind): EntityMetadata<T>;
55
+ export declare function prepareMetadataContext<T>(
56
+ context:
57
+ | ClassFieldDecoratorContext<T>
58
+ | ClassGetterDecoratorContext<T>
59
+ | ClassSetterDecoratorContext<T>
60
+ | ClassAccessorDecoratorContext<T>
61
+ | ClassMethodDecoratorContext<T>,
62
+ kind?: ReferenceKind,
63
+ ): EntityMetadata<T>;
37
64
  /**
38
65
  * Uses some dark magic to get source path to caller where decorator is used.
39
66
  * Analyzes stack trace of error created inside the function call.
40
67
  */
41
68
  export declare function lookupPathFromDecorator(name: string, stack?: string[]): string;
42
- export declare function getMetadataFromDecorator<T = any>(target: T & Dictionary & {
43
- [MetadataStorage.PATH_SYMBOL]?: string;
44
- }): EntityMetadata<T>;
69
+ /** Retrieves or creates the metadata object for a decorated entity class. */
70
+ export declare function getMetadataFromDecorator<T = any>(
71
+ target: T &
72
+ Dictionary & {
73
+ [MetadataStorage.PATH_SYMBOL]?: string;
74
+ },
75
+ ): EntityMetadata<T>;
package/utils.js CHANGED
@@ -1,28 +1,28 @@
1
- import { EntityManager, EntityRepository, MetadataError, MetadataStorage, MikroORM, Utils, } from '@mikro-orm/core';
1
+ import { EntityManager, EntityRepository, MetadataError, MetadataStorage, MikroORM, Utils } from '@mikro-orm/core';
2
2
  function getEntityManager(caller, context) {
3
- if (context instanceof EntityManager) {
4
- return context;
5
- }
6
- if (context instanceof EntityRepository) {
7
- return context.getEntityManager();
8
- }
9
- if (context instanceof MikroORM) {
10
- return context.em;
11
- }
12
- if (caller.em instanceof EntityManager) {
13
- return caller.em;
14
- }
15
- if (caller.orm instanceof MikroORM) {
16
- return caller.orm.em;
17
- }
18
- return undefined;
3
+ if (context instanceof EntityManager) {
4
+ return context;
5
+ }
6
+ if (context instanceof EntityRepository) {
7
+ return context.getEntityManager();
8
+ }
9
+ if (context instanceof MikroORM) {
10
+ return context.em;
11
+ }
12
+ if (caller.em instanceof EntityManager) {
13
+ return caller.em;
14
+ }
15
+ if (caller.orm instanceof MikroORM) {
16
+ return caller.orm.em;
17
+ }
18
+ return undefined;
19
19
  }
20
20
  /**
21
21
  * Find `EntityManager` in provided context, or else in instance's `orm` or `em` properties.
22
22
  */
23
23
  export async function resolveContextProvider(caller, provider) {
24
- const context = typeof provider === 'function' ? await provider(caller) : await provider;
25
- return getEntityManager({ orm: await caller.orm, em: await caller.em }, context);
24
+ const context = typeof provider === 'function' ? await provider(caller) : await provider;
25
+ return getEntityManager({ orm: await caller.orm, em: await caller.em }, context);
26
26
  }
27
27
  /**
28
28
  * Relation decorators allow using two signatures
@@ -34,21 +34,23 @@ export async function resolveContextProvider(caller, provider) {
34
34
  * @internal
35
35
  */
36
36
  export function processDecoratorParameters(params) {
37
- const keys = Object.keys(params);
38
- const values = Object.values(params);
39
- if (!Utils.isPlainObject(values[0])) {
40
- const lastKey = keys[keys.length - 1];
41
- const last = params[lastKey];
42
- delete params[lastKey];
43
- return { ...last, ...params };
44
- }
45
- // validate only first parameter is used if its an option object
46
- const empty = (v) => v == null || (Utils.isPlainObject(v) && !Utils.hasObjectKeys(v));
47
- if (values.slice(1).some(v => !empty(v))) {
48
- throw new Error('Mixing first decorator parameter as options object with other parameters is forbidden. ' +
49
- 'If you want to use the options parameter at first position, provide all options inside it.');
50
- }
51
- return values[0];
37
+ const keys = Object.keys(params);
38
+ const values = Object.values(params);
39
+ if (!Utils.isPlainObject(values[0])) {
40
+ const lastKey = keys[keys.length - 1];
41
+ const last = params[lastKey];
42
+ delete params[lastKey];
43
+ return { ...last, ...params };
44
+ }
45
+ // validate only first parameter is used if its an option object
46
+ const empty = v => v == null || (Utils.isPlainObject(v) && !Utils.hasObjectKeys(v));
47
+ if (values.slice(1).some(v => !empty(v))) {
48
+ throw new Error(
49
+ 'Mixing first decorator parameter as options object with other parameters is forbidden. ' +
50
+ 'If you want to use the options parameter at first position, provide all options inside it.',
51
+ );
52
+ }
53
+ return values[0];
52
54
  }
53
55
  /**
54
56
  * Validate there is only one property decorator. This disallows using `@Property()` together with e.g. `@ManyToOne()`
@@ -56,9 +58,9 @@ export function processDecoratorParameters(params) {
56
58
  * We allow the existence of the property in metadata if the reference kind is the same, this should allow things like HMR to work.
57
59
  */
58
60
  export function validateSingleDecorator(meta, propertyName, kind) {
59
- if (meta.properties[propertyName] && meta.properties[propertyName].kind !== kind) {
60
- throw MetadataError.multipleDecorators(meta.className, propertyName);
61
- }
61
+ if (meta.properties[propertyName] && meta.properties[propertyName].kind !== kind) {
62
+ throw MetadataError.multipleDecorators(meta.className, propertyName);
63
+ }
62
64
  }
63
65
  /**
64
66
  * Prepares and returns a metadata context for an entity, ensuring default structure and validating proper usage of a single decorator.
@@ -66,60 +68,64 @@ export function validateSingleDecorator(meta, propertyName, kind) {
66
68
  * exist for some base entity.
67
69
  */
68
70
  export function prepareMetadataContext(context, kind) {
69
- const meta = context.metadata;
70
- if (!Object.hasOwn(meta, 'properties')) {
71
- meta.properties = { ...meta.properties };
72
- }
73
- if (kind) {
74
- validateSingleDecorator(meta, context.name, kind);
75
- }
76
- return meta;
71
+ const meta = context.metadata;
72
+ if (!Object.hasOwn(meta, 'properties')) {
73
+ meta.properties = { ...meta.properties };
74
+ }
75
+ if (kind) {
76
+ validateSingleDecorator(meta, context.name, kind);
77
+ }
78
+ return meta;
77
79
  }
78
80
  /**
79
81
  * Uses some dark magic to get source path to caller where decorator is used.
80
82
  * Analyzes stack trace of error created inside the function call.
81
83
  */
82
84
  export function lookupPathFromDecorator(name, stack) {
83
- // use some dark magic to get source path to caller
84
- stack = stack || new Error().stack.split('\n');
85
- // In some situations (e.g. swc 1.3.4+), the presence of a source map can obscure the call to
86
- // __decorate(), replacing it with the constructor name. To support these cases we look for
87
- // Reflect.decorate() as well. Also when babel is used, we need to check
88
- // the `_applyDecoratedDescriptor` method instead.
89
- let line = stack.findIndex(line => /__decorate|Reflect\.decorate|_applyDecoratedDescriptor/.exec(line));
90
- // bun does not have those lines at all, only the DecorateProperty/DecorateConstructor,
91
- // but those are also present in node, so we need to check this only if they weren't found.
92
- if (line === -1) {
93
- // here we handle bun which stack is different from nodejs so we search for reflect-metadata
94
- // Different bun versions might have different stack traces. The "last index" works for both 1.2.6 and 1.2.7.
95
- const reflectLine = stack.findLastIndex(line => line.replace(/\\/g, '/').includes('node_modules/reflect-metadata/Reflect.js'));
96
- if (reflectLine === -1 || reflectLine + 2 >= stack.length || !stack[reflectLine + 1].includes('bun:wrap')) {
97
- return name;
98
- }
99
- line = reflectLine + 2;
100
- }
101
- if (stack[line].includes('Reflect.decorate')) {
102
- line++;
103
- }
104
- // Skip decorator runtime helpers (tslib, @oxc-project/runtime, etc.)
105
- while (line < stack.length &&
106
- /node_modules\/(tslib\/|@oxc-project\/runtime\/)/.test(stack[line].replace(/\\/g, '/'))) {
107
- line++;
108
- }
109
- try {
110
- const re = /\(.+\)/i.exec(stack[line]) ? /\((.*):\d+:\d+\)/ : /at\s*(.*):\d+:\d+$/;
111
- return stack[line].match(re)[1];
112
- }
113
- catch {
114
- return name;
115
- }
85
+ // use some dark magic to get source path to caller
86
+ stack = stack || new Error().stack.split('\n');
87
+ // In some situations (e.g. swc 1.3.4+), the presence of a source map can obscure the call to
88
+ // __decorate(), replacing it with the constructor name. To support these cases we look for
89
+ // Reflect.decorate() as well. Also when babel is used, we need to check
90
+ // the `_applyDecoratedDescriptor` method instead.
91
+ let line = stack.findIndex(line => /__decorate|Reflect\.decorate|_applyDecoratedDescriptor/.exec(line));
92
+ // bun does not have those lines at all, only the DecorateProperty/DecorateConstructor,
93
+ // but those are also present in node, so we need to check this only if they weren't found.
94
+ if (line === -1) {
95
+ // here we handle bun which stack is different from nodejs so we search for reflect-metadata
96
+ // Different bun versions might have different stack traces. The "last index" works for both 1.2.6 and 1.2.7.
97
+ const reflectLine = stack.findLastIndex(line =>
98
+ line.replace(/\\/g, '/').includes('node_modules/reflect-metadata/Reflect.js'),
99
+ );
100
+ if (reflectLine === -1 || reflectLine + 2 >= stack.length || !stack[reflectLine + 1].includes('bun:wrap')) {
101
+ return name;
102
+ }
103
+ line = reflectLine + 2;
104
+ }
105
+ if (stack[line].includes('Reflect.decorate')) {
106
+ line++;
107
+ }
108
+ // Skip decorator runtime helpers (tslib, @oxc-project/runtime, etc.)
109
+ while (
110
+ line < stack.length &&
111
+ /node_modules\/(tslib\/|@oxc-project\/runtime\/)/.test(stack[line].replace(/\\/g, '/'))
112
+ ) {
113
+ line++;
114
+ }
115
+ try {
116
+ const re = /\(.+\)/i.exec(stack[line]) ? /\((.*):\d+:\d+\)/ : /at\s*(.*):\d+:\d+$/;
117
+ return stack[line].match(re)[1];
118
+ } catch {
119
+ return name;
120
+ }
116
121
  }
122
+ /** Retrieves or creates the metadata object for a decorated entity class. */
117
123
  export function getMetadataFromDecorator(target) {
118
- if (!Object.hasOwn(target, MetadataStorage.PATH_SYMBOL)) {
119
- Object.defineProperty(target, MetadataStorage.PATH_SYMBOL, {
120
- value: lookupPathFromDecorator(target.name),
121
- writable: true,
122
- });
123
- }
124
- return MetadataStorage.getMetadata(target.name, target[MetadataStorage.PATH_SYMBOL]);
124
+ if (!Object.hasOwn(target, MetadataStorage.PATH_SYMBOL)) {
125
+ Object.defineProperty(target, MetadataStorage.PATH_SYMBOL, {
126
+ value: lookupPathFromDecorator(target.name),
127
+ writable: true,
128
+ });
129
+ }
130
+ return MetadataStorage.getMetadata(target.name, target[MetadataStorage.PATH_SYMBOL]);
125
131
  }