simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

SerializerMiddleware.js (4496B)


      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;