Refactor internal-cli bin.ts into separate command files
## Problem Statement
The internal CLI `bin.ts` file is ~1200 lines long, making it difficult to navigate. All 23 commands, their schemas, error classes, and utility functions are in a single file.
## Solution
Extract each command into its own file in a `commands/` folder. The `bin.ts` becomes a thin orchestration file that imports and registers commands.
## Implementation Plan
### Phase 1: Create shared infrastructure
1. Create `src/shared/main-layer.ts` - extract `MainLayerLive` layer (merge of `AppLayerLive` and `OpenTelemetryLive`)
2. Create `src/shared/schemas.ts` - extract `clipsSchema` (shared between `create-video-from-clips` and `send-clips-to-davinci-resolve`)
3. Update `bin.ts` to import from these new files, verify build passes
### Phase 2: Extract commands (one commit per command)
Each command file exports a `register(program: Command)` function. Extract in this order:
4. `commands/get-clips-from-latest-video.ts` - includes `FileDoesNotExistError`
5. `commands/transcribe-clips.ts` - includes `transcribeClipSchema`
6. `commands/create-video-from-clips.ts` - imports `clipsSchema` from shared
7. `commands/send-clips-to-davinci-resolve.ts` - imports `clipsSchema` from shared, includes `NoInputVideosError`
8. `commands/move-raw-footage-to-long-term-storage.ts`
9. `commands/create-timeline.ts`
10. `commands/add-current-timeline-to-render-queue.ts`
11. `commands/export-subtitles.ts`
12. `commands/append-video-to-timeline.ts`
13. `commands/edit-interview.ts`
14. `commands/export-interview.ts`
15. `commands/move-interview-to-davinci-resolve.ts`
16. `commands/create-auto-edited-video.ts` - largest command, imports from `validate-cli-flags.ts`
17. `commands/log-latest-obs-video.ts`
18. `commands/queue-auto-edited-video-for-course.ts`
19. `commands/transcribe-video.ts`
20. `commands/process-queue.ts`
21. `commands/process-information-requests.ts`
22. `commands/article-from-transcript.ts`
23. `commands/queue-status.ts` - includes `formatRelativeDate`, `analyzeArticleWorkflows`, `generateProgressBar`
24. `commands/concatenate-videos.ts`
25. `commands/notify.ts`
26. `commands/retry-queue-item.ts`
### Phase 3: Final cleanup
27. Review `bin.ts` - should be ~50-80 lines: imports, program setup, command registrations, `program.parse()`
28. Delete any dead code, unused imports
## Decision Document
- **Command file interface**: Each file exports `register(program: Command): void` that adds the command to the program
- **Shared layer location**: `src/shared/main-layer.ts` exports `MainLayerLive`
- **Shared schema location**: `src/shared/schemas.ts` exports schemas used by multiple commands
- **Boilerplate handling**: Each command includes its own `.pipe(Effect.withConfigProvider(...), Effect.provide(MainLayerLive), NodeRuntime.runMain)` - no abstraction
- **Error classes**: Stay with their command file (none are currently shared)
- **Utility functions**: Stay with their command file (`formatRelativeDate`, `analyzeArticleWorkflows`, `generateProgressBar` stay in `queue-status.ts`)
- **Naming**: Kebab-case matching command names
## Testing Decisions
- **Build verification**: `pnpm run build` must pass after each commit
- **Manual smoke testing**: User will manually test commands after refactor complete
- **No new automated tests**: Pure structural refactor, behavior unchanged
- **Existing tests**: `validate-cli-flags.test.ts` remains unchanged and must pass
## Out of Scope
- Behavior changes to any command
- Adding new tests for commands
- Refactoring command internals
- Changes to `@total-typescript/ffmpeg` package
- Changes to existing extracted files (`tracing.ts`, `utils.ts`, `validate-cli-flags.ts`)
- Creating abstractions for the repeated Effect boilerplate
关闭于 2026-01-27 23 条评论