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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122 | 5x
5x
5x
5x
5x
74x
73x
73x
62x
1x
1x
1x
61x
73x
73x
73x
73x
2x
1x
1x
1x
1x
73x
73x
1x
1x
1x
3x
5x
3x
1x
4x
7x
2x
2x
2x
1x
4x
1x
3x
3x
1x
2x
5x
| const core = require("./core");
const coreCmds = require("./cmds");
const coreInterpreters = require("./interpreters");
let interpreters = Object.assign({}, coreInterpreters);
let context = {};
function promisify(fn) {
if (fn.eadPromisified) return fn;
const validator = fn.validator;
const promised = function(...args) {
if (validator) {
try {
validator(...args);
} catch (e) {
return Promise.reject(e);
}
}
return core.call(context, interpreters, fn, ...args);
};
// try/catch because this is nice for reporting, but not
// necessary for the system to function
// Note: there is a unit test to validate this behavior
// so errors, although swallowed here, are picked
// up in the unit test.
try {
Object.defineProperty(promised, "name", {
value: fn.name,
writable: false
});
} catch (e) {}
promised.eadFn = fn;
promised.callWithContext = function(c, ...args) {
if (validator) {
try {
validator(...args);
} catch (e) {
return Promise.reject(e);
}
}
return core.call(Object.assign({}, context, c), interpreters, fn, ...args);
};
promised.eadPromisified = true;
return promised;
}
function call(fn, ...args) {
return promisify(fn)(...args);
}
function doCmd(cmd) {
return promisify(function* doCmd() {
return yield cmd;
})();
}
function setContext(c) {
context = c;
}
function getContext() {
return context;
}
function addToContext(c) {
context = Object.assign({}, context, c);
}
function setInterpreters(h) {
interpreters = h;
}
function getInterpreters() {
return interpreters;
}
function addInterpreters(h) {
interpreters = Object.assign({}, interpreters, h);
}
function reset() {
interpreters = {};
context = {};
}
function onError(fn) {
if (typeof fn !== "function") throw new Error("onError requires a function");
addToContext({ onError: fn });
}
function effect(fn, validator) {
if (validator !== undefined && typeof validator !== "function") {
throw new Error("validator must be a function");
}
return function(...args) {
if (typeof validator === "function") {
validator(...args);
}
return coreCmds.call.fn(fn, ...args);
};
}
module.exports = {
cmds: coreCmds,
interpreters: coreInterpreters,
promisify,
call,
doCmd,
setContext,
getContext,
addToContext,
setInterpreters,
getInterpreters,
addInterpreters,
reset,
onError,
effect
};
|