UNPKG

skaya

Version:

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

272 lines (271 loc) 13.5 kB
"use strict"; 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; }; })(); 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.loadComponentConfig = void 0; exports.scanExistingComponents = scanExistingComponents; exports.getDefaultFolderForComponentType = getDefaultFolderForComponentType; exports.getDefaultTemplateDirectory = getDefaultTemplateDirectory; exports.getFilesInFolder = getFilesInFolder; const path_1 = __importStar(require("path")); const configLogger_1 = require("./configLogger"); const fs_1 = require("fs"); const enums_1 = require("../types/enums"); const TemplateService_1 = __importDefault(require("../../src/services/TemplateService")); /** * Scans existing components in the project */ function scanExistingComponents(projectType, componentType) { return __awaiter(this, void 0, void 0, function* () { try { const componentsPath = `${process.cwd()}/${yield getDefaultFolderForComponentType(projectType, componentType)}`; try { // Verify the directory exists first yield fs_1.promises.access(componentsPath); const files = yield fs_1.promises.readdir(componentsPath, { withFileTypes: true }); // Get all component directories (ignore files) const componentDirs = files .filter((dirent) => dirent.isDirectory()) .map((dirent) => dirent.name); // Array to hold components with their data const componentsWithData = []; for (const dir of componentDirs) { // --- IMPROVED CONDITION HERE --- // If componentType is ApiType, skip the 'redux' folder completely if (dir === "redux") { continue; // Skip to the next directory in the loop } const componentDirPath = path_1.default.join(componentsPath, dir); let componentFiles; try { componentFiles = yield fs_1.promises.readdir(componentDirPath); } catch (error) { console.error(`❌ Failed to read directory ${dir}:`, error); continue; } // More flexible main file detection const possibleMainFiles = TemplateService_1.default.getBaseTemplateFiles(componentType) .map((file) => file.replace(new RegExp(componentType, "gi"), dir)) .concat([ // Add common fallbacks `${dir}.tsx`, `${dir}.ts`, `${dir}.jsx`, `${dir.charAt(0).toUpperCase() + dir.slice(1)}.tsx`, // Handle case where dir ends with "Page" (e.g., "asffsPage" -> "asffs.tsx") ...(dir.toLowerCase().endsWith("page") ? [`${dir.slice(0, -4)}.tsx`] : []), "index.tsx", "index.ts", ]); const mainFile = possibleMainFiles.find((file) => componentFiles.includes(file) || componentFiles.includes(path_1.default.basename(file))); if (mainFile) { try { const filePath = path_1.default.join(componentDirPath, mainFile); const fileContent = yield fs_1.promises.readFile(filePath, "utf-8"); componentsWithData.push({ name: dir, data: fileContent, }); } catch (error) { console.error(`❌ Failed to read component file in ${dir}: ${error}`); } } else { console.warn(`⚠️ No main file found for component ${dir} in ${componentDirPath}`); console.warn(`ℹ️ Looked for:`, possibleMainFiles); console.warn(`ℹ️ Found files:`, componentFiles); } } return componentsWithData; } catch (error) { console.error(`❌ Failed to read components directory for ${componentType}. Unable to send extra components to ai.`); return []; } } catch (error) { console.error(error instanceof Error ? error.message : String(error)); return []; } }); } /** * Gets the default folder for a component type * @param {ProjectType} projectType - The project type (frontend/backend) * @param {ComponentType} componentType - The component type * @returns {Promise<string>} The default folder path */ function getDefaultFolderForComponentType(projectType, componentType, fileName) { return __awaiter(this, void 0, void 0, function* () { try { const config = yield (0, configLogger_1.readConfig)(); if (!config) { throw new Error("Configuration not found."); } // Validate project type if (!Object.values(enums_1.ProjectType).includes(projectType)) { throw new Error(`Invalid project type: ${projectType}`); } // Initialize missing configurations with defaults const configMap = { [enums_1.ProjectType.FRONTEND]: config === null || config === void 0 ? void 0 : config.frontend, [enums_1.ProjectType.BACKEND]: config === null || config === void 0 ? void 0 : config.backend, [enums_1.ProjectType.BLOCKCHAIN]: config === null || config === void 0 ? void 0 : config.blockchain, }; if (!configMap[projectType]) { console.warn(`${projectType} config not found. Setting default or add your folder.`); // Update both the config map and the original config configMap[projectType] = { name: `${projectType}SkayaProject`, template: "" }; } // Get base source path const projectConfig = configMap[projectType]; const baseSrcPath = `${(projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.name) || `${projectType}SkayaProject`}/src`; // Handle component-specific paths if (!componentType) { return baseSrcPath; } const componentTypeMap = { [enums_1.FrontendComponentType.PAGE]: `${enums_1.FrontendComponentType.PAGE}s`, [enums_1.FrontendComponentType.COMPONENT]: `${enums_1.FrontendComponentType.COMPONENT}s`, [enums_1.FrontendComponentType.API]: `${enums_1.FrontendComponentType.API}s`, [enums_1.BackendComponentType.ROUTE]: `${enums_1.BackendComponentType.ROUTE}s`, [enums_1.BackendComponentType.CONTROLLER]: `${enums_1.BackendComponentType.CONTROLLER}s`, [enums_1.BlokchainComponentType.CONTRACT]: `${enums_1.BlokchainComponentType.CONTRACT}s`, }; const componentPath = componentTypeMap[componentType]; if (!componentPath) { console.warn(`Unknown component type: ${componentType}. Returning base path.`); return baseSrcPath; } if (fileName) { return `${baseSrcPath}/${componentPath}/${fileName}`; } return `${baseSrcPath}/${componentPath}`; } catch (error) { console.error(`Error in getDefaultFolder: ${error instanceof Error ? error.message : error}`); throw error; // Re-throw to allow caller to handle } }); } /** * Gets the template directory path for a given project and component type * @param projectType The project type (frontend/backend) * @param componentType The component type * @returns The full path to the template directory */ function getDefaultTemplateDirectory(projectType, componentType) { return path_1.default.join(__dirname, "..", "templates", projectType.toLowerCase(), componentType); } // Add this to componentUtils.ts const loadComponentConfig = () => { try { const configPath = (0, path_1.join)(__dirname, "../templates/", "componentImportConfig.json"); const configFile = (0, fs_1.readFileSync)(configPath, "utf-8"); return JSON.parse(configFile); } catch (error) { console.error("Error loading component import configuration:", error); return {}; } }; exports.loadComponentConfig = loadComponentConfig; /** * Gets all files inside a specified folder with their content * @param folderName The name of the folder to scan * @param componentType The type of component (page, component, route, etc.) * @param projectType The type of project (frontend, backend, blockchain) * @returns Promise<TemplateFileInfo[]> Array of file info objects * @throws Error when folder cannot be accessed or read */ function getFilesInFolder(folderName, componentType, projectType) { return __awaiter(this, void 0, void 0, function* () { // Get the base path for the component type const basePath = yield getDefaultFolderForComponentType(projectType, componentType); const fullPath = path_1.default.join(process.cwd(), basePath, folderName); try { // Verify the directory exists yield fs_1.promises.access(fullPath); } catch (error) { throw new Error(`Folder "${fullPath}" does not exist or cannot be accessed`); } try { // Read all files in the directory const files = yield fs_1.promises.readdir(fullPath); // Process each file const fileInfos = files.map((file) => __awaiter(this, void 0, void 0, function* () { const filePath = path_1.default.join(fullPath, file); const stats = yield fs_1.promises.stat(filePath); if (stats.isFile()) { const content = yield fs_1.promises.readFile(filePath, 'utf-8'); return { originalFileName: file, targetFileName: file, // Keeping same name unless you want to modify content: content }; } // For directories, we could return null and filter them out return { originalFileName: file, targetFileName: file, content: undefined // or you might want to skip directories entirely }; })); // Wait for all files to be processed and filter out directories if needed const results = yield Promise.all(fileInfos); return results.filter(file => file.content !== undefined); } catch (error) { throw new Error(`Failed to read files in folder "${fullPath}": ${error instanceof Error ? error.message : String(error)}`); } }); }