[6a3a178] | 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;
|
---|