copyAppTemplate method
Copy the main app template to the output directory
Implementation
Future<void> copyAppTemplate() async {
// arcaneJasprFlutterEmbed is a dual-package template: it ships a Jaspr
// host (_web) AND a Flutter web guest (_app) under one parent dir.
// Route the copy through the dedicated helper so each sub-package
// lands in its own scaffolded directory.
if (config.template == TemplateType.arcaneJasprFlutterEmbed) {
await _copyJasprFlutterEmbedTemplate();
return;
}
final Directory templateDir = Directory(
getTemplatePath(config.template.directoryName),
);
// For Jaspr templates, use webPackageName; for others, use appName
final String targetName = config.template.isJasprApp
? config.webPackageName
: config.appName;
final Directory targetDir = Directory(p.join(config.outputDir, targetName));
if (!templateDir.existsSync()) {
throw Exception('Template not found: ${templateDir.path}');
}
info('Copying ${config.template.displayName} template...');
// Copy template files
await _copyDirectory(templateDir, targetDir);
// Process placeholders
await _replacer.processDirectory(targetDir);
// Update pubspec with correct package name
final File pubspecFile = File(p.join(targetDir.path, 'pubspec.yaml'));
await _replacer.updatePubspec(pubspecFile, targetName);
// Add models dependency if needed
if (config.createModels) {
await _replacer.addModelsDependency(pubspecFile);
// Pure-Dart targets (Jaspr, Dart CLI) cannot resolve `arcane_models`
// out of the box because `artifact -> json_compress -> jpatch` pulls in
// the Flutter SDK via jpatch's pubspec. Vendor a pure-Dart jpatch shim
// and inject a `dependency_overrides` so the project resolves cleanly.
if (!config.template.isFlutterApp) {
await _vendorJpatchOverride(pubspecFile);
}
// Jaspr targets (web app + docs) bring in `jaspr_builder` (analyzer
// ^10.0.0). The published `artifact_gen` and `fire_crud_gen` packages
// pin `analyzer ^8.0.0`, which makes `pub get` impossible to resolve
// when both are present. Vendor pure-shim drop-ins for the gen
// packages so build_runner can satisfy `auto_apply: dependents` in the
// upstream `artifact` and `fire_crud` `build.yaml` files without
// dragging analyzer 8 into the resolution. The actual model
// generation still happens in the dedicated models package (which
// does NOT depend on jaspr_builder), so the web app only consumes
// the already-generated `.g.dart` files.
if (config.template.isJasprApp) {
await _vendorJasprBuilderShims(pubspecFile);
}
}
if (config.template.isJasprDocs) {
await _prepareJasprDocsDependencies();
}
// Patch jaspr.yaml mode for Jaspr templates so the user's selected
// render mode (CSR / SSG / SSR / Hybrid) lands in the generated
// project. Without this, every project would inherit the template's
// default mode (client) regardless of what the user picked.
if (config.template.isJasprApp) {
await _patchJasprYamlMode(targetDir);
}
// Emit IntelliJ run configurations (Serve / Build / Killall) for
// every Jaspr web target so a fresh `oracular` scaffold drops the
// user straight into a clickable dev loop in IntelliJ /
// Android Studio. No-op for Flutter/Dart-CLI templates — they have
// their own (Flutter-native) run configs created by `flutter
// create`.
if (config.template.isJasprApp) {
await TemplateRunConfigWriter.generateJasprPackage(
packageDir: targetDir.path,
);
}
success('App template copied to: ${targetDir.path}');
}