runOrmCli function

Future<void> runOrmCli(
  1. List<String> arguments, {
  2. OrmConfig? config,
})

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);
  }
}