-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.js
118 lines (101 loc) · 2.9 KB
/
index.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
'use strict'
const symbols = require('./lib/symbols')
const array = require('./lib/predicates/array')
const boolean = require('./lib/predicates/boolean')
const date = require('./lib/predicates/date')
const func = require('./lib/predicates/function')
const number = require('./lib/predicates/number')
const object = require('./lib/predicates/object')
const string = require('./lib/predicates/string')
const typePredicates = {
array,
boolean,
date,
function: func,
number,
object,
string
}
const createOw = ({
validators = [],
predicates = typePredicates,
type = null
} = { }) => {
const ow = new Proxy(function () { }, {
get: (obj, key) => {
if (key === symbols.validate) {
return (value, label = 'argument') => {
if (!type) {
return new Error('missing required type specifier')
}
for (let i = 0; i < validators.length; ++i) {
const validator = validators[i]
const result = validator.fn(value)
if (!result) {
if (i === 0) {
throw new Error(`Expected ${label} \`${value}\` to be of type \`${type}\`, but received type \`${typeof value}\``)
} else {
throw new Error(`Expected ${type} \`${label}\` \`${value}\` failed predicate \`${validator.key}\``)
}
}
}
}
}
if (!predicates) {
throw new Error(`Unknown \`${type}\` predicate \`${key}\``)
}
const predicate = predicates[key]
if (predicate) {
if (typeof predicate === 'function') {
validators.push({
key,
fn: predicate
})
return ow
} else {
return createOw({
type: key,
validators: [
{
key,
fn: predicate.validator
}
],
predicates: predicate.predicates || null
})
}
} else {
const fn = predicates[symbols.func] && predicates[symbols.func][key]
if (fn) {
return new Proxy(function () { }, {
get: () => {
throw new Error(`invalid use of functional predicate "${key}"`)
},
apply: (obj, thisArg, args) => {
validators.push({
key,
fn: fn(...args)
})
return ow
}
})
} else {
if (key === 'default' || key === '__esModule') {
return ow
}
return ow
// throw new Error(`unrecognized predicate "${key}"`)
}
}
},
apply: (obj, thisArg, args) => {
if (args.length !== 2 && args.length !== 3) {
throw new Error('invalid number of arguments to "ow"')
} else {
args[1][symbols.validate](args[0], args[2])
}
}
})
return ow
}
module.exports = createOw()