UNPKG

node-apis

Version:

šŸš€ Advanced TypeScript API generator with clean architecture, comprehensive testing, and automatic formatting. Generate production-ready Node.js APIs with complete integration test suites.

234 lines (232 loc) • 9.33 kB
"use strict"; /** * Module generation service - Main business logic */ 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.generateModuleStructurePhase2 = exports.generateModuleStructurePhase1 = exports.generateModuleStructure = void 0; const module_name_validator_1 = require("../validators/module-name.validator"); const path_utils_1 = require("../filesystem/path.utils"); const directory_operations_1 = require("../filesystem/directory.operations"); const file_generator_service_1 = require("./file-generator.service"); const path = __importStar(require("path")); /** * Generates the API module folder structure */ const generateModuleStructure = async ({ moduleName, options = {}, apiType, }) => { const { baseDir = process.cwd(), force = false, appendMode = false, targetDir } = options; try { // Validate the module name with enhanced naming const validation = (0, module_name_validator_1.validateModuleName)({ name: moduleName }); if (!validation.isValid) { return { success: false, error: validation.error, }; } const normalizedName = validation.normalizedName; const modulePath = await (0, path_utils_1.getModulePath)({ moduleName: normalizedName, baseDir, ...(targetDir && { targetDir }), }); // Check if directory already exists const exists = await (0, directory_operations_1.directoryExists)({ dirPath: modulePath }); if (exists && !force && !appendMode) { return { success: false, error: `Module directory already exists: ${modulePath}\nUse --force flag to overwrite or run in interactive mode to append.`, }; } // Create the main module directory await (0, directory_operations_1.ensureDirectory)({ dirPath: modulePath }); // Create all subdirectories based on API type const subdirectories = (0, path_utils_1.getModuleSubdirectories)(apiType, false, apiType?.framework); const createdDirs = await (0, directory_operations_1.createDirectories)({ basePath: modulePath, subdirectories, }); // Generate TypeScript files if apiType is provided let generatedFiles = []; if (apiType) { generatedFiles = await (0, file_generator_service_1.generateApiFiles)({ moduleName: normalizedName, modulePath, apiType, appendMode, }); } // Format success message const message = formatSuccessMessage({ moduleName: normalizedName, modulePath, ...(apiType && { apiType }), }); return { success: true, moduleName: normalizedName, modulePath, createdDirectories: createdDirs, generatedFiles, message, }; } catch (error) { return await handleGenerationError(error, moduleName, baseDir); } }; exports.generateModuleStructure = generateModuleStructure; /** * Phase 1: Creates only the main module directory and types subdirectory * Used for two-phase generation where we want to generate types first */ const generateModuleStructurePhase1 = async ({ moduleName, options = {}, framework, }) => { const { baseDir = process.cwd(), force = false, appendMode = false, targetDir } = options; try { // Validate the module name with enhanced naming const validation = (0, module_name_validator_1.validateModuleName)({ name: moduleName }); if (!validation.isValid) { return { success: false, error: validation.error, }; } const normalizedName = validation.normalizedName; const modulePath = await (0, path_utils_1.getModulePath)({ moduleName: normalizedName, baseDir, ...(framework && { framework }), ...(targetDir && { targetDir }), }); // Check if directory already exists const exists = await (0, directory_operations_1.directoryExists)({ dirPath: modulePath }); if (exists && !force && !appendMode) { return { success: false, error: `Module directory already exists: ${modulePath}\nUse --force flag to overwrite or run in interactive mode to append.`, }; } // Create the main module directory await (0, directory_operations_1.ensureDirectory)({ dirPath: modulePath }); // Create only the types subdirectory for phase 1 const typesDir = path.join(modulePath, 'types'); await (0, directory_operations_1.ensureDirectory)({ dirPath: typesDir }); return { success: true, moduleName: normalizedName, modulePath, createdDirectories: [modulePath, typesDir], generatedFiles: [], message: `āœ… Phase 1: Created module directory and types folder for "${normalizedName}"`, }; } catch (error) { return await handleGenerationError(error, moduleName, baseDir); } }; exports.generateModuleStructurePhase1 = generateModuleStructurePhase1; /** * Phase 2: Creates remaining subdirectories based on API type * Used after user confirms the generated types */ const generateModuleStructurePhase2 = async ({ modulePath, apiType, trpcStyle = false, framework, }) => { try { // Get all subdirectories for this API type and style const allSubdirectories = (0, path_utils_1.getModuleSubdirectories)(apiType, trpcStyle, framework); // Filter out 'types' since it was already created in phase 1 const remainingSubdirectories = allSubdirectories.filter(dir => dir !== 'types'); // Create remaining subdirectories const createdDirs = await (0, directory_operations_1.createDirectories)({ basePath: modulePath, subdirectories: remainingSubdirectories, }); return { success: true, createdDirectories: createdDirs, }; } catch (error) { return { success: false, createdDirectories: [], error: `Failed to create remaining directories: ${error.message}`, }; } }; exports.generateModuleStructurePhase2 = generateModuleStructurePhase2; /** * Formats a success message with the created structure */ const formatSuccessMessage = ({ moduleName, modulePath, apiType, }) => { const subdirs = (0, path_utils_1.getModuleSubdirectories)(apiType, false, apiType?.framework); const structure = subdirs.map(dir => ` ā”œā”€ā”€ ${dir}/`).join('\n'); return ` āœ… Successfully created API module structure for "${moduleName}" šŸ“ Created directory structure: ${modulePath}/ ${structure} šŸš€ Your API module is ready for development! `; }; /** * Handles generation errors with specific error types */ const handleGenerationError = async (error, moduleName, baseDir) => { // Handle specific file system errors if (error.code === 'EACCES') { return { success: false, error: `Permission denied. Cannot create directories at: ${await (0, path_utils_1.getModulePath)({ moduleName, baseDir })}`, }; } if (error.code === 'ENOSPC') { return { success: false, error: 'Not enough disk space to create the module structure', }; } if (error.code === 'ENOTDIR') { return { success: false, error: 'Invalid path: A file exists where a directory is expected', }; } // Generic error handling return { success: false, error: `Failed to create module structure: ${error.message}`, }; }; //# sourceMappingURL=module-generator.service.js.map