patroon 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nyc_output/494cd8ae-ab5a-494b-a750-1fef00a0ede2.json +1 -0
- package/.nyc_output/4e26d788-63bb-44c4-ab10-10cfdb5c4b73.json +1 -0
- package/.nyc_output/e0dd9c3e-df57-4924-bb75-c79df34c76c1.json +1 -0
- package/.nyc_output/processinfo/494cd8ae-ab5a-494b-a750-1fef00a0ede2.json +1 -0
- package/.nyc_output/processinfo/4e26d788-63bb-44c4-ab10-10cfdb5c4b73.json +1 -0
- package/.nyc_output/processinfo/e0dd9c3e-df57-4924-bb75-c79df34c76c1.json +1 -0
- package/.nyc_output/processinfo/index.json +1 -0
- package/LICENSE +674 -0
- package/README.md +299 -0
- package/README.mz +275 -0
- package/matching-with-regexes.md +0 -0
- package/matching-with-strings.md +9 -0
- package/package.json +19 -0
- package/src/helpers.js +52 -0
- package/src/index.js +73 -0
- package/src/index.test.js +62 -0
- package/src/walkable.js +86 -0
- package/tape-test +27 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const { test } = require('tape')
|
|
2
|
+
const { check, gen } = require('tape-check')
|
|
3
|
+
const {
|
|
4
|
+
patroon,
|
|
5
|
+
typed,
|
|
6
|
+
NoMatchError,
|
|
7
|
+
_
|
|
8
|
+
} = require('./index')
|
|
9
|
+
|
|
10
|
+
test('Matches always when pattern equals value', check(gen.any, (t, val) => {
|
|
11
|
+
patroon(val, () => t.end())(val)
|
|
12
|
+
}))
|
|
13
|
+
|
|
14
|
+
test('Matches none of the patterns and throws', t => {
|
|
15
|
+
try {
|
|
16
|
+
patroon(
|
|
17
|
+
1, () => t.fail(),
|
|
18
|
+
2, () => t.fail()
|
|
19
|
+
)(3)
|
|
20
|
+
t.fail()
|
|
21
|
+
} catch (e) {
|
|
22
|
+
t.ok(e instanceof NoMatchError)
|
|
23
|
+
t.end()
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
test('Does not match when a value does not exist', t => {
|
|
28
|
+
patroon(
|
|
29
|
+
{ a: { b: 2 } }, () => t.fail(),
|
|
30
|
+
_, () => t.end()
|
|
31
|
+
)({})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test('Throws when a typed does not receice a constructor', t => {
|
|
35
|
+
try {
|
|
36
|
+
console.log('XXX', typed(20))
|
|
37
|
+
typed(20)
|
|
38
|
+
} catch (e) {
|
|
39
|
+
t.ok(e instanceof Error)
|
|
40
|
+
t.end()
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('Throws in a predicate function', t => {
|
|
45
|
+
try {
|
|
46
|
+
patroon(
|
|
47
|
+
() => { throw new TypeError() }, () => {}
|
|
48
|
+
)()
|
|
49
|
+
} catch (e) {
|
|
50
|
+
t.ok(e instanceof TypeError)
|
|
51
|
+
t.end()
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('Throws when an uneven amount of arguments are passed', t => {
|
|
56
|
+
try {
|
|
57
|
+
patroon(1)
|
|
58
|
+
} catch (e) {
|
|
59
|
+
t.ok(e instanceof TypeError)
|
|
60
|
+
t.end()
|
|
61
|
+
}
|
|
62
|
+
})
|
package/src/walkable.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
const { isFunction, isDefined } = require('./helpers')
|
|
2
|
+
|
|
3
|
+
function walk (config, transform, item, path = []) {
|
|
4
|
+
if (config.isLeafe(item)) { return transform(item, path) }
|
|
5
|
+
|
|
6
|
+
return config.map((v, i) => walk(config, transform, v, [...path, i]), item)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function reduce (config, cb, acc, item) {
|
|
10
|
+
walk(config, (item, path) => {
|
|
11
|
+
acc = cb(acc, item, path)
|
|
12
|
+
|
|
13
|
+
return item
|
|
14
|
+
}, item)
|
|
15
|
+
|
|
16
|
+
return acc
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function isArray (v) {
|
|
20
|
+
return Array.isArray(v)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function isObject (v) {
|
|
24
|
+
return typeof v === 'object' && v !== null
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function isLeafe (x) {
|
|
28
|
+
return Number.isNaN(x) || !isDefined(x) || isFunction(x) || (!isObject(x) && !isArray(x))
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function mapLeaves (config, cb, item) {
|
|
32
|
+
return reduce(config, (acc, item, path) =>
|
|
33
|
+
[...acc, cb(item, path)], [], item)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
class PathError extends TypeError {}
|
|
37
|
+
|
|
38
|
+
function path (pth, v) {
|
|
39
|
+
if (pth.length === 0) { return v }
|
|
40
|
+
|
|
41
|
+
const [key, ...rest] = pth
|
|
42
|
+
|
|
43
|
+
if (!(key in v)) {
|
|
44
|
+
throw new PathError(
|
|
45
|
+
`Cannot read path '${JSON.stringify(pth)}' on ${JSON.stringify(v)}`)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return path(rest, v[key])
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function map (fn, x) {
|
|
52
|
+
// Should this code be here?
|
|
53
|
+
// if (!isDefined(x)) { throw new TypeError(`Cannot map over ${x}`) }
|
|
54
|
+
|
|
55
|
+
return isFunction(x.map)
|
|
56
|
+
? x.map(fn)
|
|
57
|
+
: Object.keys(x).reduce((y, prop) => {
|
|
58
|
+
y[prop] = fn(x[prop], prop)
|
|
59
|
+
return y
|
|
60
|
+
}, {})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function walkable (config = {}) {
|
|
64
|
+
config = {
|
|
65
|
+
isLeafe,
|
|
66
|
+
map,
|
|
67
|
+
...config
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const api = {
|
|
71
|
+
PathError,
|
|
72
|
+
path
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return [
|
|
76
|
+
walk,
|
|
77
|
+
reduce,
|
|
78
|
+
mapLeaves
|
|
79
|
+
].reduce((api, fn) => {
|
|
80
|
+
api[fn.name] = fn.bind(null, config)
|
|
81
|
+
|
|
82
|
+
return api
|
|
83
|
+
}, api)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
module.exports = walkable
|
package/tape-test
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
cat <(echo '
|
|
4
|
+
const { test } = require("tape")
|
|
5
|
+
const {
|
|
6
|
+
_, // placeholder,
|
|
7
|
+
t: typed,
|
|
8
|
+
ref,
|
|
9
|
+
patroon,
|
|
10
|
+
NoMatchError
|
|
11
|
+
} = require("./src/index")
|
|
12
|
+
|
|
13
|
+
const simpleObject = { a: 1 }
|
|
14
|
+
const otherObject = { b: 1 }
|
|
15
|
+
const emptyObject = {}
|
|
16
|
+
|
|
17
|
+
class A { }
|
|
18
|
+
class B { }
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
test(t => {
|
|
22
|
+
const fail = () => t.fail()
|
|
23
|
+
const pass = () => t.pass()
|
|
24
|
+
const end = () => t.end()
|
|
25
|
+
') \
|
|
26
|
+
- \
|
|
27
|
+
<(echo ' })') | node - 1>&2
|