UNPKG

@nasriya/atomix

Version:

Composable helper functions for building reliable systems

132 lines (131 loc) 4.89 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const valueIs_1 = __importDefault(require("../../valueIs")); class BodyCodec { #_helpers = { serialize: (value) => { if (value === null) return { type: 'null' }; if (value === undefined) return { type: 'undefined' }; const type = (() => { const type = typeof value; if (type === 'object') { if (valueIs_1.default.record(value)) { return 'record'; } if (valueIs_1.default.array(value)) { return 'array'; } if (value instanceof Set) { return 'set'; } if (value instanceof Map) { return 'map'; } if (value instanceof Date) { return 'date'; } } return type; })(); if (type === 'string' || type === 'number' || type === 'boolean') { return { value, type }; } if (type === 'function') { throw new TypeError('Functions cannot be encoded for transport'); } if (type === 'record' || type === 'array') { try { this.#_helpers.stringify(value); // just to detect circular return { value, type }; } catch { throw new TypeError('Object is not serializable (circular reference)'); } } if (type === 'date') { return { value: value.toISOString(), type }; } if (type === 'set') { const array = Array.from(value); this.#_helpers.stringify(array); // just to detect circular return { value: array, type }; } if (type === 'map') { const array = Array.from(value.entries()); this.#_helpers.stringify(array); // just to detect circular return { value: array, type }; } throw new TypeError(`Unsupported value type: ${type}`); }, deserialize: (payload) => { switch (payload.type) { case 'map': { return new Map(payload.value); } case 'set': { return new Set(payload.value); } case 'date': { return new Date(payload.value); } case 'null': { return null; } case 'undefined': { return undefined; } default: { return payload.value; } } }, stringify: (value, seen = new WeakSet()) => { return JSON.stringify(value, (key, val) => { if (typeof val === 'object' && val !== null) { if (seen.has(val)) throw new Error('Circular'); seen.add(val); } return val; }); } }; /** * Encodes the given value into a Buffer, which can be sent over the wire. * * The value is first serialized into a JSON-serializable payload, and then * that payload is stringified into a JSON string. The resulting string is * then encoded into a Buffer using the UTF8 encoding. * * @param value - The value to encode. * @returns The encoded Buffer. * @throws TypeError if the value cannot be serialized. * @since v1.0.2 */ encode(value) { const payload = this.#_helpers.serialize(value); const stringified = this.#_helpers.stringify(payload); return Buffer.from(stringified); } /** * Decodes the given Buffer into its original value. The buffer is expected to * contain a stringified JSON representation of an encoded payload. * * @param buffer - The buffer containing the encoded data. * @returns The original value, deserialized from the encoded payload. * @throws SyntaxError if the buffer content is not valid JSON. * @since v1.0.2 */ decode(buffer) { const stringified = buffer.toString(); const payload = JSON.parse(stringified); return this.#_helpers.deserialize(payload); } } const bodyCodec = new BodyCodec(); exports.default = bodyCodec;