UNPKG

@phnq/message

Version:

Asynchronous, incremental messaging client and server

59 lines (58 loc) 2.04 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.deserialize = exports.serialize = exports.deannotate = exports.annotate = void 0; /** * Although it may be tempting to no-op this and let `JSON.stringify` serialize * dates to ISO 8601 strings, this is not a good idea. The reason is that a * string that happens to be an ISO 8601 date string when serialized will be * deserialized as a Date object. This could have implications during message * signing and verification. * * { * str: "2025-03-22T11:53:26.424" * } * * will have the `str` deserialized as a Date object. But when verifying the message, * which involves using `JSON.stringify`, it will be serialized as: * { * str: "2025-03-22T11:53:26.424Z" * } * * The additional `Z` at the end of the string will cause the hash to be different * and the verification to fail. */ const annotate = (val) => { if (val instanceof Array) { const arr = val; return arr.map(exports.annotate); } if (val instanceof Date) { const date = val; return `${date.toISOString()}@@@D`; } if (val && typeof val === 'object') { return Object.fromEntries(Object.entries(val).map(([k, v]) => [k, (0, exports.annotate)(v)])); } return val; }; exports.annotate = annotate; const DATE_RE = /^(.+)@@@D$/; const deannotate = (val) => { if (val instanceof Array) { const arr = val; return arr.map(exports.deannotate); } const dateM = typeof val === 'string' ? DATE_RE.exec(val) : undefined; if (dateM) { return new Date(dateM[1]); } if (val && typeof val === 'object') { return Object.fromEntries(Object.entries(val).map(([k, v]) => [k, (0, exports.deannotate)(v)])); } return val; }; exports.deannotate = deannotate; const serialize = (val) => JSON.stringify((0, exports.annotate)(val)); exports.serialize = serialize; const deserialize = (str) => (0, exports.deannotate)(JSON.parse(str)); exports.deserialize = deserialize;