skaya
Version:
CLI SDK for full-stack automation: scaffold frontend, backend & blockchain. Future-ready for Web3, integrations, server components & logging.
175 lines (174 loc) • 8.51 kB
JavaScript
;
/**
* @file Template generation utilities
* @module scripts/template
* @version 1.0.0
* @license MIT
*/
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.generateFromTemplate = generateFromTemplate;
const enums_1 = require("../../bin/types/enums");
const geminiCodeGenerator_1 = require("../ai/geminiCodeGenerator");
const inquirer_1 = __importDefault(require("inquirer"));
const ProjectScanner_1 = require("../../bin/utils/ProjectScanner");
const Api_1 = require("./FolderCreator/FrontendFileCreator/Api");
const TemplateService_1 = __importDefault(require("../services/TemplateService"));
const HandleImport_1 = require("./FolderCreator/HandleImport");
const configLogger_1 = require("../../bin/utils/configLogger");
/**
* Generates component files from templates or AI
* @param {Object} params - Generation parameters
* @param {ComponentType} params.componentType - The type of component to generate
* @param {ProjectType} params.projectType - The project type (frontend/backend/blockchain)
* @param {string} params.fileName - The base name for the component
* @param {string} params.targetFolder - The target folder path
* @returns {Promise<string[]>} Array of created file paths
*/
function generateFromTemplate(params) {
return __awaiter(this, void 0, void 0, function* () {
let { componentType, projectType, fileName, updateExistingTemplateFiles } = params;
let targetFolder = params.targetFolder ||
(yield (0, ProjectScanner_1.getDefaultFolderForComponentType)(projectType, componentType));
// Handle API component type separately as an integration process
if (componentType === enums_1.FrontendComponentType.API) {
const createdFiles = yield (0, Api_1.handleApiComponentType)(projectType, componentType, targetFolder, fileName);
for (const file of createdFiles) {
yield (0, configLogger_1.logComponentCreation)({
componentType: componentType,
projectType: projectType,
fileName: file,
description: `Generated API component using template.`,
});
}
return { createdFiles, templateFiles: [] };
}
let templateFiles = yield TemplateService_1.default.getTemplateFilesForType(fileName, componentType, projectType);
if (updateExistingTemplateFiles) {
templateFiles = yield (0, ProjectScanner_1.getFilesInFolder)(fileName, componentType, projectType);
}
const answers = yield inquirer_1.default.prompt([
{
type: "confirm",
name: "useAI",
message: "Use AI to generate the component?",
default: true,
},
]);
let createdFiles = [];
let aiDescription = undefined;
let imports = undefined;
if (answers.useAI) {
const importResult = yield (0, HandleImport_1.handleComponentImport)(projectType, componentType);
const importExisting = importResult.importExisting;
imports = Object.values(importResult.dependencies).flat();
const aiGenerationResult = yield generateWithAI({
fileName,
projectType,
componentType,
templateFiles,
updateExistingTemplateFiles,
importExisting: importExisting,
componentsToImport: imports,
});
templateFiles = aiGenerationResult.files;
aiDescription = aiGenerationResult.description;
createdFiles = yield TemplateService_1.default.saveTemplateFiles({
templateFiles,
fileName,
targetFolder,
componentType,
});
for (const file of createdFiles) {
yield (0, configLogger_1.logComponentCreation)({
componentType: componentType,
projectType: projectType,
fileName: file,
description: `Generated component using AI.`,
});
}
}
else {
createdFiles = yield TemplateService_1.default.saveTemplateFiles({
templateFiles,
fileName,
targetFolder,
componentType,
});
for (const file of createdFiles) {
yield (0, configLogger_1.logComponentCreation)({
componentType: componentType,
projectType: projectType,
fileName: file,
description: `Generated component from template.`,
});
}
}
return { createdFiles, aiDescription, templateFiles, imports };
});
}
/**
* Generates component files using AI and returns the files and the user's prompt.
* @param {Object} params - Generation parameters
* @param {string} params.fileName - The base name for the component
* @param {ProjectType} params.projectType - The project type (frontend/backend)
* @param {ComponentType} params.componentType - The type of component to generate
* @param {TemplateFileInfo[]} params.templateFiles - Template files information
* @param {boolean} params.importExisting - Whether to import existing components
* @param {Array} params.componentsToImport - Components to import
* @returns {Promise<{ files: TemplateFileInfo[], description: string }>} A promise that resolves to an object containing the generated files and the user's prompt.
*/
function generateWithAI(params) {
return __awaiter(this, void 0, void 0, function* () {
const { fileName, projectType, componentType, templateFiles, updateExistingTemplateFiles } = params;
const answers = yield inquirer_1.default.prompt([
{
type: "input",
name: "description",
message: "Enter AI Prompt on how the files and code should work:",
default: "",
},
]);
const aiDescription = answers.description || "";
const options = {
style: "css",
typescript: true,
withProps: true,
withState: false,
withEffects: false,
withTests: true,
withStories: projectType === enums_1.ProjectType.FRONTEND,
};
try {
const aiResult = yield (0, geminiCodeGenerator_1.generateCodeWithAI)(fileName, projectType, componentType, aiDescription, options, templateFiles, updateExistingTemplateFiles, {
importExisting: params.importExisting,
componentsToImport: params.componentsToImport || [],
});
// Check if any file has empty content (which would indicate generation failed)
const hasEmptyContent = aiResult.some((file) => !file.content || file.content.trim() === "");
if (hasEmptyContent) {
console.error("AI generation failed for some files, returning template files");
return { files: templateFiles, description: aiDescription }; // Return original templates and the prompt
}
return {
files: aiResult.map((file) => (Object.assign({}, file))),
description: aiDescription, // Return the prompt
};
}
catch (error) {
console.error("Error generating with AI:", error);
return { files: templateFiles, description: aiDescription }; // Return original template files and the prompt on error
}
});
}