import { isBigint, isDate, isInfinite, isMap, isNaNValue, isRegExp, isSet, isUndefined, isSymbol, isArray, isError, isTypedArray, isURL, } from './is.js'; import { findArr } from './util.js'; function simpleTransformation(isApplicable, annotation, transform, untransform) { return { isApplicable, annotation, transform, untransform, }; } const simpleRules = [ simpleTransformation(isUndefined, 'undefined', () => null, () => undefined), simpleTransformation(isBigint, 'bigint', v => v.toString(), v => { if (typeof BigInt !== 'undefined') { return BigInt(v); } console.error('Please add a BigInt polyfill.'); return v; }), simpleTransformation(isDate, 'Date', v => v.toISOString(), v => new Date(v)), simpleTransformation(isError, 'Error', (v, superJson) => { const baseError = { name: v.name, message: v.message, }; superJson.allowedErrorProps.forEach(prop => { baseError[prop] = v[prop]; }); return baseError; }, (v, superJson) => { const e = new Error(v.message); e.name = v.name; e.stack = v.stack; superJson.allowedErrorProps.forEach(prop => { e[prop] = v[prop]; }); return e; }), simpleTransformation(isRegExp, 'regexp', v => '' + v, regex => { const body = regex.slice(1, regex.lastIndexOf('/')); const flags = regex.slice(regex.lastIndexOf('/') + 1); return new RegExp(body, flags); }), simpleTransformation(isSet, 'set', // (sets only exist in es6+) // eslint-disable-next-line es5/no-es6-methods v => [...v.values()], v => new Set(v)), simpleTransformation(isMap, 'map', v => [...v.entries()], v => new Map(v)), simpleTransformation((v) => isNaNValue(v) || isInfinite(v), 'number', v => { if (isNaNValue(v)) { return 'NaN'; } if (v > 0) { return 'Infinity'; } else { return '-Infinity'; } }, Number), simpleTransformation((v) => v === 0 && 1 / v === -Infinity, 'number', () => { return '-0'; }, Number), simpleTransformation(isURL, 'URL', v => v.toString(), v => new URL(v)), ]; function compositeTransformation(isApplicable, annotation, transform, untransform) { return { isApplicable, annotation, transform, untransform, }; } const symbolRule = compositeTransformation((s, superJson) => { if (isSymbol(s)) { const isRegistered = !!superJson.symbolRegistry.getIdentifier(s); return isRegistered; } return false; }, (s, superJson) => { const identifier = superJson.symbolRegistry.getIdentifier(s); return ['symbol', identifier]; }, v => v.description, (_, a, superJson) => { const value = superJson.symbolRegistry.getValue(a[1]); if (!value) { throw new Error('Trying to deserialize unknown symbol'); } return value; }); const constructorToName = [ Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array, Uint8ClampedArray, ].reduce((obj, ctor) => { obj[ctor.name] = ctor; return obj; }, {}); const typedArrayRule = compositeTransformation(isTypedArray, v => ['typed-array', v.constructor.name], v => [...v], (v, a) => { const ctor = constructorToName[a[1]]; if (!ctor) { throw new Error('Trying to deserialize unknown typed array'); } return new ctor(v); }); export function isInstanceOfRegisteredClass(potentialClass, superJson) { if (potentialClass?.constructor) { const isRegistered = !!superJson.classRegistry.getIdentifier(potentialClass.constructor); return isRegistered; } return false; } const classRule = compositeTransformation(isInstanceOfRegisteredClass, (clazz, superJson) => { const identifier = superJson.classRegistry.getIdentifier(clazz.constructor); return ['class', identifier]; }, (clazz, superJson) => { const allowedProps = superJson.classRegistry.getAllowedProps(clazz.constructor); if (!allowedProps) { return { ...clazz }; } const result = {}; allowedProps.forEach(prop => { result[prop] = clazz[prop]; }); return result; }, (v, a, superJson) => { const clazz = superJson.classRegistry.getValue(a[1]); if (!clazz) { throw new Error(`Trying to deserialize unknown class '${a[1]}' - check https://github.com/blitz-js/superjson/issues/116#issuecomment-773996564`); } return Object.assign(Object.create(clazz.prototype), v); }); const customRule = compositeTransformation((value, superJson) => { return !!superJson.customTransformerRegistry.findApplicable(value); }, (value, superJson) => { const transformer = superJson.customTransformerRegistry.findApplicable(value); return ['custom', transformer.name]; }, (value, superJson) => { const transformer = superJson.customTransformerRegistry.findApplicable(value); return transformer.serialize(value); }, (v, a, superJson) => { const transformer = superJson.customTransformerRegistry.findByName(a[1]); if (!transformer) { throw new Error('Trying to deserialize unknown custom value'); } return transformer.deserialize(v); }); const compositeRules = [classRule, symbolRule, customRule, typedArrayRule]; export const transformValue = (value, superJson) => { const applicableCompositeRule = findArr(compositeRules, rule => rule.isApplicable(value, superJson)); if (applicableCompositeRule) { return { value: applicableCompositeRule.transform(value, superJson), type: applicableCompositeRule.annotation(value, superJson), }; } const applicableSimpleRule = findArr(simpleRules, rule => rule.isApplicable(value, superJson)); if (applicableSimpleRule) { return { value: applicableSimpleRule.transform(value, superJson), type: applicableSimpleRule.annotation, }; } return undefined; }; const simpleRulesByAnnotation = {}; simpleRules.forEach(rule => { simpleRulesByAnnotation[rule.annotation] = rule; }); export const untransformValue = (json, type, superJson) => { if (isArray(type)) { switch (type[0]) { case 'symbol': return symbolRule.untransform(json, type, superJson); case 'class': return classRule.untransform(json, type, superJson); case 'custom': return customRule.untransform(json, type, superJson); case 'typed-array': return typedArrayRule.untransform(json, type, superJson); default: throw new Error('Unknown transformation: ' + type); } } else { const transformation = simpleRulesByAnnotation[type]; if (!transformation) { throw new Error('Unknown transformation: ' + type); } return transformation.untransform(json, superJson); } }; //# sourceMappingURL=transformer.js.map