• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4  value: true
5});
6exports.validate = validate;
7exports.typeIs = typeIs;
8exports.validateType = validateType;
9exports.validateOptional = validateOptional;
10exports.validateOptionalType = validateOptionalType;
11exports.arrayOf = arrayOf;
12exports.arrayOfType = arrayOfType;
13exports.validateArrayOfType = validateArrayOfType;
14exports.assertEach = assertEach;
15exports.assertOneOf = assertOneOf;
16exports.assertNodeType = assertNodeType;
17exports.assertNodeOrValueType = assertNodeOrValueType;
18exports.assertValueType = assertValueType;
19exports.assertShape = assertShape;
20exports.chain = chain;
21exports.default = defineType;
22exports.DEPRECATED_KEYS = exports.BUILDER_KEYS = exports.NODE_FIELDS = exports.FLIPPED_ALIAS_KEYS = exports.ALIAS_KEYS = exports.VISITOR_KEYS = void 0;
23
24var _is = _interopRequireDefault(require("../validators/is"));
25
26var _validate = require("../validators/validate");
27
28function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
29
30const VISITOR_KEYS = {};
31exports.VISITOR_KEYS = VISITOR_KEYS;
32const ALIAS_KEYS = {};
33exports.ALIAS_KEYS = ALIAS_KEYS;
34const FLIPPED_ALIAS_KEYS = {};
35exports.FLIPPED_ALIAS_KEYS = FLIPPED_ALIAS_KEYS;
36const NODE_FIELDS = {};
37exports.NODE_FIELDS = NODE_FIELDS;
38const BUILDER_KEYS = {};
39exports.BUILDER_KEYS = BUILDER_KEYS;
40const DEPRECATED_KEYS = {};
41exports.DEPRECATED_KEYS = DEPRECATED_KEYS;
42
43function getType(val) {
44  if (Array.isArray(val)) {
45    return "array";
46  } else if (val === null) {
47    return "null";
48  } else if (val === undefined) {
49    return "undefined";
50  } else {
51    return typeof val;
52  }
53}
54
55function validate(validate) {
56  return {
57    validate
58  };
59}
60
61function typeIs(typeName) {
62  return typeof typeName === "string" ? assertNodeType(typeName) : assertNodeType(...typeName);
63}
64
65function validateType(typeName) {
66  return validate(typeIs(typeName));
67}
68
69function validateOptional(validate) {
70  return {
71    validate,
72    optional: true
73  };
74}
75
76function validateOptionalType(typeName) {
77  return {
78    validate: typeIs(typeName),
79    optional: true
80  };
81}
82
83function arrayOf(elementType) {
84  return chain(assertValueType("array"), assertEach(elementType));
85}
86
87function arrayOfType(typeName) {
88  return arrayOf(typeIs(typeName));
89}
90
91function validateArrayOfType(typeName) {
92  return validate(arrayOfType(typeName));
93}
94
95function assertEach(callback) {
96  function validator(node, key, val) {
97    if (!Array.isArray(val)) return;
98
99    for (let i = 0; i < val.length; i++) {
100      callback(node, `${key}[${i}]`, val[i]);
101    }
102  }
103
104  validator.each = callback;
105  return validator;
106}
107
108function assertOneOf(...values) {
109  function validate(node, key, val) {
110    if (values.indexOf(val) < 0) {
111      throw new TypeError(`Property ${key} expected value to be one of ${JSON.stringify(values)} but got ${JSON.stringify(val)}`);
112    }
113  }
114
115  validate.oneOf = values;
116  return validate;
117}
118
119function assertNodeType(...types) {
120  function validate(node, key, val) {
121    let valid = false;
122
123    for (const type of types) {
124      if ((0, _is.default)(type, val)) {
125        valid = true;
126        break;
127      }
128    }
129
130    if (!valid) {
131      throw new TypeError(`Property ${key} of ${node.type} expected node to be of a type ${JSON.stringify(types)} ` + `but instead got ${JSON.stringify(val && val.type)}`);
132    }
133  }
134
135  validate.oneOfNodeTypes = types;
136  return validate;
137}
138
139function assertNodeOrValueType(...types) {
140  function validate(node, key, val) {
141    let valid = false;
142
143    for (const type of types) {
144      if (getType(val) === type || (0, _is.default)(type, val)) {
145        valid = true;
146        break;
147      }
148    }
149
150    if (!valid) {
151      throw new TypeError(`Property ${key} of ${node.type} expected node to be of a type ${JSON.stringify(types)} ` + `but instead got ${JSON.stringify(val && val.type)}`);
152    }
153  }
154
155  validate.oneOfNodeOrValueTypes = types;
156  return validate;
157}
158
159function assertValueType(type) {
160  function validate(node, key, val) {
161    const valid = getType(val) === type;
162
163    if (!valid) {
164      throw new TypeError(`Property ${key} expected type of ${type} but got ${getType(val)}`);
165    }
166  }
167
168  validate.type = type;
169  return validate;
170}
171
172function assertShape(shape) {
173  function validate(node, key, val) {
174    const errors = [];
175
176    for (const property of Object.keys(shape)) {
177      try {
178        (0, _validate.validateField)(node, property, val[property], shape[property]);
179      } catch (error) {
180        if (error instanceof TypeError) {
181          errors.push(error.message);
182          continue;
183        }
184
185        throw error;
186      }
187    }
188
189    if (errors.length) {
190      throw new TypeError(`Property ${key} of ${node.type} expected to have the following:\n${errors.join("\n")}`);
191    }
192  }
193
194  validate.shapeOf = shape;
195  return validate;
196}
197
198function chain(...fns) {
199  function validate(...args) {
200    for (const fn of fns) {
201      fn(...args);
202    }
203  }
204
205  validate.chainOf = fns;
206  return validate;
207}
208
209function defineType(type, opts = {}) {
210  const inherits = opts.inherits && store[opts.inherits] || {};
211  const fields = opts.fields || inherits.fields || {};
212  const visitor = opts.visitor || inherits.visitor || [];
213  const aliases = opts.aliases || inherits.aliases || [];
214  const builder = opts.builder || inherits.builder || opts.visitor || [];
215
216  if (opts.deprecatedAlias) {
217    DEPRECATED_KEYS[opts.deprecatedAlias] = type;
218  }
219
220  for (const key of visitor.concat(builder)) {
221    fields[key] = fields[key] || {};
222  }
223
224  for (const key of Object.keys(fields)) {
225    const field = fields[key];
226
227    if (builder.indexOf(key) === -1) {
228      field.optional = true;
229    }
230
231    if (field.default === undefined) {
232      field.default = null;
233    } else if (!field.validate) {
234      field.validate = assertValueType(getType(field.default));
235    }
236  }
237
238  VISITOR_KEYS[type] = opts.visitor = visitor;
239  BUILDER_KEYS[type] = opts.builder = builder;
240  NODE_FIELDS[type] = opts.fields = fields;
241  ALIAS_KEYS[type] = opts.aliases = aliases;
242  aliases.forEach(alias => {
243    FLIPPED_ALIAS_KEYS[alias] = FLIPPED_ALIAS_KEYS[alias] || [];
244    FLIPPED_ALIAS_KEYS[alias].push(type);
245  });
246  store[type] = opts;
247}
248
249const store = {};