1 |
3a515b92
|
cagy
|
aproba
|
2 |
|
|
======
|
3 |
|
|
|
4 |
|
|
A ridiculously light-weight function argument validator
|
5 |
|
|
|
6 |
|
|
```
|
7 |
|
|
var validate = require("aproba")
|
8 |
|
|
|
9 |
|
|
function myfunc(a, b, c) {
|
10 |
|
|
// `a` must be a string, `b` a number, `c` a function
|
11 |
|
|
validate('SNF', arguments) // [a,b,c] is also valid
|
12 |
|
|
}
|
13 |
|
|
|
14 |
|
|
myfunc('test', 23, function () {}) // ok
|
15 |
|
|
myfunc(123, 23, function () {}) // type error
|
16 |
|
|
myfunc('test', 23) // missing arg error
|
17 |
|
|
myfunc('test', 23, function () {}, true) // too many args error
|
18 |
|
|
|
19 |
|
|
```
|
20 |
|
|
|
21 |
|
|
Valid types are:
|
22 |
|
|
|
23 |
|
|
| type | description
|
24 |
|
|
| :--: | :----------
|
25 |
|
|
| * | matches any type
|
26 |
|
|
| A | `Array.isArray` OR an `arguments` object
|
27 |
|
|
| S | typeof == string
|
28 |
|
|
| N | typeof == number
|
29 |
|
|
| F | typeof == function
|
30 |
|
|
| O | typeof == object and not type A and not type E
|
31 |
|
|
| B | typeof == boolean
|
32 |
|
|
| E | `instanceof Error` OR `null` **(special: see below)**
|
33 |
|
|
| Z | == `null`
|
34 |
|
|
|
35 |
|
|
Validation failures throw one of three exception types, distinguished by a
|
36 |
|
|
`code` property of `EMISSINGARG`, `EINVALIDTYPE` or `ETOOMANYARGS`.
|
37 |
|
|
|
38 |
|
|
If you pass in an invalid type then it will throw with a code of
|
39 |
|
|
`EUNKNOWNTYPE`.
|
40 |
|
|
|
41 |
|
|
If an **error** argument is found and is not null then the remaining
|
42 |
|
|
arguments are optional. That is, if you say `ESO` then that's like using a
|
43 |
|
|
non-magical `E` in: `E|ESO|ZSO`.
|
44 |
|
|
|
45 |
|
|
### But I have optional arguments?!
|
46 |
|
|
|
47 |
|
|
You can provide more than one signature by separating them with pipes `|`.
|
48 |
|
|
If any signature matches the arguments then they'll be considered valid.
|
49 |
|
|
|
50 |
|
|
So for example, say you wanted to write a signature for
|
51 |
|
|
`fs.createWriteStream`. The docs for it describe it thusly:
|
52 |
|
|
|
53 |
|
|
```
|
54 |
|
|
fs.createWriteStream(path[, options])
|
55 |
|
|
```
|
56 |
|
|
|
57 |
|
|
This would be a signature of `SO|S`. That is, a string and and object, or
|
58 |
|
|
just a string.
|
59 |
|
|
|
60 |
|
|
Now, if you read the full `fs` docs, you'll see that actually path can ALSO
|
61 |
|
|
be a buffer. And options can be a string, that is:
|
62 |
|
|
```
|
63 |
|
|
path <String> | <Buffer>
|
64 |
|
|
options <String> | <Object>
|
65 |
|
|
```
|
66 |
|
|
|
67 |
|
|
To reproduce this you have to fully enumerate all of the possible
|
68 |
|
|
combinations and that implies a signature of `SO|SS|OO|OS|S|O`. The
|
69 |
|
|
awkwardness is a feature: It reminds you of the complexity you're adding to
|
70 |
|
|
your API when you do this sort of thing.
|
71 |
|
|
|
72 |
|
|
|
73 |
|
|
### Browser support
|
74 |
|
|
|
75 |
|
|
This has no dependencies and should work in browsers, though you'll have
|
76 |
|
|
noisier stack traces.
|
77 |
|
|
|
78 |
|
|
### Why this exists
|
79 |
|
|
|
80 |
|
|
I wanted a very simple argument validator. It needed to do two things:
|
81 |
|
|
|
82 |
|
|
1. Be more concise and easier to use than assertions
|
83 |
|
|
|
84 |
|
|
2. Not encourage an infinite bikeshed of DSLs
|
85 |
|
|
|
86 |
|
|
This is why types are specified by a single character and there's no such
|
87 |
|
|
thing as an optional argument.
|
88 |
|
|
|
89 |
|
|
This is not intended to validate user data. This is specifically about
|
90 |
|
|
asserting the interface of your functions.
|
91 |
|
|
|
92 |
|
|
If you need greater validation, I encourage you to write them by hand or
|
93 |
|
|
look elsewhere.
|