UNPKG

12.6 kBJavaScriptView Raw
1/**
2 * @since 2.2.0
3 */
4import { isLeft, isRight, left, mapLeft, right } from 'fp-ts/es6/Either';
5import { pipe } from 'fp-ts/es6/pipeable';
6import * as G from './Guard';
7import { memoize } from './Schemable';
8// -------------------------------------------------------------------------------------
9// DecodeError
10// -------------------------------------------------------------------------------------
11var empty = [];
12/**
13 * @since 2.2.0
14 */
15export function tree(value, forest) {
16 if (forest === void 0) { forest = empty; }
17 return {
18 value: value,
19 forest: forest
20 };
21}
22/**
23 * @since 2.2.0
24 */
25export function success(a) {
26 return right(a);
27}
28/**
29 * @since 2.2.0
30 */
31export function failure(message) {
32 return left([tree(message)]);
33}
34/**
35 * @since 2.2.2
36 */
37export function isNotEmpty(as) {
38 return as.length > 0;
39}
40// -------------------------------------------------------------------------------------
41// constructors
42// -------------------------------------------------------------------------------------
43/**
44 * @since 2.2.3
45 */
46export function of(a) {
47 return {
48 decode: function () { return success(a); }
49 };
50}
51/**
52 * @since 2.2.0
53 */
54export 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 * @since 2.2.0
61 */
62export 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// primitives
76// -------------------------------------------------------------------------------------
77/**
78 * @since 2.2.0
79 */
80export var never = fromGuard(G.never, 'never');
81/**
82 * @since 2.2.0
83 */
84export var string = fromGuard(G.string, 'string');
85/**
86 * @since 2.2.0
87 */
88export var number = fromGuard(G.number, 'number');
89/**
90 * @since 2.2.0
91 */
92export var boolean = fromGuard(G.boolean, 'boolean');
93/**
94 * @since 2.2.0
95 */
96export var UnknownArray = fromGuard(G.UnknownArray, 'Array<unknown>');
97/**
98 * @since 2.2.0
99 */
100export var UnknownRecord = fromGuard(G.UnknownRecord, 'Record<string, unknown>');
101// -------------------------------------------------------------------------------------
102// combinators
103// -------------------------------------------------------------------------------------
104/**
105 * @since 2.2.0
106 */
107export 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 * @since 2.2.0
116 */
117export 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 * @since 2.2.0
131 */
132export 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 * @since 2.2.0
149 */
150export function nullable(or) {
151 return union(literal(null), or);
152}
153/**
154 * @since 2.2.0
155 */
156export 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 * @since 2.2.0
183 */
184export 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 // don't add missing properties
197 if (k in r) {
198 var rk = r[k];
199 // don't strip undefined properties
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 * @since 2.2.0
221 */
222export 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 * @since 2.2.0
249 */
250export 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 * @since 2.2.0
278 */
279export 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}
306function typeOf(x) {
307 return x === null ? 'null' : typeof x;
308}
309/**
310 * @internal
311 */
312export 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 * @since 2.2.0
324 */
325export 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 * @since 2.2.0
342 */
343export 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 * @since 2.2.0
353 */
354export 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 * @since 2.2.0
382 */
383export 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// pipeables
416// -------------------------------------------------------------------------------------
417/**
418 * @since 2.2.0
419 */
420export var map = function (f) { return function (fa) { return map_(fa, f); }; };
421var 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 * @since 2.2.0
429 */
430export var alt = function (that) { return function (fa) { return alt_(fa, that); }; };
431var 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// instances
439// -------------------------------------------------------------------------------------
440/**
441 * @since 2.2.0
442 */
443export var URI = 'io-ts/Decoder';
444/**
445 * @since 2.2.3
446 */
447export var functorDecoder = {
448 URI: URI,
449 map: map_
450};
451/**
452 * @since 2.2.3
453 */
454export var altDecoder = {
455 URI: URI,
456 map: map_,
457 alt: alt_
458};
459/**
460 * @since 2.2.3
461 */
462export 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};