UNPKG

@texagon/nestjs-health

Version:

A comprehensive health monitoring package for NestJS applications with metrics and Kubernetes-ready health checks

148 lines 6.54 kB
#!/usr/bin/env node "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const commander_1 = require("commander"); const chalk = require("chalk"); const path = require("path"); const fs = require("fs"); const inquirer = require("inquirer"); const ora = require("ora"); const child_process_1 = require("child_process"); const program = new commander_1.Command(); const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, "../../package.json"), "utf8")); program .name("texagon-nestjs-health") .description("A CLI to add comprehensive health monitoring to NestJS applications") .version(packageJson.version); program .command("install") .description("Install health monitoring module into your NestJS application") .option("--no-deps", "Skip installing dependencies") .option("--path <path>", "Path to the NestJS application", process.cwd()) .option("--prefix <prefix>", "Route prefix for health endpoints", "health") .action(async (options) => { console.log(chalk.blue("🚀 Installing NestJS Health Monitor...")); const targetPath = path.resolve(options.path); console.log(chalk.gray(`Target path: ${targetPath}`)); if (!fs.existsSync(path.join(targetPath, "nest-cli.json"))) { console.error(chalk.red("❌ This does not appear to be a NestJS project. Please run this command in a NestJS project.")); process.exit(1); } const answers = await inquirer.prompt([ { type: "confirm", name: "enableMemoryMonitoring", message: "Enable memory monitoring?", default: true, }, { type: "confirm", name: "enableDiskMonitoring", message: "Enable disk monitoring?", default: true, }, { type: "input", name: "diskPath", message: "Path to monitor for disk space:", default: "/", when: (answers) => answers.enableDiskMonitoring, }, { type: "number", name: "diskThresholdPercent", message: "Disk usage threshold percentage (0-100):", default: 75, when: (answers) => answers.enableDiskMonitoring, validate: (input) => { const num = parseFloat(input); return num >= 0 && num <= 100 ? true : "Please enter a number between 0 and 100"; }, }, { type: "confirm", name: "passwordProtected", message: "Enable password protection for health endpoints?", default: false, }, { type: "password", name: "password", message: "Enter password for health endpoints:", when: (answers) => answers.passwordProtected, validate: (input) => { return input.length >= 6 ? true : "Password must be at least 6 characters long"; }, }, { type: "password", name: "confirmPassword", message: "Confirm password:", when: (answers) => answers.passwordProtected, validate: (input, answers) => { return input === answers.password ? true : "Passwords do not match"; }, }, ]); if (answers.diskThresholdPercent) { answers.diskThresholdPercent = answers.diskThresholdPercent / 100; } const sourceDir = path.join(__dirname, "../health"); const targetDir = path.join(targetPath, "src/health"); const spinner = ora("Creating health module...").start(); try { if (!fs.existsSync(targetDir)) { fs.mkdirSync(targetDir, { recursive: true }); } const files = fs.readdirSync(sourceDir); files.forEach((file) => { if (file === "test-error.controller.ts") { return; } const source = path.join(sourceDir, file); const target = path.join(targetDir, file); fs.copyFileSync(source, target); }); const appModulePath = path.join(targetPath, "src/app.module.ts"); if (fs.existsSync(appModulePath)) { let appModuleContent = fs.readFileSync(appModulePath, "utf8"); if (!appModuleContent.includes("HealthModule")) { appModuleContent = appModuleContent.replace(/(import.*from.*;\n)/, `$1import { HealthModule } from './health/health.module';\n`); appModuleContent = appModuleContent.replace(/(imports\s*:\s*\[)/, `$1\n HealthModule.register({\n enableMemoryMonitoring: ${answers.enableMemoryMonitoring},\n enableDiskMonitoring: ${answers.enableDiskMonitoring},\n ${answers.diskPath ? `diskPath: '${answers.diskPath}',\n ` : ""}${answers.diskThresholdPercent ? `diskThresholdPercent: ${answers.diskThresholdPercent},\n ` : ""}${answers.passwordProtected ? `passwordProtected: true,\n password: '${answers.password}',\n ` : ""}routePrefix: '${options.prefix}',\n }),`); fs.writeFileSync(appModulePath, appModuleContent); } } spinner.succeed("Health module created successfully"); if (options.deps) { spinner.text = "Installing dependencies..."; spinner.start(); try { (0, child_process_1.execSync)("npm install @nestjs/terminus @nestjs/axios", { cwd: targetPath, stdio: "ignore", }); spinner.succeed("Dependencies installed successfully"); } catch (error) { spinner.fail("Failed to install dependencies"); console.error(chalk.red(`Error: ${error.message}`)); } } console.log("\n" + chalk.green("==>[SUCCESS] NestJS Health Monitor installed successfully!")); console.log("\n" + chalk.yellow("Available endpoints:")); console.log(chalk.cyan(`- GET /${options.prefix}`)); console.log(chalk.cyan(`- GET /${options.prefix}/live`)); console.log(chalk.cyan(`- GET /${options.prefix}/ready`)); console.log(chalk.cyan(`- GET /${options.prefix}/stats`)); } catch (error) { spinner.fail("Failed to create health module"); console.error(chalk.red(`Error: ${error.message}`)); } }); program.parse(); //# sourceMappingURL=index.js.map