-
Notifications
You must be signed in to change notification settings - Fork 2
/
pipez.js
94 lines (59 loc) · 2.93 KB
/
pipez.js
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
"use strict";
/* ------------------------------------------------------------------------ */
const merge = (to, from) => {
for (const prop in from) { Object.defineProperty (to, prop, Object.getOwnPropertyDescriptor (from, prop)) }
return to
}
/* ------------------------------------------------------------------------ */
const pipez = module.exports = (functions_, prev) => {
let functions = {} // bound to self
const functionNames = Reflect.ownKeys (functions_) // guaranteed to be in property creation order (as defined by the standard)
const self = Object.assign (
/* Function of functions (call chain) */
(...initial) => functionNames.reduce ((memo, k) => functions[k].call (self, memo, { initialArguments: initial }), initial), // @hide
/* Additional methods */
{
configure (overrides = {}) {
const modifiedFunctions = {}
for (const k of functionNames) {
const override = overrides[k],
before = overrides['+' + k] || (x => x),
after = overrides[k + '+'] || (x => x)
const boundArgs = (typeof override === 'boolean') ? { yes: override } : (override || {})
modifiedFunctions[k] = function (x, args) {
const fn = (typeof override === 'function') ? override : functions[k] // dont cache so people can dynamically change .impl ()
const newArgs = Object.assign ({}, boundArgs, args),
maybeFn = (newArgs.yes === false) ? (x => x) : fn
return after.call (this,
maybeFn.call (this,
before.call (this, x, newArgs), newArgs), newArgs)
}
}
return pipez (modifiedFunctions, self).methods (this.methods_)
},
from (name) {
let subset = null
for (const k of functionNames) {
if (k === name) { subset = { takeFirstArgument: args => args[0] } }
if (subset) { subset[k] = functions[k] }
}
return pipez (subset, self)
},
before (name) {
let subset = {}
for (const k of functionNames) {
if (k === name) { break }
subset[k] = functions[k]
}
return pipez (subset, self)
},
methods_: {},
methods (methods) { return merge (this, merge (this.methods_, methods)) },
get impl () { return functions },
get prev () { return prev }
}
)
for (let [k, f] of Object.entries (functions_)) { functions[k] = f.bind (self) }
return self
}
/* ------------------------------------------------------------------------ */