UNPKG

nestjs-reverse-engineering

Version:

A powerful TypeScript/NestJS library for database reverse engineering, entity generation, and CRUD operations

206 lines (205 loc) 8.02 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.EntityIndexGenerator = void 0; /* eslint-disable prettier/prettier */ const fs = __importStar(require("fs")); const path = __importStar(require("path")); const glob_1 = require("glob"); class EntityIndexGenerator { constructor(options = {}) { this.options = { entitiesPath: './generated/entities', outputPath: './generated/entities/index.ts', includeNamedExports: true, includeEntitiesArray: true, filePattern: '**/*.entity.ts', ...options }; } /** * Scan directory for entity files */ async scanEntityFiles() { const entityFiles = []; const searchPattern = path.join(this.options.entitiesPath, this.options.filePattern); const files = await (0, glob_1.glob)(searchPattern, { ignore: ['**/index.ts', '**/*.spec.ts', '**/*.test.ts'], absolute: false }); for (const filePath of files) { const entityInfo = this.extractEntityInfo(filePath); if (entityInfo) { entityFiles.push(entityInfo); } } return entityFiles.sort((a, b) => a.className.localeCompare(b.className)); } /** * Extract entity class information from file */ extractEntityInfo(filePath) { try { const fullPath = path.resolve(filePath); const fileContent = fs.readFileSync(fullPath, 'utf8'); // Extract class name using regex const classMatch = fileContent.match(/export\s+class\s+(\w+)/); if (!classMatch) { console.warn(`No exported class found in ${filePath}`); return null; } const className = classMatch[1]; const fileName = path.basename(filePath); const relativePath = path.relative(path.dirname(this.options.outputPath || ''), filePath); // Remove .ts extension for import const importPath = relativePath.replace(/\.ts$/, ''); return { className, fileName, filePath: fullPath, relativePath: importPath }; } catch (error) { console.error(`Error reading file ${filePath}:`, error); return null; } } /** * Generate index.ts content */ generateIndexContent(entities) { const lines = []; // Add header comment lines.push('// Generated entity index - Auto-generated, do not edit manually'); lines.push(''); // Add imports if (entities.length > 0) { lines.push('// Entity imports'); entities.forEach(entity => { lines.push(`import { ${entity.className} } from './${entity.relativePath}';`); }); lines.push(''); } // Add named exports (re-exports) if (this.options.includeNamedExports && entities.length > 0) { lines.push('// Named exports'); lines.push('export {'); entities.forEach((entity, index) => { const comma = index < entities.length - 1 ? ',' : ''; lines.push(` ${entity.className}${comma}`); }); lines.push('};'); lines.push(''); } // Add entities array export if (this.options.includeEntitiesArray && entities.length > 0) { lines.push('// Entities array for TypeORM configuration'); lines.push('export const Entities = ['); entities.forEach((entity, index) => { const comma = index < entities.length - 1 ? ',' : ''; lines.push(` ${entity.className}${comma}`); }); lines.push('];'); lines.push(''); } // Add entity count export lines.push(`// Total entities: ${entities.length}`); lines.push(`export const ENTITY_COUNT = ${entities.length};`); lines.push(''); // Add entity names export if (entities.length > 0) { lines.push('// Entity names for reference'); lines.push('export const ENTITY_NAMES = ['); entities.forEach((entity, index) => { const comma = index < entities.length - 1 ? ',' : ''; lines.push(` '${entity.className}'${comma}`); }); lines.push('];'); lines.push(''); } // Add entity metadata export lines.push('// Entity metadata'); lines.push('export const ENTITY_METADATA = ['); entities.forEach((entity, index) => { const comma = index < entities.length - 1 ? ',' : ''; lines.push(` {`); lines.push(` name: '${entity.className}',`); lines.push(` fileName: '${entity.fileName}',`); lines.push(` class: ${entity.className}`); lines.push(` }${comma}`); }); lines.push('];'); return lines.join('\n'); } /** * Generate index.ts file */ async generateIndex() { console.log('🔍 Scanning for entity files...'); const entities = await this.scanEntityFiles(); console.log(`📄 Found ${entities.length} entity files:`); entities.forEach(entity => { console.log(` - ${entity.className} (${entity.fileName})`); }); console.log('📝 Generating index.ts...'); const indexContent = this.generateIndexContent(entities); // Ensure output directory exists const outputDir = path.dirname(this.options.outputPath); if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } // Write index file fs.writeFileSync(this.options.outputPath, indexContent, 'utf8'); console.log(`✅ Generated index.ts at ${this.options.outputPath}`); console.log(`📊 Exported ${entities.length} entities`); } /** * Watch for changes and regenerate index */ watchAndRegenerate() { console.log('👁️ Watching for entity file changes...'); // Simple file watcher (in production, consider using chokidar) setInterval(async () => { try { await this.generateIndex(); } catch (error) { console.error('Error regenerating index:', error); } }, 5000); // Check every 5 seconds } } exports.EntityIndexGenerator = EntityIndexGenerator;