UNPKG

@foxframework/core

Version:

A modern, production-ready web framework for TypeScript/Node.js with modular routing, integrated template engine, CLI tools, and enterprise features

207 lines (206 loc) 7.59 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseGenerator = void 0; // tsfox/cli/generators/base.generator.ts const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const prompt_manager_1 = require("../core/prompt.manager"); class BaseGenerator { constructor(templateManager) { this.templateManager = templateManager; this.promptManager = new prompt_manager_1.PromptManager(); } /** * Render template with variables */ async renderTemplate(templatePath, variables) { return this.templateManager.render(templatePath, variables); } /** * Write file with overwrite handling */ async writeFile(filePath, content, action = 'create') { const fullPath = path_1.default.resolve(filePath); if (action === 'create' && fs_1.default.existsSync(fullPath)) { const overwrite = await this.promptManager.confirmOverwrite(fullPath); if (!overwrite) { console.log(`Skipped: ${filePath}`); return; } } await fs_1.default.promises.mkdir(path_1.default.dirname(fullPath), { recursive: true }); if (action === 'append') { await fs_1.default.promises.appendFile(fullPath, content, 'utf8'); } else { await fs_1.default.promises.writeFile(fullPath, content, 'utf8'); } console.log(`${action === 'create' ? 'Created' : 'Updated'}: ${filePath}`); } /** * Check if file exists */ fileExists(filePath) { return fs_1.default.existsSync(path_1.default.resolve(filePath)); } /** * Read file content */ async readFile(filePath) { const fullPath = path_1.default.resolve(filePath); return fs_1.default.promises.readFile(fullPath, 'utf8'); } /** * Convert string to PascalCase */ toPascalCase(str) { return str .replace(/([a-z])([A-Z])/g, '$1-$2') .split(/[-_\s]+/) .filter(word => word.length > 0) .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) .join(''); } /** * Convert string to camelCase */ toCamelCase(str) { const pascal = this.toPascalCase(str); return pascal.charAt(0).toLowerCase() + pascal.slice(1); } /** * Convert string to kebab-case */ toKebabCase(str) { return str .replace(/([a-z])([A-Z])/g, '$1-$2') .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2') .toLowerCase() .replace(/[-_\s]+/g, '-') .replace(/^-|-$/g, ''); } /** * Convert string to snake_case */ toSnakeCase(str) { return this.toKebabCase(str).replace(/-/g, '_'); } /** * Ensure directory exists */ async ensureDirectory(dirPath) { await fs_1.default.promises.mkdir(path_1.default.resolve(dirPath), { recursive: true }); } /** * Get relative path from project root */ getRelativePath(filePath, projectRoot) { return path_1.default.relative(projectRoot, filePath); } /** * Add import to file */ async addImport(filePath, importStatement) { if (!this.fileExists(filePath)) { return; } const content = await this.readFile(filePath); // Check if import already exists if (content.includes(importStatement.trim())) { return; } // Find insertion point (after existing imports) const lines = content.split('\n'); let insertIndex = 0; for (let i = 0; i < lines.length; i++) { const line = lines[i].trim(); if (line.startsWith('import ') || line.startsWith('export ')) { insertIndex = i + 1; } else if (line && !line.startsWith('//') && !line.startsWith('/*')) { break; } } lines.splice(insertIndex, 0, importStatement); const updatedContent = lines.join('\n'); await fs_1.default.promises.writeFile(filePath, updatedContent, 'utf8'); } /** * Add content to end of file */ async appendToFile(filePath, content) { const fullPath = path_1.default.resolve(filePath); if (!fs_1.default.existsSync(fullPath)) { await this.writeFile(fullPath, content); return; } await fs_1.default.promises.appendFile(fullPath, `\n${content}`, 'utf8'); console.log(`Updated: ${filePath}`); } /** * Insert content at specific line */ async insertAtLine(filePath, lineNumber, content) { const fileContent = await this.readFile(filePath); const lines = fileContent.split('\n'); lines.splice(lineNumber, 0, content); const updatedContent = lines.join('\n'); await fs_1.default.promises.writeFile(filePath, updatedContent, 'utf8'); console.log(`Updated: ${filePath}`); } /** * Replace content in file */ async replaceInFile(filePath, searchString, replaceString) { const content = await this.readFile(filePath); const updatedContent = content.replace(searchString, replaceString); await fs_1.default.promises.writeFile(filePath, updatedContent, 'utf8'); console.log(`Updated: ${filePath}`); } /** * Validate context */ validateContext(context) { if (!context.name) { throw new Error('Generator context must have a name'); } if (!context.projectRoot) { throw new Error('Generator context must have a project root'); } if (!fs_1.default.existsSync(context.projectRoot)) { throw new Error(`Project root does not exist: ${context.projectRoot}`); } } /** * Get project structure info */ async getProjectInfo(projectRoot) { const packageJsonPath = path_1.default.join(projectRoot, 'package.json'); const foxConfigPath = path_1.default.join(projectRoot, 'fox.config.json'); const info = { hasPackageJson: fs_1.default.existsSync(packageJsonPath), hasFoxConfig: fs_1.default.existsSync(foxConfigPath), directories: { src: fs_1.default.existsSync(path_1.default.join(projectRoot, 'src')), controllers: fs_1.default.existsSync(path_1.default.join(projectRoot, 'src/controllers')), models: fs_1.default.existsSync(path_1.default.join(projectRoot, 'src/models')), services: fs_1.default.existsSync(path_1.default.join(projectRoot, 'src/services')), middleware: fs_1.default.existsSync(path_1.default.join(projectRoot, 'src/middleware')), routes: fs_1.default.existsSync(path_1.default.join(projectRoot, 'src/routes')) } }; if (info.hasPackageJson) { const packageContent = await fs_1.default.promises.readFile(packageJsonPath, 'utf8'); info.packageJson = JSON.parse(packageContent); } if (info.hasFoxConfig) { const configContent = await fs_1.default.promises.readFile(foxConfigPath, 'utf8'); info.foxConfig = JSON.parse(configContent); } return info; } } exports.BaseGenerator = BaseGenerator;