Initial commit - Event Planner application
This commit is contained in:
225
node_modules/@mikro-orm/core/metadata/EntitySchema.d.ts
generated
vendored
Normal file
225
node_modules/@mikro-orm/core/metadata/EntitySchema.d.ts
generated
vendored
Normal file
@@ -0,0 +1,225 @@
|
||||
import {
|
||||
EntityMetadata,
|
||||
type AnyEntity,
|
||||
type EntityKey,
|
||||
type Constructor,
|
||||
type DeepPartial,
|
||||
type EntityName,
|
||||
type EntityProperty,
|
||||
type CleanKeys,
|
||||
type ExpandProperty,
|
||||
type IsNever,
|
||||
type EntityCtor,
|
||||
} from '../typings.js';
|
||||
import { type EventType, ReferenceKind } from '../enums.js';
|
||||
import type { EventArgs } from '../events/EventSubscriber.js';
|
||||
import { Type } from '../types/Type.js';
|
||||
import type {
|
||||
PropertyOptions,
|
||||
ManyToOneOptions,
|
||||
OneToOneOptions,
|
||||
OneToManyOptions,
|
||||
ManyToManyOptions,
|
||||
EmbeddedOptions,
|
||||
EnumOptions,
|
||||
PrimaryKeyOptions,
|
||||
SerializedPrimaryKeyOptions,
|
||||
IndexOptions,
|
||||
UniqueOptions,
|
||||
} from './types.js';
|
||||
type TypeType =
|
||||
| string
|
||||
| NumberConstructor
|
||||
| StringConstructor
|
||||
| BooleanConstructor
|
||||
| DateConstructor
|
||||
| ArrayConstructor
|
||||
| Constructor<Type<any>>
|
||||
| Type<any>;
|
||||
type TypeDef<Target> =
|
||||
| {
|
||||
type: TypeType;
|
||||
}
|
||||
| {
|
||||
entity: () => EntityName<Target> | EntityName[];
|
||||
};
|
||||
type EmbeddedTypeDef<Target> =
|
||||
| {
|
||||
type: TypeType;
|
||||
}
|
||||
| {
|
||||
entity: () => EntityName<Target> | EntityName[];
|
||||
};
|
||||
/** Union type representing all possible property definition shapes in an EntitySchema. */
|
||||
export type EntitySchemaProperty<Target, Owner> =
|
||||
| ({
|
||||
kind: ReferenceKind.MANY_TO_ONE | 'm:1';
|
||||
} & TypeDef<Target> &
|
||||
ManyToOneOptions<Owner, Target>)
|
||||
| ({
|
||||
kind: ReferenceKind.ONE_TO_ONE | '1:1';
|
||||
} & TypeDef<Target> &
|
||||
OneToOneOptions<Owner, Target>)
|
||||
| ({
|
||||
kind: ReferenceKind.ONE_TO_MANY | '1:m';
|
||||
} & TypeDef<Target> &
|
||||
OneToManyOptions<Owner, Target>)
|
||||
| ({
|
||||
kind: ReferenceKind.MANY_TO_MANY | 'm:n';
|
||||
} & TypeDef<Target> &
|
||||
ManyToManyOptions<Owner, Target>)
|
||||
| ({
|
||||
kind: ReferenceKind.EMBEDDED | 'embedded';
|
||||
} & EmbeddedTypeDef<Target> &
|
||||
EmbeddedOptions<Owner, Target> &
|
||||
PropertyOptions<Owner>)
|
||||
| ({
|
||||
enum: true;
|
||||
} & EnumOptions<Owner>)
|
||||
| (TypeDef<Target> & PropertyOptions<Owner>);
|
||||
type OmitBaseProps<Entity, Base> = IsNever<Base> extends true ? Entity : Omit<Entity, keyof Base>;
|
||||
/** Configuration object for defining an entity via EntitySchema. */
|
||||
export type EntitySchemaMetadata<Entity, Base = never, Class extends EntityCtor = EntityCtor<Entity>> = Omit<
|
||||
Partial<EntityMetadata<Entity>>,
|
||||
'name' | 'properties' | 'extends'
|
||||
> &
|
||||
(
|
||||
| {
|
||||
name: string;
|
||||
}
|
||||
| {
|
||||
class: Class;
|
||||
name?: string;
|
||||
}
|
||||
) & {
|
||||
extends?: EntityName<Base>;
|
||||
} & {
|
||||
properties?: {
|
||||
[Key in keyof OmitBaseProps<Entity, Base> as CleanKeys<OmitBaseProps<Entity, Base>, Key>]-?: EntitySchemaProperty<
|
||||
ExpandProperty<NonNullable<Entity[Key]>>,
|
||||
Entity
|
||||
>;
|
||||
};
|
||||
} & {
|
||||
inheritance?: 'tpt';
|
||||
};
|
||||
/** Class-less entity definition that provides a programmatic API for defining entities without decorators. */
|
||||
export declare class EntitySchema<Entity = any, Base = never, Class extends EntityCtor = EntityCtor<Entity>> {
|
||||
/**
|
||||
* When schema links the entity class via `class` option, this registry allows the lookup from opposite side,
|
||||
* so we can use the class in `entities` option just like the EntitySchema instance.
|
||||
*/
|
||||
static REGISTRY: Map<AnyEntity, EntitySchema>;
|
||||
/** @internal Type-level marker for fast entity type inference */
|
||||
readonly '~entity': Entity;
|
||||
private readonly _meta;
|
||||
private internal;
|
||||
private initialized;
|
||||
constructor(meta: EntitySchemaMetadata<Entity, Base, Class>);
|
||||
/**
|
||||
* Checks if the given value is an EntitySchema instance, using duck-typing
|
||||
* as a fallback when `instanceof` fails due to CJS/ESM dual-package hazard
|
||||
* (e.g. when using `tsx` or `@swc-node/register` with `"type": "commonjs"` projects).
|
||||
*/
|
||||
static is(item: unknown): item is EntitySchema;
|
||||
/** Creates an EntitySchema from existing EntityMetadata (used internally). */
|
||||
static fromMetadata<T = AnyEntity, U = never>(
|
||||
meta: EntityMetadata<T> | DeepPartial<EntityMetadata<T>>,
|
||||
): EntitySchema<T, U>;
|
||||
/** Adds a scalar property to the entity schema. */
|
||||
addProperty(
|
||||
name: EntityKey<Entity>,
|
||||
type?: TypeType,
|
||||
options?: PropertyOptions<Entity> | EntityProperty<Entity>,
|
||||
): void;
|
||||
/** Adds an enum property to the entity schema. */
|
||||
addEnum(name: EntityKey<Entity>, type?: TypeType, options?: EnumOptions<Entity>): void;
|
||||
/** Adds a version property for optimistic locking. */
|
||||
addVersion(name: EntityKey<Entity>, type: TypeType, options?: PropertyOptions<Entity>): void;
|
||||
/** Adds a primary key property to the entity schema. */
|
||||
addPrimaryKey(name: EntityKey<Entity>, type: TypeType, options?: PrimaryKeyOptions<Entity>): void;
|
||||
/** Adds a serialized primary key property (e.g. for MongoDB ObjectId). */
|
||||
addSerializedPrimaryKey(name: EntityKey<Entity>, type: TypeType, options?: SerializedPrimaryKeyOptions<Entity>): void;
|
||||
/** Adds an embedded property to the entity schema. */
|
||||
addEmbedded<Target = AnyEntity>(name: EntityKey<Entity>, options: EmbeddedOptions<Entity, Target>): void;
|
||||
/** Adds a many-to-one relation to the entity schema. */
|
||||
addManyToOne<Target = AnyEntity>(
|
||||
name: EntityKey<Entity>,
|
||||
type: TypeType,
|
||||
options: ManyToOneOptions<Entity, Target>,
|
||||
): void;
|
||||
/** Adds a many-to-many relation to the entity schema. */
|
||||
addManyToMany<Target = AnyEntity>(
|
||||
name: EntityKey<Entity>,
|
||||
type: TypeType,
|
||||
options: ManyToManyOptions<Entity, Target>,
|
||||
): void;
|
||||
/** Adds a one-to-many relation to the entity schema. */
|
||||
addOneToMany<Target = AnyEntity>(
|
||||
name: EntityKey<Entity>,
|
||||
type: TypeType,
|
||||
options: OneToManyOptions<Entity, Target>,
|
||||
): void;
|
||||
/** Adds a one-to-one relation to the entity schema. */
|
||||
addOneToOne<Target = AnyEntity>(
|
||||
name: EntityKey<Entity>,
|
||||
type: TypeType,
|
||||
options: OneToOneOptions<Entity, Target>,
|
||||
): void;
|
||||
/** Adds an index definition to the entity schema. */
|
||||
addIndex<Key extends string>(options: IndexOptions<Entity, Key>): void;
|
||||
/** Adds a unique constraint definition to the entity schema. */
|
||||
addUnique<Key extends string>(options: UniqueOptions<Entity, Key>): void;
|
||||
/** Sets a custom repository class for this entity. */
|
||||
setCustomRepository(repository: () => Constructor): void;
|
||||
/** Sets the base entity that this schema extends. */
|
||||
setExtends(base: EntityName): void;
|
||||
/** Sets or replaces the entity class associated with this schema. */
|
||||
setClass(cls: Class): void;
|
||||
/** Returns the underlying EntityMetadata. */
|
||||
get meta(): EntityMetadata<Entity, Class>;
|
||||
/** Returns the entity class name. */
|
||||
get name(): string | EntityName<Entity>;
|
||||
/** Returns the database table name. */
|
||||
get tableName(): string;
|
||||
get class(): Class;
|
||||
get properties(): Record<string, any>;
|
||||
new(...params: ConstructorParameters<Class>): Entity;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
init(): this;
|
||||
/**
|
||||
* Check if this entity is part of a TPT hierarchy by walking up the extends chain.
|
||||
* This handles mid-level abstract entities (e.g., Animal -> Mammal -> Dog where Mammal is abstract).
|
||||
*/
|
||||
private isPartOfTPTHierarchy;
|
||||
private initProperties;
|
||||
private initPrimaryKeys;
|
||||
private normalizeType;
|
||||
private createProperty;
|
||||
private rename;
|
||||
private renameCompositeOptions;
|
||||
/**
|
||||
* Adds a lifecycle hook handler to the entity schema.
|
||||
* This method allows registering hooks after the entity is defined,
|
||||
* which can be useful for avoiding circular type references.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* export const Article = defineEntity({
|
||||
* name: 'Article',
|
||||
* properties: { ... },
|
||||
* });
|
||||
*
|
||||
* Article.addHook('beforeCreate', async args => {
|
||||
* args.entity.slug = args.entity.title.toLowerCase();
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
addHook<T extends Entity = Entity>(
|
||||
event: EventType | `${EventType}`,
|
||||
handler: (args: EventArgs<T>) => void | Promise<void>,
|
||||
): this;
|
||||
}
|
||||
export {};
|
||||
405
node_modules/@mikro-orm/core/metadata/EntitySchema.js
generated
vendored
Normal file
405
node_modules/@mikro-orm/core/metadata/EntitySchema.js
generated
vendored
Normal file
@@ -0,0 +1,405 @@
|
||||
import { EntityMetadata } from '../typings.js';
|
||||
import { BaseEntity } from '../entity/BaseEntity.js';
|
||||
import { Cascade, ReferenceKind } from '../enums.js';
|
||||
import { Type } from '../types/Type.js';
|
||||
import { Utils } from '../utils/Utils.js';
|
||||
import { EnumArrayType } from '../types/EnumArrayType.js';
|
||||
/** Class-less entity definition that provides a programmatic API for defining entities without decorators. */
|
||||
export class EntitySchema {
|
||||
/**
|
||||
* When schema links the entity class via `class` option, this registry allows the lookup from opposite side,
|
||||
* so we can use the class in `entities` option just like the EntitySchema instance.
|
||||
*/
|
||||
static REGISTRY = new Map();
|
||||
_meta;
|
||||
internal = false;
|
||||
initialized = false;
|
||||
constructor(meta) {
|
||||
meta.name = meta.class ? meta.class.name : meta.name;
|
||||
if (meta.name) {
|
||||
meta.abstract ??= false;
|
||||
}
|
||||
this._meta = new EntityMetadata({
|
||||
className: meta.name,
|
||||
...meta,
|
||||
});
|
||||
this._meta.root ??= this._meta;
|
||||
if (meta.class && !meta.internal) {
|
||||
EntitySchema.REGISTRY.set(meta.class, this);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Checks if the given value is an EntitySchema instance, using duck-typing
|
||||
* as a fallback when `instanceof` fails due to CJS/ESM dual-package hazard
|
||||
* (e.g. when using `tsx` or `@swc-node/register` with `"type": "commonjs"` projects).
|
||||
*/
|
||||
static is(item) {
|
||||
if (item instanceof EntitySchema) {
|
||||
return true;
|
||||
}
|
||||
return item != null && typeof item === 'object' && item.constructor?.name === 'EntitySchema' && 'meta' in item;
|
||||
}
|
||||
/** Creates an EntitySchema from existing EntityMetadata (used internally). */
|
||||
static fromMetadata(meta) {
|
||||
const schema = new EntitySchema({ ...meta, internal: true });
|
||||
schema.internal = true;
|
||||
return schema;
|
||||
}
|
||||
/** Adds a scalar property to the entity schema. */
|
||||
addProperty(name, type, options = {}) {
|
||||
this.renameCompositeOptions(name, options);
|
||||
const prop = {
|
||||
name,
|
||||
kind: ReferenceKind.SCALAR,
|
||||
...options,
|
||||
...this.normalizeType(options, type),
|
||||
};
|
||||
if (type && Type.isMappedType(type.prototype)) {
|
||||
prop.type = type;
|
||||
}
|
||||
if (typeof prop.formula === 'string') {
|
||||
const formula = prop.formula;
|
||||
prop.formula = () => formula;
|
||||
}
|
||||
if (prop.formula) {
|
||||
prop.persist ??= false;
|
||||
}
|
||||
this._meta.properties[name] = prop;
|
||||
}
|
||||
/** Adds an enum property to the entity schema. */
|
||||
addEnum(name, type, options = {}) {
|
||||
if (options.items instanceof Function) {
|
||||
options.items = Utils.extractEnumValues(options.items());
|
||||
}
|
||||
// enum arrays are simple numeric/string arrays, the constraint is enforced in the custom type only
|
||||
if (options.array && !options.type) {
|
||||
options.type = new EnumArrayType(`${this._meta.className}.${name}`, options.items);
|
||||
options.enum = false;
|
||||
}
|
||||
const prop = { enum: true, ...options };
|
||||
if (prop.array) {
|
||||
prop.enum = false;
|
||||
}
|
||||
// force string labels on native enums
|
||||
if (prop.nativeEnumName && Array.isArray(prop.items)) {
|
||||
prop.items = prop.items.map(val => '' + val);
|
||||
}
|
||||
this.addProperty(name, this.internal ? type : type || 'enum', prop);
|
||||
}
|
||||
/** Adds a version property for optimistic locking. */
|
||||
addVersion(name, type, options = {}) {
|
||||
this.addProperty(name, type, { version: true, ...options });
|
||||
}
|
||||
/** Adds a primary key property to the entity schema. */
|
||||
addPrimaryKey(name, type, options = {}) {
|
||||
this.addProperty(name, type, { primary: true, ...options });
|
||||
}
|
||||
/** Adds a serialized primary key property (e.g. for MongoDB ObjectId). */
|
||||
addSerializedPrimaryKey(name, type, options = {}) {
|
||||
this._meta.serializedPrimaryKey = name;
|
||||
this.addProperty(name, type, { serializedPrimaryKey: true, ...options });
|
||||
}
|
||||
/** Adds an embedded property to the entity schema. */
|
||||
addEmbedded(name, options) {
|
||||
this.renameCompositeOptions(name, options);
|
||||
Utils.defaultValue(options, 'prefix', true);
|
||||
if (options.array) {
|
||||
options.object = true; // force object mode for arrays
|
||||
}
|
||||
this._meta.properties[name] = {
|
||||
name,
|
||||
kind: ReferenceKind.EMBEDDED,
|
||||
...this.normalizeType(options),
|
||||
...options,
|
||||
};
|
||||
}
|
||||
/** Adds a many-to-one relation to the entity schema. */
|
||||
addManyToOne(name, type, options) {
|
||||
const prop = this.createProperty(ReferenceKind.MANY_TO_ONE, options);
|
||||
prop.owner = true;
|
||||
if (prop.joinColumns && !prop.fieldNames) {
|
||||
prop.fieldNames = prop.joinColumns;
|
||||
}
|
||||
if (prop.fieldNames && !prop.joinColumns) {
|
||||
prop.joinColumns = prop.fieldNames;
|
||||
}
|
||||
// By default, the foreign key constraint is created on the relation
|
||||
Utils.defaultValue(prop, 'createForeignKeyConstraint', true);
|
||||
this.addProperty(name, type, prop);
|
||||
}
|
||||
/** Adds a many-to-many relation to the entity schema. */
|
||||
addManyToMany(name, type, options) {
|
||||
options.fixedOrder = options.fixedOrder || !!options.fixedOrderColumn;
|
||||
if (!options.owner && !options.mappedBy) {
|
||||
options.owner = true;
|
||||
}
|
||||
if (options.owner) {
|
||||
Utils.renameKey(options, 'mappedBy', 'inversedBy');
|
||||
// By default, the foreign key constraint is created on the relation
|
||||
Utils.defaultValue(options, 'createForeignKeyConstraint', true);
|
||||
}
|
||||
const prop = this.createProperty(ReferenceKind.MANY_TO_MANY, options);
|
||||
this.addProperty(name, type, prop);
|
||||
}
|
||||
/** Adds a one-to-many relation to the entity schema. */
|
||||
addOneToMany(name, type, options) {
|
||||
const prop = this.createProperty(ReferenceKind.ONE_TO_MANY, options);
|
||||
this.addProperty(name, type, prop);
|
||||
}
|
||||
/** Adds a one-to-one relation to the entity schema. */
|
||||
addOneToOne(name, type, options) {
|
||||
const prop = this.createProperty(ReferenceKind.ONE_TO_ONE, options);
|
||||
Utils.defaultValue(prop, 'owner', !!prop.inversedBy || !prop.mappedBy);
|
||||
Utils.defaultValue(prop, 'unique', prop.owner);
|
||||
if (prop.owner) {
|
||||
if (options.mappedBy) {
|
||||
Utils.renameKey(prop, 'mappedBy', 'inversedBy');
|
||||
}
|
||||
// By default, the foreign key constraint is created on the relation
|
||||
Utils.defaultValue(prop, 'createForeignKeyConstraint', true);
|
||||
}
|
||||
if (prop.joinColumns && !prop.fieldNames) {
|
||||
prop.fieldNames = prop.joinColumns;
|
||||
}
|
||||
if (prop.fieldNames && !prop.joinColumns) {
|
||||
prop.joinColumns = prop.fieldNames;
|
||||
}
|
||||
this.addProperty(name, type, prop);
|
||||
}
|
||||
/** Adds an index definition to the entity schema. */
|
||||
addIndex(options) {
|
||||
this._meta.indexes.push(options);
|
||||
}
|
||||
/** Adds a unique constraint definition to the entity schema. */
|
||||
addUnique(options) {
|
||||
this._meta.uniques.push(options);
|
||||
}
|
||||
/** Sets a custom repository class for this entity. */
|
||||
setCustomRepository(repository) {
|
||||
this._meta.repository = repository;
|
||||
}
|
||||
/** Sets the base entity that this schema extends. */
|
||||
setExtends(base) {
|
||||
this._meta.extends = base;
|
||||
}
|
||||
/** Sets or replaces the entity class associated with this schema. */
|
||||
setClass(cls) {
|
||||
const oldClass = this._meta.class;
|
||||
const sameClass = this._meta.class === cls;
|
||||
this._meta.class = cls;
|
||||
this._meta.prototype = cls.prototype;
|
||||
this._meta.className = this._meta.name ?? cls.name;
|
||||
if (!sameClass || !this._meta.constructorParams) {
|
||||
this._meta.constructorParams = Utils.getConstructorParams(cls);
|
||||
}
|
||||
if (!this.internal) {
|
||||
// Remove old class from registry if it's being replaced with a different class
|
||||
if (oldClass && oldClass !== cls && EntitySchema.REGISTRY.get(oldClass) === this) {
|
||||
EntitySchema.REGISTRY.delete(oldClass);
|
||||
}
|
||||
EntitySchema.REGISTRY.set(cls, this);
|
||||
}
|
||||
const base = Object.getPrototypeOf(cls);
|
||||
// Only set extends if the parent is NOT the auto-generated class for this same entity.
|
||||
// When the user extends the auto-generated class (from defineEntity without a class option)
|
||||
// and registers their custom class via setClass, we don't want to discover the
|
||||
// auto-generated class as a separate parent entity.
|
||||
if (base !== BaseEntity && base.name !== this._meta.className) {
|
||||
this._meta.extends ??= base.name ? base : undefined;
|
||||
}
|
||||
}
|
||||
/** Returns the underlying EntityMetadata. */
|
||||
get meta() {
|
||||
return this._meta;
|
||||
}
|
||||
/** Returns the entity class name. */
|
||||
get name() {
|
||||
return this._meta.className;
|
||||
}
|
||||
/** Returns the database table name. */
|
||||
get tableName() {
|
||||
return this._meta.tableName;
|
||||
}
|
||||
get class() {
|
||||
return this._meta.class;
|
||||
}
|
||||
get properties() {
|
||||
return this._meta.properties;
|
||||
}
|
||||
new(...params) {
|
||||
return new this._meta.class(...params);
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
init() {
|
||||
if (this.initialized) {
|
||||
return this;
|
||||
}
|
||||
this.setClass(this._meta.class);
|
||||
// Abstract TPT entities keep their name because they have their own table
|
||||
const isTPT = this._meta.inheritance === 'tpt' || this.isPartOfTPTHierarchy();
|
||||
if (this._meta.abstract && !this._meta.discriminatorColumn && !isTPT) {
|
||||
delete this._meta.name;
|
||||
}
|
||||
const tableName = this._meta.collection ?? this._meta.tableName;
|
||||
if (tableName?.includes('.') && !this._meta.schema) {
|
||||
this._meta.schema = tableName.substring(0, tableName.indexOf('.'));
|
||||
this._meta.tableName = tableName.substring(tableName.indexOf('.') + 1);
|
||||
}
|
||||
this.initProperties();
|
||||
this.initPrimaryKeys();
|
||||
this._meta.props = Object.values(this._meta.properties);
|
||||
this._meta.relations = this._meta.props.filter(
|
||||
prop =>
|
||||
typeof prop.kind !== 'undefined' && prop.kind !== ReferenceKind.SCALAR && prop.kind !== ReferenceKind.EMBEDDED,
|
||||
);
|
||||
this.initialized = true;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Check if this entity is part of a TPT hierarchy by walking up the extends chain.
|
||||
* This handles mid-level abstract entities (e.g., Animal -> Mammal -> Dog where Mammal is abstract).
|
||||
*/
|
||||
isPartOfTPTHierarchy() {
|
||||
let parent = this._meta.extends;
|
||||
while (parent) {
|
||||
const parentSchema = EntitySchema.is(parent) ? parent : EntitySchema.REGISTRY.get(parent);
|
||||
if (!parentSchema) {
|
||||
break;
|
||||
}
|
||||
if (parentSchema._meta.inheritance === 'tpt') {
|
||||
return true;
|
||||
}
|
||||
parent = parentSchema._meta.extends;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
initProperties() {
|
||||
Utils.entries(this._meta.properties).forEach(([name, options]) => {
|
||||
if (Type.isMappedType(options.type)) {
|
||||
options.type ??= options.type.constructor.name;
|
||||
}
|
||||
switch (options.kind) {
|
||||
case ReferenceKind.ONE_TO_ONE:
|
||||
this.addOneToOne(name, options.type, options);
|
||||
break;
|
||||
case ReferenceKind.ONE_TO_MANY:
|
||||
this.addOneToMany(name, options.type, options);
|
||||
break;
|
||||
case ReferenceKind.MANY_TO_ONE:
|
||||
this.addManyToOne(name, options.type, options);
|
||||
break;
|
||||
case ReferenceKind.MANY_TO_MANY:
|
||||
this.addManyToMany(name, options.type, options);
|
||||
break;
|
||||
case ReferenceKind.EMBEDDED:
|
||||
this.addEmbedded(name, options);
|
||||
break;
|
||||
default:
|
||||
if (options.enum) {
|
||||
this.addEnum(name, options.type, options);
|
||||
} else if (options.primary) {
|
||||
this.addPrimaryKey(name, options.type, options);
|
||||
} else if (options.serializedPrimaryKey) {
|
||||
this.addSerializedPrimaryKey(name, options.type, options);
|
||||
} else if (options.version) {
|
||||
this.addVersion(name, options.type, options);
|
||||
} else {
|
||||
this.addProperty(name, options.type, options);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
initPrimaryKeys() {
|
||||
const pks = Object.values(this._meta.properties).filter(prop => prop.primary);
|
||||
if (pks.length > 0) {
|
||||
this._meta.primaryKeys = pks.map(prop => prop.name);
|
||||
this._meta.compositePK = pks.length > 1;
|
||||
this._meta.simplePK = !this._meta.compositePK && pks[0].kind === ReferenceKind.SCALAR && !pks[0].customType;
|
||||
}
|
||||
if (pks.length === 1 && ['number', 'bigint'].includes(pks[0].type)) {
|
||||
pks[0].autoincrement ??= true;
|
||||
}
|
||||
const serializedPrimaryKey = Object.values(this._meta.properties).find(prop => prop.serializedPrimaryKey);
|
||||
if (serializedPrimaryKey) {
|
||||
this._meta.serializedPrimaryKey = serializedPrimaryKey.name;
|
||||
}
|
||||
}
|
||||
normalizeType(options, type) {
|
||||
if ('entity' in options) {
|
||||
/* v8 ignore next */
|
||||
if (typeof options.entity === 'string') {
|
||||
throw new Error(
|
||||
`Relation target needs to be an entity class or EntitySchema instance, string '${options.entity}' given instead for ${this._meta.className}.${options.name}.`,
|
||||
);
|
||||
} else if (options.entity) {
|
||||
const tmp = options.entity();
|
||||
type = options.type = Array.isArray(tmp)
|
||||
? tmp
|
||||
.map(t => Utils.className(t))
|
||||
.sort()
|
||||
.join(' | ')
|
||||
: Utils.className(tmp);
|
||||
const target = EntitySchema.is(tmp) ? tmp.meta.class : tmp;
|
||||
return { type, target };
|
||||
}
|
||||
}
|
||||
if (type instanceof Function) {
|
||||
type = type.name;
|
||||
}
|
||||
if (['String', 'Number', 'Boolean', 'Array'].includes(type)) {
|
||||
type = type.toLowerCase();
|
||||
}
|
||||
return { type };
|
||||
}
|
||||
createProperty(kind, options) {
|
||||
return {
|
||||
kind,
|
||||
cascade: [Cascade.PERSIST],
|
||||
...options,
|
||||
};
|
||||
}
|
||||
rename(data, from, to) {
|
||||
if (from in data && !(to in data)) {
|
||||
// @ts-ignore
|
||||
data[to] = [data[from]];
|
||||
// @ts-ignore
|
||||
delete data[from];
|
||||
}
|
||||
}
|
||||
renameCompositeOptions(name, options = {}) {
|
||||
if (name !== options.name && !options.fieldNames) {
|
||||
Utils.renameKey(options, 'name', 'fieldName');
|
||||
} else if (options.name && (options.fieldNames?.length ?? 0) > 1) {
|
||||
delete options.name;
|
||||
}
|
||||
this.rename(options, 'fieldName', 'fieldNames');
|
||||
this.rename(options, 'joinColumn', 'joinColumns');
|
||||
this.rename(options, 'inverseJoinColumn', 'inverseJoinColumns');
|
||||
this.rename(options, 'referenceColumnName', 'referencedColumnNames');
|
||||
this.rename(options, 'columnType', 'columnTypes');
|
||||
}
|
||||
/**
|
||||
* Adds a lifecycle hook handler to the entity schema.
|
||||
* This method allows registering hooks after the entity is defined,
|
||||
* which can be useful for avoiding circular type references.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* export const Article = defineEntity({
|
||||
* name: 'Article',
|
||||
* properties: { ... },
|
||||
* });
|
||||
*
|
||||
* Article.addHook('beforeCreate', async args => {
|
||||
* args.entity.slug = args.entity.title.toLowerCase();
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
addHook(event, handler) {
|
||||
this._meta.hooks[event] ??= [];
|
||||
this._meta.hooks[event].push(handler);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
122
node_modules/@mikro-orm/core/metadata/MetadataDiscovery.d.ts
generated
vendored
Normal file
122
node_modules/@mikro-orm/core/metadata/MetadataDiscovery.d.ts
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
import { type EntityClass, EntityMetadata, type EntityName } from '../typings.js';
|
||||
import type { Configuration } from '../utils/Configuration.js';
|
||||
import { MetadataStorage } from './MetadataStorage.js';
|
||||
import { EntitySchema } from './EntitySchema.js';
|
||||
import type { Platform } from '../platforms/Platform.js';
|
||||
/** Discovers, validates, and processes entity metadata from configured sources. */
|
||||
export declare class MetadataDiscovery {
|
||||
#private;
|
||||
constructor(metadata: MetadataStorage, platform: Platform, config: Configuration);
|
||||
/** Discovers all entities asynchronously and returns the populated MetadataStorage. */
|
||||
discover(preferTs?: boolean): Promise<MetadataStorage>;
|
||||
/** Discovers all entities synchronously and returns the populated MetadataStorage. */
|
||||
discoverSync(): MetadataStorage;
|
||||
private mapDiscoveredEntities;
|
||||
private initAccessors;
|
||||
/** Processes discovered entities: initializes relations, embeddables, indexes, and inheritance. */
|
||||
processDiscoveredEntities(discovered: EntityMetadata[]): EntityMetadata[];
|
||||
private findEntities;
|
||||
private discoverMissingTargets;
|
||||
private tryDiscoverTargets;
|
||||
discoverReferences<T>(refs: Iterable<EntityClass<T> | EntitySchema<T>>, validate?: boolean): EntityMetadata<T>[];
|
||||
reset<T>(entityName: EntityName<T>): void;
|
||||
private getSchema;
|
||||
private getRootEntity;
|
||||
private discoverEntity;
|
||||
private initNullability;
|
||||
private applyNamingStrategy;
|
||||
private initOwnColumns;
|
||||
private initFieldName;
|
||||
private initManyToOneFieldName;
|
||||
private initManyToManyFieldName;
|
||||
private initManyToManyFields;
|
||||
private isExplicitTableName;
|
||||
private initManyToOneFields;
|
||||
private initOneToManyFields;
|
||||
private processEntity;
|
||||
private findReferencingProperties;
|
||||
private initFactoryField;
|
||||
private ensureCorrectFKOrderInPivotEntity;
|
||||
private definePivotTableEntity;
|
||||
/**
|
||||
* Create a scalar property for a pivot table column.
|
||||
*/
|
||||
private createPivotScalarProperty;
|
||||
/**
|
||||
* Get column types for an entity's primary keys, initializing them if needed.
|
||||
*/
|
||||
private getPrimaryKeyColumnTypes;
|
||||
/**
|
||||
* Add missing FK columns for a polymorphic entity to an existing pivot table.
|
||||
*/
|
||||
private addPolymorphicPivotColumns;
|
||||
/**
|
||||
* Define properties for a polymorphic pivot table.
|
||||
*/
|
||||
private definePolymorphicPivotProperties;
|
||||
/**
|
||||
* Create a virtual M:1 relation from pivot to a polymorphic owner entity.
|
||||
* This enables single-query join loading for inverse-side polymorphic M:N.
|
||||
*/
|
||||
private definePolymorphicOwnerRelation;
|
||||
private defineFixedOrderProperty;
|
||||
private definePivotProperty;
|
||||
private autoWireBidirectionalProperties;
|
||||
private defineBaseEntityProperties;
|
||||
private initPolyEmbeddables;
|
||||
private initPolymorphicRelation;
|
||||
private initEmbeddables;
|
||||
private initSingleTableInheritance;
|
||||
/**
|
||||
* First pass of TPT initialization: sets up hierarchy relationships
|
||||
* (inheritanceType, tptParent, tptChildren) before properties have fieldNames.
|
||||
*/
|
||||
private initTPTRelationships;
|
||||
/**
|
||||
* Second pass of TPT initialization: re-resolves metadata references after fieldNames
|
||||
* are set, syncs to registry metadata, and sets up discriminators.
|
||||
*/
|
||||
private finalizeTPTInheritance;
|
||||
/**
|
||||
* Initialize TPT discriminator map and virtual discriminator property.
|
||||
* Unlike STI where the discriminator is a persisted column, TPT discriminator is computed
|
||||
* at query time using CASE WHEN expressions based on which child table has data.
|
||||
*/
|
||||
private initTPTDiscriminator;
|
||||
/**
|
||||
* Recursively collect all TPT descendants (children, grandchildren, etc.)
|
||||
*/
|
||||
private collectAllTPTDescendants;
|
||||
/**
|
||||
* Computes ownProps for TPT entities - only properties defined in THIS entity,
|
||||
* not inherited from parent. Also creates synthetic join properties for parent/child relationships.
|
||||
*
|
||||
* Called multiple times during discovery as metadata is progressively built.
|
||||
* Each pass overwrites earlier results to reflect the final state of properties.
|
||||
*/
|
||||
private computeTPTOwnProps;
|
||||
/** Returns the depth of a TPT entity in its hierarchy (0 for root). */
|
||||
private getTPTDepth;
|
||||
/**
|
||||
* Find the direct TPT parent entity for the given entity.
|
||||
*/
|
||||
private getTPTParent;
|
||||
private createDiscriminatorProperty;
|
||||
private initAutoincrement;
|
||||
private createSchemaTable;
|
||||
private initCheckConstraints;
|
||||
private initGeneratedColumn;
|
||||
private getDefaultVersionValue;
|
||||
private inferDefaultValue;
|
||||
private initDefaultValue;
|
||||
private inferTypeFromDefault;
|
||||
private initVersionProperty;
|
||||
private initCustomType;
|
||||
private initRelation;
|
||||
private initColumnType;
|
||||
private getMappedType;
|
||||
private getPrefix;
|
||||
private initUnsigned;
|
||||
private initIndexes;
|
||||
private shouldForceConstructorUsage;
|
||||
}
|
||||
1973
node_modules/@mikro-orm/core/metadata/MetadataDiscovery.js
generated
vendored
Normal file
1973
node_modules/@mikro-orm/core/metadata/MetadataDiscovery.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
33
node_modules/@mikro-orm/core/metadata/MetadataProvider.d.ts
generated
vendored
Normal file
33
node_modules/@mikro-orm/core/metadata/MetadataProvider.d.ts
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import type { EntityMetadata } from '../typings.js';
|
||||
import type { Logger } from '../logging/Logger.js';
|
||||
import type { SyncCacheAdapter } from '../cache/CacheAdapter.js';
|
||||
import type { Platform } from '../platforms/Platform.js';
|
||||
export interface IConfiguration {
|
||||
get(key: string, defaultValue?: any): any;
|
||||
getLogger(): Logger;
|
||||
getMetadataCacheAdapter(): SyncCacheAdapter;
|
||||
getPlatform(): Platform;
|
||||
}
|
||||
/** Base metadata provider that resolves entity type information and manages metadata caching. */
|
||||
export declare class MetadataProvider {
|
||||
protected readonly config: IConfiguration;
|
||||
constructor(config: IConfiguration);
|
||||
/** Resolves entity references and type information for all properties in the given metadata. */
|
||||
loadEntityMetadata(meta: EntityMetadata): void;
|
||||
/** Merges cached metadata into the given entity metadata, preserving function expressions. */
|
||||
loadFromCache(meta: EntityMetadata, cache: EntityMetadata): void;
|
||||
/** Whether this provider class uses metadata caching by default. */
|
||||
static useCache(): boolean;
|
||||
/** Whether metadata caching is enabled for this instance. */
|
||||
useCache(): boolean;
|
||||
saveToCache(meta: EntityMetadata): void;
|
||||
/** Attempts to load metadata from cache, returning undefined if not available. */
|
||||
getCachedMetadata<T>(
|
||||
meta: Pick<EntityMetadata<T>, 'className' | 'path' | 'root'>,
|
||||
root: EntityMetadata<T>,
|
||||
): EntityMetadata<T> | undefined;
|
||||
/** Combines individual metadata cache entries into a single file. */
|
||||
combineCache(): void;
|
||||
/** Returns the cache key for the given entity metadata. */
|
||||
getCacheKey(meta: Pick<EntityMetadata, 'className' | 'path'>): string;
|
||||
}
|
||||
95
node_modules/@mikro-orm/core/metadata/MetadataProvider.js
generated
vendored
Normal file
95
node_modules/@mikro-orm/core/metadata/MetadataProvider.js
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
import { Utils } from '../utils/Utils.js';
|
||||
import { EntitySchema } from './EntitySchema.js';
|
||||
/** Base metadata provider that resolves entity type information and manages metadata caching. */
|
||||
export class MetadataProvider {
|
||||
config;
|
||||
constructor(config) {
|
||||
this.config = config;
|
||||
}
|
||||
/** Resolves entity references and type information for all properties in the given metadata. */
|
||||
loadEntityMetadata(meta) {
|
||||
for (const prop of meta.props) {
|
||||
/* v8 ignore next */
|
||||
if (typeof prop.entity === 'string') {
|
||||
prop.type = prop.entity;
|
||||
} else if (prop.entity) {
|
||||
const tmp = prop.entity();
|
||||
prop.type = Array.isArray(tmp)
|
||||
? tmp
|
||||
.map(t => Utils.className(t))
|
||||
.sort()
|
||||
.join(' | ')
|
||||
: Utils.className(tmp);
|
||||
prop.target = EntitySchema.is(tmp) ? tmp.meta.class : tmp;
|
||||
} else if (!prop.type && !((prop.enum || prop.array) && (prop.items?.length ?? 0) > 0)) {
|
||||
throw new Error(`Please provide either 'type' or 'entity' attribute in ${meta.className}.${prop.name}.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Merges cached metadata into the given entity metadata, preserving function expressions. */
|
||||
loadFromCache(meta, cache) {
|
||||
Object.values(cache.properties).forEach(prop => {
|
||||
const metaProp = meta.properties[prop.name];
|
||||
/* v8 ignore next */
|
||||
if (metaProp?.enum && Array.isArray(metaProp.items)) {
|
||||
delete prop.items;
|
||||
}
|
||||
});
|
||||
// Preserve function expressions from indexes/uniques — they can't survive JSON cache serialization
|
||||
const expressionMap = new Map();
|
||||
for (const arr of [meta.indexes, meta.uniques]) {
|
||||
for (const idx of arr ?? []) {
|
||||
if (typeof idx.expression === 'function' && idx.name) {
|
||||
expressionMap.set(idx.name, idx.expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
Utils.mergeConfig(meta, cache);
|
||||
// Restore function expressions that were lost during JSON serialization
|
||||
if (expressionMap.size > 0) {
|
||||
for (const arr of [meta.indexes, meta.uniques]) {
|
||||
for (const idx of arr ?? []) {
|
||||
const fn = idx.name && expressionMap.get(idx.name);
|
||||
if (fn && typeof idx.expression !== 'function') {
|
||||
idx.expression = fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Whether this provider class uses metadata caching by default. */
|
||||
static useCache() {
|
||||
return false;
|
||||
}
|
||||
/** Whether metadata caching is enabled for this instance. */
|
||||
useCache() {
|
||||
return this.config.get('metadataCache').enabled ?? MetadataProvider.useCache();
|
||||
}
|
||||
saveToCache(meta) {
|
||||
//
|
||||
}
|
||||
/** Attempts to load metadata from cache, returning undefined if not available. */
|
||||
getCachedMetadata(meta, root) {
|
||||
if (!this.useCache()) {
|
||||
return undefined;
|
||||
}
|
||||
const cache = meta.path && this.config.getMetadataCacheAdapter().get(this.getCacheKey(meta));
|
||||
if (cache) {
|
||||
this.loadFromCache(meta, cache);
|
||||
meta.root = root;
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
/** Combines individual metadata cache entries into a single file. */
|
||||
combineCache() {
|
||||
const path = this.config.getMetadataCacheAdapter().combine?.();
|
||||
// override the path in the options, so we can log it from the CLI in `cache:generate` command
|
||||
if (path) {
|
||||
this.config.get('metadataCache').combined = path;
|
||||
}
|
||||
}
|
||||
/** Returns the cache key for the given entity metadata. */
|
||||
getCacheKey(meta) {
|
||||
return meta.className;
|
||||
}
|
||||
}
|
||||
43
node_modules/@mikro-orm/core/metadata/MetadataStorage.d.ts
generated
vendored
Normal file
43
node_modules/@mikro-orm/core/metadata/MetadataStorage.d.ts
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
import { type Dictionary, EntityMetadata, type EntityName } from '../typings.js';
|
||||
import type { EntityManager } from '../EntityManager.js';
|
||||
/** Registry that stores and provides access to entity metadata by class, name, or id. */
|
||||
export declare class MetadataStorage {
|
||||
#private;
|
||||
static readonly PATH_SYMBOL: unique symbol;
|
||||
constructor(metadata?: Dictionary<EntityMetadata>);
|
||||
/** Returns the global metadata dictionary, or a specific entry by entity name and path. */
|
||||
static getMetadata(): Dictionary<EntityMetadata>;
|
||||
static getMetadata<T = any>(entity: string, path: string): EntityMetadata<T>;
|
||||
/** Checks whether an entity with the given class name exists in the global metadata. */
|
||||
static isKnownEntity(name: string): boolean;
|
||||
/** Clears all entries from the global metadata registry. */
|
||||
static clear(): void;
|
||||
/** Returns the map of all registered entity metadata. */
|
||||
getAll(): Map<EntityName, EntityMetadata>;
|
||||
/** Returns metadata for the given entity, optionally initializing it if not found. */
|
||||
get<T = any>(entityName: EntityName<T>, init?: boolean): EntityMetadata<T>;
|
||||
/** Finds metadata for the given entity, returning undefined if not registered. */
|
||||
find<T = any>(entityName: EntityName<T>): EntityMetadata<T> | undefined;
|
||||
/** Checks whether metadata exists for the given entity. */
|
||||
has<T>(entityName: EntityName<T>): boolean;
|
||||
/** Registers metadata for the given entity. */
|
||||
set<T>(entityName: EntityName<T>, meta: EntityMetadata): EntityMetadata;
|
||||
/** Removes metadata for the given entity from all internal maps. */
|
||||
reset<T>(entityName: EntityName<T>): void;
|
||||
/** Decorates all entity prototypes with helper methods (e.g. init, toJSON). */
|
||||
decorate(em: EntityManager): void;
|
||||
[Symbol.iterator](): IterableIterator<EntityMetadata>;
|
||||
/** Returns metadata by its internal numeric id. */
|
||||
getById<T>(id: number): EntityMetadata<T>;
|
||||
/** Returns metadata by class name, optionally throwing if not found. */
|
||||
getByClassName<T = any, V extends boolean = true>(
|
||||
className: string,
|
||||
validate?: V,
|
||||
): V extends true ? EntityMetadata<T> : EntityMetadata<T> | undefined;
|
||||
/** Returns metadata by unique name, optionally throwing if not found. */
|
||||
getByUniqueName<T = any, V extends boolean = true>(
|
||||
uniqueName: string,
|
||||
validate?: V,
|
||||
): V extends true ? EntityMetadata<T> : EntityMetadata<T> | undefined;
|
||||
private validate;
|
||||
}
|
||||
128
node_modules/@mikro-orm/core/metadata/MetadataStorage.js
generated
vendored
Normal file
128
node_modules/@mikro-orm/core/metadata/MetadataStorage.js
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
import { EntityMetadata } from '../typings.js';
|
||||
import { Utils } from '../utils/Utils.js';
|
||||
import { MetadataError } from '../errors.js';
|
||||
import { EntityHelper } from '../entity/EntityHelper.js';
|
||||
import { EntitySchema } from './EntitySchema.js';
|
||||
function getGlobalStorage(namespace) {
|
||||
const key = `mikro-orm-${namespace}`;
|
||||
globalThis[key] = globalThis[key] || {};
|
||||
return globalThis[key];
|
||||
}
|
||||
/** Registry that stores and provides access to entity metadata by class, name, or id. */
|
||||
export class MetadataStorage {
|
||||
static PATH_SYMBOL = Symbol.for('@mikro-orm/core/MetadataStorage.PATH_SYMBOL');
|
||||
static #metadata = getGlobalStorage('metadata');
|
||||
#metadataMap = new Map();
|
||||
#idMap;
|
||||
#classNameMap;
|
||||
#uniqueNameMap;
|
||||
constructor(metadata = {}) {
|
||||
this.#idMap = {};
|
||||
this.#uniqueNameMap = {};
|
||||
this.#classNameMap = Utils.copy(metadata, false);
|
||||
for (const meta of Object.values(this.#classNameMap)) {
|
||||
this.#idMap[meta._id] = meta;
|
||||
this.#uniqueNameMap[meta.uniqueName] = meta;
|
||||
this.#metadataMap.set(meta.class, meta);
|
||||
}
|
||||
}
|
||||
static getMetadata(entity, path) {
|
||||
const key = entity && path ? entity + '-' + Utils.hash(path) : null;
|
||||
if (key && !MetadataStorage.#metadata[key]) {
|
||||
MetadataStorage.#metadata[key] = new EntityMetadata({ className: entity, path });
|
||||
}
|
||||
if (key) {
|
||||
return MetadataStorage.#metadata[key];
|
||||
}
|
||||
return MetadataStorage.#metadata;
|
||||
}
|
||||
/** Checks whether an entity with the given class name exists in the global metadata. */
|
||||
static isKnownEntity(name) {
|
||||
return !!Object.values(this.#metadata).find(meta => meta.className === name);
|
||||
}
|
||||
/** Clears all entries from the global metadata registry. */
|
||||
static clear() {
|
||||
Object.keys(this.#metadata).forEach(k => delete this.#metadata[k]);
|
||||
}
|
||||
/** Returns the map of all registered entity metadata. */
|
||||
getAll() {
|
||||
return this.#metadataMap;
|
||||
}
|
||||
/** Returns metadata for the given entity, optionally initializing it if not found. */
|
||||
get(entityName, init = false) {
|
||||
const exists = this.find(entityName);
|
||||
if (exists) {
|
||||
return exists;
|
||||
}
|
||||
const className = Utils.className(entityName);
|
||||
if (!init) {
|
||||
throw MetadataError.missingMetadata(className);
|
||||
}
|
||||
const meta = new EntityMetadata({ class: entityName, name: className });
|
||||
this.set(entityName, meta);
|
||||
return meta;
|
||||
}
|
||||
/** Finds metadata for the given entity, returning undefined if not registered. */
|
||||
find(entityName) {
|
||||
if (!entityName) {
|
||||
return;
|
||||
}
|
||||
const meta = this.#metadataMap.get(entityName);
|
||||
if (meta) {
|
||||
return meta;
|
||||
}
|
||||
if (EntitySchema.is(entityName)) {
|
||||
return this.#metadataMap.get(entityName.meta.class) ?? entityName.meta;
|
||||
}
|
||||
return this.#classNameMap[Utils.className(entityName)];
|
||||
}
|
||||
/** Checks whether metadata exists for the given entity. */
|
||||
has(entityName) {
|
||||
return this.#metadataMap.has(entityName);
|
||||
}
|
||||
/** Registers metadata for the given entity. */
|
||||
set(entityName, meta) {
|
||||
this.#metadataMap.set(entityName, meta);
|
||||
this.#idMap[meta._id] = meta;
|
||||
this.#uniqueNameMap[meta.uniqueName] = meta;
|
||||
this.#classNameMap[Utils.className(entityName)] = meta;
|
||||
return meta;
|
||||
}
|
||||
/** Removes metadata for the given entity from all internal maps. */
|
||||
reset(entityName) {
|
||||
const meta = this.find(entityName);
|
||||
if (meta) {
|
||||
this.#metadataMap.delete(meta.class);
|
||||
delete this.#idMap[meta._id];
|
||||
delete this.#uniqueNameMap[meta.uniqueName];
|
||||
delete this.#classNameMap[meta.className];
|
||||
}
|
||||
}
|
||||
/** Decorates all entity prototypes with helper methods (e.g. init, toJSON). */
|
||||
decorate(em) {
|
||||
[...this.#metadataMap.values()].filter(meta => meta.prototype).forEach(meta => EntityHelper.decorate(meta, em));
|
||||
}
|
||||
*[Symbol.iterator]() {
|
||||
for (const meta of this.#metadataMap.values()) {
|
||||
yield meta;
|
||||
}
|
||||
}
|
||||
/** Returns metadata by its internal numeric id. */
|
||||
getById(id) {
|
||||
return this.#idMap[id];
|
||||
}
|
||||
/** Returns metadata by class name, optionally throwing if not found. */
|
||||
getByClassName(className, validate = true) {
|
||||
return this.validate(this.#classNameMap[className], className, validate);
|
||||
}
|
||||
/** Returns metadata by unique name, optionally throwing if not found. */
|
||||
getByUniqueName(uniqueName, validate = true) {
|
||||
return this.validate(this.#uniqueNameMap[uniqueName], uniqueName, validate);
|
||||
}
|
||||
validate(meta, id, validate) {
|
||||
if (!meta && validate) {
|
||||
throw MetadataError.missingMetadata(id);
|
||||
}
|
||||
return meta;
|
||||
}
|
||||
}
|
||||
47
node_modules/@mikro-orm/core/metadata/MetadataValidator.d.ts
generated
vendored
Normal file
47
node_modules/@mikro-orm/core/metadata/MetadataValidator.d.ts
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
import type { EntityMetadata, EntityName } from '../typings.js';
|
||||
import { type MetadataDiscoveryOptions } from '../utils/Configuration.js';
|
||||
import type { MetadataStorage } from './MetadataStorage.js';
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export declare class MetadataValidator {
|
||||
validateEntityDefinition<T>(metadata: MetadataStorage, name: EntityName<T>, options: MetadataDiscoveryOptions): void;
|
||||
validateDiscovered(discovered: EntityMetadata[], options: MetadataDiscoveryOptions): void;
|
||||
private validateReference;
|
||||
private validateTargetKey;
|
||||
/**
|
||||
* Checks if a property has a unique constraint (either via `unique: true` or single-property `@Unique` decorator).
|
||||
* Composite unique constraints are not sufficient for targetKey.
|
||||
*/
|
||||
private isPropertyUnique;
|
||||
private validatePolymorphicTargets;
|
||||
private validateBidirectional;
|
||||
private validateOwningSide;
|
||||
private validateInverseSide;
|
||||
private validateIndexes;
|
||||
private validateDuplicateFieldNames;
|
||||
private validateVersionField;
|
||||
/**
|
||||
* Validates that entity properties do not use dangerous names that could lead to
|
||||
* prototype pollution vulnerabilities. This validation ensures that property names
|
||||
* cannot be exploited to modify object prototypes when values are assigned during
|
||||
* entity hydration or persistence operations.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private validatePropertyNames;
|
||||
/**
|
||||
* Validates view entity configuration.
|
||||
* View entities must have an expression.
|
||||
*/
|
||||
private validateViewEntity;
|
||||
/**
|
||||
* Validates that STI and TPT are not mixed in the same inheritance hierarchy.
|
||||
* An entity hierarchy can use either STI (discriminatorColumn) or TPT (inheritance: 'tpt'),
|
||||
* but not both.
|
||||
*
|
||||
* Note: This validation runs before `initTablePerTypeInheritance` sets `inheritanceType`,
|
||||
* so we check the raw `inheritance` option from the decorator/schema.
|
||||
*/
|
||||
private validateInheritanceStrategies;
|
||||
}
|
||||
425
node_modules/@mikro-orm/core/metadata/MetadataValidator.js
generated
vendored
Normal file
425
node_modules/@mikro-orm/core/metadata/MetadataValidator.js
generated
vendored
Normal file
@@ -0,0 +1,425 @@
|
||||
import { Utils } from '../utils/Utils.js';
|
||||
import { MetadataError } from '../errors.js';
|
||||
import { ReferenceKind } from '../enums.js';
|
||||
/**
|
||||
* List of property names that could lead to prototype pollution vulnerabilities.
|
||||
* These names should never be used as entity property names because they could
|
||||
* allow malicious code to modify object prototypes when property values are assigned.
|
||||
*
|
||||
* - `__proto__`: Could modify the prototype chain
|
||||
* - `constructor`: Could modify the constructor property
|
||||
* - `prototype`: Could modify the prototype object
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
const DANGEROUS_PROPERTY_NAMES = ['__proto__', 'constructor', 'prototype'];
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class MetadataValidator {
|
||||
validateEntityDefinition(metadata, name, options) {
|
||||
const meta = metadata.get(name);
|
||||
// View entities (expression with view flag) behave like regular tables but are read-only
|
||||
// They can have primary keys and are created as actual database views
|
||||
if (meta.view) {
|
||||
this.validateViewEntity(meta);
|
||||
return;
|
||||
}
|
||||
// Virtual entities (expression without view flag) have restrictions - no PKs, limited relation types
|
||||
// Note: meta.virtual is set later in sync(), so we check for expression && !view here
|
||||
if (meta.virtual || (meta.expression && !meta.view)) {
|
||||
for (const prop of Utils.values(meta.properties)) {
|
||||
if (
|
||||
![ReferenceKind.SCALAR, ReferenceKind.EMBEDDED, ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(
|
||||
prop.kind,
|
||||
)
|
||||
) {
|
||||
throw new MetadataError(
|
||||
`Only scalars, embedded properties and to-many relations are allowed inside virtual entity. Found '${prop.kind}' in ${meta.className}.${prop.name}`,
|
||||
);
|
||||
}
|
||||
if (prop.primary) {
|
||||
throw new MetadataError(
|
||||
`Virtual entity ${meta.className} cannot have primary key ${meta.className}.${prop.name}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// entities have PK
|
||||
if (!meta.embeddable && (!meta.primaryKeys || meta.primaryKeys.length === 0)) {
|
||||
throw MetadataError.fromMissingPrimaryKey(meta);
|
||||
}
|
||||
this.validateVersionField(meta);
|
||||
this.validateDuplicateFieldNames(meta, options);
|
||||
this.validateIndexes(meta, meta.indexes ?? [], 'index');
|
||||
this.validateIndexes(meta, meta.uniques ?? [], 'unique');
|
||||
this.validatePropertyNames(meta);
|
||||
for (const prop of Utils.values(meta.properties)) {
|
||||
if (prop.kind !== ReferenceKind.SCALAR) {
|
||||
this.validateReference(meta, prop, options);
|
||||
this.validateBidirectional(meta, prop);
|
||||
} else if (metadata.getByClassName(prop.type, false)) {
|
||||
throw MetadataError.propertyTargetsEntityType(meta, prop, metadata.getByClassName(prop.type));
|
||||
}
|
||||
}
|
||||
}
|
||||
validateDiscovered(discovered, options) {
|
||||
if (discovered.length === 0 && options.warnWhenNoEntities) {
|
||||
throw MetadataError.noEntityDiscovered();
|
||||
}
|
||||
// Validate no mixing of STI and TPT in the same hierarchy
|
||||
this.validateInheritanceStrategies(discovered);
|
||||
const tableNames = discovered.filter(
|
||||
meta =>
|
||||
!meta.abstract &&
|
||||
!meta.embeddable &&
|
||||
meta === meta.root &&
|
||||
(meta.tableName || meta.collection) &&
|
||||
meta.schema !== '*',
|
||||
);
|
||||
const duplicateTableNames = Utils.findDuplicates(
|
||||
tableNames.map(meta => {
|
||||
const tableName = meta.tableName || meta.collection;
|
||||
return (meta.schema ? '.' + meta.schema : '') + tableName;
|
||||
}),
|
||||
);
|
||||
if (duplicateTableNames.length > 0 && options.checkDuplicateTableNames) {
|
||||
throw MetadataError.duplicateEntityDiscovered(duplicateTableNames);
|
||||
}
|
||||
// validate we found at least one entity (not just abstract/base entities)
|
||||
if (discovered.filter(meta => meta.name).length === 0 && options.warnWhenNoEntities) {
|
||||
throw MetadataError.onlyAbstractEntitiesDiscovered();
|
||||
}
|
||||
const unwrap = type =>
|
||||
type
|
||||
.replace(/Array<(.*)>/, '$1') // unwrap array
|
||||
.replace(/\[]$/, '') // remove array suffix
|
||||
.replace(/\((.*)\)/, '$1'); // unwrap union types
|
||||
const name = p => {
|
||||
if (typeof p === 'function' && !p.prototype) {
|
||||
return Utils.className(p());
|
||||
}
|
||||
return Utils.className(p);
|
||||
};
|
||||
const pivotProps = new Map();
|
||||
// check for not discovered entities
|
||||
discovered.forEach(meta =>
|
||||
Object.values(meta.properties).forEach(prop => {
|
||||
if (
|
||||
prop.kind !== ReferenceKind.SCALAR &&
|
||||
!unwrap(prop.type)
|
||||
.split(/ ?\| ?/)
|
||||
.every(type => discovered.find(m => m.className === type))
|
||||
) {
|
||||
throw MetadataError.fromUnknownEntity(prop.type, `${meta.className}.${prop.name}`);
|
||||
}
|
||||
if (prop.pivotEntity) {
|
||||
const props = pivotProps.get(name(prop.pivotEntity)) ?? [];
|
||||
props.push({ meta, prop });
|
||||
pivotProps.set(name(prop.pivotEntity), props);
|
||||
}
|
||||
}),
|
||||
);
|
||||
pivotProps.forEach(props => {
|
||||
// if the pivot entity is used in more than one property, check if they are linked
|
||||
if (props.length > 1 && props.every(p => !p.prop.mappedBy && !p.prop.inversedBy)) {
|
||||
throw MetadataError.invalidManyToManyWithPivotEntity(
|
||||
props[0].meta,
|
||||
props[0].prop,
|
||||
props[1].meta,
|
||||
props[1].prop,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
validateReference(meta, prop, options) {
|
||||
// references do have types
|
||||
if (!prop.type) {
|
||||
throw MetadataError.fromWrongTypeDefinition(meta, prop);
|
||||
}
|
||||
// Polymorphic relations have multiple targets, validate PK compatibility
|
||||
if (prop.polymorphic && prop.polymorphTargets) {
|
||||
this.validatePolymorphicTargets(meta, prop);
|
||||
return;
|
||||
}
|
||||
const targetMeta = prop.targetMeta;
|
||||
// references do have type of known entity
|
||||
if (!targetMeta) {
|
||||
throw MetadataError.fromWrongTypeDefinition(meta, prop);
|
||||
}
|
||||
if (targetMeta.abstract && !targetMeta.root?.inheritanceType && !targetMeta.embeddable) {
|
||||
throw MetadataError.targetIsAbstract(meta, prop);
|
||||
}
|
||||
if (
|
||||
[ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) &&
|
||||
prop.persist === false &&
|
||||
targetMeta.compositePK &&
|
||||
options.checkNonPersistentCompositeProps
|
||||
) {
|
||||
throw MetadataError.nonPersistentCompositeProp(meta, prop);
|
||||
}
|
||||
this.validateTargetKey(meta, prop, targetMeta);
|
||||
}
|
||||
validateTargetKey(meta, prop, targetMeta) {
|
||||
if (!prop.targetKey) {
|
||||
return;
|
||||
}
|
||||
// targetKey is not supported for ManyToMany relations
|
||||
if (prop.kind === ReferenceKind.MANY_TO_MANY) {
|
||||
throw MetadataError.targetKeyOnManyToMany(meta, prop);
|
||||
}
|
||||
// targetKey must point to an existing property
|
||||
const targetProp = targetMeta.properties[prop.targetKey];
|
||||
if (!targetProp) {
|
||||
throw MetadataError.targetKeyNotFound(meta, prop);
|
||||
}
|
||||
// targetKey must point to a unique property (composite unique is not sufficient)
|
||||
if (!this.isPropertyUnique(targetProp, targetMeta)) {
|
||||
throw MetadataError.targetKeyNotUnique(meta, prop);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Checks if a property has a unique constraint (either via `unique: true` or single-property `@Unique` decorator).
|
||||
* Composite unique constraints are not sufficient for targetKey.
|
||||
*/
|
||||
isPropertyUnique(prop, meta) {
|
||||
if (prop.unique) {
|
||||
return true;
|
||||
}
|
||||
// Check for single-property unique constraint via @Unique decorator
|
||||
return !!meta.uniques?.some(u => {
|
||||
const props = Utils.asArray(u.properties);
|
||||
return props.length === 1 && props[0] === prop.name && !u.options;
|
||||
});
|
||||
}
|
||||
validatePolymorphicTargets(meta, prop) {
|
||||
const targets = prop.polymorphTargets;
|
||||
// Validate targetKey exists and is compatible across all targets
|
||||
if (prop.targetKey) {
|
||||
for (const target of targets) {
|
||||
const targetProp = target.properties[prop.targetKey];
|
||||
if (!targetProp) {
|
||||
throw MetadataError.targetKeyNotFound(meta, prop, target);
|
||||
}
|
||||
// targetKey must point to a unique property (composite unique is not sufficient)
|
||||
if (!this.isPropertyUnique(targetProp, target)) {
|
||||
throw MetadataError.targetKeyNotUnique(meta, prop, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
const firstPKs = targets[0].getPrimaryProps();
|
||||
for (let i = 1; i < targets.length; i++) {
|
||||
const target = targets[i];
|
||||
const targetPKs = target.getPrimaryProps();
|
||||
if (targetPKs.length !== firstPKs.length) {
|
||||
throw MetadataError.incompatiblePolymorphicTargets(
|
||||
meta,
|
||||
prop,
|
||||
targets[0],
|
||||
target,
|
||||
'different number of primary keys',
|
||||
);
|
||||
}
|
||||
for (let j = 0; j < firstPKs.length; j++) {
|
||||
const firstPK = firstPKs[j];
|
||||
const targetPK = targetPKs[j];
|
||||
if (firstPK.runtimeType !== targetPK.runtimeType) {
|
||||
throw MetadataError.incompatiblePolymorphicTargets(
|
||||
meta,
|
||||
prop,
|
||||
targets[0],
|
||||
target,
|
||||
`incompatible primary key types: ${firstPK.name} (${firstPK.runtimeType}) vs ${targetPK.name} (${targetPK.runtimeType})`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
validateBidirectional(meta, prop) {
|
||||
if (prop.inversedBy) {
|
||||
this.validateOwningSide(meta, prop);
|
||||
} else if (prop.mappedBy) {
|
||||
this.validateInverseSide(meta, prop);
|
||||
} else if (prop.kind === ReferenceKind.ONE_TO_MANY && !prop.mappedBy) {
|
||||
// 1:m property has `mappedBy`
|
||||
throw MetadataError.fromMissingOption(meta, prop, 'mappedBy');
|
||||
}
|
||||
}
|
||||
validateOwningSide(meta, prop) {
|
||||
// For polymorphic relations, inversedBy may point to multiple entity types
|
||||
if (prop.polymorphic && prop.polymorphTargets?.length) {
|
||||
// For polymorphic relations, validate inversedBy against each target
|
||||
// The inverse property should exist on the target entities and reference back to this property
|
||||
for (const targetMeta of prop.polymorphTargets) {
|
||||
const inverse = targetMeta.properties[prop.inversedBy];
|
||||
// The inverse property is optional - some targets may not have it
|
||||
if (!inverse) {
|
||||
continue;
|
||||
}
|
||||
// Validate the inverse property
|
||||
if (inverse.targetMeta?.root.class !== meta.root.class) {
|
||||
throw MetadataError.fromWrongReference(meta, prop, 'inversedBy', inverse);
|
||||
}
|
||||
// inverse side is not defined as owner
|
||||
if (inverse.inversedBy || inverse.owner) {
|
||||
throw MetadataError.fromWrongOwnership(meta, prop, 'inversedBy');
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
const inverse = prop.targetMeta.properties[prop.inversedBy];
|
||||
// has correct `inversedBy` on owning side
|
||||
if (!inverse) {
|
||||
throw MetadataError.fromWrongReference(meta, prop, 'inversedBy');
|
||||
}
|
||||
const targetClass = inverse.targetMeta?.root.class;
|
||||
// has correct `inversedBy` reference type
|
||||
if (inverse.type !== meta.className && targetClass !== meta.root.class) {
|
||||
throw MetadataError.fromWrongReference(meta, prop, 'inversedBy', inverse);
|
||||
}
|
||||
// inverse side is not defined as owner
|
||||
if (inverse.inversedBy || inverse.owner) {
|
||||
throw MetadataError.fromWrongOwnership(meta, prop, 'inversedBy');
|
||||
}
|
||||
}
|
||||
validateInverseSide(meta, prop) {
|
||||
const owner = prop.targetMeta.properties[prop.mappedBy];
|
||||
// has correct `mappedBy` on inverse side
|
||||
if (prop.mappedBy && !owner) {
|
||||
throw MetadataError.fromWrongReference(meta, prop, 'mappedBy');
|
||||
}
|
||||
// has correct `mappedBy` reference type
|
||||
// For polymorphic relations, check if this entity is one of the polymorphic targets
|
||||
const isValidPolymorphicInverse =
|
||||
owner.polymorphic && owner.polymorphTargets?.some(target => target.class === meta.root.class);
|
||||
if (
|
||||
!isValidPolymorphicInverse &&
|
||||
owner.type !== meta.className &&
|
||||
owner.targetMeta?.root.class !== meta.root.class
|
||||
) {
|
||||
throw MetadataError.fromWrongReference(meta, prop, 'mappedBy', owner);
|
||||
}
|
||||
// owning side is not defined as inverse
|
||||
if (owner.mappedBy) {
|
||||
throw MetadataError.fromWrongOwnership(meta, prop, 'mappedBy');
|
||||
}
|
||||
// owning side is not defined as inverse
|
||||
const valid = [
|
||||
{ owner: ReferenceKind.MANY_TO_ONE, inverse: ReferenceKind.ONE_TO_MANY },
|
||||
{ owner: ReferenceKind.MANY_TO_MANY, inverse: ReferenceKind.MANY_TO_MANY },
|
||||
{ owner: ReferenceKind.ONE_TO_ONE, inverse: ReferenceKind.ONE_TO_ONE },
|
||||
];
|
||||
if (!valid.find(spec => spec.owner === owner.kind && spec.inverse === prop.kind)) {
|
||||
throw MetadataError.fromWrongReferenceKind(meta, owner, prop);
|
||||
}
|
||||
if (prop.primary) {
|
||||
throw MetadataError.fromInversideSidePrimary(meta, owner, prop);
|
||||
}
|
||||
}
|
||||
validateIndexes(meta, indexes, type) {
|
||||
for (const index of indexes) {
|
||||
for (const propName of Utils.asArray(index.properties)) {
|
||||
const prop = meta.root.properties[propName];
|
||||
if (!prop && !Object.values(meta.root.properties).some(p => propName.startsWith(p.name + '.'))) {
|
||||
throw MetadataError.unknownIndexProperty(meta, propName, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
validateDuplicateFieldNames(meta, options) {
|
||||
const candidates = Object.values(meta.properties)
|
||||
.filter(
|
||||
prop =>
|
||||
prop.persist !== false &&
|
||||
!prop.inherited &&
|
||||
prop.fieldNames?.length === 1 &&
|
||||
(prop.kind !== ReferenceKind.EMBEDDED || prop.object),
|
||||
)
|
||||
.map(prop => prop.fieldNames[0]);
|
||||
const duplicates = Utils.findDuplicates(candidates);
|
||||
if (duplicates.length > 0 && options.checkDuplicateFieldNames) {
|
||||
const pairs = duplicates.flatMap(name => {
|
||||
return Object.values(meta.properties)
|
||||
.filter(p => p.fieldNames?.[0] === name)
|
||||
.map(prop => {
|
||||
return [prop.embedded ? prop.embedded.join('.') : prop.name, prop.fieldNames[0]];
|
||||
});
|
||||
});
|
||||
throw MetadataError.duplicateFieldName(meta.class, pairs);
|
||||
}
|
||||
}
|
||||
validateVersionField(meta) {
|
||||
if (!meta.versionProperty) {
|
||||
return;
|
||||
}
|
||||
const props = Object.values(meta.properties).filter(p => p.version);
|
||||
if (props.length > 1) {
|
||||
throw MetadataError.multipleVersionFields(
|
||||
meta,
|
||||
props.map(p => p.name),
|
||||
);
|
||||
}
|
||||
const prop = meta.properties[meta.versionProperty];
|
||||
const type = prop.runtimeType ?? prop.columnTypes?.[0] ?? prop.type;
|
||||
if (type !== 'number' && type !== 'Date' && !type.startsWith('timestamp') && !type.startsWith('datetime')) {
|
||||
throw MetadataError.invalidVersionFieldType(meta);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Validates that entity properties do not use dangerous names that could lead to
|
||||
* prototype pollution vulnerabilities. This validation ensures that property names
|
||||
* cannot be exploited to modify object prototypes when values are assigned during
|
||||
* entity hydration or persistence operations.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
validatePropertyNames(meta) {
|
||||
for (const prop of Utils.values(meta.properties)) {
|
||||
if (DANGEROUS_PROPERTY_NAMES.includes(prop.name)) {
|
||||
throw MetadataError.dangerousPropertyName(meta, prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Validates view entity configuration.
|
||||
* View entities must have an expression.
|
||||
*/
|
||||
validateViewEntity(meta) {
|
||||
// View entities must have an expression
|
||||
if (!meta.expression) {
|
||||
throw MetadataError.viewEntityWithoutExpression(meta);
|
||||
}
|
||||
// Validate indexes if present
|
||||
this.validateIndexes(meta, meta.indexes ?? [], 'index');
|
||||
this.validateIndexes(meta, meta.uniques ?? [], 'unique');
|
||||
// Validate property names
|
||||
this.validatePropertyNames(meta);
|
||||
}
|
||||
/**
|
||||
* Validates that STI and TPT are not mixed in the same inheritance hierarchy.
|
||||
* An entity hierarchy can use either STI (discriminatorColumn) or TPT (inheritance: 'tpt'),
|
||||
* but not both.
|
||||
*
|
||||
* Note: This validation runs before `initTablePerTypeInheritance` sets `inheritanceType`,
|
||||
* so we check the raw `inheritance` option from the decorator/schema.
|
||||
*/
|
||||
validateInheritanceStrategies(discovered) {
|
||||
const checkedRoots = new Set();
|
||||
for (const meta of discovered) {
|
||||
if (meta.embeddable) {
|
||||
continue;
|
||||
}
|
||||
const root = meta.root;
|
||||
if (checkedRoots.has(root)) {
|
||||
continue;
|
||||
}
|
||||
checkedRoots.add(root);
|
||||
const hasSTI = !!root.discriminatorColumn;
|
||||
const hasTPT = root.inheritanceType === 'tpt' || root.inheritance === 'tpt';
|
||||
if (hasSTI && hasTPT) {
|
||||
throw MetadataError.mixedInheritanceStrategies(root, meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
node_modules/@mikro-orm/core/metadata/discover-entities.d.ts
generated
vendored
Normal file
8
node_modules/@mikro-orm/core/metadata/discover-entities.d.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import { type Constructor } from '../typings.js';
|
||||
import { EntitySchema } from './EntitySchema.js';
|
||||
export declare function discoverEntities(
|
||||
paths: string | string[],
|
||||
options?: {
|
||||
baseDir?: string;
|
||||
},
|
||||
): Promise<Iterable<EntitySchema | Constructor>>;
|
||||
40
node_modules/@mikro-orm/core/metadata/discover-entities.js
generated
vendored
Normal file
40
node_modules/@mikro-orm/core/metadata/discover-entities.js
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
import { basename } from 'node:path';
|
||||
import { fs } from '../utils/fs-utils.js';
|
||||
import { Utils } from '../utils/Utils.js';
|
||||
import { MetadataStorage } from './MetadataStorage.js';
|
||||
import { EntitySchema } from './EntitySchema.js';
|
||||
async function getEntityClassOrSchema(filepath, allTargets, baseDir) {
|
||||
const path = fs.normalizePath(baseDir, filepath);
|
||||
const exports = await fs.dynamicImport(path);
|
||||
const targets = Object.values(exports);
|
||||
// ignore class implementations that are linked from an EntitySchema
|
||||
for (const item of targets) {
|
||||
if (EntitySchema.is(item)) {
|
||||
for (const item2 of targets) {
|
||||
if (item.meta.class === item2) {
|
||||
targets.splice(targets.indexOf(item2), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const item of targets) {
|
||||
const validTarget = EntitySchema.is(item) || (item instanceof Function && MetadataStorage.isKnownEntity(item.name));
|
||||
if (validTarget && !allTargets.has(item)) {
|
||||
allTargets.set(item, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
export async function discoverEntities(paths, options) {
|
||||
paths = Utils.asArray(paths).map(path => fs.normalizePath(path));
|
||||
const baseDir = fs.absolutePath(options?.baseDir ?? process.cwd());
|
||||
const files = fs.glob(paths, fs.normalizePath(baseDir));
|
||||
const found = new Map();
|
||||
for (const filepath of files) {
|
||||
const filename = basename(filepath);
|
||||
if (!/\.[cm]?[jt]s$/.exec(filename) || /\.d\.[cm]?ts/.exec(filename)) {
|
||||
continue;
|
||||
}
|
||||
await getEntityClassOrSchema(filepath, found, baseDir);
|
||||
}
|
||||
return found.keys();
|
||||
}
|
||||
6
node_modules/@mikro-orm/core/metadata/index.d.ts
generated
vendored
Normal file
6
node_modules/@mikro-orm/core/metadata/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
export type * from './types.js';
|
||||
export * from './EntitySchema.js';
|
||||
export * from './MetadataDiscovery.js';
|
||||
export * from './MetadataStorage.js';
|
||||
export * from './MetadataProvider.js';
|
||||
export * from './MetadataValidator.js';
|
||||
5
node_modules/@mikro-orm/core/metadata/index.js
generated
vendored
Normal file
5
node_modules/@mikro-orm/core/metadata/index.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
export * from './EntitySchema.js';
|
||||
export * from './MetadataDiscovery.js';
|
||||
export * from './MetadataStorage.js';
|
||||
export * from './MetadataProvider.js';
|
||||
export * from './MetadataValidator.js';
|
||||
661
node_modules/@mikro-orm/core/metadata/types.d.ts
generated
vendored
Normal file
661
node_modules/@mikro-orm/core/metadata/types.d.ts
generated
vendored
Normal file
@@ -0,0 +1,661 @@
|
||||
import type {
|
||||
AnyEntity,
|
||||
Constructor,
|
||||
EntityName,
|
||||
AnyString,
|
||||
CheckCallback,
|
||||
GeneratedColumnCallback,
|
||||
FormulaCallback,
|
||||
FilterQuery,
|
||||
Dictionary,
|
||||
AutoPath,
|
||||
EntityClass,
|
||||
IndexCallback,
|
||||
ObjectQuery,
|
||||
Raw,
|
||||
} from '../typings.js';
|
||||
import type { Cascade, LoadStrategy, DeferMode, QueryOrderMap, EmbeddedPrefixMode } from '../enums.js';
|
||||
import type { Type, types } from '../types/index.js';
|
||||
import type { EntityManager } from '../EntityManager.js';
|
||||
import type { FilterOptions, FindOptions } from '../drivers/IDatabaseDriver.js';
|
||||
import type { SerializeOptions } from '../serialization/EntitySerializer.js';
|
||||
export type EntityOptions<T, E = T extends EntityClass<infer P> ? P : T> = {
|
||||
/** Override default collection/table name. Alias for `collection`. */
|
||||
tableName?: string;
|
||||
/** Sets the schema name. */
|
||||
schema?: string;
|
||||
/** Override default collection/table name. Alias for `tableName`. */
|
||||
collection?: string;
|
||||
/**
|
||||
* Set default ordering for this entity. This ordering is applied when:
|
||||
* - Querying the entity directly via `em.find()`, `em.findAll()`, etc.
|
||||
* - Populating the entity as a relation
|
||||
*
|
||||
* All orderings are combined together. Precedence (highest to lowest):
|
||||
* 1. Runtime `FindOptions.orderBy`
|
||||
* 2. Relation-level `@OneToMany({ orderBy })` / `@ManyToMany({ orderBy })`
|
||||
* 3. Entity-level `@Entity({ orderBy })`
|
||||
*/
|
||||
orderBy?: QueryOrderMap<E> | QueryOrderMap<E>[];
|
||||
/** For {@doclink inheritance-mapping#single-table-inheritance | Single Table Inheritance}. */
|
||||
discriminatorColumn?: (T extends EntityClass<infer P> ? keyof P : string) | AnyString;
|
||||
/** For {@doclink inheritance-mapping#single-table-inheritance | Single Table Inheritance}. */
|
||||
discriminatorMap?: Dictionary<string>;
|
||||
/** For {@doclink inheritance-mapping#single-table-inheritance | Single Table Inheritance}. */
|
||||
discriminatorValue?: number | string;
|
||||
/** Set inheritance strategy: 'tpt' for {@doclink inheritance-mapping#table-per-type-inheritance-tpt | Table-Per-Type} inheritance. When set on the root entity, each entity in the hierarchy gets its own table with a FK from child PK to parent PK. */
|
||||
inheritance?: 'tpt';
|
||||
/** Enforce use of constructor when creating managed entity instances. */
|
||||
forceConstructor?: boolean;
|
||||
/** Specify constructor parameters to be used in `em.create` or when `forceConstructor` is enabled. Those should be names of declared entity properties in the same order as your constructor uses them. The ORM tries to infer those automatically, use this option in case the inference fails. */
|
||||
constructorParams?: (T extends EntityClass<infer P> ? keyof P : string)[];
|
||||
/** Specify comment to table. (SQL only) */
|
||||
comment?: string;
|
||||
/** Marks entity as abstract, such entities are inlined during discovery. */
|
||||
abstract?: boolean;
|
||||
/** Disables change tracking - such entities are ignored during flush. */
|
||||
readonly?: boolean;
|
||||
/** Marks entity as {@doclink virtual-entities | virtual}. This is set automatically when you use `expression` option (unless `view` is set). */
|
||||
virtual?: boolean;
|
||||
/**
|
||||
* Marks entity as a database view. Unlike virtual entities which evaluate expressions at query time,
|
||||
* view entities create actual database views. The `expression` option must be provided when `view` is true.
|
||||
* View entities are read-only by default.
|
||||
*
|
||||
* Use `view: true` for regular views, or `view: { materialized: true }` for materialized views (PostgreSQL only).
|
||||
* Materialized views store the query results and must be refreshed to update data.
|
||||
* Use `view: { materialized: true, withData: false }` to create an unpopulated materialized view.
|
||||
*/
|
||||
view?:
|
||||
| boolean
|
||||
| {
|
||||
materialized?: boolean;
|
||||
withData?: boolean;
|
||||
};
|
||||
/** Used to make ORM aware of externally defined triggers. This is needed for MS SQL Server multi inserts, ignored in other dialects. */
|
||||
hasTriggers?: boolean;
|
||||
/** SQL query that maps to a {@doclink virtual-entities | virtual entity}, or for view entities, the view definition. */
|
||||
expression?:
|
||||
| string
|
||||
| ((em: any, where: ObjectQuery<E>, options: FindOptions<E, any, any, any>, stream?: boolean) => object);
|
||||
/** Set {@doclink repositories#custom-repository | custom repository class}. */
|
||||
repository?: () => Constructor;
|
||||
};
|
||||
export interface PropertyOptions<Owner> {
|
||||
/**
|
||||
* Alias for `fieldName`.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* Specify database column name for this property.
|
||||
*
|
||||
* @see https://mikro-orm.io/docs/naming-strategy
|
||||
*/
|
||||
fieldName?: string;
|
||||
/**
|
||||
* Specify database column names for this property.
|
||||
* Same as `fieldName` but for composite FKs.
|
||||
*
|
||||
* @see https://mikro-orm.io/docs/naming-strategy
|
||||
*/
|
||||
fieldNames?: string[];
|
||||
/**
|
||||
* Specify an exact database column type for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. This option is only for simple properties represented by a single column. (SQL only)
|
||||
*/
|
||||
columnType?: ColumnType | AnyString;
|
||||
/**
|
||||
* Specify an exact database column type for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. This option is suitable for composite keys, where one property is represented by multiple columns. (SQL only)
|
||||
*/
|
||||
columnTypes?: (ColumnType | AnyString)[];
|
||||
/**
|
||||
* Explicitly specify the runtime type.
|
||||
*
|
||||
* @see https://mikro-orm.io/docs/metadata-providers
|
||||
* @see https://mikro-orm.io/docs/custom-types
|
||||
*/
|
||||
type?:
|
||||
| keyof typeof types
|
||||
| 'ObjectId'
|
||||
| Date
|
||||
| Constructor<AnyEntity>
|
||||
| Constructor<Type<any>>
|
||||
| Type<any>
|
||||
| (() => unknown)
|
||||
| ColumnType
|
||||
| AnyString;
|
||||
/**
|
||||
* Runtime type of the property. This is the JS type that your property is mapped to, e.g. `string` or `number`, and is normally inferred automatically via `reflect-metadata`.
|
||||
* In some cases, the inference won't work, and you might need to specify the `runtimeType` explicitly - the most common one is when you use a union type with null like `foo: number | null`.
|
||||
*/
|
||||
runtimeType?: string;
|
||||
/**
|
||||
* Set length of database column, used for datetime/timestamp/varchar column types for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. (SQL only)
|
||||
*/
|
||||
length?: number;
|
||||
/**
|
||||
* Set precision of database column to represent the number of significant digits. (SQL only)
|
||||
*/
|
||||
precision?: number;
|
||||
/**
|
||||
* Set scale of database column to represents the number of digits after the decimal point. (SQL only)
|
||||
*/
|
||||
scale?: number;
|
||||
/**
|
||||
* Explicitly specify the auto increment of the primary key.
|
||||
*/
|
||||
autoincrement?: boolean;
|
||||
/**
|
||||
* Add the property to the `returning` statement.
|
||||
*/
|
||||
returning?: boolean;
|
||||
/**
|
||||
* Automatically set the property value when entity gets created, executed during flush operation.
|
||||
* @param entity
|
||||
*/
|
||||
onCreate?: (entity: Owner, em: EntityManager) => any;
|
||||
/**
|
||||
* Automatically update the property value every time entity gets updated, executed during flush operation.
|
||||
* @param entity
|
||||
*/
|
||||
onUpdate?: (entity: Owner, em: EntityManager) => any;
|
||||
/**
|
||||
* Specify default column value for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}.
|
||||
* This is a runtime value, assignable to the entity property. (SQL only)
|
||||
*/
|
||||
default?: string | string[] | number | number[] | boolean | null | Date | Raw;
|
||||
/**
|
||||
* Specify SQL functions for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. (SQL only)
|
||||
* Since v4 you should use defaultRaw for SQL functions. e.g. now()
|
||||
*/
|
||||
defaultRaw?: string | Raw;
|
||||
/**
|
||||
* Set to map some SQL snippet for the entity.
|
||||
*
|
||||
* @see https://mikro-orm.io/docs/defining-entities#formulas Formulas
|
||||
*/
|
||||
formula?: string | FormulaCallback<Owner>;
|
||||
/**
|
||||
* For generated columns. This will be appended to the column type after the `generated always` clause.
|
||||
*/
|
||||
generated?: string | Raw | GeneratedColumnCallback<Owner>;
|
||||
/**
|
||||
* Set column as nullable for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}.
|
||||
*/
|
||||
nullable?: boolean;
|
||||
/**
|
||||
* Set column as unsigned for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. (SQL only)
|
||||
*/
|
||||
unsigned?: boolean;
|
||||
/**
|
||||
* Set false to define {@link https://mikro-orm.io/docs/serializing#shadow-properties Shadow Property}.
|
||||
*/
|
||||
persist?: boolean;
|
||||
/**
|
||||
* Set false to disable hydration of this property. Useful for persisted getters.
|
||||
*/
|
||||
hydrate?: boolean;
|
||||
/**
|
||||
* Enable `ScalarReference` wrapper for lazy values. Use this in combination with `lazy: true` to have a type-safe accessor object in place of the value.
|
||||
*/
|
||||
ref?: boolean;
|
||||
/**
|
||||
* Set to true to omit the property when {@link https://mikro-orm.io/docs/serializing Serializing}.
|
||||
*/
|
||||
hidden?: boolean;
|
||||
/**
|
||||
* Set to true to enable {@link https://mikro-orm.io/docs/transactions#optimistic-locking Optimistic Locking} via version field. (SQL only)
|
||||
*/
|
||||
version?: boolean;
|
||||
/**
|
||||
* Set to true to enable {@link https://mikro-orm.io/docs/transactions#optimistic-locking Optimistic Locking} via concurrency fields.
|
||||
*/
|
||||
concurrencyCheck?: boolean;
|
||||
/**
|
||||
* Explicitly specify index on a property.
|
||||
*/
|
||||
index?: boolean | string;
|
||||
/**
|
||||
* Set column as unique for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. (SQL only)
|
||||
*/
|
||||
unique?: boolean | string;
|
||||
/**
|
||||
* Specify column with check constraints. (Postgres driver only)
|
||||
*
|
||||
* @see https://mikro-orm.io/docs/defining-entities#check-constraints
|
||||
*/
|
||||
check?: string | CheckCallback<Owner>;
|
||||
/**
|
||||
* Set to omit the property from the select clause for lazy loading.
|
||||
*
|
||||
* @see https://mikro-orm.io/docs/defining-entities#lazy-scalar-properties
|
||||
*/
|
||||
lazy?: boolean;
|
||||
/**
|
||||
* Set true to define entity's unique primary key identifier.
|
||||
* Alias for `@PrimaryKey()` decorator
|
||||
*
|
||||
* @see https://mikro-orm.io/docs/decorators#primarykey
|
||||
*/
|
||||
primary?: boolean;
|
||||
/**
|
||||
* Set true to define the properties as setter. (virtual)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* @Property({ setter: true })
|
||||
* set address(value: string) {
|
||||
* this._address = value.toLocaleLowerCase();
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
setter?: boolean;
|
||||
/**
|
||||
* Set true to define the properties as getter. (virtual)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* @Property({ getter: true })
|
||||
* get fullName() {
|
||||
* return this.firstName + this.lastName;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
getter?: boolean;
|
||||
/**
|
||||
* When defining a property over a method (not a getter, a regular function), you can use this option to point
|
||||
* to the method name.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* @Property({ getter: true })
|
||||
* getFullName() {
|
||||
* return this.firstName + this.lastName;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
getterName?: keyof Owner;
|
||||
/**
|
||||
* When using a private property backed by a public get/set pair, use the `accessor` option to point to the other side.
|
||||
*
|
||||
* > The `fieldName` will be inferred based on the accessor name unless specified explicitly.
|
||||
*
|
||||
* If the `accessor` option points to something, the ORM will use the backing property directly.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* @Entity()
|
||||
* export class User {
|
||||
* // the ORM will use the backing field directly
|
||||
* @Property({ accessor: 'email' })
|
||||
* private _email: string;
|
||||
*
|
||||
* get email() {
|
||||
* return this._email;
|
||||
* }
|
||||
*
|
||||
* set email() {
|
||||
* return this._email;
|
||||
* }
|
||||
* }
|
||||
*```
|
||||
*
|
||||
* If you want to the ORM to use your accessor internally too, use `accessor: true` on the get/set property instead.
|
||||
* This is handy if you want to use a native private property for the backing field.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* @Entity({ forceConstructor: true })
|
||||
* export class User {
|
||||
* #email: string;
|
||||
*
|
||||
* // the ORM will use the accessor internally
|
||||
* @Property({ accessor: true })
|
||||
* get email() {
|
||||
* return this.#email;
|
||||
* }
|
||||
*
|
||||
* set email() {
|
||||
* return this.#email;
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
accessor?: keyof Owner | AnyString | boolean;
|
||||
/**
|
||||
* Set to define serialized primary key for MongoDB. (virtual)
|
||||
* Alias for `@SerializedPrimaryKey()` decorator.
|
||||
*
|
||||
* @see https://mikro-orm.io/docs/decorators#serializedprimarykey
|
||||
*/
|
||||
serializedPrimaryKey?: boolean;
|
||||
/**
|
||||
* Set to use serialize property. Allow to specify a callback that will be used when serializing a property.
|
||||
*
|
||||
* @see https://mikro-orm.io/docs/serializing#property-serializers
|
||||
*/
|
||||
serializer?: (value: any, options?: SerializeOptions<any>) => any;
|
||||
/**
|
||||
* Specify name of key for the serialized value.
|
||||
*/
|
||||
serializedName?: string;
|
||||
/**
|
||||
* Specify serialization groups for `serialize()` calls. If a property does not specify any group, it will be included,
|
||||
* otherwise only properties with a matching group are included.
|
||||
*/
|
||||
groups?: string[];
|
||||
/**
|
||||
* Specify a custom order based on the values. (SQL only)
|
||||
*/
|
||||
customOrder?: string[] | number[] | boolean[];
|
||||
/**
|
||||
* Specify comment of column for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. (SQL only)
|
||||
*/
|
||||
comment?: string;
|
||||
/** mysql only */
|
||||
extra?: string;
|
||||
/**
|
||||
* Set to avoid a perpetual diff from the {@link https://mikro-orm.io/docs/schema-generator Schema Generator} when columns are generated.
|
||||
*
|
||||
* @see https://mikro-orm.io/docs/defining-entities#sql-generated-columns
|
||||
*/
|
||||
ignoreSchemaChanges?: ('type' | 'extra' | 'default')[];
|
||||
}
|
||||
export interface ReferenceOptions<Owner, Target> extends PropertyOptions<Owner> {
|
||||
/** Set target entity type. For polymorphic relations, pass an array of entity types. */
|
||||
entity?: () => EntityName<Target> | EntityName<Target>[];
|
||||
/** Set what actions on owning entity should be cascaded to the relationship. Defaults to [Cascade.PERSIST, Cascade.MERGE] (see {@doclink cascading}). */
|
||||
cascade?: Cascade[];
|
||||
/** Always load the relationship. Discouraged for use with to-many relations for performance reasons. */
|
||||
eager?: boolean;
|
||||
/** Override the default loading strategy for this property. This option has precedence over the global `loadStrategy`, but can be overridden by `FindOptions.strategy`. */
|
||||
strategy?: LoadStrategy | `${LoadStrategy}`;
|
||||
/** Control filter parameters for the relation. This will serve as a default value when processing filters on this relation. It's value can be overridden via `em.fork()` or `FindOptions`. */
|
||||
filters?: FilterOptions;
|
||||
}
|
||||
/**
|
||||
* Inspired by https://github.com/typeorm/typeorm/blob/941b584ba135617e55d6685caef671172ec1dc03/src/driver/types/ColumnTypes.ts
|
||||
* @ignore
|
||||
*/
|
||||
export type ColumnType =
|
||||
| 'int'
|
||||
| 'int4'
|
||||
| 'integer'
|
||||
| 'bigint'
|
||||
| 'int8'
|
||||
| 'int2'
|
||||
| 'tinyint'
|
||||
| 'smallint'
|
||||
| 'mediumint'
|
||||
| 'double'
|
||||
| 'double precision'
|
||||
| 'real'
|
||||
| 'float8'
|
||||
| 'decimal'
|
||||
| 'numeric'
|
||||
| 'float'
|
||||
| 'float4'
|
||||
| 'datetime'
|
||||
| 'time'
|
||||
| 'time with time zone'
|
||||
| 'timestamp'
|
||||
| 'timestamp with time zone'
|
||||
| 'timetz'
|
||||
| 'timestamptz'
|
||||
| 'date'
|
||||
| 'interval'
|
||||
| 'character varying'
|
||||
| 'varchar'
|
||||
| 'char'
|
||||
| 'character'
|
||||
| 'uuid'
|
||||
| 'text'
|
||||
| 'tinytext'
|
||||
| 'mediumtext'
|
||||
| 'longtext'
|
||||
| 'boolean'
|
||||
| 'bool'
|
||||
| 'bit'
|
||||
| 'enum'
|
||||
| 'blob'
|
||||
| 'tinyblob'
|
||||
| 'mediumblob'
|
||||
| 'longblob'
|
||||
| 'bytea'
|
||||
| 'point'
|
||||
| 'line'
|
||||
| 'lseg'
|
||||
| 'box'
|
||||
| 'circle'
|
||||
| 'path'
|
||||
| 'polygon'
|
||||
| 'geometry'
|
||||
| 'tsvector'
|
||||
| 'tsquery'
|
||||
| 'json'
|
||||
| 'jsonb';
|
||||
interface PolymorphicOptions {
|
||||
/**
|
||||
* For polymorphic relations. Specifies the property name that stores the entity type discriminator.
|
||||
* Defaults to the property name. Only used when `entity` returns an array of types.
|
||||
* For M:N relations, this is the column name in the pivot table.
|
||||
*/
|
||||
discriminator?: string;
|
||||
/**
|
||||
* For polymorphic relations. Custom mapping of discriminator values to entity class names.
|
||||
* If not provided, table names are used as discriminator values.
|
||||
*/
|
||||
discriminatorMap?: Dictionary<string>;
|
||||
}
|
||||
export interface ManyToOneOptions<Owner, Target> extends ReferenceOptions<Owner, Target>, PolymorphicOptions {
|
||||
/** Point to the inverse side property name. */
|
||||
inversedBy?: (string & keyof Target) | ((e: Target) => any);
|
||||
/** Wrap the entity in {@apilink Reference} wrapper. */
|
||||
ref?: boolean;
|
||||
/** Use this relation as a primary key. */
|
||||
primary?: boolean;
|
||||
/** Map this relation to the primary key value instead of an entity. */
|
||||
mapToPk?: boolean;
|
||||
/** Override the default database column name on the owning side (see {@doclink naming-strategy | Naming Strategy}). This option is only for simple properties represented by a single column. */
|
||||
joinColumn?: string;
|
||||
/** Override the default database column name on the owning side (see {@doclink naming-strategy | Naming Strategy}). This option is suitable for composite keys, where one property is represented by multiple columns. */
|
||||
joinColumns?: string[];
|
||||
/** When a part of a composite column is shared in other properties, use this option to specify what columns are considered as owned by this property. This is useful when your composite property is nullable, but parts of it are not. */
|
||||
ownColumns?: string[];
|
||||
/** Override the default database column name on the target entity (see {@doclink naming-strategy | Naming Strategy}). This option is only for simple properties represented by a single column. */
|
||||
referenceColumnName?: string;
|
||||
/** Override the default database column name on the target entity (see {@doclink naming-strategy | Naming Strategy}). This option is suitable for composite keys, where one property is represented by multiple columns. */
|
||||
referencedColumnNames?: string[];
|
||||
/** Specify the property name on the target entity that this FK references instead of the primary key. */
|
||||
targetKey?: string & keyof Target;
|
||||
/** What to do when the target entity gets deleted. */
|
||||
deleteRule?: 'cascade' | 'no action' | 'set null' | 'set default' | AnyString;
|
||||
/** What to do when the reference to the target entity gets updated. */
|
||||
updateRule?: 'cascade' | 'no action' | 'set null' | 'set default' | AnyString;
|
||||
/** Set the constraint type. Immediate constraints are checked for each statement, while deferred ones are only checked at the end of the transaction. Only for postgres unique constraints. */
|
||||
deferMode?: DeferMode | `${DeferMode}`;
|
||||
/** Enable/disable foreign key constraint creation on this relation */
|
||||
createForeignKeyConstraint?: boolean;
|
||||
/** Set a custom foreign key constraint name, overriding NamingStrategy.indexName(). */
|
||||
foreignKeyName?: string;
|
||||
}
|
||||
export interface OneToManyOptions<Owner, Target> extends ReferenceOptions<Owner, Target> {
|
||||
/** Remove the entity when it gets disconnected from the relationship (see {@doclink cascading | Cascading}). */
|
||||
orphanRemoval?: boolean;
|
||||
/** Set default ordering. */
|
||||
orderBy?: QueryOrderMap<Target> | QueryOrderMap<Target>[];
|
||||
/** Condition for {@doclink collections#declarative-partial-loading | Declarative partial loading}. */
|
||||
where?: FilterQuery<Target>;
|
||||
/** Override the default database column name on the owning side (see {@doclink naming-strategy | Naming Strategy}). This option is only for simple properties represented by a single column. */
|
||||
joinColumn?: string;
|
||||
/** Override the default database column name on the owning side (see {@doclink naming-strategy | Naming Strategy}). This option is suitable for composite keys, where one property is represented by multiple columns. */
|
||||
joinColumns?: string[];
|
||||
/** Override the default database column name on the inverse side (see {@doclink naming-strategy | Naming Strategy}). This option is only for simple properties represented by a single column. */
|
||||
inverseJoinColumn?: string;
|
||||
/** Override the default database column name on the inverse side (see {@doclink naming-strategy | Naming Strategy}). This option is suitable for composite keys, where one property is represented by multiple columns. */
|
||||
inverseJoinColumns?: string[];
|
||||
/** Override the default database column name on the target entity (see {@doclink naming-strategy | Naming Strategy}). This option is only for simple properties represented by a single column. */
|
||||
referenceColumnName?: string;
|
||||
/** Override the default database column name on the target entity (see {@doclink naming-strategy | Naming Strategy}). This option is suitable for composite keys, where one property is represented by multiple columns. */
|
||||
referencedColumnNames?: string[];
|
||||
/** Point to the owning side property name. */
|
||||
mappedBy: (string & keyof Target) | ((e: Target) => any);
|
||||
}
|
||||
export interface OneToOneOptions<Owner, Target>
|
||||
extends Partial<Omit<OneToManyOptions<Owner, Target>, 'orderBy'>>, PolymorphicOptions {
|
||||
/** Set this side as owning. Owning side is where the foreign key is defined. This option is not required if you use `inversedBy` or `mappedBy` to distinguish owning and inverse side. */
|
||||
owner?: boolean;
|
||||
/** Point to the inverse side property name. */
|
||||
inversedBy?: (string & keyof Target) | ((e: Target) => any);
|
||||
/** Wrap the entity in {@apilink Reference} wrapper. */
|
||||
ref?: boolean;
|
||||
/** Use this relation as a primary key. */
|
||||
primary?: boolean;
|
||||
/** Map this relation to the primary key value instead of an entity. */
|
||||
mapToPk?: boolean;
|
||||
/** When a part of a composite column is shared in other properties, use this option to specify what columns are considered as owned by this property. This is useful when your composite property is nullable, but parts of it are not. */
|
||||
ownColumns?: string[];
|
||||
/** Specify the property name on the target entity that this FK references instead of the primary key. */
|
||||
targetKey?: string & keyof Target;
|
||||
/** What to do when the target entity gets deleted. */
|
||||
deleteRule?: 'cascade' | 'no action' | 'set null' | 'set default' | AnyString;
|
||||
/** What to do when the reference to the target entity gets updated. */
|
||||
updateRule?: 'cascade' | 'no action' | 'set null' | 'set default' | AnyString;
|
||||
/** Set the constraint type. Immediate constraints are checked for each statement, while deferred ones are only checked at the end of the transaction. Only for postgres unique constraints. */
|
||||
deferMode?: DeferMode | `${DeferMode}`;
|
||||
/** Set a custom foreign key constraint name, overriding NamingStrategy.indexName(). */
|
||||
foreignKeyName?: string;
|
||||
/** Enable/disable foreign key constraint creation on this relation */
|
||||
createForeignKeyConstraint?: boolean;
|
||||
}
|
||||
export interface ManyToManyOptions<Owner, Target> extends ReferenceOptions<Owner, Target>, PolymorphicOptions {
|
||||
/** Set this side as owning. Owning side is where the foreign key is defined. This option is not required if you use `inversedBy` or `mappedBy` to distinguish owning and inverse side. */
|
||||
owner?: boolean;
|
||||
/** Point to the inverse side property name. */
|
||||
inversedBy?: (string & keyof Target) | ((e: Target) => any);
|
||||
/** Point to the owning side property name. */
|
||||
mappedBy?: (string & keyof Target) | ((e: Target) => any);
|
||||
/** Condition for {@doclink collections#declarative-partial-loading | Declarative partial loading}. */
|
||||
where?: FilterQuery<Target>;
|
||||
/** Set default ordering. */
|
||||
orderBy?: QueryOrderMap<Target> | QueryOrderMap<Target>[];
|
||||
/** Force stable insertion order of items in the collection (see {@doclink collections | Collections}). */
|
||||
fixedOrder?: boolean;
|
||||
/** Override default order column name (`id`) for fixed ordering. */
|
||||
fixedOrderColumn?: string;
|
||||
/** Override default name for pivot table (see {@doclink naming-strategy | Naming Strategy}). */
|
||||
pivotTable?: string;
|
||||
/** Set pivot entity for this relation (see {@doclink collections#custom-pivot-table-entity | Custom pivot table entity}). */
|
||||
pivotEntity?: () => EntityName;
|
||||
/** Override the default database column name on the owning side (see {@doclink naming-strategy | Naming Strategy}). This option is only for simple properties represented by a single column. */
|
||||
joinColumn?: string;
|
||||
/** Override the default database column name on the owning side (see {@doclink naming-strategy | Naming Strategy}). This option is suitable for composite keys, where one property is represented by multiple columns. */
|
||||
joinColumns?: string[];
|
||||
/** Override the default database column name on the inverse side (see {@doclink naming-strategy | Naming Strategy}). This option is only for simple properties represented by a single column. */
|
||||
inverseJoinColumn?: string;
|
||||
/** Override the default database column name on the inverse side (see {@doclink naming-strategy | Naming Strategy}). This option is suitable for composite keys, where one property is represented by multiple columns. */
|
||||
inverseJoinColumns?: string[];
|
||||
/** Override the default database column name on the target entity (see {@doclink naming-strategy | Naming Strategy}). This option is only for simple properties represented by a single column. */
|
||||
referenceColumnName?: string;
|
||||
/** Override the default database column name on the target entity (see {@doclink naming-strategy | Naming Strategy}). This option is suitable for composite keys, where one property is represented by multiple columns. */
|
||||
referencedColumnNames?: string[];
|
||||
/** What to do when the target entity gets deleted. */
|
||||
deleteRule?: 'cascade' | 'no action' | 'set null' | 'set default' | AnyString;
|
||||
/** What to do when the reference to the target entity gets updated. */
|
||||
updateRule?: 'cascade' | 'no action' | 'set null' | 'set default' | AnyString;
|
||||
/** Enable/disable foreign key constraint creation on this relation */
|
||||
createForeignKeyConstraint?: boolean;
|
||||
}
|
||||
export interface EmbeddedOptions<Owner, Target> extends PropertyOptions<Owner> {
|
||||
entity?: () => EntityName<Target> | EntityName[];
|
||||
prefix?: string | boolean;
|
||||
prefixMode?: EmbeddedPrefixMode;
|
||||
object?: boolean;
|
||||
array?: boolean;
|
||||
}
|
||||
export interface EmbeddableOptions<Owner> {
|
||||
/** Specify constructor parameters to be used in `em.create` or when `forceConstructor` is enabled. Those should be names of declared entity properties in the same order as your constructor uses them. The ORM tries to infer those automatically, use this option in case the inference fails. */
|
||||
constructorParams?: (Owner extends EntityClass<infer P> ? keyof P : string)[];
|
||||
/** For polymorphic embeddables. Specify the property name that stores the discriminator value. Alias for `discriminatorColumn`. */
|
||||
discriminator?: (Owner extends EntityClass<infer P> ? keyof P : string) | AnyString;
|
||||
/** For polymorphic embeddables. @deprecated Use `discriminator` instead. */
|
||||
discriminatorColumn?: (Owner extends EntityClass<infer P> ? keyof P : string) | AnyString;
|
||||
discriminatorMap?: Dictionary<string>;
|
||||
discriminatorValue?: number | string;
|
||||
abstract?: boolean;
|
||||
}
|
||||
export interface EnumOptions<T> extends PropertyOptions<T> {
|
||||
items?: (number | string)[] | (() => Dictionary);
|
||||
array?: boolean;
|
||||
/** for postgres, by default it uses text column with check constraint */
|
||||
nativeEnumName?: string;
|
||||
}
|
||||
export interface PrimaryKeyOptions<T> extends PropertyOptions<T> {}
|
||||
export interface SerializedPrimaryKeyOptions<T> extends PropertyOptions<T> {
|
||||
type?: any;
|
||||
}
|
||||
type MaybeArray<T> = T | T[];
|
||||
type Properties<T, H extends string> = MaybeArray<AutoPath<T, H>>;
|
||||
/** Options for column within an index, supporting advanced index features like prefix length and collation. */
|
||||
export interface IndexColumnOptions {
|
||||
/** Column name or property path. */
|
||||
name: string;
|
||||
/** Sort order for the column (default: ASC). */
|
||||
sort?: 'ASC' | 'DESC' | 'asc' | 'desc';
|
||||
/** NULLS ordering for the column (PostgreSQL). */
|
||||
nulls?: 'FIRST' | 'LAST' | 'first' | 'last';
|
||||
/** Prefix length for the column (MySQL, MariaDB). */
|
||||
length?: number;
|
||||
/** Collation for the column (PostgreSQL, SQLite, or MySQL/MariaDB via expression). */
|
||||
collation?: string;
|
||||
}
|
||||
interface BaseOptions<T, H extends string> {
|
||||
name?: string;
|
||||
properties?: T extends EntityClass<infer P> ? Properties<P, H> : Properties<T, H>;
|
||||
options?: Dictionary;
|
||||
expression?: string | (T extends EntityClass<infer P> ? IndexCallback<P> : IndexCallback<T>);
|
||||
/**
|
||||
* Advanced column options for the index.
|
||||
* When specified, allows fine-grained control over each column in the index including
|
||||
* sort order, nulls ordering, prefix length, and collation.
|
||||
* If both `columns` and `properties` are specified, `columns` takes precedence for index creation.
|
||||
*/
|
||||
columns?: IndexColumnOptions[];
|
||||
/**
|
||||
* Columns to include in the index but not as part of the key (PostgreSQL, MSSQL).
|
||||
* These columns are stored in the leaf level of the index but not used for searching.
|
||||
*/
|
||||
include?: T extends EntityClass<infer P> ? Properties<P, H> : Properties<T, H>;
|
||||
/** Fill factor for the index as a percentage 0-100 (PostgreSQL, MSSQL). */
|
||||
fillFactor?: number;
|
||||
}
|
||||
export interface UniqueOptions<T, H extends string = string> extends BaseOptions<T, H> {
|
||||
deferMode?: DeferMode | `${DeferMode}`;
|
||||
/**
|
||||
* Whether the index is disabled (MSSQL only).
|
||||
* A disabled index is not used for query planning and is not maintained on writes.
|
||||
* It can be re-enabled later using `ALTER INDEX ... REBUILD`.
|
||||
*/
|
||||
disabled?: boolean;
|
||||
}
|
||||
export interface IndexOptions<T, H extends string = string> extends BaseOptions<T, H> {
|
||||
type?: string;
|
||||
/**
|
||||
* Whether the index is invisible/hidden from the query optimizer (MySQL 8+, MariaDB 10.6+, MongoDB).
|
||||
* An invisible index is still maintained on writes but not used for query planning.
|
||||
* Useful for testing the impact of removing an index before actually dropping it.
|
||||
*/
|
||||
invisible?: boolean;
|
||||
/**
|
||||
* Whether the index is disabled (MSSQL only).
|
||||
* A disabled index is not used for query planning and is not maintained on writes.
|
||||
* It can be re-enabled later using `ALTER INDEX ... REBUILD`.
|
||||
*/
|
||||
disabled?: boolean;
|
||||
/**
|
||||
* Whether the index should be clustered (MariaDB, MSSQL).
|
||||
* A clustered index determines the physical order of data in the table.
|
||||
* Only one clustered index can exist per table.
|
||||
*/
|
||||
clustered?: boolean;
|
||||
}
|
||||
export {};
|
||||
1
node_modules/@mikro-orm/core/metadata/types.js
generated
vendored
Normal file
1
node_modules/@mikro-orm/core/metadata/types.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export {};
|
||||
Reference in New Issue
Block a user