UNPKG

@addon24/eslint-config

Version:

ESLint configuration rules for WorldOfTextcraft projects - Centralized configuration for all project types

241 lines (217 loc) 8.62 kB
const enforceViteHealthMetricsRule = { meta: { type: "problem", docs: { description: "Enforce Vite configuration to include required health and metrics endpoints", category: "Best Practices", recommended: true, }, fixable: null, schema: [{ type: "object", properties: { requiredEndpoints: { type: "array", items: { type: "string" }, default: ["/health", "/health/live", "/health/ready", "/metrics"], }, requiredPackages: { type: "array", items: { type: "string" }, default: ["@godaddy/terminus", "prom-client"], }, requiredServices: { type: "array", items: { type: "string" }, default: ["HealthMetricsService", "MetricsService"], }, }, additionalProperties: false, }], messages: { missingHealthEndpoint: "Missing required health endpoint: {{endpoint}}. Add middleware for {{endpoint}} in Vite config.", missingMetricsEndpoint: "Missing required metrics endpoint: {{endpoint}}. Add middleware for {{endpoint}} in Vite config.", missingPackage: "Missing required package: {{package}}. Install {{package}} for health/metrics functionality.", missingService: "Missing required service: {{service}}. Import and use {{service}} in Vite config.", incorrectContentType: "Health endpoint {{endpoint}} should return 'text/plain' content type for Prometheus metrics.", missingConfigureServer: "Vite config must include configureServer function for health/metrics endpoints.", missingMiddlewares: "Vite config must include server.middlewares.use for health/metrics endpoints.", }, }, create(context) { const options = context.options[0] || {}; const requiredEndpoints = options.requiredEndpoints || ["/health", "/health/live", "/health/ready", "/metrics"]; const requiredPackages = options.requiredPackages || ["@godaddy/terminus", "prom-client"]; const requiredServices = options.requiredServices || ["HealthMetricsService", "MetricsService"]; let hasViteConfig = false; let hasConfigureServer = false; let hasMiddlewares = false; let foundEndpoints = new Set(); let foundServices = new Set(); let foundPackages = new Set(); return { // Check for Vite config file Program() { const filename = context.getFilename(); if (filename.includes("vite.config") || filename.includes("vite.config.ts") || filename.includes("vite.config.js")) { hasViteConfig = true; } }, // Check for import statements ImportDeclaration(node) { const source = node.source.value; if (requiredPackages.includes(source)) { foundPackages.add(source); } }, // Check for configureServer function FunctionDeclaration(node) { if (node.id && node.id.name === "configureServer") { hasConfigureServer = true; } }, // Check for ArrowFunctionExpression with configureServer ArrowFunctionExpression(node) { if (node.parent && node.parent.type === "Property" && node.parent.key && node.parent.key.name === "configureServer") { hasConfigureServer = true; } }, // Check for server.middlewares.use calls and content type headers CallExpression(node) { // Check for server.middlewares.use calls if (node.callee.type === "MemberExpression" && node.callee.object.type === "MemberExpression" && node.callee.object.object.name === "server" && node.callee.object.property.name === "middlewares" && node.callee.property.name === "use") { hasMiddlewares = true; // Check for endpoint path const endpointArg = node.arguments[0]; if (endpointArg && endpointArg.type === "Literal" && typeof endpointArg.value === "string") { const endpoint = endpointArg.value; if (requiredEndpoints.includes(endpoint)) { foundEndpoints.add(endpoint); } } } // Check for content type headers if (node.callee.type === "MemberExpression" && node.callee.property.name === "setHeader") { const headerName = node.arguments[0]; const headerValue = node.arguments[1]; if (headerName && headerName.type === "Literal" && headerName.value === "Content-Type") { if (headerValue && headerValue.type === "Literal" && headerValue.value === "application/json") { // Find the endpoint this belongs to by traversing up let current = node.parent; while (current && current.type !== "CallExpression") { current = current.parent; } if (current && current.callee.type === "MemberExpression" && current.callee.property.name === "use") { const endpointArg = current.arguments[0]; if (endpointArg && endpointArg.type === "Literal" && (endpointArg.value === "/health" || endpointArg.value === "/metrics")) { context.report({ node: headerValue, messageId: "incorrectContentType", data: { endpoint: endpointArg.value } }); } } } } } }, // Check for service imports and usage VariableDeclarator(node) { if (node.init && node.init.type === "CallExpression" && node.init.callee.type === "Identifier" && node.init.callee.name === "import") { const importArg = node.init.arguments[0]; if (importArg && importArg.type === "Literal" && typeof importArg.value === "string") { const importPath = importArg.value; if (importPath.includes("HealthMetricsService") || importPath.includes("MetricsService")) { requiredServices.forEach(service => { if (importPath.includes(service)) { foundServices.add(service); } }); } } } }, // Check for service instantiation NewExpression(node) { if (node.callee.type === "Identifier") { const serviceName = node.callee.name; if (requiredServices.includes(serviceName)) { foundServices.add(serviceName); } } }, // Final validation on program end "Program:exit"() { if (!hasViteConfig) { return; // Not a Vite config file } // Check for missing packages requiredPackages.forEach(packageName => { if (!foundPackages.has(packageName)) { context.report({ node: context.getSourceCode().ast, messageId: "missingPackage", data: { package: packageName } }); } }); // Check for missing services requiredServices.forEach(serviceName => { if (!foundServices.has(serviceName)) { context.report({ node: context.getSourceCode().ast, messageId: "missingService", data: { service: serviceName } }); } }); // Check for missing endpoints requiredEndpoints.forEach(endpoint => { if (!foundEndpoints.has(endpoint)) { if (endpoint === "/health" || endpoint === "/metrics") { context.report({ node: context.getSourceCode().ast, messageId: "missingMetricsEndpoint", data: { endpoint } }); } else { context.report({ node: context.getSourceCode().ast, messageId: "missingHealthEndpoint", data: { endpoint } }); } } }); // Check for configureServer function if (!hasConfigureServer) { context.report({ node: context.getSourceCode().ast, messageId: "missingConfigureServer" }); } // Check for middlewares if (!hasMiddlewares) { context.report({ node: context.getSourceCode().ast, messageId: "missingMiddlewares" }); } } }; } }; export default { rules: { "enforce-vite-health-metrics": enforceViteHealthMetricsRule, }, };