counterfact
Version:
Generate a TypeScript-based mock server from an OpenAPI spec in seconds — with stateful routes, hot reload, and REPL support.
90 lines (89 loc) • 2.75 kB
JavaScript
function xmlEscape(xmlString) {
return xmlString.replace(/["&'<>]/gu, (character) => {
switch (character) {
case "<": {
return "<";
}
case ">": {
return ">";
}
case "&": {
return "&";
}
case "'": {
return "'";
}
case '"': {
return """;
}
default: {
return character;
}
}
});
}
function resolveNodeType(schema) {
if (schema?.xml?.nodeType !== undefined) {
return schema.xml.nodeType;
}
if (schema?.xml?.attribute || schema?.attribute) {
return "attribute";
}
return "element";
}
function objectToXml(json, schema, name) {
const xml = [];
const attributes = [];
Object.entries(json).forEach(([key, value]) => {
const properties = schema?.properties?.[key];
const nodeType = resolveNodeType(properties);
const xmlName = properties?.xml?.name ?? key;
switch (nodeType) {
case "attribute": {
attributes.push(` ${xmlName}="${xmlEscape(String(value))}"`);
break;
}
case "text": {
xml.push(xmlEscape(String(value)));
break;
}
case "cdata": {
xml.push(`<![CDATA[${String(value)}]]>`);
break;
}
case "none": {
break;
}
default: {
xml.push(jsonToXml(value, properties, key));
}
}
});
return `<${name}${attributes.join("")}>${xml.join("")}</${name}>`;
}
/**
* Converts a JSON value to an XML string using optional OpenAPI `xml` schema
* hints (element names, attributes, wrapping).
*
* @param json - The value to serialise.
* @param schema - Optional JSON Schema with an `xml` hint block.
* @param keyName - Fallback XML element name when the schema does not provide
* one. Defaults to `"root"`.
* @returns A well-formed XML string.
*/
export function jsonToXml(json, schema, keyName = "root") {
const name = schema?.xml?.name ?? keyName;
if (Array.isArray(json)) {
const items = json
.map((item) => jsonToXml(item, schema?.items, name))
.join("");
if (schema?.xml?.wrapped || schema?.xml?.nodeType === "element") {
return `<${name}>${items}</${name}>`;
}
return items;
}
if (typeof json === "object" && json !== null) {
return objectToXml(json, schema, name);
}
return `<${name}>${xmlEscape(String(json))}</${name}>`;
}