@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
JavaScript
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;
;