# v0.0.6 Implementation Plan

Add custom command alias feature to allow users to define reusable command sequences in `fluttercraft.yaml` and execute them via `flc run <alias>`.

## User Review Required

> [!IMPORTANT]
> This feature extends the `fluttercraft.yaml` schema with a new `alias` section. Existing configs will continue to work without modification.

---

## Proposed Changes

### Core Configuration System

Extend the configuration system to support custom command aliases.

---

#### [MODIFY] [build_config.dart](file:///c:/src/self/flutter-dart/cli/mobile-build-cli/lib/src/core/build_config.dart)

Add alias support to `BuildConfig`:

```dart
class CommandAlias {
  final String name;
  final List<String> commands;
  
  CommandAlias({
    required this.name,
    required this.commands,
  });
}

class BuildConfig {
  // ... existing fields ...
  
  final Map<String, CommandAlias> aliases;  // NEW
  
  BuildConfig({
    // ... existing parameters ...
    this.aliases = const {},  // NEW
  });
}
```

Update `_parseYaml` method to parse alias section:

```dart
static BuildConfig _parseYaml(YamlMap yaml, String projectRoot) {
  // ... existing parsing ...
  
  // Alias section
  final aliasMap = yaml['alias'] as YamlMap?;
  final aliases = _parseAliases(aliasMap);
  
  return BuildConfig(
    // ... existing fields ...
    aliases: aliases,
  );
}

static Map<String, CommandAlias> _parseAliases(YamlMap? aliasMap) {
  if (aliasMap == null) return {};
  
  final result = <String, CommandAlias>{};
  
  for (final entry in aliasMap.entries) {
    final name = entry.key.toString();
    final config = entry.value as YamlMap?;
    
    if (config == null) continue;
    
    final cmds = config['cmds'];
    if (cmds == null) continue;
    
    final commands = <String>[];
    if (cmds is YamlList) {
      for (final cmd in cmds) {
        commands.add(cmd.toString());
      }
    }
    
    if (commands.isNotEmpty) {
      result[name] = CommandAlias(name: name, commands: commands);
    }
  }
  
  return result;
}
```

---

### Run Command Implementation

Create new command to execute custom aliases.

---

#### [NEW] [run_command.dart](file:///c:/src/self/flutter-dart/cli/mobile-build-cli/lib/src/commands/run_command.dart)

New command to run custom aliases:

```dart
import 'dart:io';
import '../core/app_context.dart';
import '../utils/console.dart';
import '../utils/process_runner.dart';

class RunCommand {
  final AppContext context;
  
  RunCommand(this.context);
  
  Future<void> execute(List<String> args) async {
    // Parse flags
    final showList = args.contains('--list') || args.contains('-l');
    
    if (showList) {
      _listAliases();
      return;
    }
    
    if (args.isEmpty) {
      Console.error('Usage: flc run <alias> or flc run --list');
      return;
    }
    
    final aliasName = args[0];
    await _runAlias(aliasName);
  }
  
  void _listAliases() {
    final aliases = context.config.aliases;
    
    if (aliases.isEmpty) {
      Console.info('No aliases defined in fluttercraft.yaml');
      Console.info('Add aliases in the "alias" section of your config.');
      return;
    }
    
    Console.info('Available aliases:');
    for (final alias in aliases.values) {
      Console.success('  ${alias.name}');
      for (final cmd in alias.commands) {
        Console.dim('    - $cmd');
      }
    }
  }
  
  Future<void> _runAlias(String name) async {
    final alias = context.config.aliases[name];
    
    if (alias == null) {
      Console.error('Alias "$name" not found');
      Console.info('Run "flc run --list" to see available aliases');
      exit(1);
    }
    
    Console.info('Running alias: $name');
    
    for (var i = 0; i < alias.commands.length; i++) {
      final cmd = alias.commands[i];
      Console.info('[${i + 1}/${alias.commands.length}] $cmd');
      
      final result = await ProcessRunner.run(
        cmd,
        workingDirectory: context.projectRoot,
        streamOutput: true,
      );
      
      if (result.exitCode != 0) {
        Console.error('Command failed with exit code ${result.exitCode}');
        exit(result.exitCode);
      }
    }
    
    Console.success('✓ Alias "$name" completed successfully');
  }
}
```

---

#### [MODIFY] [command_registry.dart](file:///c:/src/self/flutter-dart/cli/mobile-build-cli/lib/src/core/command_registry.dart)

Register the new `run` command:

```diff
+ import '../commands/run_command.dart';

  void registerCommands(AppContext context) {
    // ... existing commands ...
+   _commands['run'] = (args) => RunCommand(context).execute(args);
  }
```

---

#### [MODIFY] [commands.dart](file:///c:/src/self/flutter-dart/cli/mobile-build-cli/lib/src/commands/commands.dart)

Export the new command:

```diff
  export 'build_command.dart';
  export 'clean_command.dart';
  export 'convert_command.dart';
  export 'gen_command.dart';
+ export 'run_command.dart';
```

---

### Configuration Generation

Update config generation to include alias examples.

---

#### [MODIFY] [gen_command.dart](file:///c:/src/self/flutter-dart/cli/mobile-build-cli/lib/src/commands/gen_command.dart)

Add alias section to generated config template:

```diff
  shorebird:
    enabled: false
    app_id: null
    artifact: null
    auto_confirm: true
+
+ # ──────────────────────────────────────────────
+ # Custom command aliases
+ # ──────────────────────────────────────────────
+ alias:
+   gen-icon:
+     cmds:
+       - fvm flutter pub get
+       - fvm flutter pub run flutter_launcher_icons
+   brn:
+     cmds:
+       - fvm flutter pub get
+       - fvm flutter packages pub run build_runner build --delete-conflicting-outputs
```

---

### Documentation & Version Bump

Update all documentation and version references.

---

#### [MODIFY] [pubspec.yaml](file:///c:/src/self/flutter-dart/cli/mobile-build-cli/pubspec.yaml)

```diff
- version: 0.0.5
+ version: 0.0.6
```

---

#### [MODIFY] [lib/src/version.dart](file:///c:/src/self/flutter-dart/cli/mobile-build-cli/lib/src/version.dart)

```diff
- const version = '0.0.5';
+ const version = '0.0.6';
```

---

#### [MODIFY] [README.md](file:///c:/src/self/flutter-dart/cli/mobile-build-cli/README.md)

Add new section for custom aliases:

```markdown
### `fluttercraft run`
```powershell
fluttercraft run --list                         # List all aliases
fluttercraft run gen-icon                       # Run gen-icon alias
fluttercraft run brn                            # Run build_runner alias
```

## Custom Command Aliases

Define reusable command sequences in `fluttercraft.yaml`:

```yaml
alias:
  gen-icon:
    cmds:
      - fvm flutter pub get
      - fvm flutter pub run flutter_launcher_icons
  brn:
    cmds:
      - fvm flutter pub get
      - fvm flutter packages pub run build_runner build --delete-conflicting-outputs
```

Then run them with:
```powershell
flc run gen-icon
flc run brn
flc run --list  # Show all available aliases
```
```

Update features list:

```diff
  - 🐦 **Shorebird Support** - Integrated Shorebird release builds
  - 🚀 **Smart Defaults** - Works without config, reads from pubspec.yaml
+ - 🔧 **Custom Aliases** - Define reusable command sequences
```

---

#### [MODIFY] [CHANGELOG.md](file:///c:/src/self/flutter-dart/cli/mobile-build-cli/CHANGELOG.md)

Add v0.0.6 entry:

```diff
+ ## 0.0.6 (2025-12-15)
+ 
+ - **feat**: Add custom command alias support via `flc run <alias>`
+ - **feat**: Add `--list` flag to show all available aliases
+ - **feat**: Update config generation to include alias examples
+ 
  ## 0.0.5 (2025-12-15)
```

---

#### [MODIFY] [shell.dart](file:///c:/src/self/flutter-dart/cli/mobile-build-cli/lib/src/ui/shell.dart)

Update help text to include `run` command:

```diff
  Available commands:
    build    - Build Flutter app
    clean    - Clean build artifacts
    convert  - Convert AAB to APK
    gen      - Generate fluttercraft.yaml
+   run      - Run custom command alias
    context  - Show current configuration
    help     - Show this help
    exit     - Exit shell
```

---

## Verification Plan

### Automated Tests

```powershell
# 1. Static analysis
fvm dart analyze

# 2. Compile verification
.\scripts\compile.ps1
```

---

### Manual Verification

#### Test 1: List Aliases (Empty Config)
1. Create a `fluttercraft.yaml` without alias section
2. Run: `flc run --list`
3. **Expected**: Shows "No aliases defined" message

---

#### Test 2: List Aliases (With Aliases)
1. Add alias section to `fluttercraft.yaml`:
   ```yaml
   alias:
     test-alias:
       cmds:
         - echo "Hello"
         - echo "World"
   ```
2. Run: `flc run --list`
3. **Expected**: Shows `test-alias` with both commands listed

---

#### Test 3: Run Valid Alias
1. Use the config from Test 2
2. Run: `flc run test-alias`
3. **Expected**: 
   - Shows "Running alias: test-alias"
   - Executes both echo commands in order
   - Shows success message

---

#### Test 4: Run Invalid Alias
1. Run: `flc run nonexistent`
2. **Expected**: 
   - Shows error "Alias 'nonexistent' not found"
   - Suggests running `flc run --list`
   - Exits with non-zero code

---

#### Test 5: Generated Config Includes Aliases
1. Run: `flc gen --force`
2. Open generated `fluttercraft.yaml`
3. **Expected**: Contains `alias` section with example aliases (`gen-icon`, `brn`)

---

#### Test 6: Shell Mode Integration
1. Run: `flc` (start shell)
2. Type: `help`
3. **Expected**: Shows `run` command in help text
4. Type: `run --list`
5. **Expected**: Lists available aliases
6. Type: `run test-alias`
7. **Expected**: Executes the alias

---

## Config Schema Update

The new `alias` section in `fluttercraft.yaml`:

```yaml
alias:
  <alias-name>:
    cmds:
      - <command-1>
      - <command-2>
      - ...
```

**Example:**
```yaml
alias:
  gen-icon:
    cmds:
      - fvm flutter pub get
      - fvm flutter pub run flutter_launcher_icons
  brn:
    cmds:
      - fvm flutter pub get
      - fvm flutter packages pub run build_runner build --delete-conflicting-outputs
  test-all:
    cmds:
      - fvm flutter test
      - fvm dart analyze
```
