| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-24 06:51:49 +08:00
										 |  |  | const memorize = require("../util/memorize"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const LAZY_TARGET = Symbol("lazy serialization target"); | 
					
						
							|  |  |  | const LAZY_SERIALIZED_VALUE = Symbol("lazy serialization data"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-24 23:51:05 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @template DeserializedType | 
					
						
							|  |  |  |  * @template SerializedType | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | class SerializerMiddleware { | 
					
						
							| 
									
										
										
										
											2020-04-16 15:37:11 +08:00
										 |  |  | 	/* istanbul ignore next */ | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2020-04-16 15:37:11 +08:00
										 |  |  | 	 * @abstract | 
					
						
							| 
									
										
										
										
											2019-01-24 23:51:05 +08:00
										 |  |  | 	 * @param {DeserializedType} data data | 
					
						
							|  |  |  | 	 * @param {Object} context context object | 
					
						
							|  |  |  | 	 * @returns {SerializedType|Promise<SerializedType>} serialized data | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 	 */ | 
					
						
							|  |  |  | 	serialize(data, context) { | 
					
						
							| 
									
										
										
										
											2020-04-16 15:37:11 +08:00
										 |  |  | 		const AbstractMethodError = require("../AbstractMethodError"); | 
					
						
							|  |  |  | 		throw new AbstractMethodError(); | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-16 15:37:11 +08:00
										 |  |  | 	/* istanbul ignore next */ | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2020-04-16 15:37:11 +08:00
										 |  |  | 	 * @abstract | 
					
						
							| 
									
										
										
										
											2019-01-24 23:51:05 +08:00
										 |  |  | 	 * @param {SerializedType} data data | 
					
						
							|  |  |  | 	 * @param {Object} context context object | 
					
						
							|  |  |  | 	 * @returns {DeserializedType|Promise<DeserializedType>} deserialized data | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 	 */ | 
					
						
							|  |  |  | 	deserialize(data, context) { | 
					
						
							| 
									
										
										
										
											2020-04-16 15:37:11 +08:00
										 |  |  | 		const AbstractMethodError = require("../AbstractMethodError"); | 
					
						
							|  |  |  | 		throw new AbstractMethodError(); | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-24 06:51:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * @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 = memorize(() => { | 
					
						
							|  |  |  | 			const r = lazy(); | 
					
						
							|  |  |  | 			if (r instanceof Promise) return r.then(data => data && serialize(data)); | 
					
						
							|  |  |  | 			if (r) return serialize(r); | 
					
						
							|  |  |  | 			return null; | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 		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 = memorize(() => { | 
					
						
							|  |  |  | 			const r = lazy(); | 
					
						
							|  |  |  | 			if (r instanceof Promise) 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; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = SerializerMiddleware; |