UNPKG

26.7 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5/**
6 * Define a struct error.
7 *
8 * @type {StructError}
9 */
10
11class StructError extends TypeError {
12 static format(attrs) {
13 const { type, path, value } = attrs;
14 const message = `Expected a value of type \`${type}\`${path.length ? ` for \`${path.join('.')}\`` : ''} but received \`${JSON.stringify(value)}\`.`;
15 return message;
16 }
17
18 constructor(attrs) {
19 const message = StructError.format(attrs);
20 super(message);
21
22 const { data, path, value, reason, type, errors = [] } = attrs;
23 this.data = data;
24 this.path = path;
25 this.value = value;
26 this.reason = reason;
27 this.type = type;
28 this.errors = errors;
29
30 if (!errors.length) {
31 errors.push(this);
32 }
33
34 if (Error.captureStackTrace) {
35 Error.captureStackTrace(this, this.constructor);
36 } else {
37 this.stack = new Error().stack;
38 }
39 }
40}
41
42var toString = Object.prototype.toString;
43
44var kindOf = function kindOf(val) {
45 if (val === void 0) return 'undefined';
46 if (val === null) return 'null';
47
48 var type = typeof val;
49 if (type === 'boolean') return 'boolean';
50 if (type === 'string') return 'string';
51 if (type === 'number') return 'number';
52 if (type === 'symbol') return 'symbol';
53 if (type === 'function') {
54 return isGeneratorFn(val) ? 'generatorfunction' : 'function';
55 }
56
57 if (isArray(val)) return 'array';
58 if (isBuffer(val)) return 'buffer';
59 if (isArguments(val)) return 'arguments';
60 if (isDate(val)) return 'date';
61 if (isError(val)) return 'error';
62 if (isRegexp(val)) return 'regexp';
63
64 switch (ctorName(val)) {
65 case 'Symbol': return 'symbol';
66 case 'Promise': return 'promise';
67
68 // Set, Map, WeakSet, WeakMap
69 case 'WeakMap': return 'weakmap';
70 case 'WeakSet': return 'weakset';
71 case 'Map': return 'map';
72 case 'Set': return 'set';
73
74 // 8-bit typed arrays
75 case 'Int8Array': return 'int8array';
76 case 'Uint8Array': return 'uint8array';
77 case 'Uint8ClampedArray': return 'uint8clampedarray';
78
79 // 16-bit typed arrays
80 case 'Int16Array': return 'int16array';
81 case 'Uint16Array': return 'uint16array';
82
83 // 32-bit typed arrays
84 case 'Int32Array': return 'int32array';
85 case 'Uint32Array': return 'uint32array';
86 case 'Float32Array': return 'float32array';
87 case 'Float64Array': return 'float64array';
88 }
89
90 if (isGeneratorObj(val)) {
91 return 'generator';
92 }
93
94 // Non-plain objects
95 type = toString.call(val);
96 switch (type) {
97 case '[object Object]': return 'object';
98 // iterators
99 case '[object Map Iterator]': return 'mapiterator';
100 case '[object Set Iterator]': return 'setiterator';
101 case '[object String Iterator]': return 'stringiterator';
102 case '[object Array Iterator]': return 'arrayiterator';
103 }
104
105 // other
106 return type.slice(8, -1).toLowerCase().replace(/\s/g, '');
107};
108
109function ctorName(val) {
110 return val.constructor ? val.constructor.name : null;
111}
112
113function isArray(val) {
114 if (Array.isArray) return Array.isArray(val);
115 return val instanceof Array;
116}
117
118function isError(val) {
119 return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number');
120}
121
122function isDate(val) {
123 if (val instanceof Date) return true;
124 return typeof val.toDateString === 'function'
125 && typeof val.getDate === 'function'
126 && typeof val.setDate === 'function';
127}
128
129function isRegexp(val) {
130 if (val instanceof RegExp) return true;
131 return typeof val.flags === 'string'
132 && typeof val.ignoreCase === 'boolean'
133 && typeof val.multiline === 'boolean'
134 && typeof val.global === 'boolean';
135}
136
137function isGeneratorFn(name, val) {
138 return ctorName(name) === 'GeneratorFunction';
139}
140
141function isGeneratorObj(val) {
142 return typeof val.throw === 'function'
143 && typeof val.return === 'function'
144 && typeof val.next === 'function';
145}
146
147function isArguments(val) {
148 try {
149 if (typeof val.length === 'number' && typeof val.callee === 'function') {
150 return true;
151 }
152 } catch (err) {
153 if (err.message.indexOf('callee') !== -1) {
154 return true;
155 }
156 }
157 return false;
158}
159
160/**
161 * If you need to support Safari 5-7 (8-10 yr-old browser),
162 * take a look at https://github.com/feross/is-buffer
163 */
164
165function isBuffer(val) {
166 if (val.constructor && typeof val.constructor.isBuffer === 'function') {
167 return val.constructor.isBuffer(val);
168 }
169 return false;
170}
171
172/**
173 * A private string to identify structs by.
174 *
175 * @type {String}
176 */
177
178const IS_STRUCT = '@@__STRUCT__@@';
179
180/**
181 * A private string to refer to a struct's kind.
182 *
183 * @type {String}
184 */
185
186const KIND = '@@__KIND__@@';
187
188/**
189 * Check if a `value` is a struct.
190 *
191 * @param {Any} value
192 * @return {Boolean}
193 */
194
195function isStruct(value) {
196 return !!(value && value[IS_STRUCT]);
197}
198
199/**
200 * Resolve `defaults`, for an optional `value`.
201 *
202 * @param {Function|Any} defaults
203 * @param {Any} value
204 * @return {Any}
205 */
206
207function resolveDefaults(defaults, value) {
208 return typeof defaults === 'function' ? defaults(value) : defaults;
209}
210
211var _extends = Object.assign || function (target) {
212 for (var i = 1; i < arguments.length; i++) {
213 var source = arguments[i];
214
215 for (var key in source) {
216 if (Object.prototype.hasOwnProperty.call(source, key)) {
217 target[key] = source[key];
218 }
219 }
220 }
221
222 return target;
223};
224
225/**
226 * Kind.
227 *
228 * @type {Kind}
229 */
230
231class Kind {
232 constructor(name, type, validate) {
233 this.name = name;
234 this.type = type;
235 this.validate = validate;
236 }
237}
238
239/**
240 * Any.
241 *
242 * @param {Array|Function|Object|String} schema
243 * @param {Any} defaults
244 * @param {Object} options
245 */
246
247function any(schema, defaults$$1, options) {
248 if (isStruct(schema)) {
249 return schema[KIND];
250 }
251
252 if (schema instanceof Kind) {
253 return schema;
254 }
255
256 switch (kindOf(schema)) {
257 case 'array':
258 {
259 return schema.length > 1 ? tuple(schema, defaults$$1, options) : list(schema, defaults$$1, options);
260 }
261
262 case 'function':
263 {
264 return func(schema, defaults$$1, options);
265 }
266
267 case 'object':
268 {
269 return object(schema, defaults$$1, options);
270 }
271
272 case 'string':
273 {
274 let required = true;
275 let type;
276
277 if (schema.endsWith('?')) {
278 required = false;
279 schema = schema.slice(0, -1);
280 }
281
282 if (schema.includes('|')) {
283 const scalars = schema.split(/\s*\|\s*/g);
284 type = union(scalars, defaults$$1, options);
285 } else if (schema.includes('&')) {
286 const scalars = schema.split(/\s*&\s*/g);
287 type = intersection(scalars, defaults$$1, options);
288 } else {
289 type = scalar(schema, defaults$$1, options);
290 }
291
292 if (!required) {
293 type = optional(type, undefined, options);
294 }
295
296 return type;
297 }
298 }
299
300 if (process.env.NODE_ENV !== 'production') {
301 throw new Error(`A schema definition must be an object, array, string or function, but you passed: ${schema}`);
302 } else {
303 throw new Error(`Invalid schema: ${schema}`);
304 }
305}
306
307/**
308 * Dict.
309 *
310 * @param {Array} schema
311 * @param {Object} defaults
312 * @param {Object} options
313 */
314
315function dict(schema, defaults$$1, options) {
316 if (kindOf(schema) !== 'array' || schema.length !== 2) {
317 if (process.env.NODE_ENV !== 'production') {
318 throw new Error(`Dict structs must be defined as an array with two elements, but you passed: ${schema}`);
319 } else {
320 throw new Error(`Invalid schema: ${schema}`);
321 }
322 }
323
324 const obj = scalar('object', undefined, options);
325 const keys = any(schema[0], undefined, options);
326 const values = any(schema[1], undefined, options);
327 const name = 'dict';
328 const type = `dict<${keys.type},${values.type}>`;
329 const validate = (value = resolveDefaults(defaults$$1)) => {
330 const [error] = obj.validate(value);
331
332 if (error) {
333 error.type = type;
334 return [error];
335 }
336
337 const ret = {};
338 const errors = [];
339
340 for (let k in value) {
341 const v = value[k];
342 const [e, r] = keys.validate(k);
343
344 if (e) {
345 e.path = [k].concat(e.path);
346 e.data = value;
347 errors.push(e);
348 continue;
349 }
350
351 k = r;
352 const [e2, r2] = values.validate(v);
353
354 if (e2) {
355 e2.path = [k].concat(e2.path);
356 e2.data = value;
357 errors.push(e2);
358 continue;
359 }
360
361 ret[k] = r2;
362 }
363
364 if (errors.length) {
365 const first = errors[0];
366 first.errors = errors;
367 return [first];
368 }
369
370 return [undefined, ret];
371 };
372
373 return new Kind(name, type, validate);
374}
375
376/**
377 * Enum.
378 *
379 * @param {Array} schema
380 * @param {Any} defaults
381 * @param {Object} options
382 */
383
384function en(schema, defaults$$1, options) {
385 if (kindOf(schema) !== 'array') {
386 if (process.env.NODE_ENV !== 'production') {
387 throw new Error(`Enum structs must be defined as an array, but you passed: ${schema}`);
388 } else {
389 throw new Error(`Invalid schema: ${schema}`);
390 }
391 }
392
393 const name = 'enum';
394 const type = schema.map(s => {
395 try {
396 return JSON.stringify(s);
397 } catch (e) {
398 return String(s);
399 }
400 }).join(' | ');
401
402 const validate = (value = resolveDefaults(defaults$$1)) => {
403 return schema.includes(value) ? [undefined, value] : [{ data: value, path: [], value, type }];
404 };
405
406 return new Kind(name, type, validate);
407}
408
409/**
410 * Enums.
411 *
412 * @param {Array} schema
413 * @param {Any} defaults
414 * @param {Object} options
415 */
416
417function enums(schema, defaults$$1, options) {
418 const e = en(schema, undefined, options);
419 const l = list([e], defaults$$1, options);
420 return l;
421}
422
423/**
424 * Function.
425 *
426 * @param {Function} schema
427 * @param {Any} defaults
428 * @param {Object} options
429 */
430
431function func(schema, defaults$$1, options) {
432 if (kindOf(schema) !== 'function') {
433 if (process.env.NODE_ENV !== 'production') {
434 throw new Error(`Function structs must be defined as a function, but you passed: ${schema}`);
435 } else {
436 throw new Error(`Invalid schema: ${schema}`);
437 }
438 }
439
440 const name = 'function';
441 const type = '<function>';
442 const validate = (value = resolveDefaults(defaults$$1), data) => {
443 const result = schema(value, data);
444 let failure = { path: [], reason: null };
445 let isValid;
446
447 switch (kindOf(result)) {
448 case 'boolean':
449 {
450 isValid = result;
451 break;
452 }
453 case 'string':
454 {
455 isValid = false;
456 failure.reason = result;
457 break;
458 }
459 case 'object':
460 {
461 isValid = false;
462 failure = _extends({}, failure, result);
463 break;
464 }
465 default:
466 {
467 if (process.env.NODE_ENV !== 'production') {
468 throw new Error(`Validator functions must return a boolean, an error reason string or an error reason object, but you passed: ${schema}`);
469 } else {
470 throw new Error(`Invalid result: ${result}`);
471 }
472 }
473 }
474
475 return isValid ? [undefined, value] : [_extends({ type, value, data: value }, failure)];
476 };
477
478 return new Kind(name, type, validate);
479}
480
481/**
482 * Instance.
483 *
484 * @param {Array} schema
485 * @param {Any} defaults
486 * @param {Object} options
487 */
488
489function instance(schema, defaults$$1, options) {
490 const name = 'instance';
491 const type = `instance<${schema.name}>`;
492 const validate = (value = resolveDefaults(defaults$$1)) => {
493 return value instanceof schema ? [undefined, value] : [{ data: value, path: [], value, type }];
494 };
495
496 return new Kind(name, type, validate);
497}
498
499/**
500 * Interface.
501 *
502 * @param {Object} schema
503 * @param {Object} defaults
504 * @param {Object} options
505 */
506
507function inter(schema, defaults$$1, options) {
508 if (kindOf(schema) !== 'object') {
509 if (process.env.NODE_ENV !== 'production') {
510 throw new Error(`Interface structs must be defined as an object, but you passed: ${schema}`);
511 } else {
512 throw new Error(`Invalid schema: ${schema}`);
513 }
514 }
515
516 const ks = [];
517 const properties = {};
518
519 for (const key in schema) {
520 ks.push(key);
521 const s = schema[key];
522 const kind = any(s, undefined, options);
523 properties[key] = kind;
524 }
525
526 const name = 'interface';
527 const type = `{${ks.join()}}`;
528 const validate = (value = resolveDefaults(defaults$$1)) => {
529 const errors = [];
530
531 for (const key in properties) {
532 const v = value[key];
533 const kind = properties[key];
534 const [e] = kind.validate(v);
535
536 if (e) {
537 e.path = [key].concat(e.path);
538 e.data = value;
539 errors.push(e);
540 continue;
541 }
542 }
543
544 if (errors.length) {
545 const first = errors[0];
546 first.errors = errors;
547 return [first];
548 }
549
550 return [undefined, value];
551 };
552
553 return new Kind(name, type, validate);
554}
555
556/**
557 * Lazy.
558 *
559 * @param {Function} schema
560 * @param {Any} defaults
561 * @param {Object} options
562 */
563
564function lazy(schema, defaults$$1, options) {
565 if (kindOf(schema) !== 'function') {
566 if (process.env.NODE_ENV !== 'production') {
567 throw new Error(`Lazy structs must be defined as an function that returns a schema, but you passed: ${schema}`);
568 } else {
569 throw new Error(`Invalid schema: ${schema}`);
570 }
571 }
572
573 let kind;
574 let struct;
575 const name = 'lazy';
576 const type = `lazy...`;
577 const compile = value => {
578 struct = schema();
579 kind.name = struct.kind;
580 kind.type = struct.type;
581 kind.validate = struct.validate;
582 return kind.validate(value);
583 };
584
585 kind = new Kind(name, type, compile);
586 return kind;
587}
588
589/**
590 * List.
591 *
592 * @param {Array} schema
593 * @param {Array} defaults
594 * @param {Object} options
595 */
596
597function list(schema, defaults$$1, options) {
598 if (kindOf(schema) !== 'array' || schema.length !== 1) {
599 if (process.env.NODE_ENV !== 'production') {
600 throw new Error(`List structs must be defined as an array with a single element, but you passed: ${schema}`);
601 } else {
602 throw new Error(`Invalid schema: ${schema}`);
603 }
604 }
605
606 const array = scalar('array', undefined, options);
607 const element = any(schema[0], undefined, options);
608 const name = 'list';
609 const type = `[${element.type}]`;
610 const validate = (value = resolveDefaults(defaults$$1)) => {
611 const [error, result] = array.validate(value);
612
613 if (error) {
614 error.type = type;
615 return [error];
616 }
617
618 value = result;
619 const errors = [];
620 const ret = [];
621
622 for (let i = 0; i < value.length; i++) {
623 const v = value[i];
624 const [e, r] = element.validate(v);
625
626 if (e) {
627 e.path = [i].concat(e.path);
628 e.data = value;
629 errors.push(e);
630 continue;
631 }
632
633 ret[i] = r;
634 }
635
636 if (errors.length) {
637 const first = errors[0];
638 first.errors = errors;
639 return [first];
640 }
641
642 return [undefined, ret];
643 };
644
645 return new Kind(name, type, validate);
646}
647
648/**
649 * Literal.
650 *
651 * @param {Array} schema
652 * @param {Any} defaults
653 * @param {Object} options
654 */
655
656function literal(schema, defaults$$1, options) {
657 const name = 'literal';
658 const type = `literal: ${JSON.stringify(schema)}`;
659 const validate = (value = resolveDefaults(defaults$$1)) => {
660 return value === schema ? [undefined, value] : [{ data: value, path: [], value, type }];
661 };
662
663 return new Kind(name, type, validate);
664}
665
666/**
667 * Object.
668 *
669 * @param {Object} schema
670 * @param {Object} defaults
671 * @param {Object} options
672 */
673
674function object(schema, defaults$$1, options) {
675 if (kindOf(schema) !== 'object') {
676 if (process.env.NODE_ENV !== 'production') {
677 throw new Error(`Object structs must be defined as an object, but you passed: ${schema}`);
678 } else {
679 throw new Error(`Invalid schema: ${schema}`);
680 }
681 }
682
683 const obj = scalar('object', undefined, options);
684 const ks = [];
685 const properties = {};
686
687 for (const key in schema) {
688 ks.push(key);
689 const s = schema[key];
690 const kind = any(s, undefined, options);
691 properties[key] = kind;
692 }
693
694 const name = 'object';
695 const type = `{${ks.join()}}`;
696 const validate = (value = resolveDefaults(defaults$$1)) => {
697 const [error] = obj.validate(value);
698
699 if (error) {
700 error.type = type;
701 return [error];
702 }
703
704 const errors = [];
705 const ret = {};
706 const valueKeys = Object.keys(value);
707 const propertiesKeys = Object.keys(properties);
708 const keys = new Set(valueKeys.concat(propertiesKeys));
709
710 keys.forEach(key => {
711 let v = value[key];
712 const kind = properties[key];
713
714 if (v === undefined) {
715 const d = defaults$$1 && defaults$$1[key];
716 v = resolveDefaults(d, value);
717 }
718
719 if (!kind) {
720 const e = { data: value, path: [key], value: v };
721 errors.push(e);
722 return;
723 }
724
725 const [e, r] = kind.validate(v, value);
726
727 if (e) {
728 e.path = [key].concat(e.path);
729 e.data = value;
730 errors.push(e);
731 return;
732 }
733
734 if (key in value || r !== undefined) {
735 ret[key] = r;
736 }
737 });
738
739 if (errors.length) {
740 const first = errors[0];
741 first.errors = errors;
742 return [first];
743 }
744
745 return [undefined, ret];
746 };
747
748 return new Kind(name, type, validate);
749}
750
751/**
752 * Optional.
753 *
754 * @param {Any} schema
755 * @param {Any} defaults
756 * @param {Object} options
757 */
758
759function optional(schema, defaults$$1, options) {
760 return union([schema, 'undefined'], defaults$$1, options);
761}
762
763/**
764 * Partial.
765 *
766 * @param {Object} schema
767 * @param {Object} defaults
768 * @param {Object} options
769 */
770
771function partial(schema, defaults$$1, options) {
772 if (kindOf(schema) !== 'object') {
773 if (process.env.NODE_ENV !== 'production') {
774 throw new Error(`Partial structs must be defined as an object, but you passed: ${schema}`);
775 } else {
776 throw new Error(`Invalid schema: ${schema}`);
777 }
778 }
779
780 const obj = scalar('object', undefined, options);
781 const ks = [];
782 const properties = {};
783
784 for (const key in schema) {
785 ks.push(key);
786 const s = schema[key];
787 const kind = any(s, undefined, options);
788 properties[key] = kind;
789 }
790
791 const name = 'partial';
792 const type = `{${ks.join()},...}`;
793 const validate = (value = resolveDefaults(defaults$$1)) => {
794 const [error] = obj.validate(value);
795
796 if (error) {
797 error.type = type;
798 return [error];
799 }
800
801 const errors = [];
802 const ret = {};
803
804 for (const key in properties) {
805 let v = value[key];
806 const kind = properties[key];
807
808 if (v === undefined) {
809 const d = defaults$$1 && defaults$$1[key];
810 v = resolveDefaults(d, value);
811 }
812
813 const [e, r] = kind.validate(v, value);
814
815 if (e) {
816 e.path = [key].concat(e.path);
817 e.data = value;
818 errors.push(e);
819 continue;
820 }
821
822 if (key in value || r !== undefined) {
823 ret[key] = r;
824 }
825 }
826
827 if (errors.length) {
828 const first = errors[0];
829 first.errors = errors;
830 return [first];
831 }
832
833 return [undefined, ret];
834 };
835
836 return new Kind(name, type, validate);
837}
838
839/**
840 * Scalar.
841 *
842 * @param {String} schema
843 * @param {Any} defaults
844 * @param {Object} options
845 */
846
847function scalar(schema, defaults$$1, options) {
848 if (kindOf(schema) !== 'string') {
849 if (process.env.NODE_ENV !== 'production') {
850 throw new Error(`Scalar structs must be defined as a string, but you passed: ${schema}`);
851 } else {
852 throw new Error(`Invalid schema: ${schema}`);
853 }
854 }
855
856 const { types } = options;
857 const fn = types[schema];
858
859 if (kindOf(fn) !== 'function') {
860 if (process.env.NODE_ENV !== 'production') {
861 throw new Error(`No struct validator function found for type "${schema}".`);
862 } else {
863 throw new Error(`Invalid type: ${schema}`);
864 }
865 }
866
867 const kind = func(fn, defaults$$1, options);
868 const name = 'scalar';
869 const type = schema;
870 const validate = value => {
871 const [error, result] = kind.validate(value);
872
873 if (error) {
874 error.type = type;
875 return [error];
876 }
877
878 return [undefined, result];
879 };
880
881 return new Kind(name, type, validate);
882}
883
884/**
885 * Tuple.
886 *
887 * @param {Array} schema
888 * @param {Array} defaults
889 * @param {Object} options
890 */
891
892function tuple(schema, defaults$$1, options) {
893 if (kindOf(schema) !== 'array') {
894 if (process.env.NODE_ENV !== 'production') {
895 throw new Error(`Tuple structs must be defined as an array, but you passed: ${schema}`);
896 } else {
897 throw new Error(`Invalid schema: ${schema}`);
898 }
899 }
900
901 const kinds = schema.map(s => any(s, undefined, options));
902 const array = scalar('array', undefined, options);
903 const name = 'tuple';
904 const type = `[${kinds.map(k => k.type).join()}]`;
905 const validate = (value = resolveDefaults(defaults$$1)) => {
906 const [error] = array.validate(value);
907
908 if (error) {
909 error.type = type;
910 return [error];
911 }
912
913 const ret = [];
914 const errors = [];
915 const length = Math.max(value.length, kinds.length);
916
917 for (let i = 0; i < length; i++) {
918 const kind = kinds[i];
919 const v = value[i];
920
921 if (!kind) {
922 const e = { data: value, path: [i], value: v };
923 errors.push(e);
924 continue;
925 }
926
927 const [e, r] = kind.validate(v);
928
929 if (e) {
930 e.path = [i].concat(e.path);
931 e.data = value;
932 errors.push(e);
933 continue;
934 }
935
936 ret[i] = r;
937 }
938
939 if (errors.length) {
940 const first = errors[0];
941 first.errors = errors;
942 return [first];
943 }
944
945 return [undefined, ret];
946 };
947
948 return new Kind(name, type, validate);
949}
950
951/**
952 * Union.
953 *
954 * @param {Array} schema
955 * @param {Any} defaults
956 * @param {Object} options
957 */
958
959function union(schema, defaults$$1, options) {
960 if (kindOf(schema) !== 'array') {
961 if (process.env.NODE_ENV !== 'production') {
962 throw new Error(`Union structs must be defined as an array, but you passed: ${schema}`);
963 } else {
964 throw new Error(`Invalid schema: ${schema}`);
965 }
966 }
967
968 const kinds = schema.map(s => any(s, undefined, options));
969 const name = 'union';
970 const type = kinds.map(k => k.type).join(' | ');
971 const validate = (value = resolveDefaults(defaults$$1)) => {
972 const errors = [];
973
974 for (const k of kinds) {
975 const [e, r] = k.validate(value);
976
977 if (!e) {
978 return [undefined, r];
979 }
980
981 errors.push(e);
982 }
983 errors[0].type = type;
984 return errors;
985 };
986
987 return new Kind(name, type, validate);
988}
989
990/**
991 * Intersection.
992 *
993 * @param {Array} schema
994 * @param {Any} defaults
995 * @param {Object} options
996 */
997
998function intersection(schema, defaults$$1, options) {
999 if (kindOf(schema) !== 'array') {
1000 if (process.env.NODE_ENV !== 'production') {
1001 throw new Error(`Intersection structs must be defined as an array, but you passed: ${schema}`);
1002 } else {
1003 throw new Error(`Invalid schema: ${schema}`);
1004 }
1005 }
1006
1007 const types = schema.map(s => any(s, undefined, options));
1008 const name = 'intersection';
1009 const type = types.map(t => t.type).join(' & ');
1010 const validate = (value = resolveDefaults(defaults$$1)) => {
1011 let v = value;
1012
1013 for (const t of types) {
1014 const [e, r] = t.validate(v);
1015
1016 if (e) {
1017 e.type = type;
1018 return [e];
1019 }
1020
1021 v = r;
1022 }
1023
1024 return [undefined, v];
1025 };
1026
1027 return new Kind(name, type, validate);
1028}
1029
1030/**
1031 * Kinds.
1032 *
1033 * @type {Object}
1034 */
1035
1036const Kinds = {
1037 any,
1038 dict,
1039 enum: en,
1040 enums,
1041 function: func,
1042 instance,
1043 interface: inter,
1044 lazy,
1045 list,
1046 literal,
1047 object,
1048 optional,
1049 partial,
1050 scalar,
1051 tuple,
1052 union,
1053 intersection
1054
1055 /**
1056 * Export.
1057 *
1058 * @type {Object}
1059 */
1060
1061};
1062
1063/**
1064 * The types that `kind-of` supports.
1065 *
1066 * @type {Array}
1067 */
1068
1069const TYPES = ['arguments', 'array', 'boolean', 'buffer', 'date', 'error', 'float32array', 'float64array', 'function', 'generatorfunction', 'int16array', 'int32array', 'int8array', 'map', 'null', 'number', 'object', 'promise', 'regexp', 'set', 'string', 'symbol', 'uint16array', 'uint32array', 'uint8array', 'uint8clampedarray', 'undefined', 'weakmap', 'weakset'];
1070
1071/**
1072 * The default types that Superstruct ships with.
1073 *
1074 * @type {Object}
1075 */
1076
1077const Types = {
1078 any: value => value !== undefined
1079};
1080
1081TYPES.forEach(type => {
1082 Types[type] = value => kindOf(value) === type;
1083});
1084
1085/**
1086 * Create a struct factory with a `config`.
1087 *
1088 * @param {Object} config
1089 * @return {Function}
1090 */
1091
1092function superstruct(config = {}) {
1093 const types = _extends({}, Types, config.types || {});
1094
1095 /**
1096 * Create a `kind` struct with `schema`, `defaults` and `options`.
1097 *
1098 * @param {Any} schema
1099 * @param {Any} defaults
1100 * @param {Object} options
1101 * @return {Function}
1102 */
1103
1104 function struct(schema, defaults$$1, options = {}) {
1105 if (isStruct(schema)) {
1106 schema = schema.schema;
1107 }
1108
1109 const kind = Kinds.any(schema, defaults$$1, _extends({}, options, { types }));
1110
1111 function Struct(data) {
1112 if (this instanceof Struct) {
1113 if (process.env.NODE_ENV !== 'production') {
1114 throw new Error('The `Struct` creation function should not be used with the `new` keyword.');
1115 } else {
1116 throw new Error('Invalid `new` keyword!');
1117 }
1118 }
1119
1120 return Struct.assert(data);
1121 }
1122
1123 Object.defineProperty(Struct, IS_STRUCT, { value: true });
1124 Object.defineProperty(Struct, KIND, { value: kind });
1125
1126 Struct.kind = kind.name;
1127 Struct.type = kind.type;
1128 Struct.schema = schema;
1129 Struct.defaults = defaults$$1;
1130 Struct.options = options;
1131
1132 Struct.assert = value => {
1133 const [error, result] = kind.validate(value);
1134
1135 if (error) {
1136 throw new StructError(error);
1137 }
1138
1139 return result;
1140 };
1141
1142 Struct.test = value => {
1143 const [error] = kind.validate(value);
1144 return !error;
1145 };
1146
1147 Struct.validate = value => {
1148 const [error, result] = kind.validate(value);
1149
1150 if (error) {
1151 return [new StructError(error)];
1152 }
1153
1154 return [undefined, result];
1155 };
1156
1157 return Struct;
1158 }
1159
1160 /**
1161 * Mix in a factory for each specific kind of struct.
1162 */
1163
1164 Object.keys(Kinds).forEach(name => {
1165 const kind = Kinds[name];
1166
1167 struct[name] = (schema, defaults$$1, options) => {
1168 const type = kind(schema, defaults$$1, _extends({}, options, { types }));
1169 const s = struct(type, defaults$$1, options);
1170 return s;
1171 };
1172 });
1173
1174 /**
1175 * Return the struct factory.
1176 */
1177
1178 return struct;
1179}
1180
1181/**
1182 * Create a convenience `struct` factory for the default types.
1183 *
1184 * @type {Function}
1185 */
1186
1187const struct = superstruct();
1188
1189exports.struct = struct;
1190exports.superstruct = superstruct;
1191exports.isStruct = isStruct;
1192exports.StructError = StructError;
1193//# sourceMappingURL=index.js.map