Skip to content
Snippets Groups Projects
Select Git revision
  • 70dba4b23957d2d0fd12cb35c430139ef8c24e61
  • main default protected
  • drip-server-timing
  • compress-middleware
  • v2.11.0
  • v2.10.0
  • v2.9.2
  • v2.9.1
  • v2.9.0
  • v2.8.0
  • v2.7.0
  • v2.6.0
  • v2.5.6
  • v2.5.5
  • v2.5.4
  • v2.5.3
  • v2.5.2
  • v2.5.1
  • v2.5.0
  • v2.4.2
  • v2.4.1
  • v2.4.0
  • v2.3.0
  • v2.2.2
24 results

assets.go

Blame
  • server.mjs 3.71 KiB
    /**
     * Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved.
     * Node module: @schukai/monster
     *
     * This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3).
     * The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html
     *
     * For those who do not wish to adhere to the AGPLv3, a commercial license is available.
     * Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms.
     * For more information about purchasing a commercial license, please contact schukai GmbH.
     *
     * SPDX-License-Identifier: AGPL-3.0
     */
    
    import { instanceSymbol } from "../../constants.mjs";
    import { isArray, isFunction, isObject } from "../../types/is.mjs";
    import { Datasource } from "../datasource.mjs";
    import { diff } from "../diff.mjs";
    import { Pathfinder } from "../pathfinder.mjs";
    import { Pipe } from "../pipe.mjs";
    
    export { Server };
    
    /**
     * @private
     * @type {symbol}
     */
    const serverVersionSymbol = Symbol("serverVersion");
    
    /**
     * Base class for all server data sources
     *
     * @license AGPLv3
     * @since 3.4.0
     * @copyright schukai GmbH
     * @memberOf Monster.Data.Datasource
     * @summary The Server class encapsulates the access to a server datasource
     */
    class Server extends Datasource {
    	/**
    	 * This method is called by the `instanceof` operator.
    	 * @returns {symbol}
    	 */
    	static get [instanceSymbol]() {
    		return Symbol.for("@schukai/monster/data/datasource/server");
    	}
    
    	/**
    	 * This prepares the data that comes from the server.
    	 * Should not be called directly.
    	 *
    	 * @private
    	 * @param {Object} payload
    	 * @returns {Object}
    	 */
    	transformServerPayload(payload) {
    		payload = doTransform.call(this, "read", payload);
    		this[serverVersionSymbol] = payload;
    
    		const dataPath = this.getOption("read.path");
    		if (dataPath) {
    			payload = new Pathfinder(payload).getVia(dataPath);
    		}
    
    		return payload;
    	}
    
    	/**
    	 * This prepares the data for writing and should not be called directly.
    	 *
    	 * @private
    	 * @param {Object} payload
    	 * @returns {Object}
    	 */
    	prepareServerPayload(payload) {
    		payload = doTransform.call(this, "write", payload);
    		payload = doDiff.call(this, payload);
    
    		const sheathingObject = this.getOption("write.sheathing.object");
    		const sheathingPath = this.getOption("write.sheathing.path");
    
    		if (sheathingObject && sheathingPath) {
    			const sub = payload;
    			payload = sheathingObject;
    			new Pathfinder(payload).setVia(sheathingPath, sub);
    		}
    
    		return payload;
    	}
    }
    
    /**
     *
     * @param obj
     * @returns {*}
     */
    function doDiff(obj) {
    	if (
    		this[serverVersionSymbol] === null ||
    		this[serverVersionSymbol] === undefined
    	) {
    		return obj;
    	}
    
    	const callback = this.getOption("write.partial.callback");
    	if (!isFunction(callback)) {
    		return obj;
    	}
    
    	const results = diff(this[serverVersionSymbol], obj);
    	if (!results) {
    		return obj;
    	}
    
    	obj = callback(obj, results);
    	this[serverVersionSymbol] = obj;
    
    	return obj;
    }
    
    /**
     * @private
     * @param {string} type
     * @param {Object} obj
     * @returns {Object}
     */
    function doTransform(type, obj) {
    	const transformation = this.getOption(`${type}.mapping.transformer`);
    	if (transformation !== undefined && transformation !== null) {
    		const pipe = new Pipe(transformation);
    		const callbacks = this.getOption(`${type}.mapping.callbacks`);
    
    		if (isArray(callbacks)) {
    			for (const callback of callbacks) {
    				if (typeof callback === "function") {
    					pipe.setCallback(callback);
    				}
    			}
    		}
    
    		if (isObject(callbacks)) {
    			for (const key in callbacks) {
    				if (
    					callbacks.hasOwnProperty(key) &&
    					typeof callbacks[key] === "function"
    				) {
    					pipe.setCallback(key, callbacks[key]);
    				}
    			}
    		}
    
    		obj = pipe.run(obj);
    	}
    
    	return obj;
    }