UNPKG

@loqate/compose

Version:

Loqate Compose SDK — high-level flows that compose base API clients into easy-to-use sessions.

145 lines (142 loc) 4.89 kB
//#region src/utils/handles.ts const DEFAULT_HELPERS = { upper: (s) => String(s).toUpperCase(), lower: (s) => String(s).toLowerCase(), truncate: (s, n = 0) => String(s).slice(0, Number(n) || 0), replace: (s, a, b) => String(s).split(a).join(b) }; const ESC = (s) => s.replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", "\"": "&quot;", "'": "&#39;" })[c]); const get = (obj, path) => { if (path === "this") return obj; if (path === "@index") return obj?.["@index"]; return path.split(".").reduce((acc, k) => acc == null ? void 0 : acc[k], obj); }; const applyPipes = (val, rawPipe, helpers) => { if (!rawPipe) return val; for (const seg of rawPipe.split("|").map((s) => s.trim()).filter(Boolean)) { const [name, ...args] = seg.split(/\s+/); const fn = helpers[name]; if (typeof fn === "function") val = fn(val, ...args.map((a) => isFinite(Number(a)) ? Number(a) : a)); } return val; }; function render(template, data, opts = {}) { const helpers = { ...DEFAULT_HELPERS, ...opts.helpers || {} }; const escapeHtml = opts.escapeHtml !== false; template = template.replace(/{{#each\s+([^}]+)}}([\s\S]*?){{\/each}}/g, (_m, path, body) => { const list = get(data, path) ?? []; if (!Array.isArray(list)) return ""; return list.map((item, i) => { return render(body, Object.assign(Object.create(data ?? null), item, { "@index": i, this: item }), opts); }).join(""); }); template = template.replace(/{{#if\s+([^}]+)}}([\s\S]*?){{\/if}}/g, (_m, condPath, body) => { const [truthy, falsy = ""] = String(body).split(/{{\s*else\s*}}/); return render(!!get(data, condPath) ? truthy : falsy, data, opts); }); template = template.replace(/{{{\s*([^}|]+)(\s*\|[^}]+)?\s*}}}/g, (_m, path, pipe) => { path = path.trim(); const val = applyPipes(get(data, path), pipe, helpers); return val == null ? "" : String(val); }); template = template.replace(/{{\s*([^}|]+)(\s*\|[^}]+)?\s*}}/g, (_m, path, pipe) => { path = path.trim(); const val = applyPipes(get(data, path), pipe, helpers); const s = val == null ? "" : String(val); return escapeHtml ? ESC(s) : s; }); return template; } //#endregion //#region src/utils/avc/parser.ts const VERIFICATION_STATUS_RANKING = { V: 5, P: 4, A: 3, R: 2, U: 1 }; const PARSING_STATUS_RANKING = { I: 2, U: 1 }; function parseAVC(code) { if (!code || typeof code !== "string") throw new Error("AVC code must be a non-empty string."); const upper = code.toUpperCase().trim(); const parts = upper.split("-"); if (parts.length !== 4) throw new Error("Invalid AVC format. Expected 4 parts."); const [part1, part2, postcodeStatus, matchscoreStr] = parts; const matchscore = numericOrThrow(matchscoreStr, "Matchscore"); const p1 = part1.split(""); if (p1.length !== 3) throw new Error("Invalid part1 format. Expected 3 characters."); const verificationStatus = p1[0]; const postMatchLevel = numericOrThrow(p1[1], "Post-Processed Verification Match Level"); const preMatchLevel = numericOrThrow(p1[2], "Pre-Processed Verification Match Level"); if (!(verificationStatus in VERIFICATION_STATUS_RANKING)) throw new Error(`Invalid Verification Status: ${verificationStatus}`); const p2 = part2.split(""); if (p2.length !== 3) throw new Error("Invalid part2 format. Expected 3 characters."); const parsingStatus = p2[0]; const lexiconIdentificationMatchLevel = numericOrThrow(p2[1], "Lexicon Identification Match Level"); const contextIdentificationMatchLevel = numericOrThrow(p2[2], "Context Identification Match Level"); if (!(parsingStatus in PARSING_STATUS_RANKING)) throw new Error(`Invalid Parsing Status: ${parsingStatus}`); return { code: upper, matchscore, verificationStatus, postMatchLevel, preMatchLevel, parsingStatus, lexiconIdentificationMatchLevel, contextIdentificationMatchLevel, postcodeStatus, postcodeStatusNumeric: postcodeStatusToNumeric(postcodeStatus) }; } function numericOrThrow(value, valueName) { const num = Number(value); if (isNaN(num)) throw new Error(`${valueName} must be numeric.`); return num; } function postcodeStatusToNumeric(value) { const chars = value.split(""); if (chars.length !== 2) throw new Error("Invalid Postcode Status format. Expected 2 characters."); return numericOrThrow(chars[1], "Postcode Status"); } //#endregion Object.defineProperty(exports, 'PARSING_STATUS_RANKING', { enumerable: true, get: function () { return PARSING_STATUS_RANKING; } }); Object.defineProperty(exports, 'VERIFICATION_STATUS_RANKING', { enumerable: true, get: function () { return VERIFICATION_STATUS_RANKING; } }); Object.defineProperty(exports, 'parseAVC', { enumerable: true, get: function () { return parseAVC; } }); Object.defineProperty(exports, 'render', { enumerable: true, get: function () { return render; } }); //# sourceMappingURL=parser-D7NErKda.cjs.map