@morodomi/ait3
Version:
AIT³ Development Platform - AI + Ticket + Test + Tool driven development methodology
127 lines (126 loc) • 5 kB
JavaScript
import { Command } from 'commander';
import { join, dirname } from 'path';
import { mkdir, writeFile, access } from 'fs/promises';
import { STYLES } from '../../common/styles.js';
import { ait3Template } from '../../assets/commands/ait3.js';
import { geminiTemplate } from '../../assets/commands/gemini.js';
import { orchestratorTemplate } from '../../assets/commands/orchestrator.js';
import { ait3InitTemplate } from '../../assets/commands/ait3-init.js';
import { codeReviewTemplate } from '../../assets/commands/code-review.js';
// Command name to template mapping
const commandTemplates = {
ait3: ait3Template,
gemini: geminiTemplate,
orchestrator: orchestratorTemplate,
'ait3-init': ait3InitTemplate,
'code-review': codeReviewTemplate
};
export async function installCommand(args) {
const { name = 'all', force = false } = args;
// Determine which files to install
let filesToInstall = [];
if (name === 'all' || !name) {
// Install all command guides
filesToInstall = Object.keys(commandTemplates).map(cmd => [cmd, cmd]);
}
else if (name in commandTemplates) {
// Install specific command guide
filesToInstall = [[name, name]];
}
else {
// Invalid command name
return {
success: false,
message: `${STYLES.danger('ERROR: Unknown command')}: ${name}\n${STYLES.info('Available commands')}: ${Object.keys(commandTemplates).join(', ')}`
};
}
const messages = [];
let installedCount = 0;
let skippedCount = 0;
let hasExistingFile = false;
// Show intent
if (!name || name === 'all') {
messages.push(`${STYLES.info('PACKAGE: Installing all command guides')}...`);
}
// Process each file
for (const [cmdName, _fileName] of filesToInstall) {
const targetPath = join('.claude', 'commands', cmdName);
const targetDir = dirname(targetPath);
try {
// Create directory if needed
try {
await access(targetDir);
}
catch {
await mkdir(targetDir, { recursive: true });
messages.push(`${STYLES.success('SUCCESS:')} Created directory: ${STYLES.info(targetDir)}`);
}
// Check if file exists
let shouldWrite = true;
try {
await access(targetPath);
hasExistingFile = true;
if (!force) {
shouldWrite = false;
messages.push(`${STYLES.warning('⚠')} Skipped: ${STYLES.info(targetPath)} already exists (use --force to overwrite)`);
skippedCount++;
}
else {
messages.push(`${STYLES.warning('⚠')} Overwriting existing file: ${STYLES.info(targetPath)}`);
}
}
catch {
// File doesn't exist, good to proceed
}
if (shouldWrite) {
// Get template content
const templateContent = commandTemplates[cmdName];
if (!templateContent) {
throw new Error(`Template not found for command: ${cmdName}`);
}
// Write file
await writeFile(targetPath, templateContent, 'utf-8');
messages.push(`${STYLES.success('SUCCESS:')} Installed: ${STYLES.info(targetPath)}`);
installedCount++;
}
}
catch (error) {
return {
success: false,
message: `${STYLES.danger('ERROR: Failed to create')}: ${targetPath}\n${error instanceof Error ? error.message : 'Unknown error'}`
};
}
}
// Check if we were trying to install a single specific file that already exists
if (name && name !== 'all' && filesToInstall.length === 1 && hasExistingFile && !force && installedCount === 0) {
return {
success: false,
message: messages.join('\n')
};
}
// Summary
messages.push('');
messages.push(`${STYLES.success('SUCCESS: Installation complete')}: ${installedCount} file(s) installed${skippedCount > 0 ? `, ${skippedCount} skipped` : ''}`);
return {
success: true,
message: messages.join('\n')
};
}
export const commandCommand = new Command('command')
.description('Install Claude command guides')
.argument('[name]', 'Command name to install (default: all)', 'all')
.option('-f, --force', 'Overwrite existing files', false)
.action(async (name, options) => {
const args = { name, force: options.force };
try {
const result = await installCommand(args);
console.log(result.message);
if (!result.success) {
process.exit(1);
}
}
catch (error) {
console.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
process.exit(1);
}
});