data/pipe.js

'use strict';

/**
 * @author schukai GmbH
 */

import {Monster} from '../namespace.js';
import {Transformer} from './transformer.js';
import {Base} from '../types/base.js';
import {validateString} from '../types/validate.js';


const DELIMITER = '|';

/**
 * Pipe class
 *
 * the pipe class makes it possible to combine several processing steps.
 *
 * you can call the method via the monster namespace `new Monster.Data.Pipe()`.
 *
 * ```
 * <script type="module">
 * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.5.0/dist/modules/data/pipe.js';
 * console.log(new Monster.Data.Pipe())
 * </script>
 * ```
 *
 * Alternatively, you can also integrate this function individually.
 *
 * ```
 * <script type="module">
 * import {Pipe} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.5.0/dist/modules/data/pipe.js';
 * console.log(new Pipe())
 * </script>
 * ```
 *
 * a pipe consists of commands whose input and output are connected with the pipe symbol `|`.
 *
 * with the Pipe, processing steps can be combined. Here, the value of an object is accessed via the pathfinder (path command).
 * the word is then converted to uppercase letters and a prefix Hello is added. the two backslash safe the space char.
 *
 * ```
 * let obj = {
 *     a: {
 *         b: {
 *             c: {
 *                 d: "world"
 *             }
 *         }
 *     }
 * }
 *
 * new Pipe('path:a.b.c.d | toupper | prefix:Hello\\ ').run(obj); // ↦ Hello WORLD
 * ```
 *
 * @since 1.5.0
 * @copyright schukai GmbH
 * @memberOf Monster/Data
 */
class Pipe extends Base {

    /**
     *
     * @param {string} pipe a pipe consists of commands whose input and output are connected with the pipe symbol `|`.
     * @throws {TypeError} 
     */
    constructor(pipe) {
        super();
        validateString(pipe);
        this.pipe = pipe.split(DELIMITER).map((v) => {
            return new Transformer(v);
        });

    }

    /**
     * run a pipe
     *
     * @param {*} value
     * @returns {*}
     */
    run(value) {
        return this.pipe.reduce((accumulator, currentValue, currentIndex, array) => {
            return currentValue.run(accumulator);
        }, value);
    }
}

Monster.assignToNamespace('Monster.Data', Pipe);
export {Monster, Pipe}