all files / oja-next/ context.js

100% Statements 26/26
100% Branches 8/8
100% Functions 3/3
100% Lines 24/24
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 521×   1×                   8× 8× 8× 5× 5× 5× 14× 14×           14× 14× 13× 9× 9× 7×     6× 1× 1×     8×     14×   17× 17×           8×  
const util = require('util');
 
const Flow = require('.').Flow;
 
/**
 * Options can be used to define mock or custom context methods or values
 * The function must be of the following signature "context => (args) => value",
 * which is function factory with injected context that will be created by
 * runtime and passed to every factory function before execution of the returned function instance
 */
class Context extends Flow {
    constructor({ functions = {}, properties = {} }) {
        super();
        Object.assign(this, properties);
        Object.keys(functions).forEach(domainName => {
            const domainFunctions = functions[domainName];
            this[domainName] = {};
            Object.keys(domainFunctions).forEach(name => {
                const act = domainFunctions[name];
                this.create(domainName, name, act);
            });
        });
    }
 
    create(domainName, name, act) {
        let resolvedAct;
        const resolveAct = () => {
            if (act instanceof Function) {
                act = act(this);
                if (act instanceof Function) {
                    return act;
                }
            }
            if (act instanceof Error) {
                return () => {
                    throw act;
                };
            }
            return () => act;
        };
 
        Object.defineProperty(this[domainName], name, {
            get() {
                resolvedAct = resolvedAct !== undefined ? resolvedAct : resolveAct();
                return resolvedAct;
            }
        });
    }
}
 
module.exports = (options = {}) => new Context(options);