#!/usr/bin/env node /** Validates payment MVP routes and module files exist */ import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; const ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), ".."); const APP = path.join(ROOT, "app", "payment"); const MODULE = path.join(ROOT, "modules", "payment"); const MAX_LINES = 25; let errors = []; const MVP_ROUTES = [ "hub", "dashboard", "overview", "kpis", "transactions", "ledger", "psp", "psp/health", "providers", "merchants", "merchants/approvals", "requests", "callbacks", "verification", "audit", "bundles", "feature-toggles", "capabilities", "settings", "metrics", "monitoring", "api-explorer", "openapi", ]; const FEATURE_FILES = [ "hub.tsx", "dashboard.tsx", "overview.tsx", "kpis.tsx", "transactions.tsx", "transactionDetail.tsx", "ledger.tsx", "psp.tsx", "gatewayHealth.tsx", "providers.tsx", "merchants.tsx", "merchantDetail.tsx", "merchantApprovals.tsx", "requests.tsx", "requestDetail.tsx", "callbacks.tsx", "verification.tsx", "audit.tsx", "bundles.tsx", "featureToggles.tsx", "capabilities.tsx", "settings.tsx", "metrics.tsx", "monitoring.tsx", "apiExplorer.tsx", "openapi.tsx", ]; const REQUIRED_FILES = [ path.join(MODULE, "index.ts"), path.join(MODULE, "services", "payment-api.ts"), path.join(ROOT, "app", "api", "payment", "[...path]", "route.ts"), path.join(APP, "layout.tsx"), path.join(APP, "page.tsx"), ]; function walkPages(dir) { for (const ent of fs.readdirSync(dir, { withFileTypes: true })) { const p = path.join(dir, ent.name); if (ent.isDirectory()) walkPages(p); else if (ent.name === "page.tsx") checkPage(p); } } function checkPage(file) { const rel = path.relative(APP, file); const content = fs.readFileSync(file, "utf8"); const lines = content.split("\n").length; if (rel !== "page.tsx" && lines > MAX_LINES) { errors.push(`${rel}: ${lines} lines (max ${MAX_LINES})`); } if (rel !== "page.tsx" && !content.includes("@/modules/payment/")) { errors.push(`${rel}: must import from @/modules/payment/`); } } for (const route of MVP_ROUTES) { for (const file of ["page.tsx", "loading.tsx", "error.tsx"]) { const p = path.join(APP, route, file); if (!fs.existsSync(p)) errors.push(`missing app/payment/${route}/${file}`); } } for (const f of FEATURE_FILES) { const p = path.join(MODULE, "features", f); if (!fs.existsSync(p)) errors.push(`missing modules/payment/features/${f}`); } for (const f of REQUIRED_FILES) { if (!fs.existsSync(f)) errors.push(`missing ${path.relative(ROOT, f)}`); } if (fs.existsSync(APP)) walkPages(APP); else errors.push("app/payment not found"); if (errors.length) { console.error("Payment route validation failed:\n" + errors.map((e) => " - " + e).join("\n")); process.exit(1); } console.log(`Payment routes OK (${MVP_ROUTES.length} MVP routes, ${FEATURE_FILES.length} features)`);