TorbatYar/frontend/scripts/validate-payment-routes.mjs
Mortezakoohjani 4451b32a33 feat(payment-frontend): ship Torbat Pay admin portal for MVP 14.0-14.5
Add payment module, BFF proxy, hub/dashboard/ops/PSP/merchant screens wired to real APIs, and mark payment-frontend complete in project status.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-27 18:35:07 +03:30

120 lines
3.1 KiB
JavaScript

#!/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)`);