├── .gitignore
├── .vscode
└── settings.json
├── README.md
├── package-lock.json
├── package.json
├── src
├── ext
│ ├── allow-null.ts
│ ├── index.ts
│ ├── strict-properties.ts
│ └── trim.ts
├── index.ts
├── schema.ts
├── util.ts
└── validator.ts
├── test-typedefs
├── tsconfig.json
└── typedefs.ts
├── test
├── allow-null.spec.ts
├── ext.spec.ts
├── index.spec.ts
├── mocha.opts
├── strict-properties.spec.ts
├── trim.spec.ts
└── tsconfig.json
├── tsconfig.json
├── tslint.json
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | lib/
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "typescript.tsdk": "node_modules/typescript/lib"
3 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Typed-JSON-Schema
2 | ------------------
3 |
4 |
5 | ## TypeScript-Friendly JSON-Schema Definitions
6 |
7 | This library is able to validate JSON-Schema at runtime, and also emit type definitions for the validated data. This means that if you define your data using our JSON-schema builder, you automatically get TypeScript safety on those types.
8 |
9 |
10 |
11 | ## Examples
12 |
13 | ### Schema generation:
14 |
15 | ``` typescript
16 | await validator.validate(string.minLength(3), 'asdf') // type: string
17 |
18 | await validator.validate(array(string.pattern(/\w+/))) // result type: string[]
19 |
20 | await validator.validate(object.required('a', 'b').properties({
21 | a: string,
22 | b: array(number)
23 | }) // result type: {a: string, b: number[] }
24 |
25 | ```
26 |
27 | ### Validation
28 |
29 | ```typescript
30 | import { schema, string, Validator } from 'typed-json-schema'
31 |
32 | const validator = new Validator()
33 |
34 | const StringOrNull = schema.type(['string', 'null'])
35 |
36 | const result = await validator.validate(StringOrNull, 'Hello'),
37 |
38 | result.toFixed(1) // error: Property 'toFixed' does not exist on type 'string'.
39 | result.toLowerCase() //error: object is possibly null
40 | result && validation.result.toLowerCase() //success!
41 |
42 | ```
43 |
44 |
45 | ## Usage
46 |
47 | ### Schema Creation
48 |
49 | In general, all [JSON-Schema keywords](https://spacetelescope.github.io/understanding-json-schema/reference/index.html) can be used as builders on the `schema` object.
50 |
51 | For example:
52 |
53 | ```typescript
54 | import { schema } from 'typed-json-schema'
55 |
56 | const mySchema = schema
57 | .type('string')
58 | .minLength(3)
59 | .pattern(/regex/)
60 | ```
61 |
62 | Refer to [JSON-Schema keywords](https://spacetelescope.github.io/understanding-json-schema/reference/index.html) for a list of available keywords.
63 |
64 | ### Shortcuts:
65 | ```typescript
66 | import { string, boolean, number, array, object }
67 |
68 | const mySchema = string //same as schema.type('string')
69 | const mySchema = number //same as schema.type('number')
70 | const mySchema = boolean //same as schema.type('boolean')
71 | const mySchema = array(string) //same as schema.type('array').items(string)
72 | const mySchema = object({ a: string, b: array(number) }) //same as schema.type('object').properties({ a: string, b: array(number) })
73 | ```
74 |
75 | ### Validation:
76 |
77 | Use a `Validator` to validate a json schema:
78 |
79 | ```typescript
80 | import { schema, Validator }
81 |
82 | const validator = new Validator({ coerceTypes: true }) //any AJV options can be supplied
83 | const result = await validator.validate(schema.type('number')) //result is a number
84 |
85 |
86 | ```
87 |
88 | see [AJV](http://epoberezkin.github.io/ajv/) for a list of options that can be passed to the validator.
89 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "typed-json-schema",
3 | "version": "4.0.4",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "@types/chai": {
8 | "version": "4.0.1",
9 | "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.0.1.tgz",
10 | "integrity": "sha512-DWrdkraJO+KvBB7+Jc6AuDd2+fwV6Z9iK8cqEEoYpcurYrH7GiUZmwjFuQIIWj5HhFz6NsSxdN72YMIHT7Fy2Q==",
11 | "dev": true
12 | },
13 | "@types/mocha": {
14 | "version": "2.2.41",
15 | "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.41.tgz",
16 | "integrity": "sha1-4nzwgXFT658nE7LT9saPHhw8pgg=",
17 | "dev": true
18 | },
19 | "ajv": {
20 | "version": "6.12.6",
21 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
22 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
23 | "requires": {
24 | "fast-deep-equal": "^3.1.1",
25 | "fast-json-stable-stringify": "^2.0.0",
26 | "json-schema-traverse": "^0.4.1",
27 | "uri-js": "^4.2.2"
28 | }
29 | },
30 | "ansi-regex": {
31 | "version": "2.1.1",
32 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
33 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
34 | "dev": true
35 | },
36 | "ansi-styles": {
37 | "version": "3.2.1",
38 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
39 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
40 | "dev": true,
41 | "requires": {
42 | "color-convert": "^1.9.0"
43 | }
44 | },
45 | "arrify": {
46 | "version": "1.0.1",
47 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
48 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
49 | "dev": true
50 | },
51 | "assertion-error": {
52 | "version": "1.1.0",
53 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
54 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
55 | "dev": true
56 | },
57 | "babel-code-frame": {
58 | "version": "6.26.0",
59 | "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
60 | "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
61 | "dev": true,
62 | "requires": {
63 | "chalk": "^1.1.3",
64 | "esutils": "^2.0.2",
65 | "js-tokens": "^3.0.2"
66 | },
67 | "dependencies": {
68 | "ansi-styles": {
69 | "version": "2.2.1",
70 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
71 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
72 | "dev": true
73 | },
74 | "chalk": {
75 | "version": "1.1.3",
76 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
77 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
78 | "dev": true,
79 | "requires": {
80 | "ansi-styles": "^2.2.1",
81 | "escape-string-regexp": "^1.0.2",
82 | "has-ansi": "^2.0.0",
83 | "strip-ansi": "^3.0.0",
84 | "supports-color": "^2.0.0"
85 | }
86 | },
87 | "supports-color": {
88 | "version": "2.0.0",
89 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
90 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
91 | "dev": true
92 | }
93 | }
94 | },
95 | "balanced-match": {
96 | "version": "1.0.0",
97 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
98 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
99 | "dev": true
100 | },
101 | "brace-expansion": {
102 | "version": "1.1.11",
103 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
104 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
105 | "dev": true,
106 | "requires": {
107 | "balanced-match": "^1.0.0",
108 | "concat-map": "0.0.1"
109 | }
110 | },
111 | "browser-stdout": {
112 | "version": "1.3.0",
113 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz",
114 | "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=",
115 | "dev": true
116 | },
117 | "camelcase": {
118 | "version": "3.0.0",
119 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
120 | "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
121 | "dev": true
122 | },
123 | "chai": {
124 | "version": "4.1.0",
125 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.0.tgz",
126 | "integrity": "sha1-MxoDkbVcOvh0CunDt0WLwcOAXm0=",
127 | "dev": true,
128 | "requires": {
129 | "assertion-error": "^1.0.1",
130 | "check-error": "^1.0.1",
131 | "deep-eql": "^2.0.1",
132 | "get-func-name": "^2.0.0",
133 | "pathval": "^1.0.0",
134 | "type-detect": "^4.0.0"
135 | }
136 | },
137 | "chalk": {
138 | "version": "2.4.2",
139 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
140 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
141 | "dev": true,
142 | "requires": {
143 | "ansi-styles": "^3.2.1",
144 | "escape-string-regexp": "^1.0.5",
145 | "supports-color": "^5.3.0"
146 | },
147 | "dependencies": {
148 | "has-flag": {
149 | "version": "3.0.0",
150 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
151 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
152 | "dev": true
153 | },
154 | "supports-color": {
155 | "version": "5.5.0",
156 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
157 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
158 | "dev": true,
159 | "requires": {
160 | "has-flag": "^3.0.0"
161 | }
162 | }
163 | }
164 | },
165 | "check-error": {
166 | "version": "1.0.2",
167 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
168 | "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
169 | "dev": true
170 | },
171 | "cliui": {
172 | "version": "3.2.0",
173 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
174 | "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
175 | "dev": true,
176 | "requires": {
177 | "string-width": "^1.0.1",
178 | "strip-ansi": "^3.0.1",
179 | "wrap-ansi": "^2.0.0"
180 | }
181 | },
182 | "code-point-at": {
183 | "version": "1.1.0",
184 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
185 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
186 | "dev": true
187 | },
188 | "color-convert": {
189 | "version": "1.9.3",
190 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
191 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
192 | "dev": true,
193 | "requires": {
194 | "color-name": "1.1.3"
195 | }
196 | },
197 | "color-name": {
198 | "version": "1.1.3",
199 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
200 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
201 | "dev": true
202 | },
203 | "colors": {
204 | "version": "1.4.0",
205 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
206 | "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
207 | "dev": true
208 | },
209 | "commander": {
210 | "version": "2.9.0",
211 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
212 | "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
213 | "dev": true,
214 | "requires": {
215 | "graceful-readlink": ">= 1.0.0"
216 | }
217 | },
218 | "concat-map": {
219 | "version": "0.0.1",
220 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
221 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
222 | "dev": true
223 | },
224 | "cross-env": {
225 | "version": "5.0.5",
226 | "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.0.5.tgz",
227 | "integrity": "sha1-Q4PTZNlmCHPdGFs5ivO/717//vM=",
228 | "dev": true,
229 | "requires": {
230 | "cross-spawn": "^5.1.0",
231 | "is-windows": "^1.0.0"
232 | }
233 | },
234 | "cross-spawn": {
235 | "version": "5.1.0",
236 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
237 | "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
238 | "dev": true,
239 | "requires": {
240 | "lru-cache": "^4.0.1",
241 | "shebang-command": "^1.2.0",
242 | "which": "^1.2.9"
243 | }
244 | },
245 | "debug": {
246 | "version": "2.6.0",
247 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz",
248 | "integrity": "sha1-vFlryr52F/Edn6FTYe3tVgi4SZs=",
249 | "dev": true,
250 | "requires": {
251 | "ms": "0.7.2"
252 | }
253 | },
254 | "decamelize": {
255 | "version": "1.2.0",
256 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
257 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
258 | "dev": true
259 | },
260 | "deep-eql": {
261 | "version": "2.0.2",
262 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-2.0.2.tgz",
263 | "integrity": "sha1-sbrAblbwp2d3aG1Qyf63XC7XZ5o=",
264 | "dev": true,
265 | "requires": {
266 | "type-detect": "^3.0.0"
267 | },
268 | "dependencies": {
269 | "type-detect": {
270 | "version": "3.0.0",
271 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-3.0.0.tgz",
272 | "integrity": "sha1-RtDMhVOrt7E6NSsNbeov1Y8tm1U=",
273 | "dev": true
274 | }
275 | }
276 | },
277 | "diff": {
278 | "version": "3.2.0",
279 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz",
280 | "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=",
281 | "dev": true
282 | },
283 | "error-ex": {
284 | "version": "1.3.2",
285 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
286 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
287 | "dev": true,
288 | "requires": {
289 | "is-arrayish": "^0.2.1"
290 | }
291 | },
292 | "escape-string-regexp": {
293 | "version": "1.0.5",
294 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
295 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
296 | "dev": true
297 | },
298 | "esutils": {
299 | "version": "2.0.3",
300 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
301 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
302 | "dev": true
303 | },
304 | "fast-deep-equal": {
305 | "version": "3.1.3",
306 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
307 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
308 | },
309 | "fast-json-stable-stringify": {
310 | "version": "2.1.0",
311 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
312 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
313 | },
314 | "find-up": {
315 | "version": "1.1.2",
316 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
317 | "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
318 | "dev": true,
319 | "requires": {
320 | "path-exists": "^2.0.0",
321 | "pinkie-promise": "^2.0.0"
322 | }
323 | },
324 | "fs.realpath": {
325 | "version": "1.0.0",
326 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
327 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
328 | "dev": true
329 | },
330 | "function-bind": {
331 | "version": "1.1.1",
332 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
333 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
334 | "dev": true
335 | },
336 | "get-caller-file": {
337 | "version": "1.0.3",
338 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
339 | "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
340 | "dev": true
341 | },
342 | "get-func-name": {
343 | "version": "2.0.0",
344 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
345 | "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
346 | "dev": true
347 | },
348 | "glob": {
349 | "version": "7.1.1",
350 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz",
351 | "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=",
352 | "dev": true,
353 | "requires": {
354 | "fs.realpath": "^1.0.0",
355 | "inflight": "^1.0.4",
356 | "inherits": "2",
357 | "minimatch": "^3.0.2",
358 | "once": "^1.3.0",
359 | "path-is-absolute": "^1.0.0"
360 | }
361 | },
362 | "graceful-fs": {
363 | "version": "4.2.4",
364 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
365 | "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
366 | "dev": true
367 | },
368 | "graceful-readlink": {
369 | "version": "1.0.1",
370 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
371 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
372 | "dev": true
373 | },
374 | "growl": {
375 | "version": "1.9.2",
376 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz",
377 | "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=",
378 | "dev": true
379 | },
380 | "has": {
381 | "version": "1.0.3",
382 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
383 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
384 | "dev": true,
385 | "requires": {
386 | "function-bind": "^1.1.1"
387 | }
388 | },
389 | "has-ansi": {
390 | "version": "2.0.0",
391 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
392 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
393 | "dev": true,
394 | "requires": {
395 | "ansi-regex": "^2.0.0"
396 | }
397 | },
398 | "has-flag": {
399 | "version": "1.0.0",
400 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
401 | "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
402 | "dev": true
403 | },
404 | "homedir-polyfill": {
405 | "version": "1.0.3",
406 | "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
407 | "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
408 | "dev": true,
409 | "requires": {
410 | "parse-passwd": "^1.0.0"
411 | }
412 | },
413 | "hosted-git-info": {
414 | "version": "2.8.8",
415 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
416 | "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
417 | "dev": true
418 | },
419 | "inflight": {
420 | "version": "1.0.6",
421 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
422 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
423 | "dev": true,
424 | "requires": {
425 | "once": "^1.3.0",
426 | "wrappy": "1"
427 | }
428 | },
429 | "inherits": {
430 | "version": "2.0.4",
431 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
432 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
433 | "dev": true
434 | },
435 | "invert-kv": {
436 | "version": "1.0.0",
437 | "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
438 | "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
439 | "dev": true
440 | },
441 | "is-arrayish": {
442 | "version": "0.2.1",
443 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
444 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
445 | "dev": true
446 | },
447 | "is-core-module": {
448 | "version": "2.0.0",
449 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.0.0.tgz",
450 | "integrity": "sha512-jq1AH6C8MuteOoBPwkxHafmByhL9j5q4OaPGdbuD+ZtQJVzH+i6E3BJDQcBA09k57i2Hh2yQbEG8yObZ0jdlWw==",
451 | "dev": true,
452 | "requires": {
453 | "has": "^1.0.3"
454 | }
455 | },
456 | "is-fullwidth-code-point": {
457 | "version": "1.0.0",
458 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
459 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
460 | "dev": true,
461 | "requires": {
462 | "number-is-nan": "^1.0.0"
463 | }
464 | },
465 | "is-utf8": {
466 | "version": "0.2.1",
467 | "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
468 | "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
469 | "dev": true
470 | },
471 | "is-windows": {
472 | "version": "1.0.2",
473 | "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
474 | "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
475 | "dev": true
476 | },
477 | "isexe": {
478 | "version": "2.0.0",
479 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
480 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
481 | "dev": true
482 | },
483 | "js-tokens": {
484 | "version": "3.0.2",
485 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
486 | "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
487 | "dev": true
488 | },
489 | "json-schema-traverse": {
490 | "version": "0.4.1",
491 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
492 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
493 | },
494 | "json3": {
495 | "version": "3.3.2",
496 | "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz",
497 | "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=",
498 | "dev": true
499 | },
500 | "lcid": {
501 | "version": "1.0.0",
502 | "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
503 | "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
504 | "dev": true,
505 | "requires": {
506 | "invert-kv": "^1.0.0"
507 | }
508 | },
509 | "load-json-file": {
510 | "version": "1.1.0",
511 | "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
512 | "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
513 | "dev": true,
514 | "requires": {
515 | "graceful-fs": "^4.1.2",
516 | "parse-json": "^2.2.0",
517 | "pify": "^2.0.0",
518 | "pinkie-promise": "^2.0.0",
519 | "strip-bom": "^2.0.0"
520 | },
521 | "dependencies": {
522 | "strip-bom": {
523 | "version": "2.0.0",
524 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
525 | "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
526 | "dev": true,
527 | "requires": {
528 | "is-utf8": "^0.2.0"
529 | }
530 | }
531 | }
532 | },
533 | "lodash": {
534 | "version": "4.17.20",
535 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
536 | "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
537 | "dev": true
538 | },
539 | "lodash._baseassign": {
540 | "version": "3.2.0",
541 | "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz",
542 | "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=",
543 | "dev": true,
544 | "requires": {
545 | "lodash._basecopy": "^3.0.0",
546 | "lodash.keys": "^3.0.0"
547 | }
548 | },
549 | "lodash._basecopy": {
550 | "version": "3.0.1",
551 | "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
552 | "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=",
553 | "dev": true
554 | },
555 | "lodash._basecreate": {
556 | "version": "3.0.3",
557 | "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz",
558 | "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=",
559 | "dev": true
560 | },
561 | "lodash._getnative": {
562 | "version": "3.9.1",
563 | "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
564 | "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=",
565 | "dev": true
566 | },
567 | "lodash._isiterateecall": {
568 | "version": "3.0.9",
569 | "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz",
570 | "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=",
571 | "dev": true
572 | },
573 | "lodash.create": {
574 | "version": "3.1.1",
575 | "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz",
576 | "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=",
577 | "dev": true,
578 | "requires": {
579 | "lodash._baseassign": "^3.0.0",
580 | "lodash._basecreate": "^3.0.0",
581 | "lodash._isiterateecall": "^3.0.0"
582 | }
583 | },
584 | "lodash.isarguments": {
585 | "version": "3.1.0",
586 | "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
587 | "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=",
588 | "dev": true
589 | },
590 | "lodash.isarray": {
591 | "version": "3.0.4",
592 | "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
593 | "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=",
594 | "dev": true
595 | },
596 | "lodash.keys": {
597 | "version": "3.1.2",
598 | "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
599 | "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
600 | "dev": true,
601 | "requires": {
602 | "lodash._getnative": "^3.0.0",
603 | "lodash.isarguments": "^3.0.0",
604 | "lodash.isarray": "^3.0.0"
605 | }
606 | },
607 | "lru-cache": {
608 | "version": "4.1.5",
609 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
610 | "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
611 | "dev": true,
612 | "requires": {
613 | "pseudomap": "^1.0.2",
614 | "yallist": "^2.1.2"
615 | }
616 | },
617 | "make-error": {
618 | "version": "1.3.6",
619 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
620 | "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
621 | "dev": true
622 | },
623 | "minimatch": {
624 | "version": "3.0.4",
625 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
626 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
627 | "dev": true,
628 | "requires": {
629 | "brace-expansion": "^1.1.7"
630 | }
631 | },
632 | "minimist": {
633 | "version": "0.0.8",
634 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
635 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
636 | "dev": true
637 | },
638 | "mkdirp": {
639 | "version": "0.5.1",
640 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
641 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
642 | "dev": true,
643 | "requires": {
644 | "minimist": "0.0.8"
645 | }
646 | },
647 | "mocha": {
648 | "version": "3.4.2",
649 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.4.2.tgz",
650 | "integrity": "sha1-0O9NMyEm2/GNDWQMmzgt1IvpdZQ=",
651 | "dev": true,
652 | "requires": {
653 | "browser-stdout": "1.3.0",
654 | "commander": "2.9.0",
655 | "debug": "2.6.0",
656 | "diff": "3.2.0",
657 | "escape-string-regexp": "1.0.5",
658 | "glob": "7.1.1",
659 | "growl": "1.9.2",
660 | "json3": "3.3.2",
661 | "lodash.create": "3.1.1",
662 | "mkdirp": "0.5.1",
663 | "supports-color": "3.1.2"
664 | }
665 | },
666 | "ms": {
667 | "version": "0.7.2",
668 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
669 | "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
670 | "dev": true
671 | },
672 | "normalize-package-data": {
673 | "version": "2.5.0",
674 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
675 | "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
676 | "dev": true,
677 | "requires": {
678 | "hosted-git-info": "^2.1.4",
679 | "resolve": "^1.10.0",
680 | "semver": "2 || 3 || 4 || 5",
681 | "validate-npm-package-license": "^3.0.1"
682 | }
683 | },
684 | "number-is-nan": {
685 | "version": "1.0.1",
686 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
687 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
688 | "dev": true
689 | },
690 | "once": {
691 | "version": "1.4.0",
692 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
693 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
694 | "dev": true,
695 | "requires": {
696 | "wrappy": "1"
697 | }
698 | },
699 | "os-locale": {
700 | "version": "1.4.0",
701 | "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
702 | "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
703 | "dev": true,
704 | "requires": {
705 | "lcid": "^1.0.0"
706 | }
707 | },
708 | "parse-json": {
709 | "version": "2.2.0",
710 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
711 | "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
712 | "dev": true,
713 | "requires": {
714 | "error-ex": "^1.2.0"
715 | }
716 | },
717 | "parse-passwd": {
718 | "version": "1.0.0",
719 | "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
720 | "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
721 | "dev": true
722 | },
723 | "path-exists": {
724 | "version": "2.1.0",
725 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
726 | "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
727 | "dev": true,
728 | "requires": {
729 | "pinkie-promise": "^2.0.0"
730 | }
731 | },
732 | "path-is-absolute": {
733 | "version": "1.0.1",
734 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
735 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
736 | "dev": true
737 | },
738 | "path-parse": {
739 | "version": "1.0.6",
740 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
741 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
742 | "dev": true
743 | },
744 | "path-type": {
745 | "version": "1.1.0",
746 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
747 | "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
748 | "dev": true,
749 | "requires": {
750 | "graceful-fs": "^4.1.2",
751 | "pify": "^2.0.0",
752 | "pinkie-promise": "^2.0.0"
753 | }
754 | },
755 | "pathval": {
756 | "version": "1.1.0",
757 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
758 | "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=",
759 | "dev": true
760 | },
761 | "pify": {
762 | "version": "2.3.0",
763 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
764 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
765 | "dev": true
766 | },
767 | "pinkie": {
768 | "version": "2.0.4",
769 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
770 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
771 | "dev": true
772 | },
773 | "pinkie-promise": {
774 | "version": "2.0.1",
775 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
776 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
777 | "dev": true,
778 | "requires": {
779 | "pinkie": "^2.0.0"
780 | }
781 | },
782 | "pseudomap": {
783 | "version": "1.0.2",
784 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
785 | "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
786 | "dev": true
787 | },
788 | "punycode": {
789 | "version": "2.1.1",
790 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
791 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
792 | },
793 | "read-pkg": {
794 | "version": "1.1.0",
795 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
796 | "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
797 | "dev": true,
798 | "requires": {
799 | "load-json-file": "^1.0.0",
800 | "normalize-package-data": "^2.3.2",
801 | "path-type": "^1.0.0"
802 | }
803 | },
804 | "read-pkg-up": {
805 | "version": "1.0.1",
806 | "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
807 | "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
808 | "dev": true,
809 | "requires": {
810 | "find-up": "^1.0.0",
811 | "read-pkg": "^1.0.0"
812 | }
813 | },
814 | "require-directory": {
815 | "version": "2.1.1",
816 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
817 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
818 | "dev": true
819 | },
820 | "require-main-filename": {
821 | "version": "1.0.1",
822 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
823 | "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
824 | "dev": true
825 | },
826 | "resolve": {
827 | "version": "1.18.1",
828 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz",
829 | "integrity": "sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==",
830 | "dev": true,
831 | "requires": {
832 | "is-core-module": "^2.0.0",
833 | "path-parse": "^1.0.6"
834 | }
835 | },
836 | "semver": {
837 | "version": "5.7.1",
838 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
839 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
840 | "dev": true
841 | },
842 | "set-blocking": {
843 | "version": "2.0.0",
844 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
845 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
846 | "dev": true
847 | },
848 | "shebang-command": {
849 | "version": "1.2.0",
850 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
851 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
852 | "dev": true,
853 | "requires": {
854 | "shebang-regex": "^1.0.0"
855 | }
856 | },
857 | "shebang-regex": {
858 | "version": "1.0.0",
859 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
860 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
861 | "dev": true
862 | },
863 | "source-map": {
864 | "version": "0.5.7",
865 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
866 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
867 | "dev": true
868 | },
869 | "source-map-support": {
870 | "version": "0.4.18",
871 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
872 | "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
873 | "dev": true,
874 | "requires": {
875 | "source-map": "^0.5.6"
876 | }
877 | },
878 | "spdx-correct": {
879 | "version": "3.1.1",
880 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
881 | "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
882 | "dev": true,
883 | "requires": {
884 | "spdx-expression-parse": "^3.0.0",
885 | "spdx-license-ids": "^3.0.0"
886 | }
887 | },
888 | "spdx-exceptions": {
889 | "version": "2.3.0",
890 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
891 | "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
892 | "dev": true
893 | },
894 | "spdx-expression-parse": {
895 | "version": "3.0.1",
896 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
897 | "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
898 | "dev": true,
899 | "requires": {
900 | "spdx-exceptions": "^2.1.0",
901 | "spdx-license-ids": "^3.0.0"
902 | }
903 | },
904 | "spdx-license-ids": {
905 | "version": "3.0.6",
906 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz",
907 | "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==",
908 | "dev": true
909 | },
910 | "string-width": {
911 | "version": "1.0.2",
912 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
913 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
914 | "dev": true,
915 | "requires": {
916 | "code-point-at": "^1.0.0",
917 | "is-fullwidth-code-point": "^1.0.0",
918 | "strip-ansi": "^3.0.0"
919 | }
920 | },
921 | "strip-ansi": {
922 | "version": "3.0.1",
923 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
924 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
925 | "dev": true,
926 | "requires": {
927 | "ansi-regex": "^2.0.0"
928 | }
929 | },
930 | "strip-bom": {
931 | "version": "3.0.0",
932 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
933 | "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
934 | "dev": true
935 | },
936 | "strip-json-comments": {
937 | "version": "2.0.1",
938 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
939 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
940 | "dev": true
941 | },
942 | "supports-color": {
943 | "version": "3.1.2",
944 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz",
945 | "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=",
946 | "dev": true,
947 | "requires": {
948 | "has-flag": "^1.0.0"
949 | }
950 | },
951 | "ts-node": {
952 | "version": "3.3.0",
953 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-3.3.0.tgz",
954 | "integrity": "sha1-wTxqMCTjC+EYDdUwOPwgkonUv2k=",
955 | "dev": true,
956 | "requires": {
957 | "arrify": "^1.0.0",
958 | "chalk": "^2.0.0",
959 | "diff": "^3.1.0",
960 | "make-error": "^1.1.1",
961 | "minimist": "^1.2.0",
962 | "mkdirp": "^0.5.1",
963 | "source-map-support": "^0.4.0",
964 | "tsconfig": "^6.0.0",
965 | "v8flags": "^3.0.0",
966 | "yn": "^2.0.0"
967 | },
968 | "dependencies": {
969 | "minimist": {
970 | "version": "1.2.5",
971 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
972 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
973 | "dev": true
974 | }
975 | }
976 | },
977 | "tsconfig": {
978 | "version": "6.0.0",
979 | "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-6.0.0.tgz",
980 | "integrity": "sha1-aw6DdgA9evGGT434+J3QBZ/80DI=",
981 | "dev": true,
982 | "requires": {
983 | "strip-bom": "^3.0.0",
984 | "strip-json-comments": "^2.0.0"
985 | }
986 | },
987 | "tslib": {
988 | "version": "1.14.1",
989 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
990 | "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
991 | "dev": true
992 | },
993 | "tslint": {
994 | "version": "5.7.0",
995 | "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.7.0.tgz",
996 | "integrity": "sha1-wl4NDJL6EgHCvDDoROCOaCtPNVI=",
997 | "dev": true,
998 | "requires": {
999 | "babel-code-frame": "^6.22.0",
1000 | "colors": "^1.1.2",
1001 | "commander": "^2.9.0",
1002 | "diff": "^3.2.0",
1003 | "glob": "^7.1.1",
1004 | "minimatch": "^3.0.4",
1005 | "resolve": "^1.3.2",
1006 | "semver": "^5.3.0",
1007 | "tslib": "^1.7.1",
1008 | "tsutils": "^2.8.1"
1009 | }
1010 | },
1011 | "tsutils": {
1012 | "version": "2.29.0",
1013 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
1014 | "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
1015 | "dev": true,
1016 | "requires": {
1017 | "tslib": "^1.8.1"
1018 | }
1019 | },
1020 | "type-detect": {
1021 | "version": "4.0.8",
1022 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
1023 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
1024 | "dev": true
1025 | },
1026 | "typescript": {
1027 | "version": "2.5.3",
1028 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.5.3.tgz",
1029 | "integrity": "sha512-ptLSQs2S4QuS6/OD1eAKG+S5G8QQtrU5RT32JULdZQtM1L3WTi34Wsu48Yndzi8xsObRAB9RPt/KhA9wlpEF6w==",
1030 | "dev": true
1031 | },
1032 | "typings-checker": {
1033 | "version": "2.0.0",
1034 | "resolved": "https://registry.npmjs.org/typings-checker/-/typings-checker-2.0.0.tgz",
1035 | "integrity": "sha1-xtWvD/P8cGXaIqaTPhKQ0Wr2zFY=",
1036 | "dev": true,
1037 | "requires": {
1038 | "lodash": "^4.17.4",
1039 | "yargs": "^6.6.0"
1040 | }
1041 | },
1042 | "uri-js": {
1043 | "version": "4.4.0",
1044 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz",
1045 | "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==",
1046 | "requires": {
1047 | "punycode": "^2.1.0"
1048 | }
1049 | },
1050 | "v8flags": {
1051 | "version": "3.2.0",
1052 | "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz",
1053 | "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==",
1054 | "dev": true,
1055 | "requires": {
1056 | "homedir-polyfill": "^1.0.1"
1057 | }
1058 | },
1059 | "validate-npm-package-license": {
1060 | "version": "3.0.4",
1061 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
1062 | "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
1063 | "dev": true,
1064 | "requires": {
1065 | "spdx-correct": "^3.0.0",
1066 | "spdx-expression-parse": "^3.0.0"
1067 | }
1068 | },
1069 | "which": {
1070 | "version": "1.3.1",
1071 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
1072 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
1073 | "dev": true,
1074 | "requires": {
1075 | "isexe": "^2.0.0"
1076 | }
1077 | },
1078 | "which-module": {
1079 | "version": "1.0.0",
1080 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
1081 | "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
1082 | "dev": true
1083 | },
1084 | "wrap-ansi": {
1085 | "version": "2.1.0",
1086 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
1087 | "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
1088 | "dev": true,
1089 | "requires": {
1090 | "string-width": "^1.0.1",
1091 | "strip-ansi": "^3.0.1"
1092 | }
1093 | },
1094 | "wrappy": {
1095 | "version": "1.0.2",
1096 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1097 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
1098 | "dev": true
1099 | },
1100 | "y18n": {
1101 | "version": "3.2.1",
1102 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
1103 | "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
1104 | "dev": true
1105 | },
1106 | "yallist": {
1107 | "version": "2.1.2",
1108 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
1109 | "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
1110 | "dev": true
1111 | },
1112 | "yargs": {
1113 | "version": "6.6.0",
1114 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz",
1115 | "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=",
1116 | "dev": true,
1117 | "requires": {
1118 | "camelcase": "^3.0.0",
1119 | "cliui": "^3.2.0",
1120 | "decamelize": "^1.1.1",
1121 | "get-caller-file": "^1.0.1",
1122 | "os-locale": "^1.4.0",
1123 | "read-pkg-up": "^1.0.1",
1124 | "require-directory": "^2.1.1",
1125 | "require-main-filename": "^1.0.1",
1126 | "set-blocking": "^2.0.0",
1127 | "string-width": "^1.0.2",
1128 | "which-module": "^1.0.0",
1129 | "y18n": "^3.2.1",
1130 | "yargs-parser": "^4.2.0"
1131 | }
1132 | },
1133 | "yargs-parser": {
1134 | "version": "4.2.1",
1135 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz",
1136 | "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=",
1137 | "dev": true,
1138 | "requires": {
1139 | "camelcase": "^3.0.0"
1140 | }
1141 | },
1142 | "yn": {
1143 | "version": "2.0.0",
1144 | "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz",
1145 | "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=",
1146 | "dev": true
1147 | }
1148 | }
1149 | }
1150 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "typed-json-schema",
3 | "version": "4.0.5",
4 | "description": "",
5 | "main": "index",
6 | "typings": "index.d.ts",
7 | "scripts": {
8 | "mocha": "cross-env TS_NODE_CACHE=false mocha test/**/*.spec.ts",
9 | "test-typedefs": "typings-checker --project test-typedefs/tsconfig.json --allow-expect-error test-typedefs/*.ts",
10 | "lint": "tslint --project . && tslint --project test && tslint --project test-typedefs",
11 | "test": "npm run mocha && npm run test-typedefs && npm run lint",
12 | "clean": "rm *.js *.d.ts; rm -rf ext/;true",
13 | "tsc": "tsc --declaration",
14 | "build": "npm run clean && npm run tsc",
15 | "prepublish": "npm test && npm run build",
16 | "postpublish": "npm run clean"
17 | },
18 | "files": [
19 | "*.js",
20 | "*.d.ts",
21 | "ext"
22 | ],
23 | "author": "Sam Beran (sberan@gmail.com)",
24 | "license": "MIT",
25 | "repository": {
26 | "type": "git",
27 | "url": "git@github.com:sberan/typed-json-schema.git"
28 | },
29 | "dependencies": {
30 | "ajv": "6.12.6"
31 | },
32 | "devDependencies": {
33 | "@types/chai": "4.0.1",
34 | "@types/mocha": "2.2.41",
35 | "chai": "4.1.0",
36 | "cross-env": "5.0.5",
37 | "mocha": "3.4.2",
38 | "ts-node": "3.3.0",
39 | "tslint": "5.7.0",
40 | "typescript": "2.5",
41 | "typings-checker": "2.0.0"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/ext/allow-null.ts:
--------------------------------------------------------------------------------
1 | import { Schema } from '../schema'
2 | import { Diff, JSONObject } from '../util'
3 | import { CustomKeyword } from '../validator'
4 |
5 | declare module '../schema' {
6 | interface Schema {
7 | allowNull (): SchemaUpdate
8 | }
9 | }
10 |
11 | Schema.prototype.allowNull = function () {
12 | const
13 | props = this.props,
14 | enums = props.enum
15 |
16 | let type = props.type
17 |
18 | if (Array.isArray(enums) && !enums.includes(null)) {
19 | enums.push(null)
20 | }
21 | if (!type || type === 'null') {
22 | return this
23 | }
24 | if (!Array.isArray(type)) {
25 | type = [type]
26 | }
27 | if (!type.includes('null')) {
28 | type.push('null')
29 | }
30 | return this.setProps({ type })
31 | }
32 |
33 | export const allowNull = []
34 |
--------------------------------------------------------------------------------
/src/ext/index.ts:
--------------------------------------------------------------------------------
1 | import { CustomKeywords } from '../validator'
2 | import './allow-null'
3 | import { allowNull } from './allow-null'
4 | import './strict-properties'
5 | import { strictProperties } from './strict-properties'
6 | import './trim'
7 | import { trim } from './trim'
8 |
9 | export { CustomKeyword } from '../validator'
10 |
11 | export const ext: CustomKeywords = [
12 | allowNull,
13 | strictProperties,
14 | trim
15 | ]
16 |
17 | export * from '../index'
18 |
--------------------------------------------------------------------------------
/src/ext/strict-properties.ts:
--------------------------------------------------------------------------------
1 | import { Schema } from '../schema'
2 | import { Diff, JSONObject } from '../util'
3 | import { CustomKeyword } from '../validator'
4 |
5 | declare module '../schema' {
6 | interface TypeDefs {
7 | strictObject: {[P in Diff]: State['strictProperties'][P] }
8 | & {[P in State['optional']]?: State['strictProperties'][P] }
9 | }
10 |
11 | interface SchemaState {
12 | strictProperties: any
13 | optional: string
14 | }
15 |
16 | interface DefaultSchemaState {
17 | strictProperties: {}
18 | optional: never
19 | }
20 |
21 | interface Schema {
22 | strictProperties}> (properties: Properties)
23 | : SchemaMultiUpdate
27 |
28 | optional (...properties: Properties[])
29 | : SchemaUpdate
30 | }
31 | }
32 |
33 | Schema.prototype.strictProperties = function (strictProperties): any {
34 | const
35 | optional = this.getState('optional') as string[] | undefined,
36 | strictKeys = Object.keys(strictProperties).filter(p => {
37 | return !optional || optional.indexOf(p) < 0
38 | })
39 | return this
40 | .properties(strictProperties)
41 | .additionalProperties(false)
42 | .required(...strictKeys)
43 | }
44 |
45 | Schema.prototype.optional = function (...properties): any {
46 | this.setState('optional', properties)
47 | const props = this.props,
48 | existingRequireds = props && props.required
49 | if (Array.isArray(existingRequireds)) {
50 | properties.forEach(property => {
51 | const existingIndex = existingRequireds.indexOf(property)
52 | if (existingIndex !== -1) {
53 | existingRequireds.splice(existingIndex, 1)
54 | }
55 | })
56 | }
57 | return this
58 | }
59 |
60 | export const strictProperties = []
61 |
--------------------------------------------------------------------------------
/src/ext/trim.ts:
--------------------------------------------------------------------------------
1 | import { Schema } from '../schema'
2 | import { CustomKeyword } from '../validator'
3 |
4 | declare module '../schema' {
5 | interface Schema {
6 | trim (trim?: boolean): Schema
7 | }
8 | }
9 |
10 | Schema.prototype.trim = function (trim = true) {
11 | return this.setProps({ trim })
12 | }
13 |
14 | export const trim: CustomKeyword = {
15 | name: 'trim',
16 | modifying: true,
17 | validate: (
18 | schema: any,
19 | data: any,
20 | parentSchema?: object,
21 | dataPath?: string,
22 | parentData?: object | any[],
23 | parentDataProperty?: string | number,
24 | rootData?: object | any[]
25 | ) => {
26 | if (typeof data === 'string' && parentData !== undefined && parentDataProperty !== undefined) {
27 | const trimmedString = data.trim();
28 | (parentData as any)[parentDataProperty] = trimmedString
29 | }
30 | return true
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import { Schema } from './schema'
2 | import { DefaultSchemaState } from './schema'
3 | import { callableInstance } from './util'
4 |
5 | export { Schema } from './schema'
6 | export { Validator, ValidationError } from './validator'
7 |
8 | export type schema> = T['TypeOf']
9 |
10 | export const
11 | schema = new Schema(),
12 | number = schema.type('number'), // tslint:disable-line:variable-name
13 | integer = schema.type('integer'),
14 | string = schema.type('string'), // tslint:disable-line:variable-name
15 | boolean = schema.type('boolean'), // tslint:disable-line:variable-name
16 | array = callableInstance(schema.type('array'), 'items'),
17 | object = callableInstance(schema.type('object'), 'properties')
18 |
--------------------------------------------------------------------------------
/src/schema.ts:
--------------------------------------------------------------------------------
1 | import { AnyJSON, copyJson, Diff, JSONObject, Omit, Overwrite } from './util'
2 |
3 | export type SchemaUpdate<
4 | State extends SchemaState, K extends keyof SchemaState,
5 | V extends SchemaState[K]
6 | > = Schema & {[P in K]: V}>
7 |
8 | export type SchemaMultiUpdate<
9 | State extends SchemaState,
10 | K extends keyof SchemaState,
11 | U extends {[P in K]: SchemaState[P]}
12 | > = Schema>
13 |
14 | export type TypeNames = 'string' | 'number' | 'integer' | 'boolean' | 'null' | 'array' | 'object'
15 |
16 | export interface TypeDefs {
17 | any: any
18 | string: string
19 | number: number
20 | integer: number
21 | boolean: boolean
22 | null: null
23 | array: Array
24 | object: State['anyOf'] & State['oneOf'] & State['allOf']
25 | & {[P in State['required']]: State['properties'][P]}
26 | & {[P in Diff]?: State['properties'][P] }
27 | & {[P in State['additionalProperties']['key'] | State['patternProperties']['key']]
28 | ?: State['additionalProperties']['type'] | State['patternProperties']['type'] },
29 | enum: State['enum']
30 | const: State['const']
31 | }
32 |
33 | export interface SchemaState {
34 | type: keyof TypeDefs
35 | items: any
36 | additionalItems: any
37 | properties: any
38 | required: string
39 | additionalProperties: {key: string, type: any}
40 | patternProperties: {key: string, type: any}
41 | enum: any
42 | anyOf: any
43 | oneOf: any
44 | allOf: any
45 | const: any
46 | }
47 |
48 | export interface DefaultSchemaState {
49 | type: 'any'
50 | items: any
51 | additionalItems: never
52 | properties: any
53 | required: never
54 | additionalProperties: {key: string, type: any}
55 | patternProperties: {key: never, type: never}
56 | enum: any
57 | const: any
58 | anyOf: {}
59 | oneOf: {}
60 | allOf: {}
61 | }
62 |
63 | export class Schema {
64 | TypeOf: TypeDefs[State['type']]
65 |
66 | constructor (readonly props: JSONObject = {}, private readonly state: JSONObject = {}) { }
67 |
68 | setProps (props: JSONObject): any {
69 | return new Schema({ ...copyJson(this.props), ...props }, { ...this.state })
70 | }
71 |
72 | getState (key: string) {
73 | return this.state[key]
74 | }
75 |
76 | setState (key: string, val: AnyJSON) {
77 | this.state[key] = val
78 | }
79 |
80 | toJSON () {
81 | return copyJson(this.props)
82 | }
83 |
84 | /*======================
85 | GLOBAL
86 | ========================*/
87 | type (type: TypeKeys[] | TypeKeys): SchemaUpdate {
88 | return this.setProps({ type })
89 | }
90 |
91 | enum (values: T[]): SchemaMultiUpdate {
92 | return this.setProps({ enum: values })
93 | }
94 |
95 | const (constValue: T): SchemaMultiUpdate {
96 | return this.setProps({ const: constValue })
97 | }
98 |
99 | anyOf> (schemas: S[]): SchemaUpdate {
100 | return this.setProps({ anyOf: schemas.map((s) => s.props) })
101 | }
102 |
103 | oneOf> (schemas: S[]): SchemaUpdate {
104 | return this.setProps({ oneOf: schemas.map((s) => s.props) })
105 | }
106 |
107 | // TODO: these should be intersection types but that doesn't work :(
108 | allOf> (schemas: S[]): SchemaUpdate {
109 | return this.setProps({ allOf: schemas.map((s) => s.props) })
110 | }
111 |
112 | title (title: string): this {
113 | return this.setProps({ title })
114 | }
115 |
116 | description (description: string): this {
117 | return this.setProps({ description })
118 | }
119 |
120 | default (defaultValue: AnyJSON): this {
121 | return this.setProps({ default: defaultValue })
122 | }
123 |
124 | example> (example: S['TypeOf']): this {
125 | return this.setProps({ example })
126 | }
127 |
128 | not (schema: Schema): this {
129 | return this.setProps({ not: schema.props })
130 | }
131 |
132 | /*============
133 | Array
134 | =============*/
135 | items> (items: ItemsSchema[] | ItemsSchema)
136 | : SchemaUpdate {
137 | if (Array.isArray(items)) {
138 | return this.setProps({ items: items.map((i) => i.props)})
139 | } else {
140 | return this.setProps({ items: items.props })
141 | }
142 | }
143 |
144 | additionalItems (additionalItems: true): SchemaUpdate
145 | additionalItems (additionalItems: false): this
146 | additionalItems> (additionalItems: ItemsSchema)
147 | : SchemaUpdate
148 | additionalItems> (additionalItems: boolean | ItemsSchema) {
149 | if (additionalItems === true) {
150 | return this.setProps({ additionalItems: true })
151 | } else if (additionalItems === false) {
152 | return this
153 | } else {
154 | return this.setProps({ additionalItems: additionalItems.props })
155 | }
156 | }
157 |
158 | contains (contains: Schema): this {
159 | return this.setProps({ contains: contains.props })
160 | }
161 |
162 | maxItems (maxItems: number): this {
163 | return this.setProps({ maxItems })
164 | }
165 |
166 | minItems (minItems: number): this {
167 | return this.setProps({ minItems })
168 | }
169 |
170 | uniqueItems (uniqueItems: boolean): this {
171 | return this.setProps({ uniqueItems })
172 | }
173 |
174 | /*===============
175 | OBJECT
176 | =================*/
177 | properties}> (properties: Properties)
178 | : SchemaUpdate {
179 | const props = Object.keys(properties).reduce((acc, key: keyof Properties) => {
180 | acc[key] = (properties[key] as Schema).props
181 | return acc
182 | }, {})
183 | return this.setProps({ properties: props })
184 | }
185 |
186 | required (...required: K[]): SchemaUpdate {
187 | return this.setProps({ required })
188 | }
189 |
190 | additionalProperties (additionalProperties: true)
191 | : SchemaUpdate
192 | additionalProperties (additionalProperties: false)
193 | : SchemaUpdate
194 | additionalProperties> (additionalProperties: T)
195 | : SchemaUpdate
196 | additionalProperties (additionalProperties: boolean | Schema): any {
197 | if (additionalProperties instanceof Schema) {
198 | return this.setProps({ additionalProperties: additionalProperties.props })
199 | } else {
200 | return this.setProps({ additionalProperties })
201 | }
202 | }
203 |
204 | patternProperties> (patternProperties: { [key: string]: T })
205 | : SchemaUpdate {
206 | const props = Object.keys(patternProperties).reduce((acc, key: keyof typeof patternProperties) => {
207 | acc[key] = patternProperties[key].props
208 | return acc
209 | }, {})
210 | return this.setProps({ patternProperties: props })
211 | }
212 |
213 | dependencies (dependencies: {[key: string]: Schema | string[]}): this {
214 | const props = Object.keys(dependencies).reduce((acc, key) => {
215 | const value = dependencies[key]
216 | if (Array.isArray(value)) {
217 | acc[key] = value
218 | } else {
219 | acc[key] = value.props
220 | }
221 | return acc
222 | }, {})
223 | return this.setProps({ dependencies: props })
224 | }
225 |
226 | maxProperties (maxProperties: number): this {
227 | return this.setProps({ maxProperties })
228 | }
229 |
230 | minProperties (minProperties: number): this {
231 | return this.setProps({ minProperties })
232 | }
233 |
234 | /*===================
235 | NUMBER
236 | =====================*/
237 | maximum (maximum: number): this {
238 | return this.setProps({ maximum })
239 | }
240 |
241 | minimum (minimum: number): this {
242 | return this.setProps({ minimum })
243 | }
244 |
245 | exclusiveMaximum (exclusiveMaximum: number | boolean): this {
246 | return this.setProps({ exclusiveMaximum })
247 | }
248 |
249 | exclusiveMinimum (exclusiveMinimum: number | boolean): this {
250 | return this.setProps({ exclusiveMinimum })
251 | }
252 |
253 | multipleOf (multipleOf: number): this {
254 | return this.setProps({ multipleOf })
255 | }
256 |
257 | /*=============
258 | STRING
259 | ===============*/
260 | maxLength (maxLength: number): this {
261 | return this.setProps({ maxLength })
262 | }
263 |
264 | minLength (minLength: number): this {
265 | return this.setProps({ minLength })
266 | }
267 |
268 | pattern (pattern: RegExp): this {
269 | return this.setProps({ pattern: pattern.source })
270 | }
271 |
272 | format (format: string): this {
273 | return this.setProps({ format })
274 | }
275 | }
276 |
277 | // make schema instances newable so that they can be validated using decorators
278 | declare module './schema' {
279 | // tslint:disable-next-line:no-shadowed-variable
280 | export interface Schema {
281 | new (...args: any[]): never
282 | }
283 | }
284 |
--------------------------------------------------------------------------------
/src/util.ts:
--------------------------------------------------------------------------------
1 | export type JSONPrimitive = string | number | boolean | null
2 | export interface JSONArray extends Array {} // tslint:disable-line:no-empty-interface
3 | export interface JSONObject { [key: string]: AnyJSON }
4 | export type AnyJSON = JSONPrimitive | JSONArray | JSONObject
5 |
6 | export function copyJson (json: T) {
7 | return JSON.parse(JSON.stringify(json)) as T
8 | }
9 |
10 | // tslint:disable-next-line:ban-types
11 | export function callableInstance (obj: T, key: K): T & T[K] {
12 | const
13 | boundMethod: T[K] = (obj[key] as Function).bind(obj), // tslint:disable-line:ban-types
14 | merged = Object.assign(boundMethod, obj)
15 |
16 | // tslint:disable-next-line:align
17 | ; (boundMethod as any).__proto__ = (obj as any).__proto__
18 | return merged
19 | }
20 |
21 | export type Diff
22 | = ({ [P in T]: P } & { [P in U]: never } & { [x: string]: never })[T]
23 | export type Overwrite = { [P in Diff]: T[P] } & U
24 | export type Omit = { [P in Diff]: T[P] }
25 |
--------------------------------------------------------------------------------
/src/validator.ts:
--------------------------------------------------------------------------------
1 |
2 | import Ajv = require('ajv')
3 | import { ErrorObject } from 'ajv'
4 | import { Schema } from './schema'
5 | import { AnyJSON } from './util'
6 |
7 | export interface CustomKeyword extends Ajv.KeywordDefinition {
8 | name: string
9 | }
10 |
11 | export type CustomKeywords = Array
12 |
13 | export interface ValidatorOptions extends Ajv.Options {
14 | customKeywords?: CustomKeywords
15 | }
16 |
17 | function addCustomKeywords (ajv: Ajv.Ajv, customKeywords: CustomKeywords) {
18 | customKeywords.forEach(kw => {
19 | if (Array.isArray(kw)) {
20 | addCustomKeywords(ajv, kw)
21 | } else {
22 | ajv.addKeyword(kw.name, kw)
23 | }
24 | })
25 | }
26 |
27 | export class ValidationError extends Error {
28 | constructor (input: any, schema: Schema, public errors: ErrorObject[]) {
29 | super(`
30 |
31 | could not validate object:
32 | ${JSON.stringify(input, null, 2)}
33 |
34 | against schema:
35 | ${JSON.stringify(schema.toJSON(), null, 2)}
36 |
37 | errors:
38 | * ${errors.map(e => e.message).join('\n * ')}`)
39 | }
40 | }
41 |
42 | // tslint:disable-next-line:max-classes-per-file
43 | export class Validator {
44 | ajv: Ajv.Ajv
45 |
46 | constructor (options: ValidatorOptions = {}) {
47 | this.ajv = new Ajv(options)
48 | if (options.customKeywords) {
49 | addCustomKeywords(this.ajv, options.customKeywords)
50 | }
51 | }
52 |
53 | /**
54 | * @deprecated use validate instead
55 | */
56 | validateSync > (schema: T, obj: any)
57 | : { valid: false, errors: ErrorObject[], result: null }
58 | | { valid: true, errors: null, result: T['TypeOf'] } {
59 | const validate = this.ajv.compile(schema.toJSON())
60 | const coercedValue: { result?: T } = { }
61 | const isValid = validate(obj, undefined, coercedValue, 'result')
62 | if (isValid) {
63 | return { errors: null, result: coercedValue.result !== undefined ? coercedValue.result : obj, valid: true }
64 | } else {
65 | return { errors: validate.errors!, result: null, valid: false }
66 | }
67 | }
68 |
69 | validate > (schema: T, obj: any): Promise {
70 | const validate = this.ajv.compile(schema.toJSON())
71 | const coercedValue: { result?: T } = { }
72 | validate(obj, undefined, coercedValue, 'result')
73 | if (!validate.errors) {
74 | return Promise.resolve(coercedValue.result !== undefined ? coercedValue.result : obj)
75 | } else {
76 | return Promise.reject(new ValidationError(obj, schema, validate.errors))
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/test-typedefs/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "target": "es5",
5 | "module": "commonjs",
6 | "lib": [ "es2016" ],
7 | "baseDir": ".",
8 | "strict": true,
9 | "noEmitOnError": true,
10 | "experimentalDecorators": true,
11 | "emitDecoratorMetadata": true
12 |
13 | },
14 | "include": [
15 | "./**/*.ts"
16 | ],
17 | "exclude": [ ]
18 | }
19 |
--------------------------------------------------------------------------------
/test-typedefs/typedefs.ts:
--------------------------------------------------------------------------------
1 | /* tslint:disable:no-unused-expression */
2 | import { array, boolean, number, object, schema, string } from '../src'
3 | import '../src/ext'
4 |
5 | schema.TypeOf // $ExpectType any
6 |
7 | schema.type('number').TypeOf // $ExpectType number
8 |
9 | schema.type(['string', 'number']).TypeOf // $ExpectType string | number
10 |
11 | array.TypeOf // $ExpectType any[]
12 |
13 | array.items(string).TypeOf // $ExpectType string[]
14 |
15 | schema.type(['number', 'array']).items(string).TypeOf // $ExpectType number | string[]
16 |
17 | array.items(string).additionalItems(number).TypeOf // $ExpectType (string | number)[]
18 |
19 | array.items([string, number]).TypeOf // $ExpectType (string | number)[]
20 |
21 | array.items([string, number]).additionalItems(boolean).TypeOf // $ExpectType (string | number | boolean)[]
22 |
23 | object.TypeOf.someRandomProperty // $ExpectType any
24 |
25 | object.properties({ a: string }).TypeOf.a // $ExpectType string | undefined
26 |
27 | object.TypeOf.b // $ExpectType any
28 |
29 | object.properties({ a: string }).required('a').TypeOf.a // $ExpectType string
30 |
31 | object.properties({ a: string }).required('b').TypeOf.b // $ExpectType any
32 |
33 | object.properties({ a: string }).additionalProperties(false).TypeOf.a // $ExpectType string | undefined
34 |
35 | // $ExpectType string | boolean | undefined
36 | object.properties({ a: string }).additionalProperties(schema.type(['string', 'boolean'])).TypeOf.b
37 |
38 | // $ExpectType string | boolean | undefined
39 | object.properties({ a: string })
40 | .additionalProperties(false)
41 | .patternProperties({ '\\w+': string, 'a': boolean })
42 | .TypeOf.c
43 |
44 | // $ExpectType string | undefined
45 | object.properties({ a: string })
46 | .additionalProperties(false)
47 | .patternProperties({ '\\w+': object.properties({a: string}) })
48 | .TypeOf.c!.a
49 |
50 | schema.enum([true, 'a', 42]).TypeOf // $ExpectType true | "a" | 42
51 |
52 | const b = object.properties({ brand: object.enum(['b']), b: string }).required('brand', 'b').additionalProperties(false)
53 | const c = object.properties({ brand: object.enum(['c']), c: string }).required('brand', 'c').additionalProperties(false)
54 | const x = object.properties({ a: number }).additionalProperties(false).anyOf([b, c]).TypeOf
55 |
56 | x.a // $ExpectType number | undefined
57 |
58 | if (x.brand === 'b') {
59 | x.b // $ExpectType string
60 | x.c // $ExpectError Property 'c' does not exist
61 | } else {
62 | x.c // $ExpectType string
63 | x.b // $ExpectError Property 'b' does not exist
64 | }
65 |
66 | const oneOf = object.properties({ a: number }).additionalProperties(false).oneOf([b]).TypeOf
67 |
68 | oneOf.a // $ExpectType number | undefined
69 |
70 | oneOf.b // $ExpectType string
71 |
72 | const ASchema = schema.type(['string', 'null'])
73 | type ASchema = schema
74 |
75 | function foo (value: ASchema) {
76 | value // $ExpectType string | null
77 | }
78 |
79 | schema.const(3).TypeOf // $ExpectType 3
80 |
81 | // $ExpectType { a: string; b: number; } & {}
82 | object.strictProperties({ a: string, b: number }).TypeOf
83 |
84 | // $ExpectType { b: number; } & { a?: string | undefined; c?: boolean | undefined; }
85 | object.optional('a', 'c').strictProperties({ a: string, b: number, c: boolean }).TypeOf
86 |
87 | // $ExpectType string | null
88 | string.allowNull().TypeOf
89 |
90 | // $ExpectType any
91 | schema.allowNull().TypeOf
92 |
93 | // $ExpectType string | null
94 | schema.type('string').allowNull().TypeOf
95 |
96 | // $ExpectType ({} & {} & {}) | null
97 | object.additionalProperties(false).allowNull().TypeOf
98 |
99 | // $ExpectType 3 | 1 | 2 | null
100 | schema.enum([1, 2, 3]).allowNull().TypeOf
101 |
102 | // $ExpectType 3 | 1 | 2 | null
103 | string.enum([1, 2, 3]).allowNull().TypeOf
104 |
--------------------------------------------------------------------------------
/test/allow-null.spec.ts:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai'
2 | import { schema, Validator } from '../src'
3 | import '../src/ext/allow-null'
4 |
5 | describe('allowNull keyword', () => {
6 | it('should create the schema for a nullable string', () => {
7 | const nullableString = schema.type('string').allowNull()
8 |
9 | expect(nullableString.toJSON()).to.eql({ type: ['string', 'null'] })
10 | })
11 |
12 | it('should create the schema for a typeless schema', () => {
13 | const nullableAny = schema.allowNull()
14 |
15 | expect(nullableAny.toJSON()).to.eql({})
16 | })
17 |
18 | it('should create the schema for an enum', () => {
19 | const nullableEnum = schema.enum([1, 2, 3]).allowNull()
20 |
21 | expect(nullableEnum.toJSON()).to.eql({ enum: [1, 2, 3, null]})
22 | })
23 |
24 | it('should create the schema for a typed enum', () => {
25 | const nullableEnum = schema.type('string').enum([1, 2, 3]).allowNull()
26 |
27 | expect(nullableEnum.toJSON()).to.eql({ type: ['string', 'null'], enum: [1, 2, 3, null]})
28 | })
29 | })
30 |
--------------------------------------------------------------------------------
/test/ext.spec.ts:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai'
2 | import { schema, Validator } from '../src'
3 | import { ext } from '../src/ext'
4 |
5 | describe('ext index', () => {
6 | it('should trim the value when validating', async () => {
7 | const trimmedStringSchema = schema.type('string').trim(true),
8 | validator = new Validator({ coerceTypes: true, customKeywords: ext })
9 |
10 | const trimmedString = await validator.validate(trimmedStringSchema, ' asdf ')
11 | expect(trimmedString).to.eql('asdf')
12 | })
13 | })
14 |
--------------------------------------------------------------------------------
/test/index.spec.ts:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai'
2 | import {
3 | array,
4 | boolean,
5 | integer,
6 | number,
7 | object,
8 | schema,
9 | string,
10 | Validator
11 | } from '../src'
12 |
13 | describe('JSON schema', () => {
14 | it('should create a number schema', () => {
15 | const numberSchema = schema.type('number')
16 |
17 | expect(numberSchema.toJSON()).to.eql({
18 | type: 'number'
19 | })
20 |
21 | const numberMinMax = number.maximum(4).minimum(3)
22 |
23 | expect(numberMinMax.toJSON()).to.eql({
24 | type: 'number',
25 | maximum: 4,
26 | minimum: 3
27 | })
28 |
29 | const numberWithExclusives = number.exclusiveMaximum(4).exclusiveMinimum(2)
30 |
31 | expect(numberWithExclusives.toJSON()).to.eql({
32 | type: 'number',
33 | exclusiveMaximum: 4,
34 | exclusiveMinimum: 2
35 | })
36 |
37 | const complexNumber = number
38 | .maximum(4)
39 | .minimum(3)
40 | .exclusiveMaximum(true)
41 | .exclusiveMinimum(true)
42 |
43 | expect(complexNumber.toJSON()).to.eql({
44 | type: 'number',
45 | maximum: 4,
46 | minimum: 3,
47 | exclusiveMaximum: true,
48 | exclusiveMinimum: true
49 | })
50 |
51 | const numberWithMultiple = number.multipleOf(3)
52 |
53 | expect(numberWithMultiple.toJSON()).to.eql({
54 | type: 'number',
55 | multipleOf: 3
56 | })
57 |
58 | const integerSchema = schema.type('integer')
59 |
60 | expect(integerSchema.toJSON()).to.eql({
61 | type: 'integer'
62 | })
63 |
64 | expect(integer.toJSON()).to.eql({
65 | type: 'integer'
66 | })
67 | })
68 |
69 | it('should create a string schema', () => {
70 | const stringSchema = schema.type('string')
71 |
72 | expect(stringSchema.toJSON()).to.eql({
73 | type: 'string'
74 | })
75 |
76 | const stringLengths = string.minLength(3).maxLength(5)
77 |
78 | expect(stringLengths.toJSON()).to.eql({
79 | type: 'string',
80 | minLength: 3,
81 | maxLength: 5
82 | })
83 |
84 | const stringPattern = string.pattern(/\w+/)
85 |
86 | expect(stringPattern.toJSON()).to.eql({
87 | type: 'string',
88 | pattern: '\\w+'
89 | })
90 | const stringFormat = string.format('email')
91 |
92 | expect(stringFormat.toJSON()).to.eql({
93 | type: 'string',
94 | format: 'email'
95 | })
96 | })
97 |
98 | it('should create a boolean schema', () => {
99 | const booleanSchema = schema.type('boolean')
100 |
101 | expect(booleanSchema.toJSON()).to.eql({
102 | type: 'boolean'
103 | })
104 | })
105 | it('should create a null schema', () => {
106 | const nullSchema = schema.type('null')
107 |
108 | expect(nullSchema.toJSON()).to.eql({
109 | type: 'null'
110 | })
111 | })
112 |
113 | it('should create an array schema', () => {
114 | const arraySchema = schema.type('array')
115 |
116 | expect(arraySchema.toJSON()).to.eql({
117 | type: 'array'
118 | })
119 |
120 | const minMaxArray = array.minItems(3).maxItems(5)
121 |
122 | expect(minMaxArray.toJSON()).to.eql({
123 | type: 'array',
124 | minItems: 3,
125 | maxItems: 5
126 | })
127 |
128 | const uniqueItems = array.uniqueItems(true)
129 |
130 | expect(uniqueItems.toJSON()).to.eql({
131 | type: 'array',
132 | uniqueItems: true
133 | })
134 |
135 | const arrayOfStrings = array(string)
136 |
137 | expect(arrayOfStrings.toJSON()).to.eql({
138 | type: 'array',
139 | items: { type: 'string' }
140 | })
141 |
142 | const stringTuple = array([string])
143 |
144 | expect(stringTuple.toJSON()).to.eql({
145 | type: 'array',
146 | items: [{ type: 'string' }]
147 | })
148 |
149 | const complexTuple = array([string, array(number), number])
150 |
151 | expect(complexTuple.toJSON()).to.eql({
152 | type: 'array',
153 | items: [
154 | { type: 'string' },
155 | { type: 'array', items: { type: 'number' } },
156 | { type: 'number' }
157 | ]
158 | })
159 |
160 | const tupleWithAdditionalItems = array([string, array(number), number]).additionalItems(true)
161 |
162 | expect(tupleWithAdditionalItems.toJSON()).to.eql({
163 | type: 'array',
164 | items: [
165 | { type: 'string' },
166 | { type: 'array', items: { type: 'number' } },
167 | { type: 'number' }
168 | ],
169 | additionalItems: true
170 | })
171 |
172 | const tupleWithBooleanAdditionalItems = array([
173 | string,
174 | array(number),
175 | number
176 | ])
177 | .additionalItems(boolean)
178 |
179 | expect(tupleWithBooleanAdditionalItems.toJSON()).to.eql({
180 | type: 'array', items: [
181 | { type: 'string' },
182 | { type: 'array', items: { type: 'number' } },
183 | { type: 'number' }
184 | ],
185 | additionalItems: { type: 'boolean' }
186 | })
187 |
188 | const arrayContains = array(string)
189 | .contains(schema.type('null'))
190 |
191 | expect(arrayContains.toJSON()).to.eql({
192 | type: 'array',
193 | items: { type: 'string' },
194 | contains: { type: 'null' }
195 | })
196 | })
197 |
198 | it('should create an object schema', () => {
199 | const objectSchema = schema.type('object')
200 |
201 | expect(objectSchema.toJSON()).to.eql({
202 | type: 'object'
203 | })
204 |
205 | const minMaxProperties = object.maxProperties(3).minProperties(1)
206 |
207 | expect(minMaxProperties.toJSON()).to.eql({
208 | type: 'object',
209 | maxProperties: 3,
210 | minProperties: 1
211 | })
212 |
213 | const schemaWithProperties = object({
214 | a: string,
215 | b: array(number)
216 | })
217 |
218 | expect(schemaWithProperties.toJSON()).to.eql({
219 | type: 'object',
220 | properties: {
221 | a: { type: 'string' },
222 | b: { type: 'array', items: { type: 'number' }}
223 | }
224 | })
225 |
226 | const schemaWithRequiredProperties = object({
227 | a: string,
228 | b: array(number)
229 | })
230 | .required('a', 'b', 'c')
231 |
232 | expect(schemaWithRequiredProperties.toJSON()).to.eql({
233 | type: 'object',
234 | properties: {
235 | a: { type: 'string' },
236 | b: { type: 'array', items: { type: 'number' }}
237 | },
238 | required: ['a', 'b', 'c']
239 | })
240 |
241 | const schemaWithNoAdditionalProperties = object.required('a', 'b', 'c').properties({
242 | a: string,
243 | b: array(number),
244 | d: boolean
245 | })
246 | .additionalProperties(false)
247 |
248 | expect(schemaWithNoAdditionalProperties.toJSON()).to.eql({
249 | type: 'object',
250 | properties: {
251 | a: { type: 'string' },
252 | b: { type: 'array', items: { type: 'number' }},
253 | d: { type: 'boolean' }
254 | },
255 | required: ['a', 'b', 'c'],
256 | additionalProperties: false
257 | })
258 |
259 | const schemaWithAdditionalProperties = object
260 | .properties({ a: string })
261 | .required('b')
262 | .additionalProperties(number)
263 |
264 | expect(schemaWithAdditionalProperties.toJSON()).to.eql({
265 | type: 'object',
266 | properties: {
267 | a: { type: 'string' }
268 | },
269 | required: ['b'],
270 | additionalProperties: { type: 'number' }
271 | })
272 |
273 | const objectWithPatternProperties = object.patternProperties({
274 | '$foo^': string,
275 | '$bar^': number
276 | })
277 | .additionalProperties(false)
278 |
279 | expect(objectWithPatternProperties.toJSON()).to.eql({
280 | type: 'object',
281 | additionalProperties: false,
282 | patternProperties: {
283 | '$foo^': { type: 'string' },
284 | '$bar^': { type: 'number' }
285 | }
286 | })
287 |
288 | const objectWithRequiredPatternProperties = object.patternProperties({
289 | '$foo^': string,
290 | '$bar^': number
291 | })
292 | .required('a')
293 | .additionalProperties(false)
294 |
295 | expect(objectWithRequiredPatternProperties.toJSON()).to.eql({
296 | type: 'object',
297 | required: ['a'],
298 | additionalProperties: false,
299 | patternProperties: {
300 | '$foo^': { type: 'string' },
301 | '$bar^': { type: 'number' }
302 | }
303 | })
304 |
305 | const objectWithDependencies = object.additionalProperties(false)
306 | .dependencies({
307 | a: string,
308 | b: ['c', 'd']
309 | })
310 |
311 | expect(objectWithDependencies.toJSON()).to.eql({
312 | type: 'object',
313 | additionalProperties: false,
314 | dependencies: {
315 | a: { type: 'string' },
316 | b: ['c', 'd']
317 | }
318 | })
319 | })
320 |
321 | it('should create a schema with multiple types (as an array)', () => {
322 | const schemaWithMultipleTypes = schema.type(['string', 'null'])
323 |
324 | expect(schemaWithMultipleTypes.toJSON()).to.eql({
325 | type: ['string', 'null']
326 | })
327 | })
328 |
329 | it('should allow any combination of keywords from different types', () => {
330 | const crazySchema = schema
331 | .type(['number', 'boolean'])
332 | .properties({a: string})
333 | .maxLength(42)
334 |
335 | expect(crazySchema.toJSON()).to.eql({
336 | type: ['number', 'boolean'],
337 | properties: { a: { type: 'string' } },
338 | maxLength: 42
339 | })
340 | })
341 |
342 | it('should allow metadata values', () => {
343 | const schemaWithMetadata = schema.title('someTitle').description('foo')
344 |
345 | expect(schemaWithMetadata.toJSON()).to.eql({
346 | title: 'someTitle',
347 | description: 'foo'
348 | })
349 | })
350 |
351 | it('should allow default values', () => {
352 | const schemaWithDefault = string.default('asdf')
353 |
354 | expect(schemaWithDefault.toJSON()).to.eql({
355 | type: 'string',
356 | default: 'asdf'
357 | })
358 | })
359 |
360 | it('should allow examples', () => {
361 | const schemaWithDefault = string.example('fizz')
362 |
363 | expect(schemaWithDefault.toJSON()).to.eql({
364 | type: 'string',
365 | example: 'fizz'
366 | })
367 | })
368 |
369 | it('should allow enumerated values', () => {
370 | const enumSchema = schema.enum([[4, 5], '3', false, null])
371 |
372 | expect(enumSchema.toJSON()).to.eql({
373 | enum: [ [4, 5], '3', false, null]
374 | })
375 |
376 | const enumWithType = string.enum(['5', null])
377 |
378 | expect(enumWithType.toJSON()).to.eql({
379 | type: 'string',
380 | enum: [ '5', null ]
381 | })
382 | })
383 |
384 | it('should allow const values', () => {
385 | const constSchema = schema.const(4)
386 |
387 | expect(constSchema.toJSON()).to.eql({
388 | const: 4
389 | })
390 | })
391 |
392 | it('should combine schemas using allOf', () => {
393 | const s = schema.allOf([
394 | array(string),
395 | number
396 | ])
397 |
398 | expect(s.toJSON()).to.eql({
399 | allOf: [
400 | { type: 'array', items: { type: 'string'} },
401 | { type: 'number' }
402 | ]
403 | })
404 | })
405 |
406 | it('should combine schemas using anyOf', () => {
407 | const s = schema.anyOf([
408 | string,
409 | number,
410 | object({ a: string }).required('a')
411 | ])
412 |
413 | expect(s.toJSON()).to.eql({
414 | anyOf: [
415 | { type: 'string' },
416 | { type: 'number' },
417 | { type: 'object', properties: { a: { type: 'string' }}, required: ['a'] }
418 | ]
419 | })
420 | })
421 |
422 | it('should combine schemas using oneOf', () => {
423 | const s = schema.oneOf([
424 | string,
425 | number,
426 | array(string)
427 | ])
428 |
429 | expect(s.toJSON()).to.eql({
430 | oneOf: [
431 | { type: 'string' },
432 | { type: 'number' },
433 | { type: 'array', items: { type: 'string' } }
434 | ]
435 | })
436 | })
437 |
438 | it('should combine schemas using not', () => {
439 | const s = string.not(schema.enum(['fizz']))
440 |
441 | expect(s.toJSON()).to.eql({
442 | type: 'string',
443 | not: {
444 | enum: ['fizz']
445 | }
446 | })
447 | })
448 |
449 | it('should validate a schema', async () => {
450 | const result = await new Validator().validate(schema.anyOf([string]), 'a')
451 |
452 | expect(result).to.eql('a')
453 | })
454 |
455 | it('should coerce validated data', async () => {
456 | const result = await new Validator({ coerceTypes: true }).validate(string, 1)
457 |
458 | expect(result).to.eql('1')
459 | })
460 | })
461 |
--------------------------------------------------------------------------------
/test/mocha.opts:
--------------------------------------------------------------------------------
1 | --compilers ts:ts-node/register
2 |
--------------------------------------------------------------------------------
/test/strict-properties.spec.ts:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai'
2 | import { boolean, number, object, schema, string, Validator } from '../src'
3 | import '../src/ext/strict-properties'
4 |
5 | describe('strict properties', () => {
6 | it('should create the schema', () => {
7 | const strictSchema = object.strictProperties({ a: number, b: string })
8 |
9 | expect(strictSchema.toJSON()).to.eql({
10 | type: 'object',
11 | properties: {
12 | a: { type: 'number' },
13 | b: { type: 'string' }
14 | },
15 | required: ['a', 'b'],
16 | additionalProperties: false
17 | })
18 | })
19 |
20 | it('should allow optional properties', () => {
21 | const strictSchema = object.strictProperties({ a: number, b: string }).optional('a')
22 |
23 | expect(strictSchema.toJSON()).to.eql({
24 | type: 'object',
25 | properties: {
26 | a: { type: 'number' },
27 | b: { type: 'string' }
28 | },
29 | required: ['b'],
30 | additionalProperties: false
31 | })
32 | })
33 |
34 | it('should allow optional properties specified before strict', () => {
35 | const strictSchema = object.optional('a', 'b').strictProperties({ a: number, b: string, c: boolean })
36 |
37 | expect(strictSchema.toJSON()).to.eql({
38 | type: 'object',
39 | properties: {
40 | a: { type: 'number' },
41 | b: { type: 'string' },
42 | c: { type: 'boolean' }
43 | },
44 | required: ['c'],
45 | additionalProperties: false
46 | })
47 | })
48 | })
49 |
--------------------------------------------------------------------------------
/test/trim.spec.ts:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai'
2 | import { schema, Validator } from '../src'
3 | import { trim } from '../src/ext/trim'
4 |
5 | describe('trim keyword', () => {
6 | it('should create the schema', () => {
7 | const trimmedString = schema.type('string').trim(true)
8 |
9 | expect(trimmedString.toJSON()).to.eql({ type: 'string', trim: true })
10 | })
11 |
12 | it('should trim the value when validating', async () => {
13 | const trimmedStringSchema = schema.type('string').trim(true),
14 | validator = new Validator({ coerceTypes: true, customKeywords: [trim] })
15 |
16 | const trimmedString = await validator.validate(trimmedStringSchema, ' asdf ')
17 | expect(trimmedString).to.eql('asdf')
18 | })
19 | })
20 |
--------------------------------------------------------------------------------
/test/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "lib": [
5 | "es2016",
6 | "dom"
7 | ],
8 | "rootDir": ".."
9 | },
10 | "include": [
11 | "**/*.ts"
12 | ]
13 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "lib": [ "es2016" ],
6 | "outDir": ".",
7 | "strict": true,
8 | "noEmitOnError": true,
9 | "experimentalDecorators": true,
10 | "emitDecoratorMetadata": true
11 | },
12 | "include": [
13 | "src/**/*.ts"
14 | ],
15 | "exclude": []
16 | }
17 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultSeverity": "error",
3 | "extends": [
4 | "tslint:recommended"
5 | ],
6 | "rules": {
7 | "semicolon": [ true, "never" ],
8 | "quotemark": [ true, "single", "avoid-escape" ],
9 | "trailing-comma": [ false ],
10 | "space-before-function-paren": {
11 | "anonymous": "always",
12 | "constructor": "always",
13 | "method": "always",
14 | "named": "always"
15 | },
16 | "object-literal-sort-keys": [false],
17 | "member-access": [true, "no-public"],
18 | "interface-name": [true, "never-prefix"],
19 | "one-variable-per-declaration": [false],
20 | "arrow-parens": [false],
21 | "no-shadowed-variable": [false]
22 | }
23 | }
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@types/ajv@^1.0.0":
6 | version "1.0.0"
7 | resolved "https://registry.yarnpkg.com/@types/ajv/-/ajv-1.0.0.tgz#4fb2440742f2f6c30e7fb0797b839fc6f696682a"
8 | dependencies:
9 | ajv "*"
10 |
11 | "@types/chai@^4.0.1":
12 | version "4.0.1"
13 | resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.0.1.tgz#37fea779617cfec3fd2b19a0247e8bbdd5133bf6"
14 |
15 | "@types/mocha@^2.2.41":
16 | version "2.2.41"
17 | resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.41.tgz#e27cf0817153eb9f2713b2d3f6c68f1e1c3ca608"
18 |
19 | ajv@*, ajv@^5.2.2:
20 | version "5.2.2"
21 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.2.tgz#47c68d69e86f5d953103b0074a9430dc63da5e39"
22 | dependencies:
23 | co "^4.6.0"
24 | fast-deep-equal "^1.0.0"
25 | json-schema-traverse "^0.3.0"
26 | json-stable-stringify "^1.0.1"
27 |
28 | ansi-regex@^2.0.0:
29 | version "2.1.1"
30 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
31 |
32 | ansi-styles@^2.2.1:
33 | version "2.2.1"
34 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
35 |
36 | ansi-styles@^3.1.0:
37 | version "3.2.0"
38 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88"
39 | dependencies:
40 | color-convert "^1.9.0"
41 |
42 | arrify@^1.0.0:
43 | version "1.0.1"
44 | resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
45 |
46 | assertion-error@^1.0.1:
47 | version "1.0.2"
48 | resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c"
49 |
50 | babel-code-frame@^6.22.0:
51 | version "6.26.0"
52 | resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
53 | dependencies:
54 | chalk "^1.1.3"
55 | esutils "^2.0.2"
56 | js-tokens "^3.0.2"
57 |
58 | balanced-match@^1.0.0:
59 | version "1.0.0"
60 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
61 |
62 | brace-expansion@^1.1.7:
63 | version "1.1.8"
64 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
65 | dependencies:
66 | balanced-match "^1.0.0"
67 | concat-map "0.0.1"
68 |
69 | browser-stdout@1.3.0:
70 | version "1.3.0"
71 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f"
72 |
73 | builtin-modules@^1.0.0:
74 | version "1.1.1"
75 | resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
76 |
77 | camelcase@^3.0.0:
78 | version "3.0.0"
79 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
80 |
81 | chai@^4.1.0:
82 | version "4.1.0"
83 | resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.0.tgz#331a0391b55c3af8740ae9c3b7458bc1c3805e6d"
84 | dependencies:
85 | assertion-error "^1.0.1"
86 | check-error "^1.0.1"
87 | deep-eql "^2.0.1"
88 | get-func-name "^2.0.0"
89 | pathval "^1.0.0"
90 | type-detect "^4.0.0"
91 |
92 | chalk@^1.1.3:
93 | version "1.1.3"
94 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
95 | dependencies:
96 | ansi-styles "^2.2.1"
97 | escape-string-regexp "^1.0.2"
98 | has-ansi "^2.0.0"
99 | strip-ansi "^3.0.0"
100 | supports-color "^2.0.0"
101 |
102 | chalk@^2.0.0:
103 | version "2.0.1"
104 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.0.1.tgz#dbec49436d2ae15f536114e76d14656cdbc0f44d"
105 | dependencies:
106 | ansi-styles "^3.1.0"
107 | escape-string-regexp "^1.0.5"
108 | supports-color "^4.0.0"
109 |
110 | check-error@^1.0.1:
111 | version "1.0.2"
112 | resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
113 |
114 | cliui@^3.2.0:
115 | version "3.2.0"
116 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
117 | dependencies:
118 | string-width "^1.0.1"
119 | strip-ansi "^3.0.1"
120 | wrap-ansi "^2.0.0"
121 |
122 | co@^4.6.0:
123 | version "4.6.0"
124 | resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
125 |
126 | code-point-at@^1.0.0:
127 | version "1.1.0"
128 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
129 |
130 | color-convert@^1.9.0:
131 | version "1.9.0"
132 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a"
133 | dependencies:
134 | color-name "^1.1.1"
135 |
136 | color-name@^1.1.1:
137 | version "1.1.3"
138 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
139 |
140 | colors@^1.1.2:
141 | version "1.1.2"
142 | resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
143 |
144 | commander@2.9.0, commander@^2.9.0:
145 | version "2.9.0"
146 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
147 | dependencies:
148 | graceful-readlink ">= 1.0.0"
149 |
150 | concat-map@0.0.1:
151 | version "0.0.1"
152 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
153 |
154 | cross-env@^5.0.5:
155 | version "5.0.5"
156 | resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.0.5.tgz#4383d364d9660873dd185b398af3bfef5efffef3"
157 | dependencies:
158 | cross-spawn "^5.1.0"
159 | is-windows "^1.0.0"
160 |
161 | cross-spawn@^5.1.0:
162 | version "5.1.0"
163 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
164 | dependencies:
165 | lru-cache "^4.0.1"
166 | shebang-command "^1.2.0"
167 | which "^1.2.9"
168 |
169 | debug@2.6.0:
170 | version "2.6.0"
171 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.0.tgz#bc596bcabe7617f11d9fa15361eded5608b8499b"
172 | dependencies:
173 | ms "0.7.2"
174 |
175 | decamelize@^1.1.1:
176 | version "1.2.0"
177 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
178 |
179 | deep-eql@^2.0.1:
180 | version "2.0.2"
181 | resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-2.0.2.tgz#b1bac06e56f0a76777686d50c9feb75c2ed7679a"
182 | dependencies:
183 | type-detect "^3.0.0"
184 |
185 | diff@3.2.0, diff@^3.1.0, diff@^3.2.0:
186 | version "3.2.0"
187 | resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
188 |
189 | error-ex@^1.2.0:
190 | version "1.3.1"
191 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc"
192 | dependencies:
193 | is-arrayish "^0.2.1"
194 |
195 | escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
196 | version "1.0.5"
197 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
198 |
199 | esutils@^2.0.2:
200 | version "2.0.2"
201 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
202 |
203 | fast-deep-equal@^1.0.0:
204 | version "1.0.0"
205 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff"
206 |
207 | find-up@^1.0.0:
208 | version "1.1.2"
209 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
210 | dependencies:
211 | path-exists "^2.0.0"
212 | pinkie-promise "^2.0.0"
213 |
214 | fs.realpath@^1.0.0:
215 | version "1.0.0"
216 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
217 |
218 | get-caller-file@^1.0.1:
219 | version "1.0.2"
220 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
221 |
222 | get-func-name@^2.0.0:
223 | version "2.0.0"
224 | resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
225 |
226 | glob@7.1.1, glob@^7.1.1:
227 | version "7.1.1"
228 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
229 | dependencies:
230 | fs.realpath "^1.0.0"
231 | inflight "^1.0.4"
232 | inherits "2"
233 | minimatch "^3.0.2"
234 | once "^1.3.0"
235 | path-is-absolute "^1.0.0"
236 |
237 | graceful-fs@^4.1.2:
238 | version "4.1.11"
239 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
240 |
241 | "graceful-readlink@>= 1.0.0":
242 | version "1.0.1"
243 | resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
244 |
245 | growl@1.9.2:
246 | version "1.9.2"
247 | resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f"
248 |
249 | has-ansi@^2.0.0:
250 | version "2.0.0"
251 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
252 | dependencies:
253 | ansi-regex "^2.0.0"
254 |
255 | has-flag@^1.0.0:
256 | version "1.0.0"
257 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
258 |
259 | has-flag@^2.0.0:
260 | version "2.0.0"
261 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
262 |
263 | hosted-git-info@^2.1.4:
264 | version "2.5.0"
265 | resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c"
266 |
267 | inflight@^1.0.4:
268 | version "1.0.6"
269 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
270 | dependencies:
271 | once "^1.3.0"
272 | wrappy "1"
273 |
274 | inherits@2:
275 | version "2.0.3"
276 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
277 |
278 | invert-kv@^1.0.0:
279 | version "1.0.0"
280 | resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
281 |
282 | is-arrayish@^0.2.1:
283 | version "0.2.1"
284 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
285 |
286 | is-builtin-module@^1.0.0:
287 | version "1.0.0"
288 | resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
289 | dependencies:
290 | builtin-modules "^1.0.0"
291 |
292 | is-fullwidth-code-point@^1.0.0:
293 | version "1.0.0"
294 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
295 | dependencies:
296 | number-is-nan "^1.0.0"
297 |
298 | is-utf8@^0.2.0:
299 | version "0.2.1"
300 | resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
301 |
302 | is-windows@^1.0.0:
303 | version "1.0.1"
304 | resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9"
305 |
306 | isexe@^2.0.0:
307 | version "2.0.0"
308 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
309 |
310 | js-tokens@^3.0.2:
311 | version "3.0.2"
312 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
313 |
314 | json-schema-traverse@^0.3.0:
315 | version "0.3.1"
316 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
317 |
318 | json-stable-stringify@^1.0.1:
319 | version "1.0.1"
320 | resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
321 | dependencies:
322 | jsonify "~0.0.0"
323 |
324 | json3@3.3.2:
325 | version "3.3.2"
326 | resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
327 |
328 | jsonify@~0.0.0:
329 | version "0.0.0"
330 | resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
331 |
332 | lcid@^1.0.0:
333 | version "1.0.0"
334 | resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
335 | dependencies:
336 | invert-kv "^1.0.0"
337 |
338 | load-json-file@^1.0.0:
339 | version "1.1.0"
340 | resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
341 | dependencies:
342 | graceful-fs "^4.1.2"
343 | parse-json "^2.2.0"
344 | pify "^2.0.0"
345 | pinkie-promise "^2.0.0"
346 | strip-bom "^2.0.0"
347 |
348 | lodash._baseassign@^3.0.0:
349 | version "3.2.0"
350 | resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
351 | dependencies:
352 | lodash._basecopy "^3.0.0"
353 | lodash.keys "^3.0.0"
354 |
355 | lodash._basecopy@^3.0.0:
356 | version "3.0.1"
357 | resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36"
358 |
359 | lodash._basecreate@^3.0.0:
360 | version "3.0.3"
361 | resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821"
362 |
363 | lodash._getnative@^3.0.0:
364 | version "3.9.1"
365 | resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
366 |
367 | lodash._isiterateecall@^3.0.0:
368 | version "3.0.9"
369 | resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c"
370 |
371 | lodash.create@3.1.1:
372 | version "3.1.1"
373 | resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7"
374 | dependencies:
375 | lodash._baseassign "^3.0.0"
376 | lodash._basecreate "^3.0.0"
377 | lodash._isiterateecall "^3.0.0"
378 |
379 | lodash.isarguments@^3.0.0:
380 | version "3.1.0"
381 | resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
382 |
383 | lodash.isarray@^3.0.0:
384 | version "3.0.4"
385 | resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
386 |
387 | lodash.keys@^3.0.0:
388 | version "3.1.2"
389 | resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
390 | dependencies:
391 | lodash._getnative "^3.0.0"
392 | lodash.isarguments "^3.0.0"
393 | lodash.isarray "^3.0.0"
394 |
395 | lodash@^4.17.4:
396 | version "4.17.4"
397 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
398 |
399 | lru-cache@^4.0.1:
400 | version "4.1.1"
401 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55"
402 | dependencies:
403 | pseudomap "^1.0.2"
404 | yallist "^2.1.2"
405 |
406 | make-error@^1.1.1:
407 | version "1.3.0"
408 | resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.0.tgz#52ad3a339ccf10ce62b4040b708fe707244b8b96"
409 |
410 | minimatch@^3.0.2, minimatch@^3.0.4:
411 | version "3.0.4"
412 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
413 | dependencies:
414 | brace-expansion "^1.1.7"
415 |
416 | minimist@0.0.8:
417 | version "0.0.8"
418 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
419 |
420 | minimist@^1.2.0:
421 | version "1.2.0"
422 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
423 |
424 | mkdirp@0.5.1, mkdirp@^0.5.1:
425 | version "0.5.1"
426 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
427 | dependencies:
428 | minimist "0.0.8"
429 |
430 | mocha@^3.4.2:
431 | version "3.4.2"
432 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.4.2.tgz#d0ef4d332126dbf18d0d640c9b382dd48be97594"
433 | dependencies:
434 | browser-stdout "1.3.0"
435 | commander "2.9.0"
436 | debug "2.6.0"
437 | diff "3.2.0"
438 | escape-string-regexp "1.0.5"
439 | glob "7.1.1"
440 | growl "1.9.2"
441 | json3 "3.3.2"
442 | lodash.create "3.1.1"
443 | mkdirp "0.5.1"
444 | supports-color "3.1.2"
445 |
446 | ms@0.7.2:
447 | version "0.7.2"
448 | resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765"
449 |
450 | normalize-package-data@^2.3.2:
451 | version "2.4.0"
452 | resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
453 | dependencies:
454 | hosted-git-info "^2.1.4"
455 | is-builtin-module "^1.0.0"
456 | semver "2 || 3 || 4 || 5"
457 | validate-npm-package-license "^3.0.1"
458 |
459 | number-is-nan@^1.0.0:
460 | version "1.0.1"
461 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
462 |
463 | once@^1.3.0:
464 | version "1.4.0"
465 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
466 | dependencies:
467 | wrappy "1"
468 |
469 | os-locale@^1.4.0:
470 | version "1.4.0"
471 | resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9"
472 | dependencies:
473 | lcid "^1.0.0"
474 |
475 | parse-json@^2.2.0:
476 | version "2.2.0"
477 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
478 | dependencies:
479 | error-ex "^1.2.0"
480 |
481 | path-exists@^2.0.0:
482 | version "2.1.0"
483 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
484 | dependencies:
485 | pinkie-promise "^2.0.0"
486 |
487 | path-is-absolute@^1.0.0:
488 | version "1.0.1"
489 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
490 |
491 | path-parse@^1.0.5:
492 | version "1.0.5"
493 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1"
494 |
495 | path-type@^1.0.0:
496 | version "1.1.0"
497 | resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
498 | dependencies:
499 | graceful-fs "^4.1.2"
500 | pify "^2.0.0"
501 | pinkie-promise "^2.0.0"
502 |
503 | pathval@^1.0.0:
504 | version "1.1.0"
505 | resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0"
506 |
507 | pify@^2.0.0:
508 | version "2.3.0"
509 | resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
510 |
511 | pinkie-promise@^2.0.0:
512 | version "2.0.1"
513 | resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
514 | dependencies:
515 | pinkie "^2.0.0"
516 |
517 | pinkie@^2.0.0:
518 | version "2.0.4"
519 | resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
520 |
521 | pseudomap@^1.0.2:
522 | version "1.0.2"
523 | resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
524 |
525 | read-pkg-up@^1.0.1:
526 | version "1.0.1"
527 | resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
528 | dependencies:
529 | find-up "^1.0.0"
530 | read-pkg "^1.0.0"
531 |
532 | read-pkg@^1.0.0:
533 | version "1.1.0"
534 | resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
535 | dependencies:
536 | load-json-file "^1.0.0"
537 | normalize-package-data "^2.3.2"
538 | path-type "^1.0.0"
539 |
540 | require-directory@^2.1.1:
541 | version "2.1.1"
542 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
543 |
544 | require-main-filename@^1.0.1:
545 | version "1.0.1"
546 | resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
547 |
548 | resolve@^1.3.2:
549 | version "1.4.0"
550 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86"
551 | dependencies:
552 | path-parse "^1.0.5"
553 |
554 | "semver@2 || 3 || 4 || 5", semver@^5.3.0:
555 | version "5.4.1"
556 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
557 |
558 | set-blocking@^2.0.0:
559 | version "2.0.0"
560 | resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
561 |
562 | shebang-command@^1.2.0:
563 | version "1.2.0"
564 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
565 | dependencies:
566 | shebang-regex "^1.0.0"
567 |
568 | shebang-regex@^1.0.0:
569 | version "1.0.0"
570 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
571 |
572 | source-map-support@^0.4.0:
573 | version "0.4.15"
574 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1"
575 | dependencies:
576 | source-map "^0.5.6"
577 |
578 | source-map@^0.5.6:
579 | version "0.5.6"
580 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
581 |
582 | spdx-correct@~1.0.0:
583 | version "1.0.2"
584 | resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40"
585 | dependencies:
586 | spdx-license-ids "^1.0.2"
587 |
588 | spdx-expression-parse@~1.0.0:
589 | version "1.0.4"
590 | resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c"
591 |
592 | spdx-license-ids@^1.0.2:
593 | version "1.2.2"
594 | resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57"
595 |
596 | string-width@^1.0.1, string-width@^1.0.2:
597 | version "1.0.2"
598 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
599 | dependencies:
600 | code-point-at "^1.0.0"
601 | is-fullwidth-code-point "^1.0.0"
602 | strip-ansi "^3.0.0"
603 |
604 | strip-ansi@^3.0.0, strip-ansi@^3.0.1:
605 | version "3.0.1"
606 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
607 | dependencies:
608 | ansi-regex "^2.0.0"
609 |
610 | strip-bom@^2.0.0:
611 | version "2.0.0"
612 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
613 | dependencies:
614 | is-utf8 "^0.2.0"
615 |
616 | strip-bom@^3.0.0:
617 | version "3.0.0"
618 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
619 |
620 | strip-json-comments@^2.0.0:
621 | version "2.0.1"
622 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
623 |
624 | supports-color@3.1.2:
625 | version "3.1.2"
626 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"
627 | dependencies:
628 | has-flag "^1.0.0"
629 |
630 | supports-color@^2.0.0:
631 | version "2.0.0"
632 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
633 |
634 | supports-color@^4.0.0:
635 | version "4.2.1"
636 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.2.1.tgz#65a4bb2631e90e02420dba5554c375a4754bb836"
637 | dependencies:
638 | has-flag "^2.0.0"
639 |
640 | ts-node@^3.3.0:
641 | version "3.3.0"
642 | resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-3.3.0.tgz#c13c6a3024e30be1180dd53038fc209289d4bf69"
643 | dependencies:
644 | arrify "^1.0.0"
645 | chalk "^2.0.0"
646 | diff "^3.1.0"
647 | make-error "^1.1.1"
648 | minimist "^1.2.0"
649 | mkdirp "^0.5.1"
650 | source-map-support "^0.4.0"
651 | tsconfig "^6.0.0"
652 | v8flags "^3.0.0"
653 | yn "^2.0.0"
654 |
655 | tsconfig@^6.0.0:
656 | version "6.0.0"
657 | resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-6.0.0.tgz#6b0e8376003d7af1864f8df8f89dd0059ffcd032"
658 | dependencies:
659 | strip-bom "^3.0.0"
660 | strip-json-comments "^2.0.0"
661 |
662 | tslib@^1.7.1:
663 | version "1.7.1"
664 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.7.1.tgz#bc8004164691923a79fe8378bbeb3da2017538ec"
665 |
666 | tslint@^5.7.0:
667 | version "5.7.0"
668 | resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.7.0.tgz#c25e0d0c92fa1201c2bc30e844e08e682b4f3552"
669 | dependencies:
670 | babel-code-frame "^6.22.0"
671 | colors "^1.1.2"
672 | commander "^2.9.0"
673 | diff "^3.2.0"
674 | glob "^7.1.1"
675 | minimatch "^3.0.4"
676 | resolve "^1.3.2"
677 | semver "^5.3.0"
678 | tslib "^1.7.1"
679 | tsutils "^2.8.1"
680 |
681 | tsutils@^2.8.1:
682 | version "2.8.2"
683 | resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.8.2.tgz#2c1486ba431260845b0ac6f902afd9d708a8ea6a"
684 | dependencies:
685 | tslib "^1.7.1"
686 |
687 | type-detect@^3.0.0:
688 | version "3.0.0"
689 | resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-3.0.0.tgz#46d0cc8553abb7b13a352b0d6dea2fd58f2d9b55"
690 |
691 | type-detect@^4.0.0:
692 | version "4.0.3"
693 | resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.3.tgz#0e3f2670b44099b0b46c284d136a7ef49c74c2ea"
694 |
695 | typescript@2.5:
696 | version "2.5.1"
697 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.1.tgz#ce7cc93ada3de19475cc9d17e3adea7aee1832aa"
698 |
699 | typings-checker@^2.0.0:
700 | version "2.0.0"
701 | resolved "https://registry.yarnpkg.com/typings-checker/-/typings-checker-2.0.0.tgz#c6d5af0ff3fc7065da22a6933e1290d16af6cc56"
702 | dependencies:
703 | lodash "^4.17.4"
704 | yargs "^6.6.0"
705 |
706 | user-home@^1.1.1:
707 | version "1.1.1"
708 | resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190"
709 |
710 | v8flags@^3.0.0:
711 | version "3.0.0"
712 | resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.0.0.tgz#4be9604488e0c4123645def705b1848d16b8e01f"
713 | dependencies:
714 | user-home "^1.1.1"
715 |
716 | validate-npm-package-license@^3.0.1:
717 | version "3.0.1"
718 | resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
719 | dependencies:
720 | spdx-correct "~1.0.0"
721 | spdx-expression-parse "~1.0.0"
722 |
723 | which-module@^1.0.0:
724 | version "1.0.0"
725 | resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
726 |
727 | which@^1.2.9:
728 | version "1.3.0"
729 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a"
730 | dependencies:
731 | isexe "^2.0.0"
732 |
733 | wrap-ansi@^2.0.0:
734 | version "2.1.0"
735 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
736 | dependencies:
737 | string-width "^1.0.1"
738 | strip-ansi "^3.0.1"
739 |
740 | wrappy@1:
741 | version "1.0.2"
742 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
743 |
744 | y18n@^3.2.1:
745 | version "3.2.1"
746 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
747 |
748 | yallist@^2.1.2:
749 | version "2.1.2"
750 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
751 |
752 | yargs-parser@^4.2.0:
753 | version "4.2.1"
754 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c"
755 | dependencies:
756 | camelcase "^3.0.0"
757 |
758 | yargs@^6.6.0:
759 | version "6.6.0"
760 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208"
761 | dependencies:
762 | camelcase "^3.0.0"
763 | cliui "^3.2.0"
764 | decamelize "^1.1.1"
765 | get-caller-file "^1.0.1"
766 | os-locale "^1.4.0"
767 | read-pkg-up "^1.0.1"
768 | require-directory "^2.1.1"
769 | require-main-filename "^1.0.1"
770 | set-blocking "^2.0.0"
771 | string-width "^1.0.2"
772 | which-module "^1.0.0"
773 | y18n "^3.2.1"
774 | yargs-parser "^4.2.0"
775 |
776 | yn@^2.0.0:
777 | version "2.0.0"
778 | resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a"
779 |
--------------------------------------------------------------------------------