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
JavaScript
"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}`);
}
});
}