| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 | /*	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");/** @typedef {SerializerMiddleware<EXPECTED_ANY, EXPECTED_ANY, Record<string, EXPECTED_ANY>>} LazyTarget *//** @typedef {Record<string, EXPECTED_ANY>} LazyOptions *//** * @template InputValue * @template OutputValue * @template {LazyTarget} InternalLazyTarget * @template {LazyOptions | undefined} InternalLazyOptions * @typedef {(() => InputValue | Promise<InputValue>) & Partial<{ [LAZY_TARGET]: InternalLazyTarget, options: InternalLazyOptions, [LAZY_SERIALIZED_VALUE]?: OutputValue | LazyFunction<OutputValue, InputValue, InternalLazyTarget, InternalLazyOptions> | undefined }>} LazyFunction *//** * @template DeserializedType * @template SerializedType * @template Context */class SerializerMiddleware {	/* istanbul ignore next */	/**	 * @abstract	 * @param {DeserializedType} data data	 * @param {Context} context context object	 * @returns {SerializedType | Promise<SerializedType> | null} serialized data	 */	serialize(data, context) {		const AbstractMethodError = require("../AbstractMethodError");		throw new AbstractMethodError();	}	/* istanbul ignore next */	/**	 * @abstract	 * @param {SerializedType} data data	 * @param {Context} context context object	 * @returns {DeserializedType | Promise<DeserializedType>} deserialized data	 */	deserialize(data, context) {		const AbstractMethodError = require("../AbstractMethodError");		throw new AbstractMethodError();	}	/**	 * @template TLazyInputValue	 * @template TLazyOutputValue	 * @template {LazyTarget} TLazyTarget	 * @template {LazyOptions | undefined} TLazyOptions	 * @param {TLazyInputValue | (() => TLazyInputValue)} value contained value or function to value	 * @param {TLazyTarget} target target middleware	 * @param {TLazyOptions=} options lazy options	 * @param {TLazyOutputValue=} serializedValue serialized value	 * @returns {LazyFunction<TLazyInputValue, TLazyOutputValue, TLazyTarget, TLazyOptions>} lazy function	 */	static createLazy(		value,		target,		options = /** @type {TLazyOptions} */ ({}),		serializedValue = undefined	) {		if (SerializerMiddleware.isLazy(value, target)) return value;		const fn =			/** @type {LazyFunction<TLazyInputValue, TLazyOutputValue, TLazyTarget, TLazyOptions>} */			(typeof value === "function" ? value : () => value);		fn[LAZY_TARGET] = target;		fn.options = options;		fn[LAZY_SERIALIZED_VALUE] = serializedValue;		return fn;	}	/**	 * @template {LazyTarget} TLazyTarget	 * @param {EXPECTED_ANY} fn lazy function	 * @param {TLazyTarget=} target target middleware	 * @returns {fn is LazyFunction<EXPECTED_ANY, EXPECTED_ANY, TLazyTarget, EXPECTED_ANY>} 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 : Boolean(t);	}	/**	 * @template TLazyInputValue	 * @template TLazyOutputValue	 * @template {LazyTarget} TLazyTarget	 * @template {Record<string, EXPECTED_ANY>} TLazyOptions	 * @template TLazySerializedValue	 * @param {LazyFunction<TLazyInputValue, TLazyOutputValue, TLazyTarget, TLazyOptions>} fn lazy function	 * @returns {LazyOptions | undefined} options	 */	static getLazyOptions(fn) {		if (typeof fn !== "function") return;		return fn.options;	}	/**	 * @template TLazyInputValue	 * @template TLazyOutputValue	 * @template {LazyTarget} TLazyTarget	 * @template {LazyOptions} TLazyOptions	 * @param {LazyFunction<TLazyInputValue, TLazyOutputValue, TLazyTarget, TLazyOptions> | EXPECTED_ANY} fn lazy function	 * @returns {TLazyOutputValue | undefined} serialized value	 */	static getLazySerializedValue(fn) {		if (typeof fn !== "function") return;		return fn[LAZY_SERIALIZED_VALUE];	}	/**	 * @template TLazyInputValue	 * @template TLazyOutputValue	 * @template {LazyTarget} TLazyTarget	 * @template {LazyOptions} TLazyOptions	 * @param {LazyFunction<TLazyInputValue, TLazyOutputValue, LazyTarget, LazyOptions>} fn lazy function	 * @param {TLazyOutputValue} value serialized value	 * @returns {void}	 */	static setLazySerializedValue(fn, value) {		fn[LAZY_SERIALIZED_VALUE] = value;	}	/**	 * @template TLazyInputValue DeserializedValue	 * @template TLazyOutputValue SerializedValue	 * @template {LazyTarget} TLazyTarget	 * @template {LazyOptions | undefined} TLazyOptions	 * @param {LazyFunction<TLazyInputValue, TLazyOutputValue, TLazyTarget, TLazyOptions>} lazy lazy function	 * @param {(value: TLazyInputValue) => TLazyOutputValue} serialize serialize function	 * @returns {LazyFunction<TLazyOutputValue, TLazyInputValue, TLazyTarget, TLazyOptions>} new lazy	 */	static serializeLazy(lazy, serialize) {		const fn =			/** @type {LazyFunction<TLazyOutputValue, TLazyInputValue, TLazyTarget, TLazyOptions>} */			(				memoize(() => {					const r = lazy();					if (						r &&						typeof (/** @type {Promise<TLazyInputValue>} */ (r).then) ===							"function"					) {						return (							/** @type {Promise<TLazyInputValue>} */							(r).then(data => data && serialize(data))						);					}					return serialize(/** @type {TLazyInputValue} */ (r));				})			);		fn[LAZY_TARGET] = lazy[LAZY_TARGET];		fn.options = lazy.options;		lazy[LAZY_SERIALIZED_VALUE] = fn;		return fn;	}	/**	 * @template TLazyInputValue SerializedValue	 * @template TLazyOutputValue DeserializedValue	 * @template SerializedValue	 * @template {LazyTarget} TLazyTarget	 * @template {LazyOptions | undefined} TLazyOptions	 * @param {LazyFunction<TLazyInputValue, TLazyOutputValue, TLazyTarget, TLazyOptions>} lazy lazy function	 * @param {(data: TLazyInputValue) => TLazyOutputValue} deserialize deserialize function	 * @returns {LazyFunction<TLazyOutputValue, TLazyInputValue, TLazyTarget, TLazyOptions>} new lazy	 */	static deserializeLazy(lazy, deserialize) {		const fn =			/** @type {LazyFunction<TLazyOutputValue, TLazyInputValue, TLazyTarget, TLazyOptions>} */ (				memoize(() => {					const r = lazy();					if (						r &&						typeof (/** @type {Promise<TLazyInputValue>} */ (r).then) ===							"function"					) {						return (							/** @type {Promise<TLazyInputValue>} */							(r).then(data => deserialize(data))						);					}					return deserialize(/** @type {TLazyInputValue} */ (r));				})			);		fn[LAZY_TARGET] = lazy[LAZY_TARGET];		fn.options = lazy.options;		fn[LAZY_SERIALIZED_VALUE] = lazy;		return fn;	}	/**	 * @template TLazyInputValue	 * @template TLazyOutputValue	 * @template {LazyTarget} TLazyTarget	 * @template {LazyOptions} TLazyOptions	 * @param {LazyFunction<TLazyInputValue | TLazyOutputValue, TLazyInputValue | TLazyOutputValue, TLazyTarget, TLazyOptions> | undefined} lazy lazy function	 * @returns {LazyFunction<TLazyInputValue | TLazyOutputValue, TLazyInputValue | TLazyOutputValue, TLazyTarget, TLazyOptions> | undefined} new lazy	 */	static unMemoizeLazy(lazy) {		if (!SerializerMiddleware.isLazy(lazy)) return lazy;		/** @type {LazyFunction<TLazyInputValue | TLazyOutputValue, TLazyInputValue | TLazyOutputValue, TLazyTarget, TLazyOptions>} */		const fn = () => {			throw new Error(				"A lazy value that has been unmemorized can't be called again"			);		};		fn[LAZY_SERIALIZED_VALUE] = SerializerMiddleware.unMemoizeLazy(			/** @type {LazyFunction<TLazyInputValue | TLazyOutputValue, TLazyInputValue | TLazyOutputValue, TLazyTarget, TLazyOptions>} */			(lazy[LAZY_SERIALIZED_VALUE])		);		fn[LAZY_TARGET] = lazy[LAZY_TARGET];		fn.options = lazy.options;		return fn;	}}module.exports = SerializerMiddleware;
 |