-
Notifications
You must be signed in to change notification settings - Fork 1
/
factory.js
75 lines (67 loc) · 2.32 KB
/
factory.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
const argumentsVerify = require('./internal/argumentsVerify')
const isIterable = require('./internal/isIterable')
function factory (options) {
function Iterum (iterable) {
argumentsVerify([{
predicate: isIterable,
type: 'iterable'
}], [iterable])
return IterumConstructor(iterable)
}
function IterumConstructor (object) {
let generator
if (isIterable(object)) {
generator = object[Symbol.iterator].bind(object)
} else {
generator = object
}
return Object.create(Iterum.prototype, {
[Symbol.iterator]: {
value: generator
}
})
}
const {staticMethods, methods} = options
const define = function (object, methodName, method) {
Object.defineProperty(object, methodName, {
value: method
})
}
Object.keys(staticMethods).forEach(function (staticMethodName) {
const {fn, validation} = staticMethods[staticMethodName]
define(Iterum, staticMethodName, function (...args) {
argumentsVerify(validation, args)
return fn.call(IterumConstructor, ...args)
})
})
Object.keys(methods).forEach(function (methodName) {
const {fn, validation, binary} = methods[methodName]
const {length} = validation
if (binary) {
define(Iterum, methodName, function (first, second) {
argumentsVerify(validation, [second, first])
return fn.call(IterumConstructor, second, first)
})
} else {
define(Iterum, methodName, curry(function (...args) {
argumentsVerify(validation, args)
return fn.call(IterumConstructor, ...args)
}, length))
}
define(Iterum.prototype, methodName, function (...args) {
const processedArgs = args.slice(0, length - 1)
argumentsVerify(validation.slice(0, -1), args)
return fn.call(IterumConstructor, ...processedArgs, this)
})
})
return Iterum
}
function curry (fn, length = fn.length) {
return function (...args) {
const diff = length - args.length
return diff > 0
? curry(fn.bind(null, ...args), diff)
: fn(...args)
}
}
module.exports = factory