You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			154 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			JavaScript
		
	
		
		
			
		
	
	
			154 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			JavaScript
		
	
| 
											9 months ago
										 | /* | ||
|  | 	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; |