patroon 0.4.0 → 1.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/CONTRIBUTING.md +18 -3
- package/CONTRIBUTING.mz +18 -3
- package/README.md +75 -26
- package/README.mz +60 -13
- package/package.json +1 -1
- package/src/helpers.js +0 -5
- package/src/index.js +19 -11
- package/src/index.test.js +12 -4
- package/src/walkable.js +10 -4
- package/tape-test +1 -0
package/CONTRIBUTING.md
CHANGED
|
@@ -21,11 +21,25 @@ npx standard || npx standard --fix
|
|
|
21
21
|
|
|
22
22
|
## Documentation
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
We generate the contributors list using node and store it in [memplate][7].
|
|
25
|
+
|
|
26
|
+
```js node -p | memplate contributors
|
|
27
|
+
require('./package.json').contributors.reduce((acc, {name, url, email}) =>
|
|
28
|
+
`${acc}- **${name}** *${url}*\n`, '')
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
We also generate the table of contents and store it in memplate.
|
|
32
|
+
|
|
33
|
+
```bash bash | memplate toc
|
|
34
|
+
npx markdown-toc --no-firsth1 --maxdepth 4 README.mz
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
We then use memplate to template the README. Then we run [markatzea][6] to run
|
|
39
|
+
the examples and show the output of those.
|
|
25
40
|
|
|
26
41
|
```bash bash
|
|
27
|
-
|
|
28
|
-
npx markdown-toc --maxdepth 4 -i README.md
|
|
42
|
+
memplate < README.mz | markatzea > README.md
|
|
29
43
|
echo 'Documentation generated successfully.' 1>&2
|
|
30
44
|
```
|
|
31
45
|
|
|
@@ -34,3 +48,4 @@ echo 'Documentation generated successfully.' 1>&2
|
|
|
34
48
|
[3]:https://github.com/bas080/patroon/blob/master/src/index.js
|
|
35
49
|
[4]:https://github.com/bas080/patroon/blob/master/src/helpers.js
|
|
36
50
|
[6]:https://github.com/bas080/markatzea
|
|
51
|
+
[7]:https://github.com/bas080/memplate
|
package/CONTRIBUTING.mz
CHANGED
|
@@ -21,11 +21,25 @@ npx standard || npx standard --fix
|
|
|
21
21
|
|
|
22
22
|
## Documentation
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
We generate the contributors list using node and store it in [memplate][7].
|
|
25
|
+
|
|
26
|
+
```js node -p | memplate contributors
|
|
27
|
+
require('./package.json').contributors.reduce((acc, {name, url, email}) =>
|
|
28
|
+
`${acc}- **${name}** *${url}*\n`, '')
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
We also generate the table of contents and store it in memplate.
|
|
32
|
+
|
|
33
|
+
```bash bash | memplate toc
|
|
34
|
+
npx markdown-toc --no-firsth1 --maxdepth 4 README.mz
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
We then use memplate to template the README. Then we run [markatzea][6] to run
|
|
39
|
+
the examples and show the output of those.
|
|
25
40
|
|
|
26
41
|
```bash bash
|
|
27
|
-
|
|
28
|
-
npx markdown-toc --maxdepth 4 -i README.md
|
|
42
|
+
memplate < README.mz | markatzea > README.md
|
|
29
43
|
echo 'Documentation generated successfully.' 1>&2
|
|
30
44
|
```
|
|
31
45
|
|
|
@@ -34,3 +48,4 @@ echo 'Documentation generated successfully.' 1>&2
|
|
|
34
48
|
[3]:https://github.com/bas080/patroon/blob/master/src/index.js
|
|
35
49
|
[4]:https://github.com/bas080/patroon/blob/master/src/helpers.js
|
|
36
50
|
[6]:https://github.com/bas080/markatzea
|
|
51
|
+
[7]:https://github.com/bas080/memplate
|
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Patroon
|
|
2
2
|
|
|
3
|
+
Pattern matching in JavaScript without additional syntax.
|
|
4
|
+
|
|
3
5
|
[](https://www.npmjs.com/package/patroon)
|
|
4
6
|
[](https://www.npmjs.com/package/patroon)
|
|
5
7
|
[](#tests)
|
|
@@ -7,10 +9,6 @@
|
|
|
7
9
|
[](https://standardjs.com)
|
|
8
10
|
[](./LICENSE)
|
|
9
11
|
|
|
10
|
-
Pattern matching in JavaScript without additional syntax.
|
|
11
|
-
|
|
12
|
-
<!-- toc -->
|
|
13
|
-
|
|
14
12
|
- [Installation](#installation)
|
|
15
13
|
- [Usage](#usage)
|
|
16
14
|
* [Primitive](#primitive)
|
|
@@ -31,8 +29,7 @@ Pattern matching in JavaScript without additional syntax.
|
|
|
31
29
|
+ [PatroonError](#patroonerror)
|
|
32
30
|
- [Tests](#tests)
|
|
33
31
|
- [Contribute](#contribute)
|
|
34
|
-
|
|
35
|
-
<!-- tocstop -->
|
|
32
|
+
* [Contributors](#contributors)
|
|
36
33
|
|
|
37
34
|
## Installation
|
|
38
35
|
|
|
@@ -46,6 +43,8 @@ npm install patroon
|
|
|
46
43
|
|
|
47
44
|
Let's see what valid and less valid uses of patroon are.
|
|
48
45
|
|
|
46
|
+
> You can try out patroon over at [RunKit][runkit].
|
|
47
|
+
|
|
49
48
|
### Primitive
|
|
50
49
|
|
|
51
50
|
The simplest thing one can do is to match on a [primitive][1].
|
|
@@ -193,8 +192,8 @@ builtin node error constructors in this example.
|
|
|
193
192
|
|
|
194
193
|
```js ./tape-test
|
|
195
194
|
patroon(
|
|
196
|
-
TypeError, 'is a type error',
|
|
197
|
-
Error, 'is an error'
|
|
195
|
+
instanceOf(TypeError), 'is a type error',
|
|
196
|
+
instanceOf(Error), 'is an error'
|
|
198
197
|
)(new Error())
|
|
199
198
|
```
|
|
200
199
|
```
|
|
@@ -214,8 +213,8 @@ Because of this you can match a TypeError with an Error.
|
|
|
214
213
|
|
|
215
214
|
```js ./tape-test
|
|
216
215
|
patroon(
|
|
217
|
-
Error, 'matches on error',
|
|
218
|
-
TypeError, 'matches on type error'
|
|
216
|
+
instanceOf(Error), 'matches on error',
|
|
217
|
+
instanceOf(TypeError), 'matches on type error'
|
|
219
218
|
)(new TypeError())
|
|
220
219
|
```
|
|
221
220
|
```
|
|
@@ -227,9 +226,9 @@ Here you should use the every helper.
|
|
|
227
226
|
|
|
228
227
|
```js ./tape-test
|
|
229
228
|
patroon(
|
|
230
|
-
every(TypeError, { value: 20 }), 'type error where value is 20',
|
|
231
|
-
every(Error, { value: 30 }), 'error where value is 30',
|
|
232
|
-
every(Error, { value: 20 }), 'error where value is 20'
|
|
229
|
+
every(instanceOf(TypeError), { value: 20 }), 'type error where value is 20',
|
|
230
|
+
every(instanceOf(Error), { value: 30 }), 'error where value is 30',
|
|
231
|
+
every(instanceOf(Error), { value: 20 }), 'error where value is 20'
|
|
233
232
|
)(Object.assign(new TypeError(), { value: 20 }))
|
|
234
233
|
```
|
|
235
234
|
```
|
|
@@ -252,6 +251,35 @@ patroon([], 'is array')([])
|
|
|
252
251
|
patroon(Array, 'is array')([])
|
|
253
252
|
```
|
|
254
253
|
|
|
254
|
+
A less intuitive case:
|
|
255
|
+
|
|
256
|
+
```js ./tape-test > /dev/null
|
|
257
|
+
patroon({}, 'is object')([])
|
|
258
|
+
patroon([], 'is array')({})
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Patroon allows this because Arrays can have properties defined.
|
|
262
|
+
|
|
263
|
+
```js ./tape-test > /dev/null
|
|
264
|
+
const array = []
|
|
265
|
+
array.prop = 42
|
|
266
|
+
|
|
267
|
+
patroon({prop: _}, 'has prop')(array)
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
The other way around is also allowed even if it seems weird.
|
|
271
|
+
|
|
272
|
+
```js ./tape-test > /dev/null
|
|
273
|
+
const object = {0: 42}
|
|
274
|
+
patroon([42], 'has 0th')(object)
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
If you do not desire this loose behavior you can use a predicate to make sure
|
|
278
|
+
something is an array or object.
|
|
279
|
+
|
|
280
|
+
```js ./tape-test > /dev/null
|
|
281
|
+
patroon(Array.isArray, 'is array')([])
|
|
282
|
+
```
|
|
255
283
|
|
|
256
284
|
### Reference
|
|
257
285
|
|
|
@@ -260,7 +288,7 @@ helper.
|
|
|
260
288
|
|
|
261
289
|
```js ./tape-test
|
|
262
290
|
patroon(
|
|
263
|
-
Error, 'is an instance of Error',
|
|
291
|
+
instanceOf(Error), 'is an instance of Error',
|
|
264
292
|
reference(Error), 'is the Error constructor'
|
|
265
293
|
)(Error)
|
|
266
294
|
```
|
|
@@ -310,6 +338,20 @@ patroon(
|
|
|
310
338
|
Index 6 has value 7
|
|
311
339
|
```
|
|
312
340
|
|
|
341
|
+
A function that returns the lenght of an array:
|
|
342
|
+
|
|
343
|
+
```js ./tape-test
|
|
344
|
+
const count = patroon(
|
|
345
|
+
[_], ([, ...xs]) => 1 + count(xs),
|
|
346
|
+
[], 0
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
count([0,1,2,3])
|
|
350
|
+
```
|
|
351
|
+
```
|
|
352
|
+
4
|
|
353
|
+
```
|
|
354
|
+
|
|
313
355
|
A function that looks for a certain pattern in an array:
|
|
314
356
|
|
|
315
357
|
```js ./tape-test
|
|
@@ -475,12 +517,12 @@ const oneIsTwo = patroon(1, 2)
|
|
|
475
517
|
oneIsTwo(3)
|
|
476
518
|
```
|
|
477
519
|
```
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
520
|
+
[ 3 ]
|
|
521
|
+
/home/ant/projects/patroon/src/index.js:92
|
|
522
|
+
throw error
|
|
523
|
+
^
|
|
481
524
|
|
|
482
|
-
NoMatchError: Not able to match any pattern for
|
|
483
|
-
at /home/ant/projects/patroon/src/index.js:79:31
|
|
525
|
+
NoMatchError: Not able to match any pattern for arguments
|
|
484
526
|
```
|
|
485
527
|
|
|
486
528
|
#### UnevenArgumentCountError
|
|
@@ -491,12 +533,12 @@ Another error that occurs is when the patroon function is not used correctly.
|
|
|
491
533
|
patroon(1)
|
|
492
534
|
```
|
|
493
535
|
```
|
|
494
|
-
/home/ant/projects/patroon/src/index.js:
|
|
536
|
+
/home/ant/projects/patroon/src/index.js:79
|
|
495
537
|
if (!isEven(list.length)) { throw new UnevenArgumentCountError('Patroon should have an even amount of arguments.') }
|
|
496
538
|
^
|
|
497
539
|
|
|
498
540
|
UnevenArgumentCountError: Patroon should have an even amount of arguments.
|
|
499
|
-
at patroon (/home/ant/projects/patroon/src/index.js:
|
|
541
|
+
at patroon (/home/ant/projects/patroon/src/index.js:79:37)
|
|
500
542
|
```
|
|
501
543
|
|
|
502
544
|
#### PatroonError
|
|
@@ -504,7 +546,7 @@ UnevenArgumentCountError: Patroon should have an even amount of arguments.
|
|
|
504
546
|
All errors patroon produces can be matched against the PatroonError using `instanceof`.
|
|
505
547
|
|
|
506
548
|
```js ./tape-test
|
|
507
|
-
const isPatroonError = patroon(PatroonError, 'patroon is causing an error')
|
|
549
|
+
const isPatroonError = patroon(instanceOf(PatroonError), 'patroon is causing an error')
|
|
508
550
|
|
|
509
551
|
isPatroonError(new NoMatchError())
|
|
510
552
|
isPatroonError(new UnevenArgumentCountError())
|
|
@@ -532,7 +574,7 @@ npx nyc npm t | npx tap-nyc
|
|
|
532
574
|
npx nyc check-coverage
|
|
533
575
|
```
|
|
534
576
|
```
|
|
535
|
-
> patroon@0.
|
|
577
|
+
> patroon@1.0.0 test
|
|
536
578
|
> tape ./src/index.test.js
|
|
537
579
|
-------------|---------|----------|---------|---------|-------------------
|
|
538
580
|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
|
|
@@ -543,10 +585,10 @@ npx nyc check-coverage
|
|
|
543
585
|
walkable.js | 100 | 100 | 100 | 100 |
|
|
544
586
|
-------------|---------|----------|---------|---------|-------------------
|
|
545
587
|
|
|
546
|
-
total:
|
|
547
|
-
passing:
|
|
588
|
+
total: 15
|
|
589
|
+
passing: 15
|
|
548
590
|
|
|
549
|
-
duration:
|
|
591
|
+
duration: 1s
|
|
550
592
|
|
|
551
593
|
```
|
|
552
594
|
|
|
@@ -555,6 +597,12 @@ npx nyc check-coverage
|
|
|
555
597
|
You may contribute in whatever manner you see fit. Do try to be helpful and
|
|
556
598
|
polite and read the [CONTRIBUTING.md][10].
|
|
557
599
|
|
|
600
|
+
### Contributors
|
|
601
|
+
|
|
602
|
+
- **Bassim Huis** *https://github.com/bas080*
|
|
603
|
+
- **Scott Sauyet** *http://scott.sauyet.com*
|
|
604
|
+
|
|
605
|
+
|
|
558
606
|
[1]:https://developer.mozilla.org/en-US/docs/Glossary/Primitive
|
|
559
607
|
[2]:https://en.wikipedia.org/wiki/Multiple_dispatch
|
|
560
608
|
[3]:https://github.com/bas080/patroon/blob/master/src/index.js
|
|
@@ -563,3 +611,4 @@ polite and read the [CONTRIBUTING.md][10].
|
|
|
563
611
|
[8]:https://github.com/istanbuljs/nyc
|
|
564
612
|
[9]:https://www.npmjs.com/package/patroon
|
|
565
613
|
[10]:./CONTRIBUTING.md
|
|
614
|
+
[runkit]:https://npm.runkit.com/patroon
|
package/README.mz
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Patroon
|
|
2
2
|
|
|
3
|
+
Pattern matching in JavaScript without additional syntax.
|
|
4
|
+
|
|
3
5
|
[](https://www.npmjs.com/package/patroon)
|
|
4
6
|
[](https://www.npmjs.com/package/patroon)
|
|
5
7
|
[](#tests)
|
|
@@ -7,9 +9,7 @@
|
|
|
7
9
|
[](https://standardjs.com)
|
|
8
10
|
[](./LICENSE)
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<!-- toc -->
|
|
12
|
+
<toc
|
|
13
13
|
|
|
14
14
|
## Installation
|
|
15
15
|
|
|
@@ -23,6 +23,8 @@ npm install patroon
|
|
|
23
23
|
|
|
24
24
|
Let's see what valid and less valid uses of patroon are.
|
|
25
25
|
|
|
26
|
+
> You can try out patroon over at [RunKit][runkit].
|
|
27
|
+
|
|
26
28
|
### Primitive
|
|
27
29
|
|
|
28
30
|
The simplest thing one can do is to match on a [primitive][1].
|
|
@@ -140,8 +142,8 @@ builtin node error constructors in this example.
|
|
|
140
142
|
|
|
141
143
|
```js ./tape-test
|
|
142
144
|
patroon(
|
|
143
|
-
TypeError, 'is a type error',
|
|
144
|
-
Error, 'is an error'
|
|
145
|
+
instanceOf(TypeError), 'is a type error',
|
|
146
|
+
instanceOf(Error), 'is an error'
|
|
145
147
|
)(new Error())
|
|
146
148
|
```
|
|
147
149
|
|
|
@@ -155,8 +157,8 @@ Because of this you can match a TypeError with an Error.
|
|
|
155
157
|
|
|
156
158
|
```js ./tape-test
|
|
157
159
|
patroon(
|
|
158
|
-
Error, 'matches on error',
|
|
159
|
-
TypeError, 'matches on type error'
|
|
160
|
+
instanceOf(Error), 'matches on error',
|
|
161
|
+
instanceOf(TypeError), 'matches on type error'
|
|
160
162
|
)(new TypeError())
|
|
161
163
|
```
|
|
162
164
|
|
|
@@ -165,9 +167,9 @@ Here you should use the every helper.
|
|
|
165
167
|
|
|
166
168
|
```js ./tape-test
|
|
167
169
|
patroon(
|
|
168
|
-
every(TypeError, { value: 20 }), 'type error where value is 20',
|
|
169
|
-
every(Error, { value: 30 }), 'error where value is 30',
|
|
170
|
-
every(Error, { value: 20 }), 'error where value is 20'
|
|
170
|
+
every(instanceOf(TypeError), { value: 20 }), 'type error where value is 20',
|
|
171
|
+
every(instanceOf(Error), { value: 30 }), 'error where value is 30',
|
|
172
|
+
every(instanceOf(Error), { value: 20 }), 'error where value is 20'
|
|
171
173
|
)(Object.assign(new TypeError(), { value: 20 }))
|
|
172
174
|
```
|
|
173
175
|
|
|
@@ -187,6 +189,35 @@ patroon([], 'is array')([])
|
|
|
187
189
|
patroon(Array, 'is array')([])
|
|
188
190
|
```
|
|
189
191
|
|
|
192
|
+
A less intuitive case:
|
|
193
|
+
|
|
194
|
+
```js ./tape-test > /dev/null
|
|
195
|
+
patroon({}, 'is object')([])
|
|
196
|
+
patroon([], 'is array')({})
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Patroon allows this because Arrays can have properties defined.
|
|
200
|
+
|
|
201
|
+
```js ./tape-test > /dev/null
|
|
202
|
+
const array = []
|
|
203
|
+
array.prop = 42
|
|
204
|
+
|
|
205
|
+
patroon({prop: _}, 'has prop')(array)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
The other way around is also allowed even if it seems weird.
|
|
209
|
+
|
|
210
|
+
```js ./tape-test > /dev/null
|
|
211
|
+
const object = {0: 42}
|
|
212
|
+
patroon([42], 'has 0th')(object)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
If you do not desire this loose behavior you can use a predicate to make sure
|
|
216
|
+
something is an array or object.
|
|
217
|
+
|
|
218
|
+
```js ./tape-test > /dev/null
|
|
219
|
+
patroon(Array.isArray, 'is array')([])
|
|
220
|
+
```
|
|
190
221
|
|
|
191
222
|
### Reference
|
|
192
223
|
|
|
@@ -195,7 +226,7 @@ helper.
|
|
|
195
226
|
|
|
196
227
|
```js ./tape-test
|
|
197
228
|
patroon(
|
|
198
|
-
Error, 'is an instance of Error',
|
|
229
|
+
instanceOf(Error), 'is an instance of Error',
|
|
199
230
|
reference(Error), 'is the Error constructor'
|
|
200
231
|
)(Error)
|
|
201
232
|
```
|
|
@@ -233,6 +264,17 @@ patroon(
|
|
|
233
264
|
)([1, 2, 3, 4, 5, 6, 7])
|
|
234
265
|
```
|
|
235
266
|
|
|
267
|
+
A function that returns the lenght of an array:
|
|
268
|
+
|
|
269
|
+
```js ./tape-test
|
|
270
|
+
const count = patroon(
|
|
271
|
+
[_], ([, ...xs]) => 1 + count(xs),
|
|
272
|
+
[], 0
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
count([0,1,2,3])
|
|
276
|
+
```
|
|
277
|
+
|
|
236
278
|
A function that looks for a certain pattern in an array:
|
|
237
279
|
|
|
238
280
|
```js ./tape-test
|
|
@@ -266,7 +308,7 @@ A helper that makes it easy to check if a value passes all patterns.
|
|
|
266
308
|
|
|
267
309
|
```js ./tape-test
|
|
268
310
|
const gte200 = x => x >= 200
|
|
269
|
-
const lt300 = x => x
|
|
311
|
+
const lt300 = x => x \< 300
|
|
270
312
|
|
|
271
313
|
patroon(
|
|
272
314
|
every(gte200, lt300), 'Is a 200 status code'
|
|
@@ -377,7 +419,7 @@ patroon(1)
|
|
|
377
419
|
All errors patroon produces can be matched against the PatroonError using `instanceof`.
|
|
378
420
|
|
|
379
421
|
```js ./tape-test
|
|
380
|
-
const isPatroonError = patroon(PatroonError, 'patroon is causing an error')
|
|
422
|
+
const isPatroonError = patroon(instanceOf(PatroonError), 'patroon is causing an error')
|
|
381
423
|
|
|
382
424
|
isPatroonError(new NoMatchError())
|
|
383
425
|
isPatroonError(new UnevenArgumentCountError())
|
|
@@ -407,6 +449,10 @@ npx nyc check-coverage
|
|
|
407
449
|
You may contribute in whatever manner you see fit. Do try to be helpful and
|
|
408
450
|
polite and read the [CONTRIBUTING.md][10].
|
|
409
451
|
|
|
452
|
+
### Contributors
|
|
453
|
+
|
|
454
|
+
<contributors
|
|
455
|
+
|
|
410
456
|
[1]:https://developer.mozilla.org/en-US/docs/Glossary/Primitive
|
|
411
457
|
[2]:https://en.wikipedia.org/wiki/Multiple_dispatch
|
|
412
458
|
[3]:https://github.com/bas080/patroon/blob/master/src/index.js
|
|
@@ -415,3 +461,4 @@ polite and read the [CONTRIBUTING.md][10].
|
|
|
415
461
|
[8]:https://github.com/istanbuljs/nyc
|
|
416
462
|
[9]:https://www.npmjs.com/package/patroon
|
|
417
463
|
[10]:./CONTRIBUTING.md
|
|
464
|
+
[runkit]:https://npm.runkit.com/patroon
|
package/package.json
CHANGED
package/src/helpers.js
CHANGED
|
@@ -8,10 +8,6 @@ const toPairs = items => {
|
|
|
8
8
|
|
|
9
9
|
const isNil = x => !(x != null)
|
|
10
10
|
|
|
11
|
-
function isConstructor (func) {
|
|
12
|
-
return Boolean(func && typeof func === 'function' && func.prototype && func.prototype.constructor)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
11
|
function isDefined (x) {
|
|
16
12
|
return x != null
|
|
17
13
|
}
|
|
@@ -24,7 +20,6 @@ const is = Ctor => instance => isDefined(instance) && (instance.constructor ===
|
|
|
24
20
|
module.exports = {
|
|
25
21
|
isDefined,
|
|
26
22
|
always: x => () => x,
|
|
27
|
-
isConstructor,
|
|
28
23
|
is,
|
|
29
24
|
toPairs,
|
|
30
25
|
isNil,
|
package/src/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
const { mapLeaves, path, PathError } = require('./walkable')()
|
|
2
|
-
const {
|
|
2
|
+
const { isFunction, equals, T, is, tryCatch, isEven, isNil, toPairs, always } = require('./helpers')
|
|
3
3
|
|
|
4
|
-
const deprecated = (fn, message) => {
|
|
4
|
+
const deprecated = (fn, message) => (...args) => {
|
|
5
5
|
console.error(`[patroon] deprecated: ${message}`)
|
|
6
|
-
return fn
|
|
6
|
+
return fn(...args)
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
const typed = deprecated(function typed (Ctor, pattern) {
|
|
10
10
|
return every(Ctor, pattern)
|
|
11
|
-
}, 'replace "typed
|
|
11
|
+
}, 'replace "typed" or "t" helpers with "every(Constructor, pattern)"')
|
|
12
12
|
|
|
13
13
|
const isRegExp = is(RegExp)
|
|
14
14
|
|
|
@@ -41,8 +41,6 @@ const predicate = pattern => {
|
|
|
41
41
|
const normalize = (value, pth) => {
|
|
42
42
|
if (isRegExp(value)) return arg => value.test(arg)
|
|
43
43
|
|
|
44
|
-
if (isConstructor(value)) { return is(value) }
|
|
45
|
-
|
|
46
44
|
if (isFunction(value)) { return arg => value(path(pth, arg)) }
|
|
47
45
|
|
|
48
46
|
return arg => equals(path(pth, arg), value)
|
|
@@ -85,16 +83,25 @@ const patroon = (...list) => {
|
|
|
85
83
|
return (...args) => {
|
|
86
84
|
const found = patterns.find(([matches]) => matches(...args))
|
|
87
85
|
|
|
88
|
-
if (isNil(found)) {
|
|
86
|
+
if (isNil(found)) {
|
|
87
|
+
const error = new NoMatchError('Not able to match any pattern for arguments')
|
|
88
|
+
error.arguments = args
|
|
89
|
+
|
|
90
|
+
console.error(args)
|
|
89
91
|
|
|
90
|
-
|
|
92
|
+
throw error
|
|
93
|
+
}
|
|
91
94
|
|
|
92
|
-
return
|
|
95
|
+
return found[1](...args)
|
|
93
96
|
}
|
|
94
97
|
}
|
|
95
98
|
|
|
96
|
-
function reference (
|
|
97
|
-
return
|
|
99
|
+
function reference (any) {
|
|
100
|
+
return value => any === value
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function instanceOf (ctor) {
|
|
104
|
+
return value => value instanceof ctor
|
|
98
105
|
}
|
|
99
106
|
|
|
100
107
|
module.exports = Object.assign(patroon, {
|
|
@@ -109,5 +116,6 @@ module.exports = Object.assign(patroon, {
|
|
|
109
116
|
reference,
|
|
110
117
|
typed,
|
|
111
118
|
t: typed,
|
|
119
|
+
instanceOf,
|
|
112
120
|
_: T
|
|
113
121
|
})
|
package/src/index.test.js
CHANGED
|
@@ -2,6 +2,7 @@ const { test } = require('tape')
|
|
|
2
2
|
const { check, gen } = require('tape-check')
|
|
3
3
|
const {
|
|
4
4
|
reference,
|
|
5
|
+
instanceOf,
|
|
5
6
|
typed,
|
|
6
7
|
t,
|
|
7
8
|
ref,
|
|
@@ -39,9 +40,9 @@ test('Match using reference', t => {
|
|
|
39
40
|
|
|
40
41
|
test('Matches on type and value', t => {
|
|
41
42
|
patroon(
|
|
42
|
-
every(Error, { x: 20 }), () => t.fail(),
|
|
43
|
-
every(Error, { x: 10 }), () => t.end(),
|
|
44
|
-
|
|
43
|
+
every(instanceOf(Error), { x: 20 }), () => t.fail(),
|
|
44
|
+
every(instanceOf(Error), { x: 10 }), () => t.end(),
|
|
45
|
+
instanceOf(Error), () => t.fail()
|
|
45
46
|
)(Object.assign(new Error(), { x: 10 }))
|
|
46
47
|
})
|
|
47
48
|
|
|
@@ -152,9 +153,16 @@ test('Matches when arguments match multi pattern', check(gen.any, (t, val) => {
|
|
|
152
153
|
}))
|
|
153
154
|
|
|
154
155
|
test('Deprecated functions', ts => {
|
|
155
|
-
ts.plan(
|
|
156
|
+
ts.plan(3)
|
|
157
|
+
|
|
158
|
+
const consoleError = console.error
|
|
159
|
+
|
|
160
|
+
console.error = message =>
|
|
161
|
+
ts.ok(message.startsWith('[patroon] deprecated: '))
|
|
162
|
+
|
|
156
163
|
typed(Error, null)(new Error())
|
|
157
164
|
t(Error, null)(new Error())
|
|
158
165
|
ref(Error, null)(Error)
|
|
166
|
+
console.error = consoleError
|
|
159
167
|
ts.end()
|
|
160
168
|
})
|
package/src/walkable.js
CHANGED
|
@@ -35,17 +35,23 @@ function mapLeaves (config, cb, item) {
|
|
|
35
35
|
|
|
36
36
|
class PathError extends TypeError {}
|
|
37
37
|
|
|
38
|
-
function path (pth, v) {
|
|
38
|
+
function path (pth, v, errorData) {
|
|
39
|
+
if (isNil(errorData)) { return path(pth, v, { path: pth, value: v }) }
|
|
40
|
+
|
|
39
41
|
if (pth.length === 0) { return v }
|
|
40
42
|
|
|
41
43
|
const [key, ...rest] = pth
|
|
42
44
|
|
|
43
45
|
if (!(key in v)) {
|
|
44
|
-
|
|
45
|
-
`Cannot read
|
|
46
|
+
const error = new PathError(
|
|
47
|
+
`Cannot read property '${JSON.stringify(pth)}' of ${JSON.stringify(v)}`)
|
|
48
|
+
|
|
49
|
+
Object.assign(error, errorData)
|
|
50
|
+
|
|
51
|
+
throw error
|
|
46
52
|
}
|
|
47
53
|
|
|
48
|
-
return path(rest, v[key])
|
|
54
|
+
return path(rest, v[key], errorData)
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
function map (fn, x) {
|