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 = {};