context-forge
Version:
AI orchestration platform with autonomous teams, enhancement planning, migration tools, 25+ slash commands, checkpoints & hooks. Multi-IDE: Claude, Cursor, Windsurf, Cline, Copilot
146 lines (136 loc) ⢠7.03 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateDocumentation = generateDocumentation;
const path_1 = __importDefault(require("path"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const ora_1 = __importDefault(require("ora"));
const chalk_1 = __importDefault(require("chalk"));
const adapters_1 = require("../adapters");
const hooks_1 = require("./hooks");
async function generateDocumentation(config, outputPath) {
// Ensure output directory exists
await fs_extra_1.default.ensureDir(outputPath);
// Default to Claude if no IDEs specified
const targetIDEs = config.targetIDEs || ['claude'];
console.log(chalk_1.default.blue(`\nš Generating documentation for ${targetIDEs.length} IDE(s)...\n`));
// Generate files for each selected IDE
for (const ide of targetIDEs) {
const ideInfo = (0, adapters_1.getIDEInfo)(ide);
console.log(chalk_1.default.cyan(`\nGenerating ${ideInfo.name} configuration...`));
try {
const adapter = (0, adapters_1.createAdapter)(ide, config);
const files = await adapter.generateFiles(outputPath);
// Create necessary directories and write files
for (const file of files) {
const spinner = (0, ora_1.default)(`Creating ${path_1.default.basename(file.path)}...`).start();
try {
await fs_extra_1.default.ensureDir(path_1.default.dirname(file.path));
// Check if file already exists
if (await fs_extra_1.default.pathExists(file.path)) {
// Special handling for CLAUDE.md in retrofit mode
if (config.isRetrofit && path_1.default.basename(file.path) === 'CLAUDE.md') {
spinner.info(`Appending to existing ${path_1.default.basename(file.path)}...`);
const existingContent = await fs_extra_1.default.readFile(file.path, 'utf-8');
const retrofitSection = `\n\n<!-- ===== APPENDED BY CONTEXT FORGE RETROFIT - ${new Date().toLocaleDateString()} ===== -->\n\n## Retrofit Updates - ${new Date().toLocaleDateString()}\n\n${file.content}`;
await fs_extra_1.default.writeFile(file.path, existingContent + retrofitSection, 'utf-8');
spinner.succeed(`Updated ${path_1.default.basename(file.path)}`);
}
else {
spinner.warn(`Skipped ${path_1.default.basename(file.path)} - file already exists`);
}
continue;
}
await fs_extra_1.default.writeFile(file.path, file.content, 'utf-8');
spinner.succeed(`Created ${path_1.default.basename(file.path)}`);
}
catch (error) {
spinner.fail(`Failed to create ${path_1.default.basename(file.path)}`);
throw error;
}
}
console.log(chalk_1.default.green(`ā ${ideInfo.name} configuration complete`));
}
catch (error) {
if (error.message.includes('not yet implemented')) {
console.log(chalk_1.default.yellow(`ā ļø ${ideInfo.name} adapter coming soon`));
}
else {
throw error;
}
}
}
// Generate common directories if needed
if (config.extras.aiDocs) {
await fs_extra_1.default.ensureDir(path_1.default.join(outputPath, 'ai_docs'));
const aiDocsContent = await generateAIDocsReadme(config);
await fs_extra_1.default.writeFile(path_1.default.join(outputPath, 'ai_docs', 'README.md'), aiDocsContent, 'utf-8');
}
// Generate hooks if enabled
if (config.extras.hooks) {
console.log(chalk_1.default.cyan('\nšŖ Generating Claude Code hooks...'));
const hooksFiles = await (0, hooks_1.generateHooks)(config);
for (const file of hooksFiles) {
const spinner = (0, ora_1.default)(`Creating ${path_1.default.basename(file.path)}...`).start();
try {
await fs_extra_1.default.ensureDir(path_1.default.dirname(file.path));
await fs_extra_1.default.writeFile(path_1.default.join(outputPath, file.path), file.content, 'utf-8');
// Make Python hooks executable
if (file.path.endsWith('.py')) {
await fs_extra_1.default.chmod(path_1.default.join(outputPath, file.path), 0o755);
}
spinner.succeed(`Created ${path_1.default.basename(file.path)}`);
}
catch (error) {
spinner.fail(`Failed to create ${path_1.default.basename(file.path)}`);
throw error;
}
}
console.log(chalk_1.default.green('ā Claude Code hooks generated'));
}
console.log(chalk_1.default.green('\nā
All documentation files generated successfully!'));
}
async function generateAIDocsReadme(config) {
return `# AI Documentation
This directory contains curated documentation for AI-assisted development with Claude Code.
## Purpose
Place library documentation, API references, and other technical documentation here that should be included in the AI's context when working on this project.
## Usage
1. Add markdown files with relevant documentation
2. Reference these files in your PRPs using:
\`\`\`yaml
- docfile: ai_docs/library-name.md
why: Specific sections or methods needed
\`\`\`
## Recommended Documentation
Based on your tech stack (${Object.values(config.techStack).filter(Boolean).join(', ')}), consider adding:
${generateRecommendedDocs(config.techStack)}
## File Naming Convention
- Use lowercase with hyphens: \`library-name.md\`
- Be descriptive: \`fastapi-security-best-practices.md\`
- Version if needed: \`react-19-hooks.md\`
`;
}
function generateRecommendedDocs(techStack) {
const recommendations = [];
if (techStack.frontend === 'nextjs') {
recommendations.push('- Next.js 15 App Router patterns');
recommendations.push('- React Server Components guide');
}
if (techStack.backend === 'fastapi') {
recommendations.push('- FastAPI async patterns');
recommendations.push('- Pydantic v2 migration guide');
}
if (techStack.database === 'postgresql') {
recommendations.push('- PostgreSQL optimization tips');
recommendations.push('- Common SQL patterns');
}
if (techStack.auth === 'jwt') {
recommendations.push('- JWT best practices');
recommendations.push('- Security considerations');
}
return recommendations.join('\n') || '- Add relevant documentation for your tech stack';
}
//# sourceMappingURL=index.js.map