@mikro-orm/cli 7.0.0-dev.31 → 7.0.0-dev.310

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';
@@ -6,69 +7,67 @@ import { CreateSeederCommand } from './commands/CreateSeederCommand.js';
6
7
  import { DatabaseSeedCommand } from './commands/DatabaseSeedCommand.js';
7
8
  import { DebugCommand } from './commands/DebugCommand.js';
8
9
  import { GenerateCacheCommand } from './commands/GenerateCacheCommand.js';
10
+ import { CompileCommand } from './commands/CompileCommand.js';
9
11
  import { GenerateEntitiesCommand } from './commands/GenerateEntitiesCommand.js';
10
12
  import { ImportCommand } from './commands/ImportCommand.js';
11
13
  import { MigrationCommandFactory } from './commands/MigrationCommandFactory.js';
12
14
  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
- }
15
+ import { CLIHelper } from './CLIHelper.js';
16
+ function createBasicConfig() {
17
+ return yargs()
18
+ .scriptName('mikro-orm')
19
+ .usage('Usage: $0 <command> [options]')
20
+ .example('$0 debug', 'Show debugging information')
21
+ .example('$0 schema:update --run', 'Runs schema synchronization')
22
+ .option('config', {
23
+ type: 'string',
24
+ array: true,
25
+ desc: `Set path to the ORM configuration file`,
26
+ })
27
+ .option('contextName', {
28
+ alias: 'context',
29
+ type: 'string',
30
+ desc: 'Set name of config to load out of the ORM configuration file. Used when config file exports an array or a function',
31
+ default: process.env.MIKRO_ORM_CONTEXT_NAME ?? 'default',
32
+ })
33
+ .alias('v', 'version')
34
+ .alias('h', 'help')
35
+ .recommendCommands()
36
+ .showHelpOnFail(true)
37
+ .demandCommand(1, '')
38
+ .strict();
39
+ }
40
+ export async function configure() {
41
+ fs.checkPackageVersion();
42
+ const settings = CLIHelper.getSettings();
43
+ const version = Utils.getORMVersion();
44
+ if (settings.preferTs !== false) {
45
+ const preferTs = await CLIHelper.registerTypeScriptSupport(settings.tsConfigPath, settings.tsLoader);
46
+ /* v8 ignore next */
47
+ if (!preferTs) {
48
+ process.env.MIKRO_ORM_CLI_PREFER_TS ??= '0';
51
49
  }
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
50
  }
51
+ return createBasicConfig()
52
+ .version(version)
53
+ .command(new ClearCacheCommand())
54
+ .command(new GenerateCacheCommand())
55
+ .command(new CompileCommand())
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());
74
73
  }
package/CLIHelper.d.ts CHANGED
@@ -1,22 +1,52 @@
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>>;
14
+ static commonJSCompat(options: Partial<Options>): void;
7
15
  static getORM<D extends IDatabaseDriver = IDatabaseDriver>(contextName?: string, configPaths?: string[], opts?: Partial<Options<D>>): Promise<MikroORM<D>>;
8
16
  static isDBConnected(config: Configuration, reason?: false): Promise<boolean>;
9
17
  static isDBConnected(config: Configuration, reason: true): Promise<true | string>;
10
- static getNodeVersion(): string;
11
18
  static getDriverDependencies(config: Configuration): string[];
12
19
  static dump(text: string, config?: Configuration): void;
13
- static getConfigPaths(): string[];
14
- static dumpDependencies(): Promise<void>;
15
- static getModuleVersion(name: string): Promise<string>;
20
+ static getSettings(): Settings;
21
+ static getConfigPaths(): Promise<string[]>;
22
+ private static getConfigFile;
23
+ private static loadEnvironmentVars;
24
+ static dumpDependencies(): void;
25
+ static getModuleVersion(name: string): string;
26
+ /**
27
+ * Resolve path to a module.
28
+ * @param id The module to require
29
+ * @param [from] Location to start the node resolution
30
+ */
31
+ private static resolveModulePath;
16
32
  static dumpTable(options: {
17
33
  columns: string[];
18
34
  rows: string[][];
19
35
  empty: string;
20
36
  }): void;
37
+ /**
38
+ * Tries to register TS support in the following order: swc, tsx, jiti, tsimp
39
+ * Use `MIKRO_ORM_CLI_TS_LOADER` env var to set the loader explicitly.
40
+ * This method is used only in CLI context.
41
+ */
42
+ static registerTypeScriptSupport(configPath?: string, tsLoader?: 'swc' | 'tsx' | 'jiti' | 'tsimp' | 'auto'): Promise<boolean>;
43
+ static isESM(): boolean;
21
44
  static showHelp(): void;
22
45
  }
46
+ export interface Settings {
47
+ verbose?: boolean;
48
+ preferTs?: boolean;
49
+ tsLoader?: 'swc' | 'tsx' | 'jiti' | 'tsimp' | 'auto';
50
+ tsConfigPath?: string;
51
+ configPaths?: string[];
52
+ }
package/CLIHelper.js CHANGED
@@ -1,27 +1,111 @@
1
- import { readFile } from 'node:fs/promises';
1
+ import { extname, join } from 'node:path';
2
+ import { createRequire } from 'node:module';
3
+ import { fileURLToPath, pathToFileURL } from 'node:url';
2
4
  import yargs from 'yargs';
3
- import { colors, ConfigurationLoader, MikroORM, Utils } from '@mikro-orm/core';
5
+ import { colors, Configuration, loadEnvironmentVars, loadOptionalDependencies, MikroORM, Utils, } from '@mikro-orm/core';
6
+ import { fs } from '@mikro-orm/core/fs-utils';
4
7
  /**
5
8
  * @internal
6
9
  */
7
10
  export class CLIHelper {
8
- static async getConfiguration(contextName, configPaths, options = {}) {
9
- const deps = ConfigurationLoader.getORMPackages();
11
+ /**
12
+ * Gets a named configuration
13
+ *
14
+ * @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.
15
+ * @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}.
16
+ * @param options Additional options to augment the final configuration with.
17
+ */
18
+ static async getConfiguration(contextName, paths, options = {}) {
19
+ this.commonJSCompat(options);
20
+ paths ??= await this.getConfigPaths();
21
+ const deps = fs.getORMPackages();
10
22
  if (!deps.has('@mikro-orm/cli') && !process.env.MIKRO_ORM_ALLOW_GLOBAL_CLI) {
11
23
  throw new Error('@mikro-orm/cli needs to be installed as a local dependency!');
12
24
  }
13
- ConfigurationLoader.registerDotenv(options);
14
- configPaths ??= ConfigurationLoader.getConfigPaths();
15
25
  contextName ??= process.env.MIKRO_ORM_CONTEXT_NAME ?? 'default';
16
- return ConfigurationLoader.getConfiguration(contextName, configPaths, options);
26
+ const env = await this.loadEnvironmentVars();
27
+ await loadOptionalDependencies(options);
28
+ // oxfmt-ignore
29
+ const configFinder = (cfg) => {
30
+ return typeof cfg === 'object' && cfg !== null && ('contextName' in cfg ? cfg.contextName === contextName : contextName === 'default');
31
+ };
32
+ const isValidConfigFactoryResult = (cfg) => {
33
+ return typeof cfg === 'object' && cfg !== null && (!('contextName' in cfg) || cfg.contextName === contextName);
34
+ };
35
+ const result = await this.getConfigFile(paths);
36
+ if (!result[0]) {
37
+ if (Utils.hasObjectKeys(env)) {
38
+ return new Configuration(Utils.mergeConfig({ contextName }, options.preferEnvVars ? options : env, options.preferEnvVars ? env : options));
39
+ }
40
+ throw new Error(`MikroORM config file not found in ['${paths.join(`', '`)}']`);
41
+ }
42
+ const path = result[0];
43
+ let tmp = result[1];
44
+ if (Array.isArray(tmp)) {
45
+ const tmpFirstIndex = tmp.findIndex(configFinder);
46
+ if (tmpFirstIndex === -1) {
47
+ // Static config not found. Try factory functions
48
+ let configCandidate;
49
+ for (let i = 0, l = tmp.length; i < l; ++i) {
50
+ const f = tmp[i];
51
+ if (typeof f !== 'function') {
52
+ continue;
53
+ }
54
+ configCandidate = await f(contextName);
55
+ if (!isValidConfigFactoryResult(configCandidate)) {
56
+ continue;
57
+ }
58
+ tmp = configCandidate;
59
+ break;
60
+ }
61
+ if (Array.isArray(tmp)) {
62
+ 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.`);
63
+ }
64
+ }
65
+ else {
66
+ const tmpLastIndex = tmp.findLastIndex(configFinder);
67
+ if (tmpLastIndex !== tmpFirstIndex) {
68
+ throw new Error(`MikroORM config '${contextName}' is not unique within the array exported by '${path}' (first occurrence index: ${tmpFirstIndex}; last occurrence index: ${tmpLastIndex})`);
69
+ }
70
+ tmp = tmp[tmpFirstIndex];
71
+ }
72
+ }
73
+ else {
74
+ if (tmp instanceof Function) {
75
+ tmp = await tmp(contextName);
76
+ if (!isValidConfigFactoryResult(tmp)) {
77
+ 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.`);
78
+ }
79
+ }
80
+ else {
81
+ if (!configFinder(tmp)) {
82
+ throw new Error(`MikroORM config '${contextName}' was not what the default export from '${path}' provided.`);
83
+ }
84
+ }
85
+ }
86
+ const esmConfigOptions = this.isESM() ? { entityGenerator: { esmImport: true } } : {};
87
+ await loadOptionalDependencies(tmp);
88
+ const preferEnvVars = options.preferEnvVars ?? tmp.preferEnvVars;
89
+ return new Configuration(Utils.mergeConfig({}, esmConfigOptions, tmp, preferEnvVars ? options : env, preferEnvVars ? env : options));
90
+ }
91
+ static commonJSCompat(options) {
92
+ if (this.isESM()) {
93
+ return;
94
+ }
95
+ /* v8 ignore next */
96
+ options.dynamicImportProvider ??=
97
+ globalThis.dynamicImportProvider ??
98
+ ((id) => {
99
+ return createRequire(process.cwd())(fileURLToPath(id));
100
+ });
101
+ globalThis.dynamicImportProvider = options.dynamicImportProvider;
17
102
  }
18
103
  static async getORM(contextName, configPaths, opts = {}) {
19
- const options = await CLIHelper.getConfiguration(contextName, configPaths, opts);
20
- const settings = ConfigurationLoader.getSettings();
104
+ const options = await this.getConfiguration(contextName, configPaths, opts);
105
+ const settings = this.getSettings();
21
106
  options.set('allowGlobalContext', true);
22
107
  options.set('debug', !!settings.verbose);
23
108
  options.getLogger().setDebugMode(!!settings.verbose);
24
- options.set('connect', false);
25
109
  if (settings.preferTs !== false) {
26
110
  options.set('preferTs', true);
27
111
  }
@@ -43,9 +127,6 @@ export class CLIHelper {
43
127
  return false;
44
128
  }
45
129
  }
46
- static getNodeVersion() {
47
- return process.versions.node;
48
- }
49
130
  static getDriverDependencies(config) {
50
131
  try {
51
132
  return config.getDriver().getDependencies();
@@ -61,21 +142,94 @@ export class CLIHelper {
61
142
  // eslint-disable-next-line no-console
62
143
  console.log(text);
63
144
  }
64
- static getConfigPaths() {
65
- return ConfigurationLoader.getConfigPaths();
145
+ static getSettings() {
146
+ const config = fs.getPackageConfig();
147
+ const settings = { ...config['mikro-orm'] };
148
+ const bool = (v) => ['true', 't', '1'].includes(v.toLowerCase());
149
+ settings.preferTs =
150
+ process.env.MIKRO_ORM_CLI_PREFER_TS != null ? bool(process.env.MIKRO_ORM_CLI_PREFER_TS) : settings.preferTs;
151
+ settings.tsLoader = process.env.MIKRO_ORM_CLI_TS_LOADER ?? settings.tsLoader;
152
+ settings.tsConfigPath = process.env.MIKRO_ORM_CLI_TS_CONFIG_PATH ?? settings.tsConfigPath;
153
+ settings.verbose =
154
+ process.env.MIKRO_ORM_CLI_VERBOSE != null ? bool(process.env.MIKRO_ORM_CLI_VERBOSE) : settings.verbose;
155
+ if (process.env.MIKRO_ORM_CLI_CONFIG?.endsWith('.ts')) {
156
+ settings.preferTs = true;
157
+ }
158
+ return settings;
159
+ }
160
+ static async getConfigPaths() {
161
+ const settings = this.getSettings();
162
+ const typeScriptSupport = settings.preferTs ?? Utils.detectTypeScriptSupport();
163
+ const paths = [];
164
+ if (process.env.MIKRO_ORM_CLI_CONFIG) {
165
+ paths.push(process.env.MIKRO_ORM_CLI_CONFIG);
166
+ }
167
+ paths.push(...(settings.configPaths || []));
168
+ if (typeScriptSupport) {
169
+ paths.push('./src/mikro-orm.config.ts');
170
+ paths.push('./mikro-orm.config.ts');
171
+ }
172
+ const distDir = fs.pathExists(process.cwd() + '/dist');
173
+ const buildDir = fs.pathExists(process.cwd() + '/build');
174
+ /* v8 ignore next */
175
+ const path = distDir ? 'dist' : buildDir ? 'build' : 'src';
176
+ paths.push(`./${path}/mikro-orm.config.js`);
177
+ paths.push('./mikro-orm.config.js');
178
+ /* v8 ignore next */
179
+ return Utils.unique(paths).filter(p => !/\.[mc]?ts$/.exec(p) || typeScriptSupport);
180
+ }
181
+ static async getConfigFile(paths) {
182
+ for (let path of paths) {
183
+ path = fs.absolutePath(path);
184
+ path = fs.normalizePath(path);
185
+ if (fs.pathExists(path)) {
186
+ const config = await fs.dynamicImport(path);
187
+ /* v8 ignore next */
188
+ return [path, await (config.default ?? config)];
189
+ }
190
+ }
191
+ return [];
66
192
  }
67
- static async dumpDependencies() {
193
+ static async loadEnvironmentVars() {
194
+ const ret = loadEnvironmentVars();
195
+ /* v8 ignore next */
196
+ switch (process.env.MIKRO_ORM_TYPE) {
197
+ case 'mongo':
198
+ ret.driver ??= await import('@mikro-orm/sqlite').then(m => m.SqliteDriver);
199
+ break;
200
+ case 'mysql':
201
+ ret.driver ??= await import('@mikro-orm/mysql').then(m => m.MySqlDriver);
202
+ break;
203
+ case 'mssql':
204
+ ret.driver ??= await import('@mikro-orm/mssql').then(m => m.MsSqlDriver);
205
+ break;
206
+ case 'mariadb':
207
+ ret.driver ??= await import('@mikro-orm/mariadb').then(m => m.MariaDbDriver);
208
+ break;
209
+ case 'postgresql':
210
+ ret.driver ??= await import('@mikro-orm/postgresql').then(m => m.PostgreSqlDriver);
211
+ break;
212
+ case 'sqlite':
213
+ ret.driver ??= await import('@mikro-orm/sqlite').then(m => m.SqliteDriver);
214
+ break;
215
+ case 'libsql':
216
+ ret.driver ??= await import('@mikro-orm/libsql').then(m => m.LibSqlDriver);
217
+ break;
218
+ }
219
+ return ret;
220
+ }
221
+ static dumpDependencies() {
68
222
  const version = Utils.getORMVersion();
69
223
  CLIHelper.dump(' - dependencies:');
70
224
  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 */
225
+ CLIHelper.dump(` - node ${colors.green(process.versions.node)}`);
226
+ if (fs.pathExists(process.cwd() + '/package.json')) {
227
+ /* v8 ignore if */
74
228
  if (process.versions.bun) {
75
229
  CLIHelper.dump(` - typescript via bun`);
76
230
  }
77
231
  else {
78
- CLIHelper.dump(` - typescript ${await CLIHelper.getModuleVersion('typescript')}`);
232
+ CLIHelper.dump(` - typescript ${CLIHelper.getModuleVersion('typescript')}`);
79
233
  }
80
234
  CLIHelper.dump(' - package.json ' + colors.green('found'));
81
235
  }
@@ -83,22 +237,31 @@ export class CLIHelper {
83
237
  CLIHelper.dump(' - package.json ' + colors.red('not found'));
84
238
  }
85
239
  }
86
- static async getModuleVersion(name) {
240
+ static getModuleVersion(name) {
87
241
  try {
88
- const pkg = Utils.requireFrom(`${name}/package.json`);
242
+ const path = `${this.resolveModulePath(name)}/package.json`;
243
+ const pkg = fs.readJSONSync(path);
89
244
  return colors.green(pkg.version);
90
245
  }
91
246
  catch {
92
- try {
93
- const path = `${Utils.resolveModulePath(name)}/package.json`;
94
- const pkg = await readFile(path, { encoding: 'utf8' });
95
- return colors.green(JSON.parse(pkg).version);
96
- }
97
- catch {
98
- return '';
99
- }
247
+ return '';
100
248
  }
101
249
  }
250
+ /**
251
+ * Resolve path to a module.
252
+ * @param id The module to require
253
+ * @param [from] Location to start the node resolution
254
+ */
255
+ static resolveModulePath(id, from = process.cwd()) {
256
+ if (!extname(from)) {
257
+ from = join(from, '__fake.js');
258
+ }
259
+ const path = fs.normalizePath(import.meta.resolve(id, pathToFileURL(from)));
260
+ const parts = path.split('/');
261
+ const idx = parts.lastIndexOf(id) + 1;
262
+ parts.splice(idx, parts.length - idx);
263
+ return parts.join('/');
264
+ }
102
265
  static dumpTable(options) {
103
266
  if (options.rows.length === 0) {
104
267
  return CLIHelper.dump(options.empty);
@@ -112,15 +275,69 @@ export class CLIHelper {
112
275
  });
113
276
  let ret = '';
114
277
  ret += colors.grey('┌' + lengths.map(length => '─'.repeat(length)).join('┬') + '┐\n');
115
- ret += colors.grey('│') + lengths.map((length, idx) => ' ' + colors.red(options.columns[idx]) + ' '.repeat(length - options.columns[idx].length - 1)).join(colors.grey('│')) + colors.grey('│\n');
278
+ ret +=
279
+ colors.grey('│') +
280
+ lengths
281
+ .map((length, idx) => ' ' + colors.red(options.columns[idx]) + ' '.repeat(length - options.columns[idx].length - 1))
282
+ .join(colors.grey('│')) +
283
+ colors.grey('│\n');
116
284
  ret += colors.grey('├' + lengths.map(length => '─'.repeat(length)).join('┼') + '┤\n');
117
285
  options.rows.forEach(row => {
118
- ret += colors.grey('│') + lengths.map((length, idx) => ' ' + row[idx] + ' '.repeat(length - row[idx].length - 1)).join(colors.grey('│')) + colors.grey('│\n');
286
+ ret +=
287
+ colors.grey('│') +
288
+ lengths.map((length, idx) => ' ' + row[idx] + ' '.repeat(length - row[idx].length - 1)).join(colors.grey('│')) +
289
+ colors.grey('│\n');
119
290
  });
120
291
  ret += colors.grey('└' + lengths.map(length => '─'.repeat(length)).join('┴') + '┘');
121
292
  CLIHelper.dump(ret);
122
293
  }
123
- /* v8 ignore next 3 */
294
+ /**
295
+ * Tries to register TS support in the following order: swc, tsx, jiti, tsimp
296
+ * Use `MIKRO_ORM_CLI_TS_LOADER` env var to set the loader explicitly.
297
+ * This method is used only in CLI context.
298
+ */
299
+ static async registerTypeScriptSupport(configPath = 'tsconfig.json', tsLoader) {
300
+ /* v8 ignore if */
301
+ if (process.versions.bun) {
302
+ return true;
303
+ }
304
+ process.env.SWC_NODE_PROJECT ??= configPath;
305
+ process.env.TSIMP_PROJECT ??= configPath;
306
+ process.env.MIKRO_ORM_CLI_ALWAYS_ALLOW_TS ??= '1';
307
+ const explicitLoader = tsLoader ?? process.env.MIKRO_ORM_CLI_TS_LOADER ?? 'auto';
308
+ const setEsmImportProvider = () => {
309
+ return (globalThis.dynamicImportProvider = (id) => import(id).then(mod => mod?.default ?? mod));
310
+ };
311
+ const loaders = {
312
+ swc: { esm: '@swc-node/register/esm-register', cjs: '@swc-node/register' },
313
+ tsx: { esm: 'tsx/esm/api', cjs: 'tsx/cjs/api', cb: (tsx) => tsx.register({ tsconfig: configPath }) },
314
+ jiti: { cjs: 'jiti/register', cb: setEsmImportProvider },
315
+ tsimp: { cjs: 'tsimp/import', cb: setEsmImportProvider },
316
+ };
317
+ for (const loader of Utils.keys(loaders)) {
318
+ if (explicitLoader !== 'auto' && loader !== explicitLoader) {
319
+ continue;
320
+ }
321
+ const { esm, cjs, cb } = loaders[loader];
322
+ const isEsm = this.isESM();
323
+ const module = isEsm && esm ? esm : cjs;
324
+ const mod = await Utils.tryImport({ module });
325
+ if (mod) {
326
+ cb?.(mod);
327
+ process.env.MIKRO_ORM_CLI_TS_LOADER = loader;
328
+ return true;
329
+ }
330
+ }
331
+ // eslint-disable-next-line no-console
332
+ 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`.');
333
+ return false;
334
+ }
335
+ static isESM() {
336
+ const config = fs.getPackageConfig();
337
+ const type = config?.type ?? '';
338
+ return type === 'module';
339
+ }
340
+ /* v8 ignore next */
124
341
  static showHelp() {
125
342
  yargs(process.argv.slice(2)).showHelp();
126
343
  }
package/README.md CHANGED
@@ -6,10 +6,10 @@ TypeScript ORM for Node.js based on Data Mapper, [Unit of Work](https://mikro-or
6
6
 
7
7
  > Heavily inspired by [Doctrine](https://www.doctrine-project.org/) and [Hibernate](https://hibernate.org/).
8
8
 
9
- [![NPM version](https://img.shields.io/npm/v/@mikro-orm/core.svg)](https://www.npmjs.com/package/@mikro-orm/core)
10
- [![NPM dev version](https://img.shields.io/npm/v/@mikro-orm/core/next.svg)](https://www.npmjs.com/package/@mikro-orm/core)
9
+ [![NPM version](https://img.shields.io/npm/v/@mikro-orm/core.svg)](https://npmx.dev/package/@mikro-orm/core)
10
+ [![NPM dev version](https://img.shields.io/npm/v/@mikro-orm/core/next.svg)](https://npmx.dev/package/@mikro-orm/core)
11
11
  [![Chat on discord](https://img.shields.io/discord/1214904142443839538?label=discord&color=blue)](https://discord.gg/w8bjxFHS7X)
12
- [![Downloads](https://img.shields.io/npm/dm/@mikro-orm/core.svg)](https://www.npmjs.com/package/@mikro-orm/core)
12
+ [![Downloads](https://img.shields.io/npm/dm/@mikro-orm/core.svg)](https://npmx.dev/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
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)
15
15
 
@@ -381,6 +381,8 @@ See also the list of contributors who [participated](https://github.com/mikro-or
381
381
 
382
382
  Please ⭐️ this repository if this project helped you!
383
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
+
384
386
  ## 📝 License
385
387
 
386
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();
@@ -0,0 +1,21 @@
1
+ import type { ArgumentsCamelCase, Argv } from 'yargs';
2
+ import { MetadataStorage, type Configuration } from '@mikro-orm/core';
3
+ import type { BaseArgs, BaseCommand } from '../CLIConfigurator.js';
4
+ type CompileArgs = BaseArgs & {
5
+ out?: string;
6
+ };
7
+ export declare class CompileCommand implements BaseCommand<CompileArgs> {
8
+ command: string;
9
+ describe: string;
10
+ builder: (args: Argv<BaseArgs>) => Argv<CompileArgs>;
11
+ /**
12
+ * @inheritDoc
13
+ */
14
+ handler(args: ArgumentsCamelCase<CompileArgs>): Promise<void>;
15
+ static capture(metadata: MetadataStorage, config: Configuration): {
16
+ key: string;
17
+ contextKeys: string[];
18
+ code: string;
19
+ }[];
20
+ }
21
+ export {};