run method

  1. @override
Future<void> run()
override

Runs this command.

The return value is wrapped in a Future if necessary and returned by CommandRunner.runCommand.

Implementation

@override
Future<void> run() async {
  String projectName;
  String orgName;

  if (argResults?.rest.length == 2) {
    projectName = argResults!.rest[0];
    orgName = argResults!.rest[1];
  } else {
    projectName = Input(
      prompt: 'Enter project name (snake_case):',
      validator: (input) => input.isEmpty ? throw ValidationError('Project name is required') : true,
    ).interact();

    orgName = Input(
      prompt: 'Enter organization name (e.g., com.example):',
      defaultValue: 'com.example',
      validator: (input) => input.isEmpty ? throw ValidationError('Organization name is required') : true,
    ).interact();
  }

  final currentDir = Directory.current.path;
  final targetDir = p.join(currentDir, projectName);

  stdout.writeln('🚀 Bootstrapping project "$projectName" with org "$orgName"...');

  // 1. Run flutter create
  final createProcess = await Process.start(
    'fvm',
    ['flutter', 'create', '--org', orgName, projectName],
    mode: ProcessStartMode.inheritStdio,
  );

  final exitCode = await createProcess.exitCode;
  if (exitCode != 0) {
    stdout.writeln('❌ Failed to create Flutter project.');
    return;
  }

  stdout.writeln('✅ Flutter project created. Now applying Simple Architecture templates...');

  // 2. Identify template source
  String? templateDir;

  // Check if we are in development mode (running from simple_architecture root)
  if (Directory(p.join(currentDir, 'lib/core')).existsSync()) {
    templateDir = currentDir;
  } else {
    // Resolve template from package
    final uri = await Isolate.resolvePackageUri(
      Uri.parse('package:flutter_simple_architecture/main.dart'),
    );
    if (uri != null) {
      // uri is file:///.../lib/main.dart
      // We want the package root (parent of lib)
      templateDir = p.dirname(p.dirname(uri.toFilePath()));
    }
  }

  if (templateDir == null) {
    stdout.writeln('❌ Failed to find Simple Architecture templates.');
    return;
  }

  // 3. Copy architecture directories
  final dirsToCopy = ['lib/core', 'lib/domain', 'lib/presentation', 'doc'];
  for (final dir in dirsToCopy) {
    final source = Directory(p.join(templateDir, dir));
    final destination = Directory(p.join(targetDir, dir));
    if (source.existsSync()) {
      await _copyDirectory(source, destination);
    }
  }

  // 4. Copy specific files
  final filesToCopy = [
    'lib/main.dart',
    'analysis_options.yaml',
    'l10n.yaml',
    '.fvmrc',
    'GEMINI.md'
  ];
  for (final fileName in filesToCopy) {
    final source = File(p.join(templateDir, fileName));
    final destination = File(p.join(targetDir, fileName));
    if (source.existsSync()) {
      await source.copy(destination.path);
    }
  }

  // 5. Update pubspec.yaml
  await _updatePubspec(targetDir, templateDir, projectName);

  stdout.writeln('✅ Simple Architecture templates applied.');
  stdout.writeln('📦 Running pub get in "$projectName"...');

  await Process.run(
    'fvm',
    ['flutter', 'pub', 'get'],
    workingDirectory: targetDir,
  );

  stdout.writeln('✨ Project "$projectName" is ready! Happy coding!');
}