run method
Runs this command.
The return value is wrapped in a Future if necessary and returned by
CommandRunner.runCommand.
Implementation
@override
Future<int> run() async {
final all = argResults?['all'] as bool? ?? false;
var componentsToAdd = argResults?.rest ?? [];
if (componentsToAdd.isEmpty && !all) {
throw UsageException('Especifique ao menos um componente ou use --all.', usage);
}
final variant = argResults?['variant'] as String?;
final overwrite = argResults?['overwrite'] as bool? ?? false;
final projectRoot = Directory.current.path;
try {
// 1. Setup Infra
final templatesPath = await resolveTemplatesPath();
final loader = TemplateLoader(templatesPath);
final stateService = BuildStateService(projectRoot);
// 2. Setup Pipeline (Fyarn v4 Formal Build System)
final engine = PipelineEngine();
engine.addStage(EnvironmentStage());
engine.addStage(GraphBuilderStage(loader));
engine.addStage(GraphValidationStage());
engine.addStage(DeltaComputationStage(stateService));
engine.addStage(IncrementalBuildEngineStage());
engine.addStage(ConsistencyCheckStage(loader));
engine.addStage(TestStage());
engine.addStage(VerificationStage());
engine.addStage(ResolutionStage());
engine.addStage(RenderingStage(loader));
engine.addStage(PersistenceStage());
engine.addStage(FormatStage());
// 3. Resolver componentes a serem adicionados
if (all) {
final uiPath = p.join(templatesPath, 'ui');
final uiDir = Directory(uiPath);
if (await uiDir.exists()) {
final List<String> validComponents = [];
final entities = await uiDir.list().where((e) => e is Directory).toList();
for (final entity in entities) {
final name = p.basename(entity.path);
if (name == 'auth') continue;
final mainTemplatePath = p.join(entity.path, 'fyarn_$name.dart.tpl');
if (await File(mainTemplatePath).exists()) {
validComponents.add(name);
}
}
componentsToAdd = validComponents;
Logger.info('🧶 Adicionando ${componentsToAdd.length} componentes válidos (v1.1.0)...\n');
}
}
// 4. Execute para cada componente
for (final component in componentsToAdd) {
final context = PipelineContext(
componentName: component.toLowerCase(),
variant: variant,
overwrite: overwrite,
projectRoot: projectRoot,
);
await engine.run(context);
// 4. Salva a prova de build (Persistence of Truth)
// Construímos o índice reverso: para cada dependência do IR, este componente é um dependente
final Map<String, List<String>> reverseDeps = {};
for (final dep in context.ir.dependencies) {
reverseDeps[dep] = [context.componentName];
}
final buildProofIR = BuildProofIR(
componentName: context.componentName,
buildProofHash: context.ir.irHash,
contentHashes: context.ir.resolvedFiles.map(
(k, v) => MapEntry(k, v.contentHash),
),
dependencyIndex: reverseDeps,
proof: context.proof,
);
await stateService.saveBuild(buildProofIR);
}
Logger.success('\nProcess completed successfully! 🧶');
return 0;
} catch (e, s) {
Logger.error(e.toString());
Logger.debug(s.toString());
return 1;
}
}