UNPKG

skaya

Version:

CLI SDK for full-stack automation: scaffold frontend, backend & blockchain. Future-ready for Web3, integrations, server components & logging.

176 lines (172 loc) 7.83 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateCodeWithAI = generateCodeWithAI; const openai_1 = __importDefault(require("openai")); const fs_1 = require("fs"); const path_1 = __importDefault(require("path")); const enums_1 = require("../../bin/types/enums"); const config_1 = require("../config"); function generateCodeWithAI(fileName_1, projectType_1, componentType_1) { return __awaiter(this, arguments, void 0, function* (fileName, projectType, componentType, aiDescription = '', options = { style: 'css', typescript: true, withProps: true, withState: false, withEffects: false, withTests: true, withStories: projectType === enums_1.ProjectType.FRONTEND }, templateFiles = [], extraOptions = {}) { const apiKey = (0, config_1.getApiKey)(); if (!apiKey) throw new Error(`${apiKey} API key is required.`); const openai = new openai_1.default({ apiKey }); const updatedFiles = []; const baseConfig = Object.assign({ componentName: fileName, aiDescription, projectType, componentType }, options); for (const fileTemplate of templateFiles) { const templateDir = path_1.default.join(__dirname, '..', 'templates', projectType.toLowerCase(), componentType); const sourcePath = path_1.default.join(templateDir, fileTemplate.originalFileName); if (!(0, fs_1.existsSync)(sourcePath)) { throw new Error(`Template file not found: ${sourcePath}`); } const originalContent = (0, fs_1.readFileSync)(sourcePath, 'utf-8'); // Now reading the file, not the directory const fileType = path_1.default.extname(fileTemplate.originalFileName).replace('.', ''); const systemPrompt = getSystemPrompt(fileType, componentType); const userPrompt = buildFilePrompt(originalContent, baseConfig, fileTemplate.originalFileName); const aiUpdatedContent = yield generateWithAI(openai, systemPrompt, userPrompt); updatedFiles.push(Object.assign(Object.assign({}, fileTemplate), { content: aiUpdatedContent })); } return updatedFiles; }); } function generateWithAI(openai, systemPrompt, userPrompt) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c; try { const response = yield openai.chat.completions.create({ model: 'gpt-4', messages: [ { role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt } ], temperature: 0.3, max_tokens: 2000 }); return ((_c = (_b = (_a = response.choices[0]) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.trim()) || ''; } catch (error) { console.error('Error generating file with AI:', error); return ''; } }); } function getSystemPrompt(fileType, componentType) { const basePrompt = `You are an expert full-stack developer. Generate clean, production-ready code that: - Follows best practices for the specific file type - Includes proper TypeScript types - Has clear, concise comments where needed - Is fully functional - Matches modern architectural patterns - Uses appropriate error handling - Follows security best practices`; // Handle file extensions first switch (fileType) { case 'tsx': return componentType === enums_1.FrontendComponentType.PAGE ? `${basePrompt} for React page components. Include: - Proper page-level structure - SEO considerations if applicable - Data fetching methods if needed - Layout integration` : `${basePrompt} for React components. Include: - Proper component structure - TypeScript interfaces - Clean JSX - Accessibility best practices`; case 'test.tsx': return `${basePrompt} for React component tests. Include: - Testing Library best practices - Meaningful test cases - Proper mocking where needed - Accessibility tests`; case 'stories.tsx': return `${basePrompt} for Storybook stories. Include: - Comprehensive controls - Multiple interaction states - Documentation`; case 'css': case 'scss': return `${basePrompt} for styles. Include: - Modular CSS patterns - Responsive design considerations - BEM naming if appropriate - Variables for theming`; case 'test.ts': return `${basePrompt} for backend tests. Include: - Unit tests for business logic - Integration tests for APIs - Proper test setup/teardown - Mocking of external services`; case 'ts': // Handle backend-specific component types if (componentType) { switch (componentType) { case enums_1.BackendComponentType.ROUTE: return `${basePrompt} for API routes. Include: - RESTful design principles - Proper HTTP status codes - Input validation - Error handling - Documentation`; case enums_1.BackendComponentType.CONTROLLER: return `${basePrompt} for backend controllers. Include: - Business logic encapsulation - Clean separation of concerns - Proper error handling - Type-safe inputs/outputs - Dependency injection`; default: return `${basePrompt} for general TypeScript files`; } } return `${basePrompt} for general TypeScript files`; default: return basePrompt; } } function buildFilePrompt(originalFileContent, config, originalFileName) { return ` Update the following file based on the configuration below: Configuration: - Component Name: ${config.componentName} - Component Type: ${config.componentType} - Description: ${config.description} - Project Type: ${config.projectType} - Style: ${config.style} - TypeScript: ${config.typescript} - With Props: ${config.withProps} - With State: ${config.withState} - With Effects: ${config.withEffects} - With Tests: ${config.withTests} - With Stories: ${config.withStories} - Original File Name: ${originalFileName} File Content: \`\`\` ${originalFileContent} \`\`\` Return only the updated file content. Do not include explanation or markdown syntax. `; }