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

590 lines (589 loc) • 23.1 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.manageWorkspaceTemplate = manageWorkspaceTemplate; const chalk_1 = __importDefault(require("chalk")); const prompts_1 = __importDefault(require("prompts")); const path = __importStar(require("path")); const fs = __importStar(require("fs-extra")); const yaml = __importStar(require("yaml")); const workspace_template_1 = require("../utils/workspace-template"); const workspace_schema_1 = require("../utils/workspace-schema"); const spinner_1 = require("../utils/spinner"); const error_handler_1 = require("../utils/error-handler"); const DEFAULT_WORKSPACE_FILE = 're-shell.workspaces.yaml'; async function manageWorkspaceTemplate(options = {}) { const { spinner, verbose, json } = options; try { if (options.list) { await listTemplates(options, spinner); return; } if (options.create) { await createTemplateInteractive(options, spinner); return; } if (options.apply) { await applyTemplate(options, spinner); return; } if (options.show) { await showTemplate(options, spinner); return; } if (options.delete) { await deleteTemplate(options, spinner); return; } if (options.export) { await exportTemplate(options, spinner); return; } if (options.interactive) { await interactiveTemplateManagement(options, spinner); return; } // Default: list templates await listTemplates(options, spinner); } catch (error) { if (spinner) spinner.fail(chalk_1.default.red('Template operation failed')); throw error; } } async function listTemplates(options, spinner) { if (spinner) spinner.setText('Loading templates...'); try { const manager = await (0, workspace_template_1.createWorkspaceTemplateManager)(); const templates = await manager.listTemplates(); if (spinner) spinner.stop(); if (options.json) { console.log(JSON.stringify(templates, null, 2)); return; } if (templates.length === 0) { console.log(chalk_1.default.yellow('\nāš ļø No templates found')); console.log(chalk_1.default.gray('Create one with: re-shell workspace-template create')); return; } console.log(chalk_1.default.cyan('\nšŸ“‹ Available Workspace Templates')); console.log(chalk_1.default.gray('═'.repeat(50))); for (const template of templates) { console.log(`\n${chalk_1.default.bold(template.name)} v${template.version}`); if (template.description) { console.log(` ${chalk_1.default.gray(template.description)}`); } if (template.extends) { console.log(` ${chalk_1.default.yellow('Extends:')} ${template.extends}`); } if (template.variables && template.variables.length > 0) { console.log(` ${chalk_1.default.blue('Variables:')} ${template.variables.map(v => v.name).join(', ')}`); } if (options.verbose) { if (template.patterns && template.patterns.length > 0) { console.log(` ${chalk_1.default.green('Patterns:')} ${template.patterns.join(', ')}`); } if (template.scripts && Object.keys(template.scripts).length > 0) { console.log(` ${chalk_1.default.magenta('Scripts:')} ${Object.keys(template.scripts).join(', ')}`); } } } console.log(chalk_1.default.cyan('\nšŸ› ļø Commands:')); console.log(' • re-shell workspace-template show <name>'); console.log(' • re-shell workspace-template apply <name>'); console.log(' • re-shell workspace-template create'); } catch (error) { if (spinner) spinner.fail(chalk_1.default.red('Failed to load templates')); throw error; } } async function createTemplateInteractive(options, spinner) { if (spinner) spinner.stop(); console.log(chalk_1.default.cyan('\nšŸŽØ Create Workspace Template')); console.log(chalk_1.default.gray('═'.repeat(50))); const response = await (0, prompts_1.default)([ { type: 'text', name: 'name', message: 'Template name:', validate: value => value.trim() ? true : 'Name is required' }, { type: 'text', name: 'description', message: 'Description (optional):' }, { type: 'text', name: 'version', message: 'Version:', initial: '1.0.0' }, { type: 'text', name: 'extends', message: 'Extends template (optional):' }, { type: 'confirm', name: 'addVariables', message: 'Add template variables?', initial: true } ]); if (!response.name) return; const template = { name: response.name, version: response.version, description: response.description || undefined, extends: response.extends || undefined, variables: [] }; // Add variables if (response.addVariables) { while (true) { const varResponse = await (0, prompts_1.default)([ { type: 'text', name: 'name', message: 'Variable name (empty to finish):' }, { type: prev => prev ? 'select' : null, name: 'type', message: 'Variable type:', choices: [ { title: 'String', value: 'string' }, { title: 'Number', value: 'number' }, { title: 'Boolean', value: 'boolean' }, { title: 'Array', value: 'array' }, { title: 'Object', value: 'object' } ] }, { type: prev => prev ? 'text' : null, name: 'description', message: 'Description (optional):' }, { type: prev => prev ? 'confirm' : null, name: 'required', message: 'Required?', initial: false }, { type: (prev, values) => values.type === 'string' || values.type === 'number' ? 'text' : null, name: 'default', message: 'Default value (optional):' } ]); if (!varResponse.name) break; const variable = { name: varResponse.name, type: varResponse.type, description: varResponse.description || undefined, required: varResponse.required }; if (varResponse.default) { variable.default = varResponse.type === 'number' ? Number(varResponse.default) : varResponse.default; } template.variables.push(variable); } } // Add template content const contentResponse = await (0, prompts_1.default)([ { type: 'confirm', name: 'addPatterns', message: 'Add workspace patterns?', initial: false }, { type: prev => prev ? 'list' : null, name: 'patterns', message: 'Patterns (comma-separated):', separator: ',' }, { type: 'confirm', name: 'addScripts', message: 'Add default scripts?', initial: false } ]); if (contentResponse.patterns) { template.patterns = contentResponse.patterns.map((p) => p.trim()); } if (contentResponse.addScripts) { template.scripts = {}; const commonScripts = ['dev', 'build', 'test', 'lint']; for (const scriptName of commonScripts) { const scriptResponse = await (0, prompts_1.default)({ type: 'text', name: 'command', message: `${scriptName} script (optional):` }); if (scriptResponse.command) { template.scripts[scriptName] = scriptResponse.command; } } } // Save template spinner = (0, spinner_1.createSpinner)('Creating template...').start(); try { const manager = await (0, workspace_template_1.createWorkspaceTemplateManager)(); await manager.createTemplate(template); if (spinner) spinner.succeed(chalk_1.default.green(`Template '${template.name}' created successfully!`)); // Show next steps console.log(chalk_1.default.cyan('\nšŸš€ Next steps:')); console.log(` • Apply template: re-shell workspace-template apply ${template.name}`); console.log(` • View template: re-shell workspace-template show ${template.name}`); } catch (error) { if (spinner) spinner.fail(chalk_1.default.red('Failed to create template')); throw error; } } async function applyTemplate(options, spinner) { if (!options.template) { throw new error_handler_1.ValidationError('Template name is required'); } if (spinner) spinner.setText(`Loading template: ${options.template}`); try { const manager = await (0, workspace_template_1.createWorkspaceTemplateManager)(); const template = await manager.getTemplate(options.template); if (!template) { throw new error_handler_1.ValidationError(`Template '${options.template}' not found`); } if (spinner) spinner.stop(); // Collect variables const variables = {}; // Load from file if provided if (options.varsFile) { const varsPath = path.resolve(options.varsFile); if (await fs.pathExists(varsPath)) { const content = await fs.readFile(varsPath, 'utf8'); Object.assign(variables, yaml.parse(content)); } } // Parse command line variables if (options.variables) { try { const parsed = JSON.parse(options.variables); Object.assign(variables, parsed); } catch (error) { throw new error_handler_1.ValidationError('Invalid variables JSON format'); } } // Prompt for missing required variables if (template.variables) { for (const varDef of template.variables) { if (varDef.required && !(varDef.name in variables)) { const response = await (0, prompts_1.default)({ type: varDef.type === 'number' ? 'number' : varDef.type === 'boolean' ? 'confirm' : 'text', name: 'value', message: `${varDef.name}${varDef.description ? ` (${varDef.description})` : ''}:`, initial: varDef.default }); if (response.value !== undefined) { variables[varDef.name] = response.value; } } } } // Apply template if (spinner) spinner = (0, spinner_1.createSpinner)('Applying template...').start(); const context = { variables }; const result = await manager.applyTemplate(options.template, context); if (spinner) spinner.stop(); if (options.output) { // Save to file const outputPath = path.resolve(options.output); await fs.ensureDir(path.dirname(outputPath)); await fs.writeFile(outputPath, yaml.stringify(result)); console.log(chalk_1.default.green(`āœ… Template applied and saved to: ${options.output}`)); } else if (options.json) { // Output as JSON console.log(JSON.stringify(result, null, 2)); } else { // Display result console.log(chalk_1.default.cyan('\nšŸ“„ Applied Template Result')); console.log(chalk_1.default.gray('═'.repeat(50))); console.log(yaml.stringify(result)); } } catch (error) { if (spinner) spinner.fail(chalk_1.default.red('Failed to apply template')); throw error; } } async function showTemplate(options, spinner) { if (!options.template) { throw new error_handler_1.ValidationError('Template name is required'); } if (spinner) spinner.setText(`Loading template: ${options.template}`); try { const manager = await (0, workspace_template_1.createWorkspaceTemplateManager)(); const template = await manager.getTemplate(options.template); if (!template) { throw new error_handler_1.ValidationError(`Template '${options.template}' not found`); } // Resolve inheritance chain const chain = await manager.resolveInheritanceChain(options.template); if (spinner) spinner.stop(); if (options.json) { console.log(JSON.stringify({ template, inheritance: chain.templates.map(t => t.name), mergedVariables: chain.variables }, null, 2)); return; } console.log(chalk_1.default.cyan(`\nšŸ“‹ Template: ${template.name}`)); console.log(chalk_1.default.gray('═'.repeat(50))); console.log(`Version: ${template.version}`); if (template.description) { console.log(`Description: ${template.description}`); } if (template.extends) { console.log(`\n${chalk_1.default.yellow('Inheritance Chain:')}`); for (let i = 0; i < chain.templates.length; i++) { console.log(` ${i + 1}. ${chain.templates[i].name} v${chain.templates[i].version}`); } } if (Object.keys(chain.variables).length > 0) { console.log(`\n${chalk_1.default.blue('Variables:')}`); for (const [name, varDef] of Object.entries(chain.variables)) { console.log(` ${name}:`); console.log(` Type: ${varDef.type}`); if (varDef.description) { console.log(` Description: ${varDef.description}`); } if (varDef.required) { console.log(` Required: ${chalk_1.default.red('yes')}`); } if (varDef.default !== undefined) { console.log(` Default: ${JSON.stringify(varDef.default)}`); } if (varDef.enum) { console.log(` Values: ${varDef.enum.join(', ')}`); } if (varDef.pattern) { console.log(` Pattern: ${varDef.pattern}`); } } } if (options.verbose) { console.log(`\n${chalk_1.default.green('Template Content:')}`); console.log(yaml.stringify(chain.merged)); } console.log(chalk_1.default.cyan('\nšŸ› ļø Commands:')); console.log(` • Apply: re-shell workspace-template apply ${template.name}`); console.log(` • Delete: re-shell workspace-template delete ${template.name}`); } catch (error) { if (spinner) spinner.fail(chalk_1.default.red('Failed to load template')); throw error; } } async function deleteTemplate(options, spinner) { if (!options.template) { throw new error_handler_1.ValidationError('Template name is required'); } if (spinner) spinner.setText(`Deleting template: ${options.template}`); try { const manager = await (0, workspace_template_1.createWorkspaceTemplateManager)(); await manager.deleteTemplate(options.template); if (spinner) spinner.succeed(chalk_1.default.green(`Template '${options.template}' deleted successfully!`)); } catch (error) { if (spinner) spinner.fail(chalk_1.default.red('Failed to delete template')); throw error; } } async function exportTemplate(options, spinner) { const workspaceFile = options.workspaceFile || DEFAULT_WORKSPACE_FILE; if (!options.name) { throw new error_handler_1.ValidationError('Template name is required for export'); } if (spinner) spinner.setText('Exporting workspace as template...'); try { const definition = await (0, workspace_schema_1.loadWorkspaceDefinition)(workspaceFile); // Create variables for common fields const variables = [ { name: 'projectName', type: 'string', required: true, description: 'Project name' }, { name: 'description', type: 'string', required: false, description: 'Project description' } ]; const template = await (0, workspace_template_1.exportWorkspaceAsTemplate)(definition, options.name, variables); if (spinner) spinner.stop(); if (options.output) { // Save to file const outputPath = path.resolve(options.output); await fs.ensureDir(path.dirname(outputPath)); await fs.writeFile(outputPath, yaml.stringify(template)); console.log(chalk_1.default.green(`āœ… Template exported to: ${options.output}`)); } else { // Create template const manager = await (0, workspace_template_1.createWorkspaceTemplateManager)(); await manager.createTemplate(template); console.log(chalk_1.default.green(`āœ… Template '${options.name}' created from workspace`)); } } catch (error) { if (spinner) spinner.fail(chalk_1.default.red('Failed to export template')); throw error; } } async function interactiveTemplateManagement(options, spinner) { if (spinner) spinner.stop(); const response = await (0, prompts_1.default)([ { type: 'select', name: 'action', message: 'What would you like to do?', choices: [ { title: 'šŸ“‹ List templates', value: 'list' }, { title: 'šŸŽØ Create new template', value: 'create' }, { title: 'šŸ”§ Apply template', value: 'apply' }, { title: 'šŸ‘ļø Show template details', value: 'show' }, { title: 'šŸ“¤ Export workspace as template', value: 'export' }, { title: 'šŸ—‘ļø Delete template', value: 'delete' } ] } ]); if (!response.action) return; switch (response.action) { case 'list': await listTemplates({ ...options, interactive: false }); break; case 'create': await createTemplateInteractive({ ...options, interactive: false }); break; case 'apply': const applyResponse = await (0, prompts_1.default)({ type: 'text', name: 'template', message: 'Template name:' }); if (applyResponse.template) { await applyTemplate({ ...options, template: applyResponse.template, interactive: false }); } break; case 'show': const showResponse = await (0, prompts_1.default)({ type: 'text', name: 'template', message: 'Template name:' }); if (showResponse.template) { await showTemplate({ ...options, template: showResponse.template, interactive: false }); } break; case 'export': const exportResponse = await (0, prompts_1.default)({ type: 'text', name: 'name', message: 'Template name:' }); if (exportResponse.name) { await exportTemplate({ ...options, name: exportResponse.name, interactive: false }); } break; case 'delete': const deleteResponse = await (0, prompts_1.default)({ type: 'text', name: 'template', message: 'Template name to delete:' }); if (deleteResponse.template) { const confirmResponse = await (0, prompts_1.default)({ type: 'confirm', name: 'confirm', message: `Are you sure you want to delete '${deleteResponse.template}'?`, initial: false }); if (confirmResponse.confirm) { await deleteTemplate({ ...options, template: deleteResponse.template, interactive: false }); } } break; } }