UNPKG

@nestbox-ai/cli

Version:

The cli tools that helps developers to build agents

154 lines (123 loc) 4.36 kB
import path from "path"; import fs from 'fs'; import chalk from "chalk"; import ora from "ora"; import { promisify } from "util"; import { exec } from "child_process"; import AdmZip from "adm-zip"; import * as os from 'os'; import axios from "axios"; const execAsync = promisify(exec); export async function findProjectRoot(startDir = process.cwd()) { let currentDir = startDir; while (currentDir !== path.parse(currentDir).root) { const nestboxConfigPath = path.join(currentDir, 'nestbox.config.json'); const packageJsonPath = path.join(currentDir, 'package.json'); if (fs.existsSync(nestboxConfigPath) || fs.existsSync(packageJsonPath)) { return currentDir; } currentDir = path.dirname(currentDir); } return startDir; // Fallback to current directory if no root markers found } // Function to load and parse nestbox.config.json if it exists export function loadNestboxConfig(projectRoot: any) { const configPath = path.join(projectRoot, 'nestbox.config.json'); if (fs.existsSync(configPath)) { try { const configContent = fs.readFileSync(configPath, 'utf8'); return JSON.parse(configContent); } catch (error: any) { console.warn(chalk.yellow(`Warning: Error parsing nestbox.config.json: ${error.message}`)); } } return null; } // Function to detect if a directory contains TypeScript files export function isTypeScriptProject(directoryPath: any) { // Check for tsconfig.json if (fs.existsSync(path.join(directoryPath, 'tsconfig.json'))) { return true; } // Check for .ts files try { const files = fs.readdirSync(directoryPath); return files.some(file => file.endsWith('.ts') || file.endsWith('.tsx')); } catch (error) { return false; } } export async function runPredeployScripts(scripts: any, projectRoot: any) { if (!scripts || !Array.isArray(scripts) || scripts.length === 0) { return; } const spinner = ora('Running predeploy scripts...').start(); try { for (const script of scripts) { spinner.text = `Running: ${script}`; // Make sure we're running in the correct directory await execAsync(script, { cwd: projectRoot, }); } spinner.succeed('Predeploy scripts completed successfully'); } catch (error: any) { spinner.fail(`Predeploy script failed: ${error.message}`); throw new Error(`Predeploy failed: ${error.message}`); } } export function createZipFromDirectory(dirPath: any, excludePatterns = ['node_modules']) { const dirName = path.basename(dirPath); const timestamp = Date.now(); // Create zip in temp directory const tempZipFilePath = path.join(os.tmpdir(), `${dirName}_${timestamp}.zip`); const zip = new AdmZip(); // Function to recursively add files to zip function addFilesToZip(currentPath: any, relativePath = '') { const items = fs.readdirSync(currentPath); for (const item of items) { const itemPath = path.join(currentPath, item); const itemRelativePath = path.join(relativePath, item); // Check if item should be excluded if (excludePatterns.some((pattern: any) => typeof pattern === 'string' ? itemRelativePath === pattern || item === pattern : pattern.test(itemRelativePath) )) { continue; } const stats = fs.statSync(itemPath); if (stats.isDirectory()) { addFilesToZip(itemPath, itemRelativePath); } else { zip.addLocalFile(itemPath, path.dirname(itemRelativePath)); } } } addFilesToZip(dirPath); // Write zip to temp directory (for upload) zip.writeZip(tempZipFilePath); // Return the temp path for upload return tempZipFilePath; } export interface TemplateInfo { name: string; description: string; fileId: string; lang: string; type: string; } export function createNestboxConfig(projectPath: string, isTypeScript: boolean): void { if (!isTypeScript) return; const configPath = path.join(projectPath, 'nestbox.config.json'); const config = { agents: { predeploy: [ 'rm -rf dist', 'npm run lint', 'npm run build' ] } }; fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); console.log(chalk.green(`Created nestbox.config.json at ${configPath}`)); }