UNPKG

skaya

Version:

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

196 lines (195 loc) 11.6 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.handleApiComponentType = handleApiComponentType; const inquirer_1 = __importDefault(require("inquirer")); const enums_1 = require("../../../../bin/types/enums"); const path_1 = __importDefault(require("path")); const fs_extra_1 = __importDefault(require("fs-extra")); const configLogger_1 = require("../../../../bin/utils/configLogger"); const prompt_1 = require("../../../../bin/utils/prompt"); const TemplateService_1 = __importDefault(require("../../../services/TemplateService")); const ProjectScanner_1 = require("../../../../bin/utils/ProjectScanner"); /** * Handles API component type by updating the base API endpoints file * @param {ApiEndpointConfig} apiConfig - The API endpoint configuration * @param {string} targetFolder - The target folder path * @param {string} fileName - The API endpoint name * @returns {Promise<string[]>} Array of created/updated file paths */ function handleApiComponentType(projectType, componentType, targetFolder, fileName) { return __awaiter(this, void 0, void 0, function* () { const createdFiles = []; const apiFilePath = path_1.default.join(process.cwd(), targetFolder, "apiEndpoints.ts"); let apiType; let apiConfig; const { selectedApiType } = yield inquirer_1.default.prompt([ { type: "list", name: "selectedApiType", message: "Select API type:", choices: [ { name: "API with Redux", value: enums_1.ApiType.REDUX }, { name: "API without Redux", value: enums_1.ApiType.WITHOUT_REDUX }, ], }, ]); apiType = selectedApiType; apiConfig = yield (0, prompt_1.askApiEndpointConfig)(); // Check if Redux store files already exist const config = yield (0, configLogger_1.readConfig)(); if (config === null || config === void 0 ? void 0 : config.frontend) { const defaultReducerFolder = yield (0, ProjectScanner_1.getDefaultFolderForComponentType)(projectType, componentType); const reduxStorePath = path_1.default.join(process.cwd(), defaultReducerFolder); const storeFilePath = `${path_1.default.join(reduxStorePath, "redux", "store.tsx")}`; const storeProviderPath = path_1.default.join(reduxStorePath, "redux", "storeProvider.tsx"); try { // Check if store files exist const storeExists = yield fs_extra_1.default.pathExists(storeFilePath); const providerExists = yield fs_extra_1.default.pathExists(storeProviderPath); const templateDirReduc = (0, ProjectScanner_1.getDefaultTemplateDirectory)(projectType, componentType); if (!storeExists || !providerExists) { console.log("store doesn't exist creating one"); // Create the store directory if it doesn't exist yield fs_extra_1.default.ensureDir(reduxStorePath); // Get base template files for Redux store initialization const baseFiles = TemplateService_1.default.getBaseTemplateFiles(enums_1.ApiType.REDUX); for (const file of baseFiles) { const sourcePath = path_1.default.join(templateDirReduc, file); const targetPath = path_1.default.join(reduxStorePath, file); // Create target path with filename if (yield fs_extra_1.default.pathExists(sourcePath)) { let content = yield fs_extra_1.default.readFile(sourcePath, "utf-8"); yield fs_extra_1.default.outputFile(targetPath, content); // Use targetPath instead of targetFolder createdFiles.push(targetPath); } } } } catch (error) { console.error("❌ Error checking/initializing Redux store:", error); } } // Convert fileName to uppercase for the endpoint key const endpointKey = fileName.toUpperCase(); // Create the new API endpoint object const newEndpoint = { apiId: apiConfig.apiId, withAuth: apiConfig.withAuth, url: apiConfig.url, method: apiConfig.method, }; // Format the new endpoint as a string to be added to the file const newEndpointString = `${endpointKey}: ${JSON.stringify(newEndpoint, null, 2).replace(/"([^"]+)":/g, "$1:")},`; try { let fileContent = ""; const baseFiles = TemplateService_1.default.getBaseTemplateFiles(enums_1.FrontendComponentType.API); // --- Start of new logic to handle base files --- const targetDir = path_1.default.join(process.cwd(), targetFolder); yield fs_extra_1.default.ensureDir(targetDir); const apiSliceFolder = path_1.default.join(targetDir, fileName); // Create a new folder for the slice const apiSliceIndexPath = path_1.default.join(apiSliceFolder, "index.ts"); // The index.ts file inside the new folder const apiSliceTemplatePath = path_1.default.join((0, ProjectScanner_1.getDefaultTemplateDirectory)(projectType, componentType), "apiSlice.tsx"); for (const file of baseFiles) { let content = ""; if (file === "apiSlice.tsx") { yield fs_extra_1.default.ensureDir(apiSliceFolder); // Ensure the new folder exists if (yield fs_extra_1.default.pathExists(apiSliceTemplatePath)) { content = yield fs_extra_1.default.readFile(apiSliceTemplatePath, "utf-8"); // Use a single regex with a callback to handle all cases content = content.replace(/(fetch|create|reset|set|select)?(Api|api|API)(Data|State|Loading|Error)?/g, (match, prefix, caseMatch, suffix) => { let replacement = ""; // Handle the casing of the core "Api" part if (caseMatch === "api") { replacement = fileName.toLowerCase(); // 'api' -> 'filename' } else if (caseMatch === "Api") { // Capitalize the first letter for PascalCase replacement = fileName.charAt(0).toUpperCase() + fileName.slice(1); // 'Api' -> 'Filename' } else if (caseMatch === "API") { replacement = fileName.toUpperCase(); // 'API' -> 'FILENAME' } else { // This case shouldn't be reached, but as a fallback, return the original return match; } // Reassemble the replaced string with its prefix and suffix return (prefix || "") + replacement + (suffix || ""); }); yield fs_extra_1.default.outputFile(apiSliceIndexPath, content); // Save the file as index.ts in the new folder createdFiles.push(apiSliceIndexPath); } else { console.warn(`Template file not found: ${apiSliceTemplatePath}`); } } else if (file === "backendRequest.ts") { const targetBackendRequestPath = path_1.default.join(targetDir, file); const sourceBackendRequestPath = path_1.default.join((0, ProjectScanner_1.getDefaultTemplateDirectory)(projectType, componentType), file); // Only copy if it doesn't already exist if (!(yield fs_extra_1.default.pathExists(targetBackendRequestPath))) { if (yield fs_extra_1.default.pathExists(sourceBackendRequestPath)) { content = yield fs_extra_1.default.readFile(sourceBackendRequestPath, "utf-8"); yield fs_extra_1.default.outputFile(targetBackendRequestPath, content); createdFiles.push(targetBackendRequestPath); console.log(`Backend API Call added: ${targetBackendRequestPath}`); } else { console.warn(`Template file not found: ${sourceBackendRequestPath}`); } } } } // --- End of new logic --- // Check if file exists if (yield fs_extra_1.default.pathExists(apiFilePath)) { fileContent = yield fs_extra_1.default.readFile(apiFilePath, "utf-8"); // Check if endpoint already exists const endpointRegex = new RegExp(`^\\s*${endpointKey}:\\s*{[^}]*},?\\s*$`, "m"); if (endpointRegex.test(fileContent)) { // Update existing endpoint fileContent = fileContent.replace(endpointRegex, newEndpointString); } else { // Add new endpoint before the closing brace const lastBraceIndex = fileContent.lastIndexOf("}"); if (lastBraceIndex !== -1) { fileContent = fileContent.slice(0, lastBraceIndex) + (fileContent.trimEnd().endsWith("}") ? "\n" : "") + newEndpointString + "\n" + fileContent.slice(lastBraceIndex); } else { // If no closing brace found, create a new file fileContent = `export const ApiEndpoint: Record<string, any> = {\n${newEndpointString}\n};`; } } } else { // Create new file with the endpoint fileContent = `export const ApiEndpoint: Record<string, any> = {\n${newEndpointString}\n};`; } // Write the updated content back to the file yield fs_extra_1.default.outputFile(apiFilePath, fileContent); createdFiles.push(apiFilePath); return createdFiles; } catch (error) { throw new Error(`Failed to update API endpoints file: ${error}`); } }); }