@mbc-cqrs-serverless/cli
Version:
a CLI to get started with MBC CQRS serverless framework
225 lines (224 loc) • 8.24 kB
JavaScript
;
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}`);
});
}