UNPKG

@re-shell/cli

Version:

Full-stack development platform uniting microservices and microfrontends. Build complete applications with .NET (ASP.NET Core Web API, Minimal API), Java (Spring Boot, Quarkus, Micronaut, Vert.x), Rust (Actix-Web, Warp, Rocket, Axum), Python (FastAPI, Dja

369 lines (368 loc) • 14.2 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 __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.listWorkspaces = listWorkspaces; exports.updateWorkspaces = updateWorkspaces; exports.generateWorkspaceGraph = generateWorkspaceGraph; const fs = __importStar(require("fs-extra")); const path = __importStar(require("path")); const child_process_1 = require("child_process"); const util_1 = require("util"); const chalk_1 = __importDefault(require("chalk")); const monorepo_1 = require("../utils/monorepo"); const execAsync = (0, util_1.promisify)(child_process_1.exec); /** * List all workspaces in the monorepo */ async function listWorkspaces(options = {}) { const { spinner } = options; try { if (spinner) { spinner.setText('Finding monorepo root...'); } // Add timeout to prevent hanging const monorepoRoot = await Promise.race([ (0, monorepo_1.findMonorepoRoot)(), new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout finding monorepo root')), 5000)), ]); if (!monorepoRoot) { throw new Error('Not in a monorepo. Run this command from a monorepo root or workspace.'); } if (spinner) { spinner.setText('Loading workspace information...'); } const workspaces = await (0, monorepo_1.getWorkspaces)(monorepoRoot); // Filter workspaces based on options let filteredWorkspaces = workspaces; if (options.type) { filteredWorkspaces = filteredWorkspaces.filter(ws => ws.type === options.type); } if (options.framework) { filteredWorkspaces = filteredWorkspaces.filter(ws => ws.framework === options.framework); } if (spinner) { spinner.stop(); } if (options.json) { console.log(JSON.stringify(filteredWorkspaces, null, 2)); return; } // Display workspaces in a formatted table console.log(chalk_1.default.cyan('\nšŸ“¦ Workspaces\n')); if (filteredWorkspaces.length === 0) { console.log(chalk_1.default.yellow('No workspaces found.')); return; } // Group by type const groupedWorkspaces = filteredWorkspaces.reduce((acc, ws) => { if (!acc[ws.type]) acc[ws.type] = []; acc[ws.type].push(ws); return acc; }, {}); for (const [type, workspaceList] of Object.entries(groupedWorkspaces)) { console.log(chalk_1.default.bold(`\n${type.toUpperCase()}S:`)); workspaceList.forEach((ws) => { const frameworkBadge = ws.framework ? chalk_1.default.blue(`[${ws.framework}]`) : ''; const versionBadge = chalk_1.default.gray(`v${ws.version}`); console.log(` ${chalk_1.default.green('ā—')} ${chalk_1.default.bold(ws.name)} ${frameworkBadge} ${versionBadge}`); console.log(` ${chalk_1.default.gray(ws.path)}`); if (ws.dependencies.length > 0) { const depCount = ws.dependencies.length; console.log(` ${chalk_1.default.gray(`${depCount} dependencies`)}`); } }); } console.log(chalk_1.default.gray(`\nTotal: ${filteredWorkspaces.length} workspaces`)); } catch (error) { if (spinner) { spinner.fail(chalk_1.default.red('Error listing workspaces')); } console.error(chalk_1.default.red('Error listing workspaces:'), error); throw error; } } /** * Update dependencies across workspaces */ async function updateWorkspaces(options = {}) { const { spinner } = options; try { if (spinner) { spinner.setText('Finding monorepo root...'); } const monorepoRoot = await (0, monorepo_1.findMonorepoRoot)(); if (!monorepoRoot) { throw new Error('Not in a monorepo. Run this command from a monorepo root or workspace.'); } if (spinner) { spinner.setText('Loading workspace information...'); } const workspaces = await (0, monorepo_1.getWorkspaces)(monorepoRoot); if (options.workspace) { // Update specific workspace const workspace = workspaces.find((ws) => ws.name === options.workspace || (options.workspace && ws.path.includes(options.workspace))); if (!workspace) { throw new Error(`Workspace "${options.workspace}" not found.`); } if (spinner) { spinner.setText(`Updating workspace: ${workspace.name}...`); } await updateSingleWorkspace(monorepoRoot, workspace, options); if (spinner) { spinner.succeed(chalk_1.default.green(`āœ“ Workspace "${workspace.name}" updated successfully`)); } } else { // Update all workspaces if (spinner) { spinner.setText('Updating all workspaces...'); } for (let i = 0; i < workspaces.length; i++) { const workspace = workspaces[i]; if (spinner) { spinner.setText(`Updating ${workspace.name} (${i + 1}/${workspaces.length})...`); } await updateSingleWorkspace(monorepoRoot, workspace, options); } if (spinner) { spinner.succeed(chalk_1.default.green('āœ“ All workspaces updated')); } } } catch (error) { if (spinner) { spinner.fail(chalk_1.default.red('Error updating workspaces')); } console.error(chalk_1.default.red('Error updating workspaces:'), error); throw error; } } async function updateSingleWorkspace(monorepoRoot, workspace, options) { const workspacePath = path.join(monorepoRoot, workspace.path); if (options.dependency && options.version) { // Update specific dependency const depFlag = options.dev ? '--save-dev' : '--save'; const packageManager = await detectPackageManager(monorepoRoot); let command; switch (packageManager) { case 'pnpm': command = `pnpm add ${depFlag} ${options.dependency}@${options.version}`; break; case 'yarn': command = `yarn add ${depFlag} ${options.dependency}@${options.version}`; break; default: command = `npm install ${depFlag} ${options.dependency}@${options.version}`; } await execAsync(command, { cwd: workspacePath }); console.log(chalk_1.default.green(`āœ“ Updated ${options.dependency} to ${options.version} in ${workspace.name}`)); } else { // Update all dependencies const packageManager = await detectPackageManager(monorepoRoot); let command; switch (packageManager) { case 'pnpm': command = 'pnpm update'; break; case 'yarn': command = 'yarn upgrade'; break; default: command = 'npm update'; } await execAsync(command, { cwd: workspacePath }); } } /** * Generate workspace dependency graph */ async function generateWorkspaceGraph(options = {}) { const { spinner } = options; try { if (spinner) { spinner.setText('Finding monorepo root...'); } const monorepoRoot = await (0, monorepo_1.findMonorepoRoot)(); if (!monorepoRoot) { throw new Error('Not in a monorepo. Run this command from a monorepo root or workspace.'); } if (spinner) { spinner.setText('Loading workspace information...'); } const workspaces = await (0, monorepo_1.getWorkspaces)(monorepoRoot); if (spinner) { spinner.setText('Building dependency graph...'); } const graph = await buildDependencyGraph(workspaces); if (spinner) { spinner.stop(); } switch (options.format) { case 'json': { const jsonOutput = JSON.stringify(graph, null, 2); if (options.output) { await fs.writeFile(options.output, jsonOutput); console.log(chalk_1.default.green(`Graph saved to ${options.output}`)); } else { console.log(jsonOutput); } break; } case 'mermaid': { const mermaidOutput = generateMermaidGraph(graph); if (options.output) { await fs.writeFile(options.output, mermaidOutput); console.log(chalk_1.default.green(`Mermaid graph saved to ${options.output}`)); } else { console.log(mermaidOutput); } break; } default: displayTextGraph(graph); } } catch (error) { if (spinner) { spinner.fail(chalk_1.default.red('Error generating workspace graph')); } console.error(chalk_1.default.red('Error generating workspace graph:'), error); throw error; } } async function buildDependencyGraph(workspaces) { const graph = { nodes: workspaces.map(ws => ({ id: ws.name, type: ws.type, framework: ws.framework, path: ws.path, })), edges: [], }; // Build edges based on package.json dependencies for (const workspace of workspaces) { const packageJsonPath = path.join(workspace.path, 'package.json'); try { const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8')); const allDeps = { ...packageJson.dependencies, ...packageJson.devDependencies, }; for (const depName of Object.keys(allDeps)) { const targetWorkspace = workspaces.find(ws => ws.name === depName); if (targetWorkspace) { graph.edges.push({ from: workspace.name, to: targetWorkspace.name, type: packageJson.dependencies?.[depName] ? 'dependency' : 'devDependency', }); } } } catch (error) { // Skip if package.json is not readable } } return graph; } function displayTextGraph(graph) { console.log(chalk_1.default.cyan('\nšŸ”— Workspace Dependency Graph\n')); for (const node of graph.nodes) { const dependencies = graph.edges.filter((edge) => edge.from === node.id); const dependents = graph.edges.filter((edge) => edge.to === node.id); console.log(chalk_1.default.bold(`${node.id} (${node.type})`)); if (dependencies.length > 0) { console.log(chalk_1.default.gray(' Dependencies:')); dependencies.forEach((dep) => { const typeColor = dep.type === 'dependency' ? chalk_1.default.green : chalk_1.default.yellow; console.log(` ${typeColor('→')} ${dep.to}`); }); } if (dependents.length > 0) { console.log(chalk_1.default.gray(' Dependents:')); dependents.forEach((dep) => { console.log(` ${chalk_1.default.blue('←')} ${dep.from}`); }); } console.log(); } } function generateMermaidGraph(graph) { let mermaid = 'graph TD\n'; // Add nodes for (const node of graph.nodes) { const shape = getNodeShape(node.type); mermaid += ` ${node.id}${shape}\n`; } // Add edges for (const edge of graph.edges) { const style = edge.type === 'dependency' ? '-->' : '-..->'; mermaid += ` ${edge.from} ${style} ${edge.to}\n`; } return mermaid; } function getNodeShape(type) { switch (type) { case 'app': return '[App]'; case 'package': return '(Package)'; case 'lib': return '{Library}'; case 'tool': return '[[Tool]]'; default: return '[Unknown]'; } } async function detectPackageManager(rootPath) { if (await fs.pathExists(path.join(rootPath, 'pnpm-lock.yaml'))) { return 'pnpm'; } if (await fs.pathExists(path.join(rootPath, 'yarn.lock'))) { return 'yarn'; } return 'npm'; }