You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
153 lines
4.4 KiB
153 lines
4.4 KiB
/* |
|
MIT License http://www.opensource.org/licenses/mit-license.php |
|
*/ |
|
|
|
"use strict"; |
|
|
|
const memoize = require("../util/memoize"); |
|
|
|
const LAZY_TARGET = Symbol("lazy serialization target"); |
|
const LAZY_SERIALIZED_VALUE = Symbol("lazy serialization data"); |
|
|
|
/** |
|
* @template DeserializedType |
|
* @template SerializedType |
|
*/ |
|
class SerializerMiddleware { |
|
/* istanbul ignore next */ |
|
/** |
|
* @abstract |
|
* @param {DeserializedType} data data |
|
* @param {Object} context context object |
|
* @returns {SerializedType|Promise<SerializedType>} serialized data |
|
*/ |
|
serialize(data, context) { |
|
const AbstractMethodError = require("../AbstractMethodError"); |
|
throw new AbstractMethodError(); |
|
} |
|
|
|
/* istanbul ignore next */ |
|
/** |
|
* @abstract |
|
* @param {SerializedType} data data |
|
* @param {Object} context context object |
|
* @returns {DeserializedType|Promise<DeserializedType>} deserialized data |
|
*/ |
|
deserialize(data, context) { |
|
const AbstractMethodError = require("../AbstractMethodError"); |
|
throw new AbstractMethodError(); |
|
} |
|
|
|
/** |
|
* @param {any | function(): Promise<any> | any} value contained value or function to value |
|
* @param {SerializerMiddleware<any, any>} target target middleware |
|
* @param {object=} options lazy options |
|
* @param {any=} serializedValue serialized value |
|
* @returns {function(): Promise<any> | any} lazy function |
|
*/ |
|
static createLazy(value, target, options = {}, serializedValue) { |
|
if (SerializerMiddleware.isLazy(value, target)) return value; |
|
const fn = typeof value === "function" ? value : () => value; |
|
fn[LAZY_TARGET] = target; |
|
/** @type {any} */ (fn).options = options; |
|
fn[LAZY_SERIALIZED_VALUE] = serializedValue; |
|
return fn; |
|
} |
|
|
|
/** |
|
* @param {function(): Promise<any> | any} fn lazy function |
|
* @param {SerializerMiddleware<any, any>=} target target middleware |
|
* @returns {boolean} true, when fn is a lazy function (optionally of that target) |
|
*/ |
|
static isLazy(fn, target) { |
|
if (typeof fn !== "function") return false; |
|
const t = fn[LAZY_TARGET]; |
|
return target ? t === target : !!t; |
|
} |
|
|
|
/** |
|
* @param {function(): Promise<any> | any} fn lazy function |
|
* @returns {object} options |
|
*/ |
|
static getLazyOptions(fn) { |
|
if (typeof fn !== "function") return undefined; |
|
return /** @type {any} */ (fn).options; |
|
} |
|
|
|
/** |
|
* @param {function(): Promise<any> | any} fn lazy function |
|
* @returns {any} serialized value |
|
*/ |
|
static getLazySerializedValue(fn) { |
|
if (typeof fn !== "function") return undefined; |
|
return fn[LAZY_SERIALIZED_VALUE]; |
|
} |
|
|
|
/** |
|
* @param {function(): Promise<any> | any} fn lazy function |
|
* @param {any} value serialized value |
|
* @returns {void} |
|
*/ |
|
static setLazySerializedValue(fn, value) { |
|
fn[LAZY_SERIALIZED_VALUE] = value; |
|
} |
|
|
|
/** |
|
* @param {function(): Promise<any> | any} lazy lazy function |
|
* @param {function(any): Promise<any> | any} serialize serialize function |
|
* @returns {function(): Promise<any> | any} new lazy |
|
*/ |
|
static serializeLazy(lazy, serialize) { |
|
const fn = memoize(() => { |
|
const r = lazy(); |
|
if (r && typeof r.then === "function") { |
|
return r.then(data => data && serialize(data)); |
|
} |
|
return serialize(r); |
|
}); |
|
fn[LAZY_TARGET] = lazy[LAZY_TARGET]; |
|
/** @type {any} */ (fn).options = /** @type {any} */ (lazy).options; |
|
lazy[LAZY_SERIALIZED_VALUE] = fn; |
|
return fn; |
|
} |
|
|
|
/** |
|
* @param {function(): Promise<any> | any} lazy lazy function |
|
* @param {function(any): Promise<any> | any} deserialize deserialize function |
|
* @returns {function(): Promise<any> | any} new lazy |
|
*/ |
|
static deserializeLazy(lazy, deserialize) { |
|
const fn = memoize(() => { |
|
const r = lazy(); |
|
if (r && typeof r.then === "function") { |
|
return r.then(data => deserialize(data)); |
|
} |
|
return deserialize(r); |
|
}); |
|
fn[LAZY_TARGET] = lazy[LAZY_TARGET]; |
|
/** @type {any} */ (fn).options = /** @type {any} */ (lazy).options; |
|
fn[LAZY_SERIALIZED_VALUE] = lazy; |
|
return fn; |
|
} |
|
|
|
/** |
|
* @param {function(): Promise<any> | any} lazy lazy function |
|
* @returns {function(): Promise<any> | any} new lazy |
|
*/ |
|
static unMemoizeLazy(lazy) { |
|
if (!SerializerMiddleware.isLazy(lazy)) return lazy; |
|
const fn = () => { |
|
throw new Error( |
|
"A lazy value that has been unmemorized can't be called again" |
|
); |
|
}; |
|
fn[LAZY_SERIALIZED_VALUE] = SerializerMiddleware.unMemoizeLazy( |
|
lazy[LAZY_SERIALIZED_VALUE] |
|
); |
|
fn[LAZY_TARGET] = lazy[LAZY_TARGET]; |
|
fn.options = /** @type {any} */ (lazy).options; |
|
return fn; |
|
} |
|
} |
|
|
|
module.exports = SerializerMiddleware;
|
|
|