UNPKG

tupleson

Version:

A hackable JSON serializer/deserializer

86 lines 2.62 kB
import { TsonCircularReferenceError } from "../errors.js"; import { getDefaultNonce } from "../internals/getNonce.js"; import { mapOrReturn } from "../internals/mapOrReturn.js"; function getHandlers(opts) { const byPrimitive = {}; const nonPrimitives = []; for (const handler of opts.types) { if (handler.primitive) { if (byPrimitive[handler.primitive]) { throw new Error( `Multiple handlers for primitive ${handler.primitive} found` ); } byPrimitive[handler.primitive] = handler; } else { nonPrimitives.push(handler); } } const getNonce = opts.nonce ? opts.nonce : getDefaultNonce; return [getNonce, nonPrimitives, byPrimitive]; } function createTsonStringify(opts) { const serializer = createTsonSerialize(opts); return (obj, space) => JSON.stringify(serializer(obj), null, space); } function createTsonSerialize(opts) { const [getNonce, nonPrimitive, byPrimitive] = getHandlers(opts); const walker = (nonce) => { const seen = /* @__PURE__ */ new WeakSet(); const cache = /* @__PURE__ */ new WeakMap(); const walk = (value) => { const type = typeof value; const isComplex = !!value && type === "object"; if (isComplex) { if (seen.has(value)) { const cached = cache.get(value); if (!cached) { throw new TsonCircularReferenceError(value); } return cached; } seen.add(value); } const cacheAndReturn = (result) => { if (isComplex) { cache.set(value, result); } return result; }; const primitiveHandler = byPrimitive[type]; if (primitiveHandler && (!primitiveHandler.test || primitiveHandler.test(value))) { return cacheAndReturn([ primitiveHandler.key, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion walk(primitiveHandler.serialize(value)), nonce ]); } for (const handler of nonPrimitive) { if (handler.test(value)) { return cacheAndReturn([ handler.key, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion walk(handler.serialize(value)), nonce ]); } } return cacheAndReturn(mapOrReturn(value, walk)); }; return walk; }; return (obj) => { const nonce = getNonce(); const json = walker(nonce)(obj); return { json, nonce }; }; } export { createTsonSerialize, createTsonStringify }; //# sourceMappingURL=serialize.mjs.map