runOrmCli function
Runs package commands or a project entrypoint configured with config.
When no configuration is passed, project commands load orm.config.dart in
a child Dart process. Help, initialization and explicit source generation do
not require a database. Reports go to stdout; failures go to stderr and set
the process exit code. Pass --json in arguments for machine-readable output.
Implementation
Future<void> runOrmCli(List<String> arguments, {OrmConfig? config}) async {
final json = arguments.contains('--json');
final output = CliOutput(json);
try {
final args = List<String>.of(arguments);
if (args.where((a) => a == '--json').length > 1) {
throw const FormatException('Repeated option --json.');
}
args.remove('--json');
String? configPath;
final configIndex = args.indexOf('--config');
if (configIndex >= 0) {
if (config != null ||
args.where((a) => a == '--config').length > 1 ||
configIndex + 1 >= args.length ||
args[configIndex + 1].startsWith('--')) {
throw const FormatException(
'Use --config <project-entrypoint.dart> once.',
);
}
configPath = args[configIndex + 1];
args.removeRange(configIndex, configIndex + 2);
}
if (args.isEmpty ||
args.first == 'help' ||
args.contains('--help') ||
args.length == 1 && args.first == 'migrate') {
final topic = args.isEmpty || args.first == '--help'
? ''
: args.first == 'help'
? (args.length > 1 ? args[1] : '')
: args.first;
final help = _help[topic];
if (help == null) throw FormatException('Unknown command: $topic.');
if (json) {
output.report({'help': help});
} else {
stdout.writeln(help);
}
return;
}
if (args.first == 'init') {
if (config != null || configPath != null) {
throw const FormatException(
'Run init from the package CLI without --config.',
);
}
await initializeProject(args.skip(1).toList(), output);
return;
}
final projectCommand =
args.first == 'migrate' || args.first == 'generate' && args.length == 1;
if (config == null && projectCommand) {
final path = configPath ?? 'orm.config.dart';
if (await File(path).exists()) {
final child = await Process.start(Platform.resolvedExecutable, [
'run',
path,
...args,
if (json) '--json',
], mode: ProcessStartMode.inheritStdio);
exitCode = await child.exitCode;
return;
}
if (configPath != null || args.first == 'migrate') {
throw FormatException(
'Missing $path. Run dart run orm init --database <engine>.',
);
}
args.add('lib/schema.dart');
} else if (configPath != null) {
throw const FormatException(
'--config applies to generate without a path and migrate commands.',
);
}
if (config != null && args.first == 'generate' && args.length == 1) {
await writeGeneratedSchema(config.schema, output: config.output);
output.report({
'generated':
config.output ?? p.setExtension(config.schema, '.orm.dart'),
});
return;
}
if (config != null && args.first == 'migrate') {
var snapshot = config.snapshot;
if (args.length > 1 && args[1] == 'create') {
if (!(args.length == 3 ||
args.length == 4 && args.last == '--allow-destructive') ||
args[2].startsWith('--')) {
throw const FormatException(
'Use migrate create <id> [--allow-destructive].',
);
}
// Generate before diffing so an edited model cannot silently use the
// snapshot compiled into this invocation's configuration.
final generated = await generateSchema(
config.schema,
outputPath: config.output,
);
final client =
config.output ?? p.setExtension(config.schema, '.orm.dart');
await File(client).parent.create(recursive: true);
await File(client).writeAsString(generated.dart);
final snapshotPath = client.endsWith('.orm.dart')
? '${client.substring(0, client.length - '.orm.dart'.length)}.snapshot.dart'
: p.setExtension(client, '.snapshot.dart');
await File(snapshotPath).writeAsString(generated.snapshotDart);
snapshot = generated.snapshot;
}
await runMigrationCli(
args.skip(1).toList(),
history: config.history,
directory: config.migrations,
schema: snapshot,
connect: config.connect,
renames: config.renames,
using: config.using,
json: json,
);
return;
}
await runExplicitCli(args, json: json);
} on FormatException catch (error) {
output.error(error.message, 64);
} on ArgumentError catch (_) {
output.error('Invalid command option or configuration. Use --help.', 64);
} catch (error) {
output.error(error.toString(), 1);
}
}