Files
bodyshop/server/rr/rr-wsdl.js

124 lines
3.4 KiB
JavaScript

/**
* @file rr-wsdl.js
* @description Lightweight service description + utilities for the Rome (R&R) SOAP actions.
* - Maps actions to SOAPAction headers (from rr-constants)
* - Maps actions to Mustache template filenames (xml-templates/*.xml)
* - Provides verification helpers to ensure templates exist
* - Provides normalized SOAP headers used by the transport
*/
const path = require("path");
const fs = require("fs/promises");
const { RR_ACTIONS, RR_SOAP_HEADERS } = require("./rr-constants");
// ---- Action <-> Template wiring ----
// Keep action names consistent with rr-helpers / rr-lookup / rr-repair-orders / rr-customer
const ACTION_TEMPLATES = Object.freeze({
InsertCustomer: "InsertCustomer",
UpdateCustomer: "UpdateCustomer",
InsertServiceVehicle: "InsertServiceVehicle",
CreateRepairOrder: "CreateRepairOrder",
UpdateRepairOrder: "UpdateRepairOrder",
GetAdvisors: "GetAdvisors",
GetParts: "GetParts",
CombinedSearch: "CombinedSearch"
});
/**
* Get the SOAPAction string for a known action.
* Throws if action is unknown.
*/
function getSoapAction(action) {
const entry = RR_ACTIONS[action];
if (!entry) {
const known = Object.keys(RR_ACTIONS).join(", ");
throw new Error(`Unknown RR action "${action}". Known: ${known}`);
}
return entry.soapAction;
}
/**
* Get the template filename (without extension) for a known action.
* e.g., "CreateRepairOrder" -> "CreateRepairOrder"
*/
function getTemplateForAction(action) {
const tpl = ACTION_TEMPLATES[action];
if (!tpl) {
const known = Object.keys(ACTION_TEMPLATES).join(", ");
throw new Error(`No template mapping for RR action "${action}". Known: ${known}`);
}
return tpl;
}
/**
* Build headers for a SOAP request, including SOAPAction.
* Consumers: rr-helpers (transport).
*/
function buildSoapHeadersForAction(action) {
return {
...RR_SOAP_HEADERS,
SOAPAction: getSoapAction(action)
};
}
/**
* List all known actions with their SOAPAction + template.
* Useful for diagnostics (e.g., /rr/actions route).
*/
function listActions() {
return Object.keys(ACTION_TEMPLATES).map((action) => ({
action,
soapAction: getSoapAction(action),
template: getTemplateForAction(action)
}));
}
/**
* Verify that every required template exists in xml-templates/.
* Returns an array of issues; empty array means all good.
*/
async function verifyTemplatesExist() {
const issues = [];
const baseDir = path.join(__dirname, "xml-templates");
for (const [action, tpl] of Object.entries(ACTION_TEMPLATES)) {
const filePath = path.join(baseDir, `${tpl}.xml`);
try {
const stat = await fs.stat(filePath);
if (!stat.isFile()) {
issues.push({ action, template: tpl, error: "Not a regular file" });
}
} catch {
issues.push({ action, template: tpl, error: `Missing file: ${filePath}` });
}
}
return issues;
}
/**
* Quick assert that throws if any template is missing.
* You can call this once during boot and log the result.
*/
async function assertTemplates() {
const issues = await verifyTemplatesExist();
if (issues.length) {
const msg =
"RR xml-templates verification failed:\n" +
issues.map((i) => ` - ${i.action} -> ${i.template}.xml :: ${i.error}`).join("\n");
throw new Error(msg);
}
}
module.exports = {
// Maps / helpers
ACTION_TEMPLATES,
listActions,
getSoapAction,
getTemplateForAction,
buildSoapHeadersForAction,
// Verification
verifyTemplatesExist,
assertTemplates
};