@texagon/nestjs-health
Version:
A comprehensive health monitoring package for NestJS applications with metrics and Kubernetes-ready health checks
148 lines • 6.54 kB
JavaScript
;
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