@mikro-orm/cli 7.0.0-dev.9 → 7.0.0-dev.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,20 +2,20 @@ import { type CommandModule } from 'yargs';
2
2
  /**
3
3
  * @internal
4
4
  */
5
- export type BaseArgs = Awaited<ReturnType<typeof CLIConfigurator['createBasicConfig']>['argv']>;
5
+ export type BaseArgs = Awaited<ReturnType<typeof createBasicConfig>['argv']>;
6
6
  /**
7
7
  * @internal
8
8
  */
9
9
  export interface BaseCommand<CommandArgs extends BaseArgs = BaseArgs> extends CommandModule<BaseArgs, CommandArgs> {
10
10
  }
11
- /**
12
- * @internal
13
- */
14
- export declare class CLIConfigurator {
15
- private static createBasicConfig;
16
- static configure(): Promise<import("yargs").Argv<{
17
- config: string[] | undefined;
18
- } & {
19
- contextName: string;
20
- }>>;
21
- }
11
+ declare function createBasicConfig(): import("yargs").Argv<{
12
+ config: string[] | undefined;
13
+ } & {
14
+ contextName: string;
15
+ }>;
16
+ export declare function configure(): Promise<import("yargs").Argv<{
17
+ config: string[] | undefined;
18
+ } & {
19
+ contextName: string;
20
+ }>>;
21
+ export {};
@@ -1,4 +1,5 @@
1
- import { ConfigurationLoader, Utils } from '@mikro-orm/core';
1
+ import { Utils } from '@mikro-orm/core';
2
+ import { fs } from '@mikro-orm/core/fs-utils';
2
3
  import yargs from 'yargs';
3
4
  import { ClearCacheCommand } from './commands/ClearCacheCommand.js';
4
5
  import { CreateDatabaseCommand } from './commands/CreateDatabaseCommand.js';
@@ -10,65 +11,61 @@ import { GenerateEntitiesCommand } from './commands/GenerateEntitiesCommand.js';
10
11
  import { ImportCommand } from './commands/ImportCommand.js';
11
12
  import { MigrationCommandFactory } from './commands/MigrationCommandFactory.js';
12
13
  import { SchemaCommandFactory } from './commands/SchemaCommandFactory.js';
13
- /**
14
- * @internal
15
- */
16
- export class CLIConfigurator {
17
- static createBasicConfig() {
18
- return yargs()
19
- .scriptName('mikro-orm')
20
- .usage('Usage: $0 <command> [options]')
21
- .example('$0 debug', 'Show debugging information')
22
- .example('$0 schema:update --run', 'Runs schema synchronization')
23
- .option('config', {
24
- type: 'string',
25
- array: true,
26
- desc: `Set path to the ORM configuration file`,
27
- })
28
- .option('contextName', {
29
- alias: 'context',
30
- type: 'string',
31
- desc: 'Set name of config to load out of the ORM configuration file. Used when config file exports an array or a function',
32
- default: process.env.MIKRO_ORM_CONTEXT_NAME ?? 'default',
33
- })
34
- .alias('v', 'version')
35
- .alias('h', 'help')
36
- .recommendCommands()
37
- .showHelpOnFail(true)
38
- .demandCommand(1, '')
39
- .strict();
40
- }
41
- static async configure() {
42
- ConfigurationLoader.checkPackageVersion();
43
- const settings = ConfigurationLoader.getSettings();
44
- const version = Utils.getORMVersion();
45
- if (settings.preferTs !== false) {
46
- const preferTs = await ConfigurationLoader.registerTypeScriptSupport(settings.tsConfigPath);
47
- /* v8 ignore next 3 */
48
- if (!preferTs) {
49
- process.env.MIKRO_ORM_CLI_PREFER_TS ??= '0';
50
- }
14
+ import { CLIHelper } from './CLIHelper.js';
15
+ function createBasicConfig() {
16
+ return yargs()
17
+ .scriptName('mikro-orm')
18
+ .usage('Usage: $0 <command> [options]')
19
+ .example('$0 debug', 'Show debugging information')
20
+ .example('$0 schema:update --run', 'Runs schema synchronization')
21
+ .option('config', {
22
+ type: 'string',
23
+ array: true,
24
+ desc: `Set path to the ORM configuration file`,
25
+ })
26
+ .option('contextName', {
27
+ alias: 'context',
28
+ type: 'string',
29
+ desc: 'Set name of config to load out of the ORM configuration file. Used when config file exports an array or a function',
30
+ default: process.env.MIKRO_ORM_CONTEXT_NAME ?? 'default',
31
+ })
32
+ .alias('v', 'version')
33
+ .alias('h', 'help')
34
+ .recommendCommands()
35
+ .showHelpOnFail(true)
36
+ .demandCommand(1, '')
37
+ .strict();
38
+ }
39
+ export async function configure() {
40
+ fs.checkPackageVersion();
41
+ const settings = CLIHelper.getSettings();
42
+ const version = Utils.getORMVersion();
43
+ if (settings.preferTs !== false) {
44
+ const preferTs = await CLIHelper.registerTypeScriptSupport(settings.tsConfigPath, settings.tsLoader);
45
+ /* v8 ignore next */
46
+ if (!preferTs) {
47
+ process.env.MIKRO_ORM_CLI_PREFER_TS ??= '0';
51
48
  }
52
- return CLIConfigurator.createBasicConfig()
53
- .version(version)
54
- .command(new ClearCacheCommand())
55
- .command(new GenerateCacheCommand())
56
- .command(new GenerateEntitiesCommand())
57
- .command(new CreateDatabaseCommand())
58
- .command(new ImportCommand())
59
- .command(new DatabaseSeedCommand())
60
- .command(new CreateSeederCommand())
61
- .command(SchemaCommandFactory.create('create'))
62
- .command(SchemaCommandFactory.create('drop'))
63
- .command(SchemaCommandFactory.create('update'))
64
- .command(SchemaCommandFactory.create('fresh'))
65
- .command(MigrationCommandFactory.create('create'))
66
- .command(MigrationCommandFactory.create('up'))
67
- .command(MigrationCommandFactory.create('down'))
68
- .command(MigrationCommandFactory.create('list'))
69
- .command(MigrationCommandFactory.create('check'))
70
- .command(MigrationCommandFactory.create('pending'))
71
- .command(MigrationCommandFactory.create('fresh'))
72
- .command(new DebugCommand());
73
49
  }
50
+ return createBasicConfig()
51
+ .version(version)
52
+ .command(new ClearCacheCommand())
53
+ .command(new GenerateCacheCommand())
54
+ .command(new GenerateEntitiesCommand())
55
+ .command(new CreateDatabaseCommand())
56
+ .command(new ImportCommand())
57
+ .command(new DatabaseSeedCommand())
58
+ .command(new CreateSeederCommand())
59
+ .command(SchemaCommandFactory.create('create'))
60
+ .command(SchemaCommandFactory.create('drop'))
61
+ .command(SchemaCommandFactory.create('update'))
62
+ .command(SchemaCommandFactory.create('fresh'))
63
+ .command(MigrationCommandFactory.create('create'))
64
+ .command(MigrationCommandFactory.create('up'))
65
+ .command(MigrationCommandFactory.create('down'))
66
+ .command(MigrationCommandFactory.create('list'))
67
+ .command(MigrationCommandFactory.create('check'))
68
+ .command(MigrationCommandFactory.create('pending'))
69
+ .command(MigrationCommandFactory.create('fresh'))
70
+ .command(new DebugCommand());
74
71
  }
package/CLIHelper.d.ts CHANGED
@@ -1,22 +1,51 @@
1
- import { MikroORM, type Configuration, type IDatabaseDriver, type Options } from '@mikro-orm/core';
1
+ import { Configuration, type EntityManager, type EntityManagerType, type IDatabaseDriver, MikroORM, type Options } from '@mikro-orm/core';
2
2
  /**
3
3
  * @internal
4
4
  */
5
5
  export declare class CLIHelper {
6
- static getConfiguration<D extends IDatabaseDriver = IDatabaseDriver>(contextName?: string, configPaths?: string[], options?: Partial<Options<D>>): Promise<Configuration<D>>;
6
+ /**
7
+ * Gets a named configuration
8
+ *
9
+ * @param contextName Load a config with the given `contextName` value. Used when config file exports array or factory function. Setting it to "default" matches also config objects without `contextName` set.
10
+ * @param paths Array of possible paths for a configuration file. Files will be checked in order, and the first existing one will be used. Defaults to the output of {@link fs.getConfigPaths}.
11
+ * @param options Additional options to augment the final configuration with.
12
+ */
13
+ static getConfiguration<D extends IDatabaseDriver = IDatabaseDriver, EM extends D[typeof EntityManagerType] & EntityManager<D> = D[typeof EntityManagerType] & EntityManager<D>>(contextName?: string, paths?: string[], options?: Partial<Options<D>>): Promise<Configuration<D, EM>>;
7
14
  static getORM<D extends IDatabaseDriver = IDatabaseDriver>(contextName?: string, configPaths?: string[], opts?: Partial<Options<D>>): Promise<MikroORM<D>>;
8
15
  static isDBConnected(config: Configuration, reason?: false): Promise<boolean>;
9
16
  static isDBConnected(config: Configuration, reason: true): Promise<true | string>;
10
- static getNodeVersion(): string;
11
17
  static getDriverDependencies(config: Configuration): string[];
12
18
  static dump(text: string, config?: Configuration): void;
13
- static getConfigPaths(): string[];
14
- static dumpDependencies(): Promise<void>;
15
- static getModuleVersion(name: string): Promise<string>;
19
+ static getSettings(): Settings;
20
+ static getConfigPaths(): Promise<string[]>;
21
+ private static getConfigFile;
22
+ private static loadEnvironmentVars;
23
+ static dumpDependencies(): void;
24
+ static getModuleVersion(name: string): string;
25
+ /**
26
+ * Resolve path to a module.
27
+ * @param id The module to require
28
+ * @param [from] Location to start the node resolution
29
+ */
30
+ private static resolveModulePath;
16
31
  static dumpTable(options: {
17
32
  columns: string[];
18
33
  rows: string[][];
19
34
  empty: string;
20
35
  }): void;
36
+ /**
37
+ * Tries to register TS support in the following order: swc, tsx, jiti, tsimp
38
+ * Use `MIKRO_ORM_CLI_TS_LOADER` env var to set the loader explicitly.
39
+ * This method is used only in CLI context.
40
+ */
41
+ static registerTypeScriptSupport(configPath?: string, tsLoader?: 'swc' | 'tsx' | 'jiti' | 'tsimp' | 'auto'): Promise<boolean>;
42
+ static isESM(): boolean;
21
43
  static showHelp(): void;
22
44
  }
45
+ export interface Settings {
46
+ verbose?: boolean;
47
+ preferTs?: boolean;
48
+ tsLoader?: 'swc' | 'tsx' | 'jiti' | 'tsimp' | 'auto';
49
+ tsConfigPath?: string;
50
+ configPaths?: string[];
51
+ }
package/CLIHelper.js CHANGED
@@ -1,27 +1,95 @@
1
+ import { extname, join } from 'node:path';
2
+ import { pathToFileURL } from 'node:url';
1
3
  import yargs from 'yargs';
2
- import { colors, ConfigurationLoader, MikroORM, Utils } from '@mikro-orm/core';
4
+ import { colors, Configuration, loadEnvironmentVars, lookupExtensions, MikroORM, Utils, } from '@mikro-orm/core';
5
+ import { fs } from '@mikro-orm/core/fs-utils';
3
6
  /**
4
7
  * @internal
5
8
  */
6
9
  export class CLIHelper {
7
- static async getConfiguration(contextName, configPaths, options = {}) {
8
- const deps = ConfigurationLoader.getORMPackages();
10
+ /**
11
+ * Gets a named configuration
12
+ *
13
+ * @param contextName Load a config with the given `contextName` value. Used when config file exports array or factory function. Setting it to "default" matches also config objects without `contextName` set.
14
+ * @param paths Array of possible paths for a configuration file. Files will be checked in order, and the first existing one will be used. Defaults to the output of {@link fs.getConfigPaths}.
15
+ * @param options Additional options to augment the final configuration with.
16
+ */
17
+ static async getConfiguration(contextName, paths, options = {}) {
18
+ paths ??= await this.getConfigPaths();
19
+ const deps = fs.getORMPackages();
9
20
  if (!deps.has('@mikro-orm/cli') && !process.env.MIKRO_ORM_ALLOW_GLOBAL_CLI) {
10
21
  throw new Error('@mikro-orm/cli needs to be installed as a local dependency!');
11
22
  }
12
- ConfigurationLoader.commonJSCompat(options);
13
- ConfigurationLoader.registerDotenv(options);
14
- configPaths ??= ConfigurationLoader.getConfigPaths();
15
23
  contextName ??= process.env.MIKRO_ORM_CONTEXT_NAME ?? 'default';
16
- return ConfigurationLoader.getConfiguration(contextName, configPaths, options);
24
+ const env = await this.loadEnvironmentVars();
25
+ await lookupExtensions(options);
26
+ const configFinder = (cfg) => {
27
+ return typeof cfg === 'object' && cfg !== null && ('contextName' in cfg ? cfg.contextName === contextName : (contextName === 'default'));
28
+ };
29
+ const isValidConfigFactoryResult = (cfg) => {
30
+ return typeof cfg === 'object' && cfg !== null && (!('contextName' in cfg) || cfg.contextName === contextName);
31
+ };
32
+ const result = await this.getConfigFile(paths);
33
+ if (!result[0]) {
34
+ if (Utils.hasObjectKeys(env)) {
35
+ return new Configuration(Utils.mergeConfig({ contextName }, options, env));
36
+ }
37
+ throw new Error(`MikroORM config file not found in ['${paths.join(`', '`)}']`);
38
+ }
39
+ const path = result[0];
40
+ let tmp = result[1];
41
+ if (Array.isArray(tmp)) {
42
+ const tmpFirstIndex = tmp.findIndex(configFinder);
43
+ if (tmpFirstIndex === -1) {
44
+ // Static config not found. Try factory functions
45
+ let configCandidate;
46
+ for (let i = 0, l = tmp.length; i < l; ++i) {
47
+ const f = tmp[i];
48
+ if (typeof f !== 'function') {
49
+ continue;
50
+ }
51
+ configCandidate = await f(contextName);
52
+ if (!isValidConfigFactoryResult(configCandidate)) {
53
+ continue;
54
+ }
55
+ tmp = configCandidate;
56
+ break;
57
+ }
58
+ if (Array.isArray(tmp)) {
59
+ throw new Error(`MikroORM config '${contextName}' was not found within the config file '${path}'. Either add a config with this name to the array, or add a function that when given this name will return a configuration object without a name, or with name set to this name.`);
60
+ }
61
+ }
62
+ else {
63
+ const tmpLastIndex = tmp.findLastIndex(configFinder);
64
+ if (tmpLastIndex !== tmpFirstIndex) {
65
+ throw new Error(`MikroORM config '${contextName}' is not unique within the array exported by '${path}' (first occurrence index: ${tmpFirstIndex}; last occurrence index: ${tmpLastIndex})`);
66
+ }
67
+ tmp = tmp[tmpFirstIndex];
68
+ }
69
+ }
70
+ else {
71
+ if (tmp instanceof Function) {
72
+ tmp = await tmp(contextName);
73
+ if (!isValidConfigFactoryResult(tmp)) {
74
+ throw new Error(`MikroORM config '${contextName}' was not what the function exported from '${path}' provided. Ensure it returns a config object with no name, or name matching the requested one.`);
75
+ }
76
+ }
77
+ else {
78
+ if (!configFinder(tmp)) {
79
+ throw new Error(`MikroORM config '${contextName}' was not what the default export from '${path}' provided.`);
80
+ }
81
+ }
82
+ }
83
+ const esmConfigOptions = this.isESM() ? { entityGenerator: { esmImport: true } } : {};
84
+ await lookupExtensions(tmp);
85
+ return new Configuration(Utils.mergeConfig({}, esmConfigOptions, tmp, options, env));
17
86
  }
18
87
  static async getORM(contextName, configPaths, opts = {}) {
19
- const options = await CLIHelper.getConfiguration(contextName, configPaths, opts);
20
- const settings = ConfigurationLoader.getSettings();
88
+ const options = await this.getConfiguration(contextName, configPaths, opts);
89
+ const settings = this.getSettings();
21
90
  options.set('allowGlobalContext', true);
22
91
  options.set('debug', !!settings.verbose);
23
92
  options.getLogger().setDebugMode(!!settings.verbose);
24
- options.set('connect', false);
25
93
  if (settings.preferTs !== false) {
26
94
  options.set('preferTs', true);
27
95
  }
@@ -43,9 +111,6 @@ export class CLIHelper {
43
111
  return false;
44
112
  }
45
113
  }
46
- static getNodeVersion() {
47
- return process.versions.node;
48
- }
49
114
  static getDriverDependencies(config) {
50
115
  try {
51
116
  return config.getDriver().getDependencies();
@@ -61,21 +126,92 @@ export class CLIHelper {
61
126
  // eslint-disable-next-line no-console
62
127
  console.log(text);
63
128
  }
64
- static getConfigPaths() {
65
- return ConfigurationLoader.getConfigPaths();
129
+ static getSettings() {
130
+ const config = fs.getPackageConfig();
131
+ const settings = { ...config['mikro-orm'] };
132
+ const bool = (v) => ['true', 't', '1'].includes(v.toLowerCase());
133
+ settings.preferTs = process.env.MIKRO_ORM_CLI_PREFER_TS != null ? bool(process.env.MIKRO_ORM_CLI_PREFER_TS) : settings.preferTs;
134
+ settings.tsLoader = process.env.MIKRO_ORM_CLI_TS_LOADER ?? settings.tsLoader;
135
+ settings.tsConfigPath = process.env.MIKRO_ORM_CLI_TS_CONFIG_PATH ?? settings.tsConfigPath;
136
+ settings.verbose = process.env.MIKRO_ORM_CLI_VERBOSE != null ? bool(process.env.MIKRO_ORM_CLI_VERBOSE) : settings.verbose;
137
+ if (process.env.MIKRO_ORM_CLI_CONFIG?.endsWith('.ts')) {
138
+ settings.preferTs = true;
139
+ }
140
+ return settings;
141
+ }
142
+ static async getConfigPaths() {
143
+ const settings = this.getSettings();
144
+ const typeScriptSupport = settings.preferTs ?? Utils.detectTypeScriptSupport();
145
+ const paths = [];
146
+ if (process.env.MIKRO_ORM_CLI_CONFIG) {
147
+ paths.push(process.env.MIKRO_ORM_CLI_CONFIG);
148
+ }
149
+ paths.push(...(settings.configPaths || []));
150
+ if (typeScriptSupport) {
151
+ paths.push('./src/mikro-orm.config.ts');
152
+ paths.push('./mikro-orm.config.ts');
153
+ }
154
+ const distDir = fs.pathExists(process.cwd() + '/dist');
155
+ const buildDir = fs.pathExists(process.cwd() + '/build');
156
+ /* v8 ignore next */
157
+ const path = distDir ? 'dist' : (buildDir ? 'build' : 'src');
158
+ paths.push(`./${path}/mikro-orm.config.js`);
159
+ paths.push('./mikro-orm.config.js');
160
+ /* v8 ignore next */
161
+ return Utils.unique(paths).filter(p => !p.match(/\.[mc]?ts$/) || typeScriptSupport);
162
+ }
163
+ static async getConfigFile(paths) {
164
+ for (let path of paths) {
165
+ path = Utils.absolutePath(path);
166
+ path = Utils.normalizePath(path);
167
+ if (fs.pathExists(path)) {
168
+ const config = await Utils.dynamicImport(path);
169
+ /* v8 ignore next */
170
+ return [path, await (config.default ?? config)];
171
+ }
172
+ }
173
+ return [];
174
+ }
175
+ static async loadEnvironmentVars() {
176
+ const ret = loadEnvironmentVars();
177
+ /* v8 ignore next */
178
+ switch (process.env.MIKRO_ORM_TYPE) {
179
+ case 'mongo':
180
+ ret.driver ??= await import('@mikro-orm/sqlite').then(m => m.SqliteDriver);
181
+ break;
182
+ case 'mysql':
183
+ ret.driver ??= await import('@mikro-orm/mysql').then(m => m.MySqlDriver);
184
+ break;
185
+ case 'mssql':
186
+ ret.driver ??= await import('@mikro-orm/mssql').then(m => m.MsSqlDriver);
187
+ break;
188
+ case 'mariadb':
189
+ ret.driver ??= await import('@mikro-orm/mariadb').then(m => m.MariaDbDriver);
190
+ break;
191
+ case 'postgresql':
192
+ ret.driver ??= await import('@mikro-orm/postgresql').then(m => m.PostgreSqlDriver);
193
+ break;
194
+ case 'sqlite':
195
+ ret.driver ??= await import('@mikro-orm/sqlite').then(m => m.SqliteDriver);
196
+ break;
197
+ case 'libsql':
198
+ ret.driver ??= await import('@mikro-orm/libsql').then(m => m.LibSqlDriver);
199
+ break;
200
+ }
201
+ return ret;
66
202
  }
67
- static async dumpDependencies() {
203
+ static dumpDependencies() {
68
204
  const version = Utils.getORMVersion();
69
205
  CLIHelper.dump(' - dependencies:');
70
206
  CLIHelper.dump(` - mikro-orm ${colors.green(version)}`);
71
- CLIHelper.dump(` - node ${colors.green(CLIHelper.getNodeVersion())}`);
72
- if (Utils.pathExistsSync(process.cwd() + '/package.json')) {
73
- /* v8 ignore next 3 */
207
+ CLIHelper.dump(` - node ${colors.green(process.versions.node)}`);
208
+ if (fs.pathExists(process.cwd() + '/package.json')) {
209
+ /* v8 ignore if */
74
210
  if (process.versions.bun) {
75
211
  CLIHelper.dump(` - typescript via bun`);
76
212
  }
77
213
  else {
78
- CLIHelper.dump(` - typescript ${await CLIHelper.getModuleVersion('typescript')}`);
214
+ CLIHelper.dump(` - typescript ${CLIHelper.getModuleVersion('typescript')}`);
79
215
  }
80
216
  CLIHelper.dump(' - package.json ' + colors.green('found'));
81
217
  }
@@ -83,15 +219,31 @@ export class CLIHelper {
83
219
  CLIHelper.dump(' - package.json ' + colors.red('not found'));
84
220
  }
85
221
  }
86
- static async getModuleVersion(name) {
222
+ static getModuleVersion(name) {
87
223
  try {
88
- const pkg = Utils.requireFrom(`${name}/package.json`);
224
+ const path = `${this.resolveModulePath(name)}/package.json`;
225
+ const pkg = fs.readJSONSync(path);
89
226
  return colors.green(pkg.version);
90
227
  }
91
228
  catch {
92
229
  return '';
93
230
  }
94
231
  }
232
+ /**
233
+ * Resolve path to a module.
234
+ * @param id The module to require
235
+ * @param [from] Location to start the node resolution
236
+ */
237
+ static resolveModulePath(id, from = process.cwd()) {
238
+ if (!extname(from)) {
239
+ from = join(from, '__fake.js');
240
+ }
241
+ const path = Utils.normalizePath(import.meta.resolve(id, pathToFileURL(from)));
242
+ const parts = path.split('/');
243
+ const idx = parts.lastIndexOf(id) + 1;
244
+ parts.splice(idx, parts.length - idx);
245
+ return parts.join('/');
246
+ }
95
247
  static dumpTable(options) {
96
248
  if (options.rows.length === 0) {
97
249
  return CLIHelper.dump(options.empty);
@@ -113,7 +265,48 @@ export class CLIHelper {
113
265
  ret += colors.grey('└' + lengths.map(length => '─'.repeat(length)).join('┴') + '┘');
114
266
  CLIHelper.dump(ret);
115
267
  }
116
- /* v8 ignore next 3 */
268
+ /**
269
+ * Tries to register TS support in the following order: swc, tsx, jiti, tsimp
270
+ * Use `MIKRO_ORM_CLI_TS_LOADER` env var to set the loader explicitly.
271
+ * This method is used only in CLI context.
272
+ */
273
+ static async registerTypeScriptSupport(configPath = 'tsconfig.json', tsLoader) {
274
+ /* v8 ignore if */
275
+ if (process.versions.bun) {
276
+ return true;
277
+ }
278
+ process.env.SWC_NODE_PROJECT ??= configPath;
279
+ process.env.TSIMP_PROJECT ??= configPath;
280
+ process.env.MIKRO_ORM_CLI_ALWAYS_ALLOW_TS ??= '1';
281
+ const explicitLoader = tsLoader ?? process.env.MIKRO_ORM_CLI_TS_LOADER ?? 'auto';
282
+ const loaders = {
283
+ swc: { module: '@swc-node/register/esm-register' },
284
+ tsx: { module: 'tsx/esm/api', cb: (tsx) => tsx.register({ tsconfig: configPath }) },
285
+ jiti: { module: 'jiti/register', cb: () => Utils.dynamicImportProvider = id => import(id).then(mod => mod?.default ?? mod) },
286
+ tsimp: { module: 'tsimp/import' },
287
+ };
288
+ for (const loader of Utils.keys(loaders)) {
289
+ if (explicitLoader !== 'auto' && loader !== explicitLoader) {
290
+ continue;
291
+ }
292
+ const { module, cb } = loaders[loader];
293
+ const mod = await Utils.tryImport({ module });
294
+ if (mod) {
295
+ cb?.(mod);
296
+ process.env.MIKRO_ORM_CLI_TS_LOADER = loader;
297
+ return true;
298
+ }
299
+ }
300
+ // eslint-disable-next-line no-console
301
+ console.warn('Neither `swc`, `tsx`, `jiti` nor `tsimp` found in the project dependencies, support for working with TypeScript files might not work. To use `swc`, you need to install both `@swc-node/register` and `@swc/core`.');
302
+ return false;
303
+ }
304
+ static isESM() {
305
+ const config = fs.getPackageConfig();
306
+ const type = config?.type ?? '';
307
+ return type === 'module';
308
+ }
309
+ /* v8 ignore next */
117
310
  static showHelp() {
118
311
  yargs(process.argv.slice(2)).showHelp();
119
312
  }
package/README.md CHANGED
@@ -11,7 +11,6 @@ TypeScript ORM for Node.js based on Data Mapper, [Unit of Work](https://mikro-or
11
11
  [![Chat on discord](https://img.shields.io/discord/1214904142443839538?label=discord&color=blue)](https://discord.gg/w8bjxFHS7X)
12
12
  [![Downloads](https://img.shields.io/npm/dm/@mikro-orm/core.svg)](https://www.npmjs.com/package/@mikro-orm/core)
13
13
  [![Coverage Status](https://img.shields.io/coveralls/mikro-orm/mikro-orm.svg)](https://coveralls.io/r/mikro-orm/mikro-orm?branch=master)
14
- [![Maintainability](https://api.codeclimate.com/v1/badges/27999651d3adc47cfa40/maintainability)](https://codeclimate.com/github/mikro-orm/mikro-orm/maintainability)
15
14
  [![Build Status](https://github.com/mikro-orm/mikro-orm/workflows/tests/badge.svg?branch=master)](https://github.com/mikro-orm/mikro-orm/actions?workflow=tests)
16
15
 
17
16
  ## 🤔 Unit of What?
@@ -141,7 +140,7 @@ There is also auto-generated [CHANGELOG.md](CHANGELOG.md) file based on commit m
141
140
  - [Composite and Foreign Keys as Primary Key](https://mikro-orm.io/docs/composite-keys)
142
141
  - [Filters](https://mikro-orm.io/docs/filters)
143
142
  - [Using `QueryBuilder`](https://mikro-orm.io/docs/query-builder)
144
- - [Preloading Deeply Nested Structures via populate](https://mikro-orm.io/docs/nested-populate)
143
+ - [Populating relations](https://mikro-orm.io/docs/populating-relations)
145
144
  - [Property Validation](https://mikro-orm.io/docs/property-validation)
146
145
  - [Lifecycle Hooks](https://mikro-orm.io/docs/events#hooks)
147
146
  - [Vanilla JS Support](https://mikro-orm.io/docs/usage-with-js)
@@ -382,6 +381,8 @@ See also the list of contributors who [participated](https://github.com/mikro-or
382
381
 
383
382
  Please ⭐️ this repository if this project helped you!
384
383
 
384
+ > If you'd like to support my open-source work, consider sponsoring me directly at [github.com/sponsors/b4nan](https://github.com/sponsors/b4nan).
385
+
385
386
  ## 📝 License
386
387
 
387
388
  Copyright © 2018 [Martin Adámek](https://github.com/b4nan).
package/cli CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { CLIHelper } from './CLIHelper.js';
3
- import { CLIConfigurator } from './CLIConfigurator.js';
4
- const argv = await CLIConfigurator.configure();
3
+ import { configure } from './CLIConfigurator.js';
4
+ const argv = await configure();
5
5
  const args = await argv.parse(process.argv.slice(2));
6
6
  if (args._.length === 0) {
7
7
  CLIHelper.showHelp();
package/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { CLIHelper } from './CLIHelper.js';
3
- import { CLIConfigurator } from './CLIConfigurator.js';
4
- const argv = await CLIConfigurator.configure();
3
+ import { configure } from './CLIConfigurator.js';
4
+ const argv = await configure();
5
5
  const args = await argv.parse(process.argv.slice(2));
6
6
  if (args._.length === 0) {
7
7
  CLIHelper.showHelp();
@@ -7,8 +7,7 @@ export class CreateDatabaseCommand {
7
7
  */
8
8
  async handler(args) {
9
9
  const orm = await CLIHelper.getORM(args.contextName, args.config);
10
- const schemaGenerator = orm.getSchemaGenerator();
11
- await schemaGenerator.ensureDatabase();
10
+ await orm.schema.ensureDatabase();
12
11
  await orm.close(true);
13
12
  }
14
13
  }
@@ -16,8 +16,7 @@ export class CreateSeederCommand {
16
16
  async handler(args) {
17
17
  const className = CreateSeederCommand.getSeederClassName(args.seeder);
18
18
  const orm = await CLIHelper.getORM(args.contextName, args.config);
19
- const seeder = orm.getSeeder();
20
- const path = await seeder.createSeeder(className);
19
+ const path = await orm.seeder.create(className);
21
20
  CLIHelper.dump(colors.green(`Seeder ${args.seeder} successfully created at ${path}`));
22
21
  await orm.close(true);
23
22
  }
@@ -17,7 +17,7 @@ export class DatabaseSeedCommand {
17
17
  async handler(args) {
18
18
  const orm = await CLIHelper.getORM(args.contextName, args.config);
19
19
  const className = args.class ?? orm.config.get('seeder').defaultSeeder;
20
- await orm.getSeeder().seedString(className);
20
+ await orm.seeder.seedString(className);
21
21
  CLIHelper.dump(colors.green(`Seeder ${className} successfully executed`));
22
22
  await orm.close(true);
23
23
  }
@@ -1,4 +1,5 @@
1
- import { ConfigurationLoader, Utils, colors } from '@mikro-orm/core';
1
+ import { colors, Utils } from '@mikro-orm/core';
2
+ import { fs } from '@mikro-orm/core/fs-utils';
2
3
  import { CLIHelper } from '../CLIHelper.js';
3
4
  export class DebugCommand {
4
5
  command = 'debug';
@@ -8,12 +9,13 @@ export class DebugCommand {
8
9
  */
9
10
  async handler(args) {
10
11
  CLIHelper.dump(`Current ${colors.cyan('MikroORM')} CLI configuration`);
11
- await CLIHelper.dumpDependencies();
12
- const settings = ConfigurationLoader.getSettings();
12
+ CLIHelper.dumpDependencies();
13
+ const settings = CLIHelper.getSettings();
13
14
  if (!process.versions.bun && settings.preferTs !== false) {
14
- CLIHelper.dump(' - TypeScript support ' + colors.green('enabled'));
15
+ const loader = process.env.MIKRO_ORM_CLI_TS_LOADER ?? 'auto';
16
+ CLIHelper.dump(' - TypeScript support ' + colors.green(`enabled (${loader})`));
15
17
  }
16
- const configPaths = args.config ?? CLIHelper.getConfigPaths();
18
+ const configPaths = args.config ?? await CLIHelper.getConfigPaths();
17
19
  CLIHelper.dump(' - searched config paths:');
18
20
  await DebugCommand.checkPaths(configPaths, 'yellow');
19
21
  CLIHelper.dump(` - searched for config name: ${colors.green(args.contextName)}`);
@@ -23,7 +25,7 @@ export class DebugCommand {
23
25
  const drivers = CLIHelper.getDriverDependencies(config);
24
26
  CLIHelper.dump(' - driver dependencies:');
25
27
  for (const driver of drivers) {
26
- CLIHelper.dump(` - ${driver} ${await CLIHelper.getModuleVersion(driver)}`);
28
+ CLIHelper.dump(` - ${driver} ${CLIHelper.getModuleVersion(driver)}`);
27
29
  }
28
30
  const isConnected = await CLIHelper.isDBConnected(config, true);
29
31
  if (isConnected === true) {
@@ -39,8 +41,8 @@ export class DebugCommand {
39
41
  }
40
42
  const entities = config.get('entities', []);
41
43
  if (entities.length > 0) {
42
- const refs = entities.filter(p => !Utils.isString(p));
43
- const paths = entities.filter(p => Utils.isString(p));
44
+ const refs = entities.filter(p => typeof p !== 'string');
45
+ const paths = entities.filter(p => typeof p === 'string');
44
46
  const will = !config.get('preferTs') ? 'will' : 'could';
45
47
  CLIHelper.dump(` - ${will} use \`entities\` array (contains ${refs.length} references and ${paths.length} paths)`);
46
48
  if (paths.length > 0) {
@@ -49,8 +51,8 @@ export class DebugCommand {
49
51
  }
50
52
  const entitiesTs = config.get('entitiesTs', []);
51
53
  if (entitiesTs.length > 0) {
52
- const refs = entitiesTs.filter(p => !Utils.isString(p));
53
- const paths = entitiesTs.filter(p => Utils.isString(p));
54
+ const refs = entitiesTs.filter(p => typeof p !== 'string');
55
+ const paths = entitiesTs.filter(p => typeof p === 'string');
54
56
  /* v8 ignore next */
55
57
  const will = config.get('preferTs') ? 'will' : 'could';
56
58
  CLIHelper.dump(` - ${will} use \`entitiesTs\` array (contains ${refs.length} references and ${paths.length} paths)`);
@@ -67,8 +69,7 @@ export class DebugCommand {
67
69
  for (let path of paths) {
68
70
  path = Utils.absolutePath(path, baseDir);
69
71
  path = Utils.normalizePath(path);
70
- const found = await Utils.pathExists(path);
71
- if (found) {
72
+ if (fs.pathExists(path)) {
72
73
  CLIHelper.dump(` - ${path} (${colors.green('found')})`);
73
74
  }
74
75
  else {
@@ -1,4 +1,5 @@
1
- import { MetadataDiscovery, MetadataStorage, colors, FileCacheAdapter } from '@mikro-orm/core';
1
+ import { MetadataDiscovery, MetadataStorage, colors } from '@mikro-orm/core';
2
+ import { FileCacheAdapter } from '@mikro-orm/core/fs-utils';
2
3
  import { CLIHelper } from '../CLIHelper.js';
3
4
  export class GenerateCacheCommand {
4
5
  command = 'cache:generate';
@@ -25,7 +26,7 @@ export class GenerateCacheCommand {
25
26
  await config.getMetadataCacheAdapter().clear();
26
27
  config.set('logger', CLIHelper.dump.bind(null));
27
28
  config.set('debug', true);
28
- const discovery = new MetadataDiscovery(MetadataStorage.init(), config.getDriver().getPlatform(), config);
29
+ const discovery = new MetadataDiscovery(new MetadataStorage(), config.getDriver().getPlatform(), config);
29
30
  await discovery.discover(args.ts ?? false);
30
31
  const combined = args.combined && config.get('metadataCache').combined;
31
32
  CLIHelper.dump(colors.green(`${combined ? 'Combined ' : ''}${args.ts ? 'TS' : 'JS'} metadata cache was successfully generated${combined ? ' to ' + combined : ''}`));
@@ -1,4 +1,4 @@
1
- import { Utils, colors } from '@mikro-orm/core';
1
+ import { colors, Utils, } from '@mikro-orm/core';
2
2
  import { CLIHelper } from '../CLIHelper.js';
3
3
  export class MigrationCommandFactory {
4
4
  static DESCRIPTIONS = {
@@ -80,26 +80,25 @@ export class MigrationCommandFactory {
80
80
  // to be able to run have a master transaction, but run marked migrations outside of it, we need a second connection
81
81
  const options = { pool: { min: 1, max: 2 } };
82
82
  const orm = await CLIHelper.getORM(args.contextName, args.config, options);
83
- const migrator = orm.getMigrator();
84
83
  switch (method) {
85
84
  case 'create':
86
- await this.handleCreateCommand(migrator, args, orm.config);
85
+ await this.handleCreateCommand(orm.migrator, args, orm.config);
87
86
  break;
88
87
  case 'check':
89
- await this.handleCheckCommand(migrator, orm);
88
+ await this.handleCheckCommand(orm.migrator, orm);
90
89
  break;
91
90
  case 'list':
92
- await this.handleListCommand(migrator);
91
+ await this.handleListCommand(orm.migrator);
93
92
  break;
94
93
  case 'pending':
95
- await this.handlePendingCommand(migrator);
94
+ await this.handlePendingCommand(orm.migrator);
96
95
  break;
97
96
  case 'up':
98
97
  case 'down':
99
- await this.handleUpDownCommand(args, migrator, method);
98
+ await this.handleUpDownCommand(args, orm.migrator, method);
100
99
  break;
101
100
  case 'fresh':
102
- await this.handleFreshCommand(args, migrator, orm);
101
+ await this.handleFreshCommand(args, orm.migrator, orm);
103
102
  }
104
103
  await orm.close(true);
105
104
  }
@@ -121,7 +120,7 @@ export class MigrationCommandFactory {
121
120
  CLIHelper.dump(colors.green(message));
122
121
  }
123
122
  static async handlePendingCommand(migrator) {
124
- const pending = await migrator.getPendingMigrations();
123
+ const pending = await migrator.getPending();
125
124
  CLIHelper.dumpTable({
126
125
  columns: ['Name'],
127
126
  rows: pending.map(row => [row.name]),
@@ -129,7 +128,7 @@ export class MigrationCommandFactory {
129
128
  });
130
129
  }
131
130
  static async handleListCommand(migrator) {
132
- const executed = await migrator.getExecutedMigrations();
131
+ const executed = await migrator.getExecuted();
133
132
  CLIHelper.dumpTable({
134
133
  columns: ['Name', 'Executed at'],
135
134
  rows: executed.map(row => {
@@ -141,7 +140,7 @@ export class MigrationCommandFactory {
141
140
  });
142
141
  }
143
142
  static async handleCreateCommand(migrator, args, config) {
144
- const ret = await migrator.createMigration(args.path, args.blank, args.initial, args.name);
143
+ const ret = await migrator.create(args.path, args.blank, args.initial, args.name);
145
144
  if (ret.diff.up.length === 0) {
146
145
  return CLIHelper.dump(colors.green(`No changes required, schema is up-to-date`));
147
146
  }
@@ -149,7 +148,7 @@ export class MigrationCommandFactory {
149
148
  CLIHelper.dump(colors.green('Creating migration with following queries:'));
150
149
  CLIHelper.dump(colors.green('up:'));
151
150
  CLIHelper.dump(ret.diff.up.map(sql => ' ' + sql).join('\n'), config);
152
- /* v8 ignore next 3 */
151
+ /* v8 ignore if */
153
152
  if (config.getDriver().getPlatform().supportsDownMigrations()) {
154
153
  CLIHelper.dump(colors.green('down:'));
155
154
  CLIHelper.dump(ret.diff.down.map(sql => ' ' + sql).join('\n'), config);
@@ -161,7 +160,7 @@ export class MigrationCommandFactory {
161
160
  CLIHelper.dump(colors.green(`${ret.fileName} successfully created`));
162
161
  }
163
162
  static async handleCheckCommand(migrator, orm) {
164
- if (!(await migrator.checkMigrationNeeded())) {
163
+ if (!(await migrator.checkSchema())) {
165
164
  return CLIHelper.dump(colors.green(`No changes required, schema is up-to-date`));
166
165
  }
167
166
  await orm.close(true);
@@ -169,17 +168,15 @@ export class MigrationCommandFactory {
169
168
  process.exit(1);
170
169
  }
171
170
  static async handleFreshCommand(args, migrator, orm) {
172
- const generator = orm.getSchemaGenerator();
173
- await generator.dropSchema({ dropMigrationsTable: true, dropDb: args.dropDb });
171
+ await orm.schema.drop({ dropMigrationsTable: true, dropDb: args.dropDb });
174
172
  CLIHelper.dump(colors.green('Dropped schema successfully'));
175
173
  const opts = MigrationCommandFactory.getUpDownOptions(args);
176
174
  await migrator.up(opts);
177
175
  const message = this.getUpDownSuccessMessage('up', opts);
178
176
  CLIHelper.dump(colors.green(message));
179
177
  if (args.seed !== undefined) {
180
- const seeder = orm.getSeeder();
181
178
  const seederClass = args.seed || orm.config.get('seeder').defaultSeeder;
182
- await seeder.seedString(seederClass);
179
+ await orm.seeder.seedString(seederClass);
183
180
  CLIHelper.dump(colors.green(`Database seeded successfully with seeder class ${seederClass}`));
184
181
  }
185
182
  }
@@ -203,10 +200,10 @@ export class MigrationCommandFactory {
203
200
  if (method === 'up' && Utils.isEmpty(options)) {
204
201
  return msg + ' to the latest version';
205
202
  }
206
- if (Utils.isString(options.to)) {
203
+ if (typeof options.to === 'string') {
207
204
  return msg + ' to version ' + options.to;
208
205
  }
209
- if (options.migrations && options.migrations.length === 1) {
206
+ if (options.migrations?.length === 1) {
210
207
  return msg + ' to version ' + options.migrations[0];
211
208
  }
212
209
  return msg;
@@ -80,12 +80,11 @@ export class SchemaCommandFactory {
80
80
  return CLIHelper.showHelp();
81
81
  }
82
82
  const orm = await CLIHelper.getORM(args.contextName, args.config);
83
- const generator = orm.getSchemaGenerator();
84
83
  const params = { wrap: args.fkChecks == null ? undefined : !args.fkChecks, ...args };
85
84
  if (args.dump) {
86
85
  const m = `get${method.substr(0, 1).toUpperCase()}${method.substr(1)}SchemaSQL`;
87
- const dump = await generator[m](params);
88
- /* v8 ignore next 3 */
86
+ const dump = await orm.schema[m](params);
87
+ /* v8 ignore if */
89
88
  if (dump) {
90
89
  CLIHelper.dump(dump, orm.config);
91
90
  successMessage = '';
@@ -95,16 +94,13 @@ export class SchemaCommandFactory {
95
94
  }
96
95
  }
97
96
  else if (method === 'fresh') {
98
- await generator.dropSchema(params);
99
- await generator.createSchema(params);
97
+ await orm.schema.refresh(params);
100
98
  }
101
99
  else {
102
- const m = method + 'Schema';
103
- await generator[m](params);
100
+ await orm.schema[method](params);
104
101
  }
105
102
  if (typeof args.seed !== 'undefined') {
106
- const seeder = orm.getSeeder();
107
- await seeder.seedString(args.seed || orm.config.get('seeder').defaultSeeder);
103
+ await orm.seeder.seedString(args.seed || orm.config.get('seeder').defaultSeeder);
108
104
  }
109
105
  CLIHelper.dump(colors.green(successMessage));
110
106
  await orm.close(true);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mikro-orm/cli",
3
3
  "type": "module",
4
- "version": "7.0.0-dev.9",
4
+ "version": "7.0.0-dev.91",
5
5
  "description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
6
6
  "exports": {
7
7
  "./package.json": "./package.json",
@@ -41,7 +41,7 @@
41
41
  "mikro-orm": "./cli"
42
42
  },
43
43
  "engines": {
44
- "node": ">= 22.11.0"
44
+ "node": ">= 22.17.0"
45
45
  },
46
46
  "scripts": {
47
47
  "build": "yarn clean && yarn compile && yarn copy",
@@ -53,13 +53,14 @@
53
53
  "access": "public"
54
54
  },
55
55
  "dependencies": {
56
- "@mikro-orm/core": "7.0.0-dev.9",
57
- "@mikro-orm/knex": "7.0.0-dev.9",
56
+ "@mikro-orm/core": "7.0.0-dev.91",
57
+ "@mikro-orm/knex": "7.0.0-dev.91",
58
+ "mikro-orm": "7.0.0-dev.91",
58
59
  "yargs": "17.7.2"
59
60
  },
60
61
  "devDependencies": {
61
- "@mikro-orm/entity-generator": "^6.4.13",
62
- "@mikro-orm/migrations": "^6.4.13",
63
- "@mikro-orm/seeder": "^6.4.13"
62
+ "@mikro-orm/entity-generator": "^6.6.2",
63
+ "@mikro-orm/migrations": "^6.6.2",
64
+ "@mikro-orm/seeder": "^6.6.2"
64
65
  }
65
66
  }