feat: create tm-core and apps/cli (#1093)
- add typescript - add npm workspaces
This commit is contained in:
131
docs/CLI-COMMANDER-PATTERN.md
Normal file
131
docs/CLI-COMMANDER-PATTERN.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# CLI Commander Class Pattern
|
||||
|
||||
## Overview
|
||||
We're using Commander.js's native class pattern instead of custom abstractions. This is cleaner, more maintainable, and uses the framework as designed.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
@tm/core (Business Logic) @tm/cli (Presentation)
|
||||
┌─────────────────────┐ ┌──────────────────────────┐
|
||||
│ TaskMasterCore │◄───────────│ ListTasksCommand │
|
||||
│ - getTaskList() │ │ extends Commander.Command│
|
||||
│ - getTask() │ │ - display logic only │
|
||||
│ - getNextTask() │ │ - formatting │
|
||||
└─────────────────────┘ └──────────────────────────┘
|
||||
▲ ▲
|
||||
│ │
|
||||
└──────── Gets Data ──────────────────┘
|
||||
Displays Data
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
### Command Class Pattern
|
||||
|
||||
```typescript
|
||||
// apps/cli/src/commands/list-tasks-commander.ts
|
||||
export class ListTasksCommand extends Command {
|
||||
constructor(name?: string) {
|
||||
super(name || 'list');
|
||||
|
||||
this
|
||||
.description('List tasks')
|
||||
.option('-s, --status <status>', 'Filter by status')
|
||||
.action(async (options) => {
|
||||
// 1. Get data from @tm/core
|
||||
const result = await this.tmCore.getTaskList(options);
|
||||
|
||||
// 2. Display data (presentation only)
|
||||
this.displayResults(result, options);
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Main CLI Class
|
||||
|
||||
```typescript
|
||||
// apps/cli/src/cli-commander.ts
|
||||
class TaskMasterCLI extends Command {
|
||||
createCommand(name?: string): Command {
|
||||
switch (name) {
|
||||
case 'list':
|
||||
return new ListTasksCommand(name);
|
||||
default:
|
||||
return new Command(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Integration with Existing Scripts
|
||||
|
||||
### Gradual Migration Path
|
||||
|
||||
```javascript
|
||||
// scripts/modules/commands.js
|
||||
|
||||
// OLD WAY (keep working during migration)
|
||||
program
|
||||
.command('old-list')
|
||||
.action(async (options) => {
|
||||
await listTasksV2(...);
|
||||
});
|
||||
|
||||
// NEW WAY (add alongside old)
|
||||
import { ListTasksCommand } from '@tm/cli';
|
||||
program.addCommand(new ListTasksCommand());
|
||||
```
|
||||
|
||||
### Benefits
|
||||
|
||||
1. **No Custom Abstractions**: Using Commander.js as designed
|
||||
2. **Clean Separation**: Business logic in core, presentation in CLI
|
||||
3. **Gradual Migration**: Can migrate one command at a time
|
||||
4. **Type Safety**: Full TypeScript support with Commander types
|
||||
5. **Framework Native**: Better documentation, examples, and community support
|
||||
|
||||
## Migration Steps
|
||||
|
||||
1. **Phase 1**: Build command classes in @tm/cli (current)
|
||||
2. **Phase 2**: Import in scripts/modules/commands.js
|
||||
3. **Phase 3**: Replace old implementations one by one
|
||||
4. **Phase 4**: Remove old code when all migrated
|
||||
|
||||
## Example Usage
|
||||
|
||||
### In New Code
|
||||
```javascript
|
||||
import { ListTasksCommand } from '@tm/cli';
|
||||
const program = new Command();
|
||||
program.addCommand(new ListTasksCommand());
|
||||
```
|
||||
|
||||
### In Existing Scripts
|
||||
```javascript
|
||||
// Gradual adoption
|
||||
const listCmd = new ListTasksCommand();
|
||||
program.addCommand(listCmd);
|
||||
```
|
||||
|
||||
### Programmatic Usage
|
||||
```javascript
|
||||
const listCommand = new ListTasksCommand();
|
||||
await listCommand.parseAsync(['node', 'script', '--format', 'json']);
|
||||
```
|
||||
|
||||
## POC Status
|
||||
|
||||
✅ **Completed**:
|
||||
- ListTasksCommand extends Commander.Command
|
||||
- Clean separation of concerns
|
||||
- Integration examples
|
||||
- Build configuration
|
||||
|
||||
🚧 **Next Steps**:
|
||||
- Migrate more commands
|
||||
- Update existing scripts to use new classes
|
||||
- Remove old implementations gradually
|
||||
|
||||
This POC proves the pattern works and provides a clean migration path!
|
||||
Reference in New Issue
Block a user