SerializerMiddleware.js (4496B)
1 /* 2 MIT License http://www.opensource.org/licenses/mit-license.php 3 */ 4 5 "use strict"; 6 7 const memoize = require("../util/memoize"); 8 9 const LAZY_TARGET = Symbol("lazy serialization target"); 10 const LAZY_SERIALIZED_VALUE = Symbol("lazy serialization data"); 11 12 /** 13 * @template DeserializedType 14 * @template SerializedType 15 */ 16 class SerializerMiddleware { 17 /* istanbul ignore next */ 18 /** 19 * @abstract 20 * @param {DeserializedType} data data 21 * @param {Object} context context object 22 * @returns {SerializedType|Promise<SerializedType>} serialized data 23 */ 24 serialize(data, context) { 25 const AbstractMethodError = require("../AbstractMethodError"); 26 throw new AbstractMethodError(); 27 } 28 29 /* istanbul ignore next */ 30 /** 31 * @abstract 32 * @param {SerializedType} data data 33 * @param {Object} context context object 34 * @returns {DeserializedType|Promise<DeserializedType>} deserialized data 35 */ 36 deserialize(data, context) { 37 const AbstractMethodError = require("../AbstractMethodError"); 38 throw new AbstractMethodError(); 39 } 40 41 /** 42 * @param {any | function(): Promise<any> | any} value contained value or function to value 43 * @param {SerializerMiddleware<any, any>} target target middleware 44 * @param {object=} options lazy options 45 * @param {any=} serializedValue serialized value 46 * @returns {function(): Promise<any> | any} lazy function 47 */ 48 static createLazy(value, target, options = {}, serializedValue) { 49 if (SerializerMiddleware.isLazy(value, target)) return value; 50 const fn = typeof value === "function" ? value : () => value; 51 fn[LAZY_TARGET] = target; 52 /** @type {any} */ (fn).options = options; 53 fn[LAZY_SERIALIZED_VALUE] = serializedValue; 54 return fn; 55 } 56 57 /** 58 * @param {function(): Promise<any> | any} fn lazy function 59 * @param {SerializerMiddleware<any, any>=} target target middleware 60 * @returns {boolean} true, when fn is a lazy function (optionally of that target) 61 */ 62 static isLazy(fn, target) { 63 if (typeof fn !== "function") return false; 64 const t = fn[LAZY_TARGET]; 65 return target ? t === target : !!t; 66 } 67 68 /** 69 * @param {function(): Promise<any> | any} fn lazy function 70 * @returns {object} options 71 */ 72 static getLazyOptions(fn) { 73 if (typeof fn !== "function") return undefined; 74 return /** @type {any} */ (fn).options; 75 } 76 77 /** 78 * @param {function(): Promise<any> | any} fn lazy function 79 * @returns {any} serialized value 80 */ 81 static getLazySerializedValue(fn) { 82 if (typeof fn !== "function") return undefined; 83 return fn[LAZY_SERIALIZED_VALUE]; 84 } 85 86 /** 87 * @param {function(): Promise<any> | any} fn lazy function 88 * @param {any} value serialized value 89 * @returns {void} 90 */ 91 static setLazySerializedValue(fn, value) { 92 fn[LAZY_SERIALIZED_VALUE] = value; 93 } 94 95 /** 96 * @param {function(): Promise<any> | any} lazy lazy function 97 * @param {function(any): Promise<any> | any} serialize serialize function 98 * @returns {function(): Promise<any> | any} new lazy 99 */ 100 static serializeLazy(lazy, serialize) { 101 const fn = memoize(() => { 102 const r = lazy(); 103 if (r && typeof r.then === "function") { 104 return r.then(data => data && serialize(data)); 105 } 106 return serialize(r); 107 }); 108 fn[LAZY_TARGET] = lazy[LAZY_TARGET]; 109 /** @type {any} */ (fn).options = /** @type {any} */ (lazy).options; 110 lazy[LAZY_SERIALIZED_VALUE] = fn; 111 return fn; 112 } 113 114 /** 115 * @param {function(): Promise<any> | any} lazy lazy function 116 * @param {function(any): Promise<any> | any} deserialize deserialize function 117 * @returns {function(): Promise<any> | any} new lazy 118 */ 119 static deserializeLazy(lazy, deserialize) { 120 const fn = memoize(() => { 121 const r = lazy(); 122 if (r && typeof r.then === "function") { 123 return r.then(data => deserialize(data)); 124 } 125 return deserialize(r); 126 }); 127 fn[LAZY_TARGET] = lazy[LAZY_TARGET]; 128 /** @type {any} */ (fn).options = /** @type {any} */ (lazy).options; 129 fn[LAZY_SERIALIZED_VALUE] = lazy; 130 return fn; 131 } 132 133 /** 134 * @param {function(): Promise<any> | any} lazy lazy function 135 * @returns {function(): Promise<any> | any} new lazy 136 */ 137 static unMemoizeLazy(lazy) { 138 if (!SerializerMiddleware.isLazy(lazy)) return lazy; 139 const fn = () => { 140 throw new Error( 141 "A lazy value that has been unmemorized can't be called again" 142 ); 143 }; 144 fn[LAZY_SERIALIZED_VALUE] = SerializerMiddleware.unMemoizeLazy( 145 lazy[LAZY_SERIALIZED_VALUE] 146 ); 147 fn[LAZY_TARGET] = lazy[LAZY_TARGET]; 148 fn.options = /** @type {any} */ (lazy).options; 149 return fn; 150 } 151 } 152 153 module.exports = SerializerMiddleware;