Files
evento/node_modules/@mikro-orm/core/MikroORM.js
2026-03-18 14:55:56 -03:00

220 lines
7.0 KiB
JavaScript

import { MetadataDiscovery } from './metadata/MetadataDiscovery.js';
import { MetadataStorage } from './metadata/MetadataStorage.js';
import { Configuration } from './utils/Configuration.js';
import { loadEnvironmentVars } from './utils/env-vars.js';
import { Utils } from './utils/Utils.js';
import { colors } from './logging/colors.js';
async function tryRegisterExtension(name, pkg, extensions) {
try {
const url = import.meta.resolve(pkg);
const mod = await import(url);
if (mod[name]) {
extensions.push(mod[name]);
}
} catch {
// not installed
}
}
/** @internal */
export async function loadOptionalDependencies(options) {
await import('@mikro-orm/core/fs-utils').then(m => m.fs.init()).catch(() => null);
const extensions = options.extensions ?? [];
const exists = name => extensions.some(ext => ext.name === name);
if (!exists('SeedManager')) {
await tryRegisterExtension('SeedManager', '@mikro-orm/seeder', extensions);
}
if (!exists('Migrator')) {
await tryRegisterExtension('Migrator', '@mikro-orm/migrations', extensions);
}
/* v8 ignore if */
if (!exists('Migrator')) {
await tryRegisterExtension('Migrator', '@mikro-orm/migrations-mongodb', extensions);
}
if (!exists('EntityGenerator')) {
await tryRegisterExtension('EntityGenerator', '@mikro-orm/entity-generator', extensions);
}
options.extensions = extensions;
const metadataCacheEnabled = options.metadataCache?.enabled || options.metadataProvider?.useCache?.();
if (metadataCacheEnabled) {
options.metadataCache ??= {};
options.metadataCache.adapter ??= await import('@mikro-orm/core/fs-utils').then(m => m.FileCacheAdapter);
}
}
/**
* The main class used to configure and bootstrap the ORM.
*
* @example
* ```ts
* // import from driver package
* import { MikroORM, defineEntity, p } from '@mikro-orm/sqlite';
*
* const User = defineEntity({
* name: 'User',
* properties: {
* id: p.integer().primary(),
* name: p.string(),
* },
* });
*
* const orm = new MikroORM({
* entities: [User],
* dbName: 'my.db',
* });
* await orm.schema.update();
*
* const em = orm.em.fork();
* const u1 = em.create(User, { name: 'John' });
* const u2 = em.create(User, { name: 'Ben' });
* await em.flush();
* ```
*/
export class MikroORM {
/** The global EntityManager instance. If you are using `RequestContext` helper, it will automatically pick the request specific context under the hood */
em;
/** The database driver instance used by this ORM. */
driver;
/** The ORM configuration instance. */
config;
#metadata;
#logger;
#discovery;
/**
* Initialize the ORM, load entity metadata, create EntityManager and connect to the database.
* If you omit the `options` parameter, your CLI config will be used.
*/
static async init(options) {
/* v8 ignore next */
if (!options) {
throw new Error(`options parameter is required`);
}
options = { ...options };
options.discovery ??= {};
options.discovery.skipSyncDiscovery ??= true;
await loadOptionalDependencies(options);
const orm = new this(options);
const preferTs = orm.config.get('preferTs', Utils.detectTypeScriptSupport());
orm.#metadata = await orm.#discovery.discover(preferTs);
orm.createEntityManager();
return orm;
}
/**
* Synchronous variant of the `init` method with some limitations:
* - folder-based discovery not supported
* - ORM extensions are not autoloaded
* - when metadata cache is enabled, `FileCacheAdapter` needs to be explicitly set in the config
*/
constructor(options) {
const env = loadEnvironmentVars();
options = options.preferEnvVars ? Utils.merge(options, env) : Utils.merge(env, options);
this.config = new Configuration(options);
const discovery = this.config.get('discovery');
this.driver = this.config.getDriver();
this.#logger = this.config.getLogger();
this.#logger.log('info', `MikroORM version: ${colors.green(Utils.getORMVersion())}`);
this.#discovery = new MetadataDiscovery(new MetadataStorage(), this.driver.getPlatform(), this.config);
this.driver.getPlatform().init(this);
for (const extension of this.config.get('extensions')) {
extension.register(this);
}
if (!discovery.skipSyncDiscovery) {
this.#metadata = this.#discovery.discoverSync();
this.createEntityManager();
}
}
/**
* Connects to the database.
*/
async connect() {
await this.driver.connect();
return this.driver;
}
/**
* Reconnects, possibly to a different database.
*/
async reconnect(options = {}) {
/* v8 ignore next */
for (const key of Utils.keys(options)) {
this.config.set(key, options[key]);
}
await this.driver.reconnect();
}
/**
* Checks whether the database connection is active.
*/
async isConnected() {
return this.driver.getConnection().isConnected();
}
/**
* Checks whether the database connection is active, returns the reason if not.
*/
async checkConnection() {
return this.driver.getConnection().checkConnection();
}
/**
* Closes the database connection.
*/
async close(force = false) {
await this.driver.close(force);
await this.config.getMetadataCacheAdapter()?.close?.();
await this.config.getResultCacheAdapter()?.close?.();
}
/**
* Gets the `MetadataStorage` (without parameters) or `EntityMetadata` instance when provided with the `entityName` parameter.
*/
getMetadata(entityName) {
if (entityName) {
return this.#metadata.get(entityName);
}
return this.#metadata;
}
createEntityManager() {
this.driver.setMetadata(this.#metadata);
this.em = this.driver.createEntityManager();
this.em.global = true;
this.#metadata.decorate(this.em);
this.driver.setMetadata(this.#metadata);
}
/**
* Allows dynamically discovering new entity by reference, handy for testing schema diffing.
*/
discoverEntity(entities, reset) {
for (const className of Utils.asArray(reset)) {
this.#metadata.reset(className);
this.#discovery.reset(className);
}
const tmp = this.#discovery.discoverReferences(Utils.asArray(entities));
const metadata = this.#discovery.processDiscoveredEntities(tmp);
for (const meta of metadata) {
this.#metadata.set(meta.class, meta);
meta.root = this.#metadata.get(meta.root.class);
}
this.#metadata.decorate(this.em);
}
/**
* Gets the SchemaGenerator.
*/
get schema() {
return this.config.getExtension('@mikro-orm/schema-generator');
}
/**
* Gets the SeedManager
*/
get seeder() {
return this.driver.getPlatform().getExtension('SeedManager', '@mikro-orm/seeder', '@mikro-orm/seeder', this.em);
}
/**
* Gets the Migrator.
*/
get migrator() {
return this.driver.getPlatform().getExtension('Migrator', '@mikro-orm/migrator', '@mikro-orm/migrations', this.em);
}
/**
* Gets the EntityGenerator.
*/
get entityGenerator() {
return this.driver
.getPlatform()
.getExtension('EntityGenerator', '@mikro-orm/entity-generator', '@mikro-orm/entity-generator', this.em);
}
}