#!/usr/bin/env node /** * RR smoke test / CLI (STAR-only) */ const path = require("path"); const fs = require("fs"); const dotenv = require("dotenv"); const { MakeRRCall, renderXmlTemplate, buildStarEnvelope } = require("./rr-helpers"); const { getBaseRRConfig } = require("./rr-constants"); // Load env file for local runs const defaultEnvPath = path.resolve(__dirname, "../../.env.development"); if (fs.existsSync(defaultEnvPath)) { const result = dotenv.config({ path: defaultEnvPath }); if (result?.parsed) { console.log( `${defaultEnvPath}\n[dotenv@${require("dotenv/package.json").version}] injecting env (${Object.keys(result.parsed).length}) from ../../.env.development` ); } } // Parse CLI args const argv = process.argv.slice(2); const args = { _: [] }; for (let i = 0; i < argv.length; i++) { const a = argv[i]; if (a.startsWith("--")) { const eq = a.indexOf("="); if (eq > -1) { const k = a.slice(2, eq); const v = a.slice(eq + 1); args[k] = v; } else { const k = a.slice(2); const next = argv[i + 1]; if (next && !next.startsWith("-")) { args[k] = next; i++; // consume value } else { args[k] = true; // boolean flag } } } else if (a.startsWith("-") && a.length > 1) { // simple short flag handling: -a value const k = a.slice(1); const next = argv[i + 1]; if (next && !next.startsWith("-")) { args[k] = next; i++; } else { args[k] = true; } } else { args._.push(a); } } function toIntOr(defaultVal, maybe) { const n = parseInt(maybe, 10); return Number.isFinite(n) ? n : defaultVal; } // āœ… fixed guard clause function pickActionName(raw) { if (!raw || typeof raw !== "string") return "ping"; const x = raw.toLowerCase(); if (x === "combined" || x === "combinedsearch" || x === "comb") return "combined"; if (x === "advisors" || x === "advisor" || x === "getadvisors") return "advisors"; if (x === "parts" || x === "getparts" || x === "part") return "parts"; if (x === "ping") return "ping"; return x; } function buildBodyForAction(action, args, cfg) { switch (action) { case "ping": case "advisors": { const max = toIntOr(1, args.max); const data = { DealerCode: cfg.dealerNumber, DealerNumber: cfg.dealerNumber, StoreNumber: cfg.storeNumber, BranchNumber: cfg.branchNumber, SearchCriteria: { AdvisorId: args.advisorId, FirstName: args.first || args.firstname, LastName: args.last || args.lastname, Department: args.department, Status: args.status || "ACTIVE", IncludeInactive: args.includeInactive ? "true" : undefined, MaxResults: max } }; return { template: "GetAdvisors", data, appArea: {} }; } case "combined": { const max = toIntOr(10, args.max); const data = { DealerNumber: cfg.dealerNumber, StoreNumber: cfg.storeNumber, BranchNumber: cfg.branchNumber, Customer: { FirstName: args.first, LastName: args.last, PhoneNumber: args.phone, EmailAddress: args.email }, Vehicle: { VIN: args.vin, LicensePlate: args.plate }, MaxResults: max }; return { template: "CombinedSearch", data, appArea: {} }; } case "parts": { const max = toIntOr(5, args.max); const data = { DealerNumber: cfg.dealerNumber, StoreNumber: cfg.storeNumber, BranchNumber: cfg.branchNumber, SearchCriteria: { PartNumber: args.part, Description: args.desc, Make: args.make, Model: args.model, Year: args.year, MaxResults: max } }; return { template: "GetParts", data, appArea: {} }; } default: throw new Error(`Unsupported action: ${action}`); } } async function main() { const action = pickActionName(args.action || args.a || args._[0]); const rrAction = action === "ping" ? "GetAdvisors" : action === "advisors" ? "GetAdvisors" : action === "combined" ? "CombinedSearch" : action === "parts" ? "GetParts" : action; const cfg = getBaseRRConfig(); const body = buildBodyForAction(action, args, cfg); const templateName = body.template || rrAction; try { const xml = await renderXmlTemplate(templateName, body.data); console.log("āœ… Templates verified."); } catch (e) { console.error("āŒ Template verification failed:", e.message); process.exit(1); } if (args.dry) { const business = await renderXmlTemplate(templateName, body.data); const envelope = await buildStarEnvelope(business, cfg, body.appArea); console.log("\n--- FULL SOAP ENVELOPE ---\n"); console.log(envelope); console.log("\n(dry run) 🚫 Skipping network call."); return; } try { console.log(`\nā–¶ Calling Rome action: ${rrAction}`); const xml = await MakeRRCall({ action: rrAction, body, dealerConfig: cfg }); console.log("\nāœ… RR call succeeded.\n"); console.log(xml); } catch (err) { console.dir(err); console.error("[RR] rr-test failed", { message: err.message, stack: err.stack }); process.exit(1); } } main().catch((e) => { process.exit(1); });