Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save possibilities/2c22603051fa523fe48bd333e6694dca to your computer and use it in GitHub Desktop.
Save possibilities/2c22603051fa523fe48bd333e6694dca to your computer and use it in GitHub Desktop.
# Tag Composer Validation Implementation Summary
## Overview
This document summarizes the implementation of Commander.js validation for the tag-composer CLI tool, including the analysis of the validate-calling-command module and recent refactoring work.
## Implementation Summary
### Initial Request
The goal was to use the Commander.js parser on arbitrary strings to validate commands within markdown files, in addition to using it for CLI invocation. The key requirement was that commands marked as "isCallingCommand" should be validated using the same rules as the actual CLI.
### Key Components Implemented
1. **create-command.ts**
- Extracted command configuration from the CLI into a reusable function
- Configures Commander.js with tag-composer's validation rules:
- Accepts exactly one argument (via `.allowExcessArguments(false)`)
- Argument must be an existing file
- File must have a `.md` extension (case-insensitive)
2. **validate-calling-command.ts**
- Purpose: Validates commands that match the calling command name using Commander.js
- Includes a custom `parseCommandArgs` function that properly handles:
- Quoted arguments (both single and double quotes)
- Escaped characters
- Space-separated arguments
- Creates a Commander instance using the shared configuration
- Parses command strings and throws validation errors if they fail
3. **parse-commands.ts modifications**
- Added validation for commands where `isCallingCommand` is true
- Validation occurs during parsing, before execution
- Errors are wrapped with context about which command failed
### Design Decisions
1. **Synchronous Implementation**
- Initially implemented with async/await using `parseAsync()`
- Reverted to synchronous `parse()` to simplify the codebase
- No async operations were needed for validation
2. **Generic Validation**
- Removed hardcoded 'tag-composer' check
- Validation applies to any command marked as the calling command
- Makes the system more flexible and reusable
3. **Removed isCallingCommand from API**
- The flag was only used internally for validation
- Not needed in the returned CommandLine object
- Simplified the API by removing this implementation detail
## validate-calling-command Module Analysis
### Purpose
The validate-calling-command module serves to validate "calling commands" - when a command in a markdown file matches the calling command name (e.g., `tag-composer`), it validates that command using the same rules as the actual CLI.
### How It Works
1. **Input**: Takes a command string like `"tag-composer file.md"`
2. **Parsing**: Uses `parseCommandArgs` to split into arguments: `['tag-composer', 'file.md']`
3. **Validation**: Creates a Commander.js program with the same rules as the CLI
4. **Execution**: Runs the parsed arguments through Commander.js validation
5. **Output**: Throws an error if validation fails
### Validation Rules Enforced
- Must have exactly one argument (enforced by Commander.js)
- The argument must be a file that exists
- The file must have a `.md` extension
### Use Case Example
When processing markdown files containing commands:
```markdown
Here's how to process another file:
!!tag-composer other-file.md
```
The validator ensures such recursive calls would be valid if executed, preventing invalid tag-composer commands from being embedded in documentation.
## Testing Strategy
Tests were implemented to cover:
- Valid commands with existing .md files
- File paths with spaces (quoted arguments)
- Missing file arguments
- Too many arguments
- Non-existent files
- Non-markdown files
- Edge cases with quotes and escapes
All validation tests mock the file system to control test conditions without requiring actual files.
## Recent Refactoring
The most recent change removed `isCallingCommand` from the CommandLine interface because:
- It was only used internally for validation logic
- It was explicitly filtered out in rendering and some tests
- Removing it simplified the API without changing behavior
## Future Considerations
The current implementation is specific to tag-composer's validation rules. If other tools need different validation:
- The validate-calling-command module could be made more generic
- Different validators could be injected based on the command name
- The current design already supports any command as a "calling command"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment