@limitrate/cli
Version:
CLI dashboard for LimitRate rate limiting inspection
150 lines (146 loc) • 5.84 kB
JavaScript
import {
inspect
} from "./chunk-PKQ457TL.mjs";
import "./chunk-ZWXM33YD.mjs";
// src/cli.ts
import { Command } from "commander";
// src/commands/inspect-endpoints.ts
import Table from "cli-table3";
import { getGlobalEndpointTracker } from "@limitrate/core";
function inspectEndpoints(options = {}) {
const tracker = getGlobalEndpointTracker();
const endpoints = tracker.getEndpoints();
const stats = tracker.getStats();
if (options.json) {
console.log(
JSON.stringify(
{
summary: stats,
endpoints: endpoints.map((e) => ({
method: e.method,
path: e.path,
hasRateLimit: e.hasRateLimit,
requestCount: e.requestCount,
rateLimitedCount: e.rateLimitedCount,
policy: e.policy,
limit: e.limit,
firstSeen: e.firstSeen,
lastSeen: e.lastSeen
}))
},
null,
2
)
);
if (options.failOnUnprotected && stats.unprotectedEndpoints > 0) {
process.exit(1);
}
return;
}
console.log("\n\u{1F50D} Endpoint Auto-Discovery (Last 24 Hours)\n");
console.log("=" + "=".repeat(80));
console.log("");
console.log(`\u{1F4CA} Summary:`);
console.log(` Total Endpoints: ${stats.totalEndpoints}`);
console.log(` Protected: ${stats.protectedEndpoints} \u2705`);
console.log(` Unprotected: ${stats.unprotectedEndpoints} ${stats.unprotectedEndpoints > 0 ? "\u26A0\uFE0F" : "\u2705"}`);
console.log(` Total Requests: ${stats.totalRequests.toLocaleString()}`);
console.log(` Rate Limited: ${stats.totalRateLimited.toLocaleString()}`);
console.log("");
if (endpoints.length === 0) {
console.log("\u{1F4ED} No endpoints discovered yet. Start making requests!\n");
console.log("=" + "=".repeat(80));
console.log("");
return;
}
const protectedEndpoints = endpoints.filter((e) => e.hasRateLimit);
if (protectedEndpoints.length > 0) {
console.log("\u2705 Protected Endpoints:\n");
const protectedTable = new Table({
head: ["Status", "Method", "Path", "Requests", "Limited", "Policy", "Limit"],
colWidths: [8, 8, 30, 12, 10, 12, 10]
});
for (const endpoint of protectedEndpoints) {
protectedTable.push([
"\u2713",
endpoint.method,
endpoint.path.length > 28 ? endpoint.path.substring(0, 25) + "..." : endpoint.path,
endpoint.requestCount.toLocaleString(),
endpoint.rateLimitedCount.toLocaleString(),
endpoint.policy || "-",
endpoint.limit ? `${endpoint.limit}/min` : "-"
]);
}
console.log(protectedTable.toString());
console.log("");
}
const unprotectedEndpoints = endpoints.filter((e) => !e.hasRateLimit);
if (unprotectedEndpoints.length > 0) {
console.log("\u26A0\uFE0F UNPROTECTED Endpoints (NO RATE LIMITS):\n");
const unprotectedTable = new Table({
head: ["Status", "Method", "Path", "Requests", "Severity"],
colWidths: [8, 8, 30, 12, 20],
style: { head: ["yellow"] }
});
for (const endpoint of unprotectedEndpoints) {
const severity = getSeverity(endpoint.requestCount);
unprotectedTable.push([
"\u26A0",
endpoint.method,
endpoint.path.length > 28 ? endpoint.path.substring(0, 25) + "..." : endpoint.path,
endpoint.requestCount.toLocaleString(),
severity
]);
}
console.log(unprotectedTable.toString());
console.log("");
console.log("\u{1F6A8} WARNING: These endpoints have NO rate limiting!\n");
console.log("Suggestions:");
console.log(" - Add limitrate middleware before these routes");
console.log(" - Or add them to your policy configuration");
console.log(" - Or use skip() to intentionally bypass rate limiting");
console.log("");
const highTraffic = unprotectedEndpoints.filter((e) => e.requestCount >= 50);
if (highTraffic.length > 0) {
console.log("\u{1F525} High Priority (high traffic, no protection):");
for (const endpoint of highTraffic) {
console.log(` ${endpoint.method} ${endpoint.path} - ${endpoint.requestCount} requests`);
}
console.log("");
}
}
console.log("=" + "=".repeat(80));
console.log("");
if (stats.unprotectedEndpoints > 0) {
console.log("\u{1F4A1} Tip: Add rate limits to unprotected endpoints to prevent abuse");
console.log("\u{1F4D6} Docs: https://github.com/limitrate/limitrate\n");
if (options.failOnUnprotected) {
console.log("\u274C CI/CD Check FAILED: Unprotected endpoints detected\n");
process.exit(1);
}
} else {
console.log("\u2705 All discovered endpoints are protected by rate limiting!");
console.log("\u{1F4D6} Docs: https://github.com/limitrate/limitrate\n");
}
}
function getSeverity(requestCount) {
if (requestCount >= 500) return "\u{1F534} CRITICAL";
if (requestCount >= 100) return "\u{1F7E0} HIGH";
if (requestCount >= 50) return "\u{1F7E1} MEDIUM";
return "\u{1F7E2} LOW";
}
// src/cli.ts
var program = new Command();
program.name("limitrate").description("LimitRate CLI - Inspect rate limiting and cost control events").version("0.1.0");
program.command("inspect").description("Show dashboard with endpoint stats, top offenders, and recent events").action(() => {
inspect();
});
program.command("inspect-endpoints").description("Show endpoint auto-discovery (v1.4.0) - which endpoints have rate limits").option("--json", "Output as JSON for CI/CD").option("--fail-on-unprotected", "Exit with code 1 if unprotected endpoints found (for CI/CD)").action((options) => {
inspectEndpoints({ json: options.json, failOnUnprotected: options.failOnUnprotected });
});
if (process.argv.length === 2) {
inspect();
} else {
program.parse();
}