1 |
|
2 |
|
3 |
|
4 | import { isLeft, isRight, left, mapLeft, right } from 'fp-ts/es6/Either';
|
5 | import { pipe } from 'fp-ts/es6/pipeable';
|
6 | import * as G from './Guard';
|
7 | import { memoize } from './Schemable';
|
8 |
|
9 |
|
10 |
|
11 | var empty = [];
|
12 |
|
13 |
|
14 |
|
15 | export function tree(value, forest) {
|
16 | if (forest === void 0) { forest = empty; }
|
17 | return {
|
18 | value: value,
|
19 | forest: forest
|
20 | };
|
21 | }
|
22 |
|
23 |
|
24 |
|
25 | export function success(a) {
|
26 | return right(a);
|
27 | }
|
28 |
|
29 |
|
30 |
|
31 | export function failure(message) {
|
32 | return left([tree(message)]);
|
33 | }
|
34 |
|
35 |
|
36 |
|
37 | export function isNotEmpty(as) {
|
38 | return as.length > 0;
|
39 | }
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 | export function of(a) {
|
47 | return {
|
48 | decode: function () { return success(a); }
|
49 | };
|
50 | }
|
51 |
|
52 |
|
53 |
|
54 | export function fromGuard(guard, expected) {
|
55 | return {
|
56 | decode: function (u) { return (guard.is(u) ? success(u) : failure("cannot decode " + JSON.stringify(u) + ", should be " + expected)); }
|
57 | };
|
58 | }
|
59 |
|
60 |
|
61 |
|
62 | export function literal() {
|
63 | var _a;
|
64 | var values = [];
|
65 | for (var _i = 0; _i < arguments.length; _i++) {
|
66 | values[_i] = arguments[_i];
|
67 | }
|
68 | if (values.length === 0) {
|
69 | return never;
|
70 | }
|
71 | var expected = values.map(function (value) { return JSON.stringify(value); }).join(' | ');
|
72 | return fromGuard((_a = G.schemableGuard).literal.apply(_a, values), expected);
|
73 | }
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 | export var never = fromGuard(G.never, 'never');
|
81 |
|
82 |
|
83 |
|
84 | export var string = fromGuard(G.string, 'string');
|
85 |
|
86 |
|
87 |
|
88 | export var number = fromGuard(G.number, 'number');
|
89 |
|
90 |
|
91 |
|
92 | export var boolean = fromGuard(G.boolean, 'boolean');
|
93 |
|
94 |
|
95 |
|
96 | export var UnknownArray = fromGuard(G.UnknownArray, 'Array<unknown>');
|
97 |
|
98 |
|
99 |
|
100 | export var UnknownRecord = fromGuard(G.UnknownRecord, 'Record<string, unknown>');
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 | export function withExpected(decoder, expected) {
|
108 | return {
|
109 | decode: function (u) {
|
110 | return pipe(decoder.decode(u), mapLeft(function (nea) { return expected(u, nea); }));
|
111 | }
|
112 | };
|
113 | }
|
114 |
|
115 |
|
116 |
|
117 | export function refinement(from, refinement, expected) {
|
118 | return {
|
119 | decode: function (u) {
|
120 | var e = from.decode(u);
|
121 | if (isLeft(e)) {
|
122 | return e;
|
123 | }
|
124 | var a = e.right;
|
125 | return refinement(a) ? success(a) : failure("cannot refine " + JSON.stringify(u) + ", should be " + expected);
|
126 | }
|
127 | };
|
128 | }
|
129 |
|
130 |
|
131 |
|
132 | export function parse(from, parser) {
|
133 | return {
|
134 | decode: function (u) {
|
135 | var e = from.decode(u);
|
136 | if (isLeft(e)) {
|
137 | return e;
|
138 | }
|
139 | var pe = parser(e.right);
|
140 | if (isLeft(pe)) {
|
141 | return failure(pe.left);
|
142 | }
|
143 | return pe;
|
144 | }
|
145 | };
|
146 | }
|
147 |
|
148 |
|
149 |
|
150 | export function nullable(or) {
|
151 | return union(literal(null), or);
|
152 | }
|
153 |
|
154 |
|
155 |
|
156 | export function type(properties) {
|
157 | return {
|
158 | decode: function (u) {
|
159 | var e = UnknownRecord.decode(u);
|
160 | if (isLeft(e)) {
|
161 | return e;
|
162 | }
|
163 | else {
|
164 | var r = e.right;
|
165 | var a = {};
|
166 | var errors = [];
|
167 | for (var k in properties) {
|
168 | var e_1 = properties[k].decode(r[k]);
|
169 | if (isLeft(e_1)) {
|
170 | errors.push(tree("required property " + JSON.stringify(k), e_1.left));
|
171 | }
|
172 | else {
|
173 | a[k] = e_1.right;
|
174 | }
|
175 | }
|
176 | return isNotEmpty(errors) ? left(errors) : success(a);
|
177 | }
|
178 | }
|
179 | };
|
180 | }
|
181 |
|
182 |
|
183 |
|
184 | export function partial(properties) {
|
185 | return {
|
186 | decode: function (u) {
|
187 | var e = UnknownRecord.decode(u);
|
188 | if (isLeft(e)) {
|
189 | return e;
|
190 | }
|
191 | else {
|
192 | var r = e.right;
|
193 | var a = {};
|
194 | var errors = [];
|
195 | for (var k in properties) {
|
196 |
|
197 | if (k in r) {
|
198 | var rk = r[k];
|
199 |
|
200 | if (rk === undefined) {
|
201 | a[k] = undefined;
|
202 | }
|
203 | else {
|
204 | var e_2 = properties[k].decode(rk);
|
205 | if (isLeft(e_2)) {
|
206 | errors.push(tree("optional property " + JSON.stringify(k), e_2.left));
|
207 | }
|
208 | else {
|
209 | a[k] = e_2.right;
|
210 | }
|
211 | }
|
212 | }
|
213 | }
|
214 | return isNotEmpty(errors) ? left(errors) : success(a);
|
215 | }
|
216 | }
|
217 | };
|
218 | }
|
219 |
|
220 |
|
221 |
|
222 | export function record(codomain) {
|
223 | return {
|
224 | decode: function (u) {
|
225 | var e = UnknownRecord.decode(u);
|
226 | if (isLeft(e)) {
|
227 | return e;
|
228 | }
|
229 | else {
|
230 | var r = e.right;
|
231 | var a = {};
|
232 | var errors = [];
|
233 | for (var k in r) {
|
234 | var e_3 = codomain.decode(r[k]);
|
235 | if (isLeft(e_3)) {
|
236 | errors.push(tree("key " + JSON.stringify(k), e_3.left));
|
237 | }
|
238 | else {
|
239 | a[k] = e_3.right;
|
240 | }
|
241 | }
|
242 | return isNotEmpty(errors) ? left(errors) : success(a);
|
243 | }
|
244 | }
|
245 | };
|
246 | }
|
247 |
|
248 |
|
249 |
|
250 | export function array(items) {
|
251 | return {
|
252 | decode: function (u) {
|
253 | var e = UnknownArray.decode(u);
|
254 | if (isLeft(e)) {
|
255 | return e;
|
256 | }
|
257 | else {
|
258 | var us = e.right;
|
259 | var len = us.length;
|
260 | var a = new Array(len);
|
261 | var errors = [];
|
262 | for (var i = 0; i < len; i++) {
|
263 | var e_4 = items.decode(us[i]);
|
264 | if (isLeft(e_4)) {
|
265 | errors.push(tree("item " + i, e_4.left));
|
266 | }
|
267 | else {
|
268 | a[i] = e_4.right;
|
269 | }
|
270 | }
|
271 | return isNotEmpty(errors) ? left(errors) : success(a);
|
272 | }
|
273 | }
|
274 | };
|
275 | }
|
276 |
|
277 |
|
278 |
|
279 | export function tuple() {
|
280 | var components = [];
|
281 | for (var _i = 0; _i < arguments.length; _i++) {
|
282 | components[_i] = arguments[_i];
|
283 | }
|
284 | return {
|
285 | decode: function (u) {
|
286 | var e = UnknownArray.decode(u);
|
287 | if (isLeft(e)) {
|
288 | return e;
|
289 | }
|
290 | var us = e.right;
|
291 | var a = [];
|
292 | var errors = [];
|
293 | for (var i = 0; i < components.length; i++) {
|
294 | var e_5 = components[i].decode(us[i]);
|
295 | if (isLeft(e_5)) {
|
296 | errors.push(tree("component " + i, e_5.left));
|
297 | }
|
298 | else {
|
299 | a.push(e_5.right);
|
300 | }
|
301 | }
|
302 | return isNotEmpty(errors) ? left(errors) : success(a);
|
303 | }
|
304 | };
|
305 | }
|
306 | function typeOf(x) {
|
307 | return x === null ? 'null' : typeof x;
|
308 | }
|
309 |
|
310 |
|
311 |
|
312 | export function intersect(a, b) {
|
313 | if (a !== undefined && b !== undefined) {
|
314 | var tx = typeOf(a);
|
315 | var ty = typeOf(b);
|
316 | if (tx === 'object' || ty === 'object') {
|
317 | return Object.assign({}, a, b);
|
318 | }
|
319 | }
|
320 | return b;
|
321 | }
|
322 |
|
323 |
|
324 |
|
325 | export function intersection(left, right) {
|
326 | return {
|
327 | decode: function (u) {
|
328 | var ea = left.decode(u);
|
329 | if (isLeft(ea)) {
|
330 | return ea;
|
331 | }
|
332 | var eb = right.decode(u);
|
333 | if (isLeft(eb)) {
|
334 | return eb;
|
335 | }
|
336 | return success(intersect(ea.right, eb.right));
|
337 | }
|
338 | };
|
339 | }
|
340 |
|
341 |
|
342 |
|
343 | export function lazy(id, f) {
|
344 | var get = memoize(f);
|
345 | return {
|
346 | decode: function (u) {
|
347 | return pipe(get().decode(u), mapLeft(function (nea) { return [tree(id, nea)]; }));
|
348 | }
|
349 | };
|
350 | }
|
351 |
|
352 |
|
353 |
|
354 | export function sum(tag) {
|
355 | return function (members) {
|
356 | var keys = Object.keys(members);
|
357 | if (keys.length === 0) {
|
358 | return never;
|
359 | }
|
360 | var expected = keys.map(function (k) { return JSON.stringify(k); }).join(' | ');
|
361 | return {
|
362 | decode: function (u) {
|
363 | var e = UnknownRecord.decode(u);
|
364 | if (isLeft(e)) {
|
365 | return e;
|
366 | }
|
367 | var v = e.right[tag];
|
368 | if (G.string.is(v) && v in members) {
|
369 | return members[v].decode(u);
|
370 | }
|
371 | return left([
|
372 | tree("required property " + JSON.stringify(tag), [
|
373 | tree("cannot decode " + JSON.stringify(v) + ", should be " + expected)
|
374 | ])
|
375 | ]);
|
376 | }
|
377 | };
|
378 | };
|
379 | }
|
380 |
|
381 |
|
382 |
|
383 | export function union() {
|
384 | var members = [];
|
385 | for (var _i = 0; _i < arguments.length; _i++) {
|
386 | members[_i] = arguments[_i];
|
387 | }
|
388 | var len = members.length;
|
389 | if (len === 0) {
|
390 | return never;
|
391 | }
|
392 | return {
|
393 | decode: function (u) {
|
394 | var e = members[0].decode(u);
|
395 | if (isRight(e)) {
|
396 | return e;
|
397 | }
|
398 | else {
|
399 | var errors = [tree("member 0", e.left)];
|
400 | for (var i = 1; i < len; i++) {
|
401 | var e_6 = members[i].decode(u);
|
402 | if (isRight(e_6)) {
|
403 | return e_6;
|
404 | }
|
405 | else {
|
406 | errors.push(tree("member " + i, e_6.left));
|
407 | }
|
408 | }
|
409 | return left(errors);
|
410 | }
|
411 | }
|
412 | };
|
413 | }
|
414 |
|
415 |
|
416 |
|
417 |
|
418 |
|
419 |
|
420 | export var map = function (f) { return function (fa) { return map_(fa, f); }; };
|
421 | var map_ = function (fa, f) { return ({
|
422 | decode: function (u) {
|
423 | var e = fa.decode(u);
|
424 | return isLeft(e) ? e : right(f(e.right));
|
425 | }
|
426 | }); };
|
427 |
|
428 |
|
429 |
|
430 | export var alt = function (that) { return function (fa) { return alt_(fa, that); }; };
|
431 | var alt_ = function (fx, fy) { return ({
|
432 | decode: function (u) {
|
433 | var e = fx.decode(u);
|
434 | return isLeft(e) ? fy().decode(u) : e;
|
435 | }
|
436 | }); };
|
437 |
|
438 |
|
439 |
|
440 |
|
441 |
|
442 |
|
443 | export var URI = 'io-ts/Decoder';
|
444 |
|
445 |
|
446 |
|
447 | export var functorDecoder = {
|
448 | URI: URI,
|
449 | map: map_
|
450 | };
|
451 |
|
452 |
|
453 |
|
454 | export var altDecoder = {
|
455 | URI: URI,
|
456 | map: map_,
|
457 | alt: alt_
|
458 | };
|
459 |
|
460 |
|
461 |
|
462 | export var schemableDecoder = {
|
463 | URI: URI,
|
464 | literal: literal,
|
465 | string: string,
|
466 | number: number,
|
467 | boolean: boolean,
|
468 | nullable: nullable,
|
469 | type: type,
|
470 | partial: partial,
|
471 | record: record,
|
472 | array: array,
|
473 | tuple: tuple,
|
474 | intersection: intersection,
|
475 | sum: sum,
|
476 | lazy: lazy,
|
477 | UnknownArray: UnknownArray,
|
478 | UnknownRecord: UnknownRecord,
|
479 | union: union,
|
480 | refinement: refinement
|
481 | };
|