run method

Future<int> run()

Implementation

Future<int> run() async {
  // Parse CLI flags
  final input   = _arg('--input',  '-i') ?? '';
  final output  = _arg('--output', '-o') ?? '';
  final verbose = _hasFlag('--verbose', '-v');
  final noFmt   = _hasFlag('--no-format');
  final noDed   = _hasFlag('--no-deduplicate');
  final noNull  = _hasFlag('--no-null-safety');

  // Load project config (may be overridden by CLI flags)
  final defaults = NebulaProjectConfig(
    input:  input.isNotEmpty  ? input  : 'swagger.json',
    output: output.isNotEmpty ? output : 'lib/api',
  );
  final cfg = await ConfigLoader.loadOrDefault(defaults);

  final effectiveInput  = input.isNotEmpty  ? input  : cfg.input;
  final effectiveOutput = output.isNotEmpty ? output : cfg.output;

  // Validate
  if (!await File(effectiveInput).exists()) {
    stderr.writeln('❌  Spec file not found: $effectiveInput');
    stderr.writeln('   Use --input <path> or create nebula.config.json');
    return 1;
  }

  // Build options
  final options = CompilerOptions(
    outputDir:        effectiveOutput,
    deduplicate:      !noDed  && cfg.deduplicate,
    inferNullability: !noNull && cfg.inferNullability,
    format:           !noFmt  && cfg.format,
    verbose:          verbose  || cfg.verbose,
    baseUrlOverride:  cfg.baseUrl,
  );

  // Compile
  try {
    final compiler = NebulaCompiler();
    final result   = await compiler.compileFile(effectiveInput, options);

    if (!options.verbose) {
      // Always print the summary even in non-verbose mode
      print(result.emitResult.toString());
      if (result.warnings.isNotEmpty) {
        print('\n⚠️  Warnings (${result.warnings.length}):');
        for (final w in result.warnings) {
          print('   • $w');
        }
      }
    }

    return 0;
  } on CompilerException catch (e) {
    stderr.writeln('❌  $e');
    return 1;
  } catch (e, st) {
    stderr.writeln('❌  Unexpected error: $e');
    if (verbose) stderr.writeln(st);
    return 1;
  }
}