UNPKG

@mbc-cqrs-serverless/cli

Version:

a CLI to get started with MBC CQRS serverless framework

225 lines (224 loc) 8.24 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.VERSION_FILE_NAME = void 0; exports.getSkillsSourcePath = getSkillsSourcePath; exports.getPersonalSkillsPath = getPersonalSkillsPath; exports.getProjectSkillsPath = getProjectSkillsPath; exports.copySkills = copySkills; exports.getInstalledVersion = getInstalledVersion; exports.getPackageVersion = getPackageVersion; exports.writeVersionFile = writeVersionFile; exports.default = installSkillsAction; const fs_1 = require("fs"); const os_1 = __importDefault(require("os")); const path_1 = __importDefault(require("path")); const ui_1 = require("../ui"); /** * Version file name for tracking installed skills version */ exports.VERSION_FILE_NAME = '.mbc-skills-version'; /** * Get the path to the mcp-server skills source directory */ function getSkillsSourcePath() { // Try to find the mcp-server package const possiblePaths = [ // When installed globally or locally via npm path_1.default.join(__dirname, '..', '..', '..', 'mcp-server', 'skills'), // When running from monorepo path_1.default.join(__dirname, '..', '..', '..', '..', 'mcp-server', 'skills'), // When installed via npm in node_modules path_1.default.join(process.cwd(), 'node_modules', '@mbc-cqrs-serverless', 'mcp-server', 'skills'), ]; for (const p of possiblePaths) { if ((0, fs_1.existsSync)(p)) { return p; } } // Try to resolve from npm package try { const mcpServerPath = require.resolve('@mbc-cqrs-serverless/mcp-server'); return path_1.default.join(path_1.default.dirname(mcpServerPath), '..', 'skills'); } catch { // Package not found } throw new Error('Could not find mcp-server skills directory. Please ensure @mbc-cqrs-serverless/mcp-server is installed.'); } /** * Get the path to personal skills directory (~/.claude/skills/) */ function getPersonalSkillsPath() { return path_1.default.join(os_1.default.homedir(), '.claude', 'skills'); } /** * Get the path to project skills directory (.claude/skills/) */ function getProjectSkillsPath() { return path_1.default.join(process.cwd(), '.claude', 'skills'); } /** * Copy skills from source to destination * @returns List of copied skill names */ function copySkills(sourcePath, destPath) { // Create destination directory if it doesn't exist if (!(0, fs_1.existsSync)(destPath)) { (0, fs_1.mkdirSync)(destPath, { recursive: true }); } // Get all skill directories const entries = (0, fs_1.readdirSync)(sourcePath, { withFileTypes: true }); const skillDirs = entries.filter((entry) => entry.isDirectory()); const copiedSkills = []; for (const skillDir of skillDirs) { const skillSourcePath = path_1.default.join(sourcePath, skillDir.name); const skillDestPath = path_1.default.join(destPath, skillDir.name); (0, fs_1.cpSync)(skillSourcePath, skillDestPath, { recursive: true }); copiedSkills.push(skillDir.name); } return copiedSkills; } /** * List available skills */ function listSkills(sourcePath) { const entries = (0, fs_1.readdirSync)(sourcePath, { withFileTypes: true }); return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name); } /** * Get the installed version of skills from the version file * @returns The installed version or null if not found */ function getInstalledVersion(destPath) { const versionFilePath = path_1.default.join(destPath, exports.VERSION_FILE_NAME); if (!(0, fs_1.existsSync)(versionFilePath)) { return null; } try { const version = (0, fs_1.readFileSync)(versionFilePath, 'utf-8'); return version.trim(); } catch { return null; } } /** * Get the package version from mcp-server package.json * @returns The package version or null if not found */ function getPackageVersion(sourcePath) { // The package.json is one level up from the skills directory const packageJsonPath = path_1.default.join(sourcePath, '..', 'package.json'); if (!(0, fs_1.existsSync)(packageJsonPath)) { return null; } try { const packageJson = JSON.parse((0, fs_1.readFileSync)(packageJsonPath, 'utf-8')); return packageJson.version || null; } catch { return null; } } /** * Write the version file to track installed skills version */ function writeVersionFile(destPath, version) { const versionFilePath = path_1.default.join(destPath, exports.VERSION_FILE_NAME); (0, fs_1.writeFileSync)(versionFilePath, version, 'utf-8'); } /** * Install Claude Code skills for MBC CQRS Serverless */ async function installSkillsAction(options, command) { if (!command) { throw new Error('Command is required'); } ui_1.logger.info(`Executing command '${command.name()}'...`); const { project, force, list, check } = options; // Get source path let sourcePath; try { sourcePath = getSkillsSourcePath(); } catch (error) { ui_1.logger.error(error.message); throw error; } // Verify source exists if (!(0, fs_1.existsSync)(sourcePath)) { const errorMsg = `Skills source directory not found: ${sourcePath}`; ui_1.logger.error(errorMsg); throw new Error(errorMsg); } // List mode if (list) { const skills = listSkills(sourcePath); ui_1.logger.title('skills', 'Available Claude Code Skills:'); skills.forEach((skill) => { ui_1.logger.log(` - ${skill}`); }); ui_1.logger.log(''); ui_1.logger.info(`Total: ${skills.length} skills`); return; } // Determine destination path const destPath = project ? getProjectSkillsPath() : getPersonalSkillsPath(); // Check mode - compare versions without installing if (check) { const installedVersion = getInstalledVersion(destPath); const packageVersion = getPackageVersion(sourcePath); if (!installedVersion) { ui_1.logger.warn('Skills are not installed.'); ui_1.logger.info(`Available version: ${packageVersion || 'unknown'}`); ui_1.logger.info('Run `mbc install-skills` to install.'); return; } if (!packageVersion) { ui_1.logger.warn('Could not determine package version.'); ui_1.logger.info(`Installed version: ${installedVersion}`); return; } if (installedVersion === packageVersion) { ui_1.logger.success(`Skills are up to date (${installedVersion}).`); } else { ui_1.logger.warn(`Update available: ${installedVersion}${packageVersion}`); ui_1.logger.info('Run `mbc install-skills --force` to update.'); } return; } // Check if skills already exist if ((0, fs_1.existsSync)(destPath) && !force) { const existingSkills = (0, fs_1.readdirSync)(destPath, { withFileTypes: true }) .filter((entry) => entry.isDirectory()) .map((entry) => entry.name); if (existingSkills.length > 0) { ui_1.logger.warn(`Skills already exist at ${destPath}. Use --force to overwrite.`); } } // Copy skills ui_1.logger.title('install', `Installing skills to ${destPath}`); const copiedSkills = copySkills(sourcePath, destPath); // Write version file const packageVersion = getPackageVersion(sourcePath); if (packageVersion) { writeVersionFile(destPath, packageVersion); } ui_1.logger.success(`Successfully installed ${copiedSkills.length} skills:`); copiedSkills.forEach((skill) => { ui_1.logger.log(` - ${skill}`); }); if (packageVersion) { ui_1.logger.log(''); ui_1.logger.info(`Version: ${packageVersion}`); } ui_1.logger.log(''); ui_1.logger.info('You can now use these skills in Claude Code:'); copiedSkills.forEach((skill) => { ui_1.logger.log(` /${skill}`); }); }