@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.
- package/README.md +128 -294
- package/es/Check.d.ts +4 -1
- package/es/Check.js +7 -6
- package/es/CreateRequestContext.d.ts +15 -2
- package/es/CreateRequestContext.js +26 -22
- package/es/Embeddable.d.ts +4 -1
- package/es/Embeddable.js +10 -9
- package/es/Embedded.d.ts +5 -1
- package/es/Embedded.js +11 -10
- package/es/Entity.d.ts +4 -1
- package/es/Entity.js +10 -9
- package/es/Enum.d.ts +4 -1
- package/es/Enum.js +11 -10
- package/es/Filter.d.ts +1 -0
- package/es/Filter.js +5 -4
- package/es/Formula.d.ts +5 -1
- package/es/Formula.js +10 -9
- package/es/Indexed.d.ts +8 -2
- package/es/Indexed.js +13 -11
- package/es/ManyToMany.d.ts +6 -1
- package/es/ManyToMany.js +9 -8
- package/es/ManyToOne.d.ts +5 -1
- package/es/ManyToOne.js +8 -7
- package/es/OneToMany.d.ts +9 -2
- package/es/OneToMany.js +8 -8
- package/es/OneToOne.d.ts +6 -1
- package/es/OneToOne.js +10 -9
- package/es/PrimaryKey.d.ts +8 -2
- package/es/PrimaryKey.js +14 -12
- package/es/Property.d.ts +12 -1
- package/es/Property.js +38 -41
- package/es/Transactional.d.ts +8 -3
- package/es/Transactional.js +18 -15
- package/es/hooks.d.ts +40 -8
- package/es/hooks.js +25 -17
- package/legacy/Check.d.ts +4 -1
- package/legacy/Check.js +10 -9
- package/legacy/CreateRequestContext.d.ts +6 -1
- package/legacy/CreateRequestContext.js +28 -24
- package/legacy/Embeddable.d.ts +1 -0
- package/legacy/Embeddable.js +9 -8
- package/legacy/Embedded.d.ts +5 -1
- package/legacy/Embedded.js +12 -11
- package/legacy/Entity.d.ts +1 -0
- package/legacy/Entity.js +9 -8
- package/legacy/Enum.d.ts +4 -1
- package/legacy/Enum.js +11 -10
- package/legacy/Filter.d.ts +1 -0
- package/legacy/Filter.js +5 -4
- package/legacy/Formula.d.ts +5 -1
- package/legacy/Formula.js +10 -9
- package/legacy/Indexed.d.ts +8 -2
- package/legacy/Indexed.js +14 -12
- package/legacy/ManyToMany.d.ts +9 -2
- package/legacy/ManyToMany.js +8 -8
- package/legacy/ManyToOne.d.ts +8 -2
- package/legacy/ManyToOne.js +8 -8
- package/legacy/OneToMany.d.ts +9 -2
- package/legacy/OneToMany.js +8 -8
- package/legacy/OneToOne.d.ts +9 -2
- package/legacy/OneToOne.js +10 -10
- package/legacy/PrimaryKey.d.ts +8 -2
- package/legacy/PrimaryKey.js +15 -13
- package/legacy/Property.d.ts +4 -1
- package/legacy/Property.js +26 -25
- package/legacy/ReflectMetadataProvider.d.ts +3 -2
- package/legacy/ReflectMetadataProvider.js +49 -44
- package/legacy/Transactional.d.ts +2 -2
- package/legacy/Transactional.js +20 -17
- package/legacy/hooks.d.ts +8 -0
- package/legacy/hooks.js +23 -15
- package/package.json +3 -3
- package/utils.d.ts +41 -10
- package/utils.js +91 -85
package/legacy/Property.js
CHANGED
|
@@ -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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
5
|
-
|
|
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
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
5
|
-
|
|
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()`.
|
package/legacy/Transactional.js
CHANGED
|
@@ -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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
24
|
+
return hook(EventType.afterUpdate);
|
|
21
25
|
}
|
|
26
|
+
/** Called before an entity is upserted (legacy TypeScript decorator). */
|
|
22
27
|
export function BeforeUpsert() {
|
|
23
|
-
|
|
28
|
+
return hook(EventType.beforeUpsert);
|
|
24
29
|
}
|
|
30
|
+
/** Called after an entity has been upserted (legacy TypeScript decorator). */
|
|
25
31
|
export function AfterUpsert() {
|
|
26
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
52
|
+
"@mikro-orm/core": "^7.0.2"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
|
-
"@mikro-orm/core": "7.0.2
|
|
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 {
|
|
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> =
|
|
6
|
-
|
|
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>(
|
|
27
|
+
export declare function resolveContextProvider<T>(
|
|
28
|
+
caller: T & {
|
|
12
29
|
orm?: MaybePromise<MikroORM>;
|
|
13
30
|
em?: MaybePromise<EntityManager>;
|
|
14
|
-
},
|
|
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>(
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
|
1
|
+
import { EntityManager, EntityRepository, MetadataError, MetadataStorage, MikroORM, Utils } from '@mikro-orm/core';
|
|
2
2
|
function getEntityManager(caller, context) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
25
|
-
|
|
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
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
60
|
-
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
}
|