) and per cause (#detail-).
// The JSON is the contract; this page is a reading of it and is regenerated, never edited.
// The contracts test fails when the two disagree.
//
// node contracts/generate-reason-codes-html.mjs
import { readFile, writeFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
const escape = (text) => String(text ?? '').replace(/[&<>"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[c]);
const code = (text) => `${escape(text)}`;
export function renderReasonCodes(contract) {
const seen = new Set();
// The first place a code appears carries its anchor; a code listed under two checks is one address.
const anchor = (name) => (seen.has(name) ? '' : (seen.add(name), ` id="${escape(name)}"`));
const row = (name, status, note) => `${code(name)} ${escape(status ?? '')} ${escape(note)} `;
const table = (rows) => `Code HTTP What it means ${rows.join('')}
`;
const plain = (section) => Object.entries(section).filter(([k]) => k !== '$comment').map(([name, note]) => row(name, '', note));
const steps = Object.entries(contract.steps).map(([n, step]) => `Check ${escape(n)}: ${escape(step.name)}
${step.entry ? 'Writes a signed request.refused entry.' : 'Writes no entry; counted.'}
${table(Object.entries(step.codes).map(([name, c]) => row(name, c.status, `${c.legacy ? '(legacy) ' : ''}${c.note ?? ''}`)))}`);
const details = Object.entries(contract.details ?? {}).filter(([k]) => k !== '$comment').map(([name, d]) => `${code(name)} ${d.code.includes(' ') ? escape(d.code) : `${code(d.code)}`} ${escape(d.text)} `);
return `
Reason codes
Reason codes
Generated from reason-codes.json, which is the contract. ${escape(contract.$comment)}
Causes
${escape(contract.details?.$comment ?? '')}
Cause Code What failed ${details.join('')}
By check
${steps.join('\n')}
Other seller codes
${table(plain(contract.other_seller_codes))}
Buyer side
${escape(contract.buyer_side.$comment)}
${table(plain(contract.buyer_side))}
Authority side
${escape(contract.authority_side.$comment)}
${table(plain(contract.authority_side))}
`;
}
if (process.argv[1] === fileURLToPath(import.meta.url)) {
const contract = JSON.parse(await readFile(new URL('./reason-codes.json', import.meta.url), 'utf8'));
await writeFile(new URL('./reason-codes.html', import.meta.url), renderReasonCodes(contract));
}