1 | import RandExp from 'randexp';
|
2 | import jsonpath from 'jsonpath';
|
3 | import $RefParser from 'json-schema-ref-parser';
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | var Registry = function Registry() {
|
9 |
|
10 | this.data = {};
|
11 | };
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | Registry.prototype.unregister = function unregister (name) {
|
19 | if (!name) {
|
20 | this.data = {};
|
21 | } else {
|
22 | delete this.data[name];
|
23 | }
|
24 | };
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 | Registry.prototype.register = function register (name, callback) {
|
31 | this.data[name] = callback;
|
32 | };
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 | Registry.prototype.registerMany = function registerMany (formats) {
|
39 | var this$1 = this;
|
40 |
|
41 | Object.keys(formats).forEach(function (name) {
|
42 | this$1.data[name] = formats[name];
|
43 | });
|
44 | };
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 | Registry.prototype.get = function get (name) {
|
51 | var format = this.data[name];
|
52 | return format;
|
53 | };
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 | Registry.prototype.list = function list () {
|
60 | return this.data;
|
61 | };
|
62 |
|
63 | var defaults = {};
|
64 | defaults.defaultInvalidTypeProduct = null;
|
65 | defaults.defaultRandExpMax = 10;
|
66 | defaults.ignoreProperties = [];
|
67 | defaults.ignoreMissingRefs = false;
|
68 | defaults.failOnInvalidTypes = true;
|
69 | defaults.failOnInvalidFormat = true;
|
70 | defaults.alwaysFakeOptionals = false;
|
71 | defaults.optionalsProbability = false;
|
72 | defaults.fixedProbabilities = false;
|
73 | defaults.useExamplesValue = false;
|
74 | defaults.useDefaultValue = false;
|
75 | defaults.requiredOnly = false;
|
76 | defaults.minItems = 0;
|
77 | defaults.maxItems = null;
|
78 | defaults.minLength = 0;
|
79 | defaults.maxLength = null;
|
80 | defaults.resolveJsonPath = false;
|
81 | defaults.reuseProperties = false;
|
82 | defaults.fillProperties = true;
|
83 | defaults.random = Math.random;
|
84 |
|
85 |
|
86 |
|
87 |
|
88 | var OptionRegistry = (function (Registry$$1) {
|
89 | function OptionRegistry() {
|
90 | Registry$$1.call(this);
|
91 | this.data = Object.assign({}, defaults);
|
92 | this._defaults = defaults;
|
93 | }
|
94 |
|
95 | if ( Registry$$1 ) OptionRegistry.__proto__ = Registry$$1;
|
96 | OptionRegistry.prototype = Object.create( Registry$$1 && Registry$$1.prototype );
|
97 | OptionRegistry.prototype.constructor = OptionRegistry;
|
98 |
|
99 | var prototypeAccessors = { defaults: { configurable: true } };
|
100 |
|
101 | prototypeAccessors.defaults.get = function () {
|
102 | return Object.assign({}, this._defaults);
|
103 | };
|
104 |
|
105 | Object.defineProperties( OptionRegistry.prototype, prototypeAccessors );
|
106 |
|
107 | return OptionRegistry;
|
108 | }(Registry));
|
109 |
|
110 | var registry = new OptionRegistry();
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 |
|
117 |
|
118 | function optionAPI(nameOrOptionMap) {
|
119 | if (typeof nameOrOptionMap === 'string') {
|
120 | return registry.get(nameOrOptionMap);
|
121 | }
|
122 |
|
123 | return registry.registerMany(nameOrOptionMap);
|
124 | }
|
125 |
|
126 | optionAPI.getDefaults = function () { return registry.defaults; };
|
127 |
|
128 | var ALL_TYPES = ['array', 'object', 'integer', 'number', 'string', 'boolean', 'null'];
|
129 | var MOST_NEAR_DATETIME = 2524608000000;
|
130 | var MIN_INTEGER = -100000000;
|
131 | var MAX_INTEGER = 100000000;
|
132 | var MIN_NUMBER = -100;
|
133 | var MAX_NUMBER = 100;
|
134 | var env = {
|
135 | ALL_TYPES: ALL_TYPES,
|
136 | MIN_NUMBER: MIN_NUMBER,
|
137 | MAX_NUMBER: MAX_NUMBER,
|
138 | MIN_INTEGER: MIN_INTEGER,
|
139 | MAX_INTEGER: MAX_INTEGER,
|
140 | MOST_NEAR_DATETIME: MOST_NEAR_DATETIME
|
141 | };
|
142 |
|
143 | function getRandomInteger(min, max) {
|
144 | min = typeof min === 'undefined' ? env.MIN_INTEGER : min;
|
145 | max = typeof max === 'undefined' ? env.MAX_INTEGER : max;
|
146 | return Math.floor(optionAPI('random')() * (max - min + 1)) + min;
|
147 | }
|
148 |
|
149 | function _randexp(value) {
|
150 |
|
151 | RandExp.prototype.max = optionAPI('defaultRandExpMax');
|
152 |
|
153 | RandExp.prototype.randInt = function (a, b) { return a + Math.floor(optionAPI('random')() * (1 + (b - a))); };
|
154 |
|
155 | var re = new RandExp(value);
|
156 | return re.gen();
|
157 | }
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 | function pick(collection) {
|
167 | return collection[Math.floor(optionAPI('random')() * collection.length)];
|
168 | }
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 |
|
176 |
|
177 | function shuffle(collection) {
|
178 | var tmp;
|
179 | var key;
|
180 | var length = collection.length;
|
181 | var copy = collection.slice();
|
182 |
|
183 | for (; length > 0;) {
|
184 | key = Math.floor(optionAPI('random')() * length);
|
185 |
|
186 | length -= 1;
|
187 | tmp = copy[length];
|
188 | copy[length] = copy[key];
|
189 | copy[key] = tmp;
|
190 | }
|
191 |
|
192 | return copy;
|
193 | }
|
194 |
|
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 |
|
201 | function getRandom(min, max) {
|
202 | return optionAPI('random')() * (max - min) + min;
|
203 | }
|
204 |
|
205 |
|
206 |
|
207 |
|
208 |
|
209 |
|
210 |
|
211 |
|
212 |
|
213 |
|
214 |
|
215 |
|
216 | function number(min, max, defMin, defMax, hasPrecision) {
|
217 | if ( hasPrecision === void 0 ) hasPrecision = false;
|
218 |
|
219 | defMin = typeof defMin === 'undefined' ? env.MIN_NUMBER : defMin;
|
220 | defMax = typeof defMax === 'undefined' ? env.MAX_NUMBER : defMax;
|
221 | min = typeof min === 'undefined' ? defMin : min;
|
222 | max = typeof max === 'undefined' ? defMax : max;
|
223 |
|
224 | if (max < min) {
|
225 | max += min;
|
226 | }
|
227 |
|
228 | if (hasPrecision) {
|
229 | return getRandom(min, max);
|
230 | }
|
231 |
|
232 | return getRandomInteger(min, max);
|
233 | }
|
234 |
|
235 | function by(type) {
|
236 | switch (type) {
|
237 | case 'seconds':
|
238 | return number(0, 60) * 60;
|
239 |
|
240 | case 'minutes':
|
241 | return number(15, 50) * 612;
|
242 |
|
243 | case 'hours':
|
244 | return number(12, 72) * 36123;
|
245 |
|
246 | case 'days':
|
247 | return number(7, 30) * 86412345;
|
248 |
|
249 | case 'weeks':
|
250 | return number(4, 52) * 604812345;
|
251 |
|
252 | case 'months':
|
253 | return number(2, 13) * 2592012345;
|
254 |
|
255 | case 'years':
|
256 | return number(1, 20) * 31104012345;
|
257 |
|
258 | default:
|
259 | break;
|
260 | }
|
261 | }
|
262 |
|
263 | function date(step) {
|
264 | if (step) {
|
265 | return by(step);
|
266 | }
|
267 |
|
268 | var now = new Date();
|
269 | var days = number(-1000, env.MOST_NEAR_DATETIME);
|
270 | now.setTime(now.getTime() - days);
|
271 | return now;
|
272 | }
|
273 |
|
274 | var random = {
|
275 | pick: pick,
|
276 | date: date,
|
277 | shuffle: shuffle,
|
278 | number: number,
|
279 | randexp: _randexp
|
280 | };
|
281 |
|
282 | function getSubAttribute(obj, dotSeparatedKey) {
|
283 | var keyElements = dotSeparatedKey.split('.');
|
284 |
|
285 | while (keyElements.length) {
|
286 | var prop = keyElements.shift();
|
287 |
|
288 | if (!obj[prop]) {
|
289 | break;
|
290 | }
|
291 |
|
292 | obj = obj[prop];
|
293 | }
|
294 |
|
295 | return obj;
|
296 | }
|
297 |
|
298 |
|
299 |
|
300 |
|
301 |
|
302 |
|
303 |
|
304 |
|
305 |
|
306 | function hasProperties(obj) {
|
307 | var properties = [], len = arguments.length - 1;
|
308 | while ( len-- > 0 ) properties[ len ] = arguments[ len + 1 ];
|
309 |
|
310 | return properties.filter(function (key) {
|
311 | return typeof obj[key] !== 'undefined';
|
312 | }).length > 0;
|
313 | }
|
314 |
|
315 |
|
316 |
|
317 |
|
318 |
|
319 |
|
320 |
|
321 |
|
322 |
|
323 |
|
324 |
|
325 |
|
326 | function typecast(type, schema, callback) {
|
327 | var params = {};
|
328 |
|
329 | switch (type || schema.type) {
|
330 | case 'integer':
|
331 | case 'number':
|
332 | if (typeof schema.minimum !== 'undefined') {
|
333 | params.minimum = schema.minimum;
|
334 | }
|
335 |
|
336 | if (typeof schema.maximum !== 'undefined') {
|
337 | params.maximum = schema.maximum;
|
338 | }
|
339 |
|
340 | if (schema.enum) {
|
341 | var min = Math.max(params.minimum || 0, 0);
|
342 | var max = Math.min(params.maximum || Infinity, Infinity);
|
343 |
|
344 | if (schema.exclusiveMinimum && min === schema.minimum) {
|
345 | min += schema.multipleOf || 1;
|
346 | }
|
347 |
|
348 | if (schema.exclusiveMaximum && max === schema.maximum) {
|
349 | max -= schema.multipleOf || 1;
|
350 | }
|
351 |
|
352 |
|
353 | if (min || max !== Infinity) {
|
354 | schema.enum = schema.enum.filter(function (x) {
|
355 | if (x >= min && x <= max) {
|
356 | return true;
|
357 | }
|
358 |
|
359 | return false;
|
360 | });
|
361 | }
|
362 | }
|
363 |
|
364 | break;
|
365 |
|
366 | case 'string':
|
367 | {
|
368 | if (typeof schema.minLength !== 'undefined') {
|
369 | params.minLength = schema.minLength;
|
370 | }
|
371 |
|
372 | if (typeof schema.maxLength !== 'undefined') {
|
373 | params.maxLength = schema.maxLength;
|
374 | }
|
375 |
|
376 | var _maxLength = optionAPI('maxLength');
|
377 |
|
378 | var _minLength = optionAPI('minLength');
|
379 |
|
380 |
|
381 | if (_maxLength && params.maxLength > _maxLength) {
|
382 | params.maxLength = _maxLength;
|
383 | }
|
384 |
|
385 |
|
386 | if (_minLength && params.minLength < _minLength) {
|
387 | params.minLength = _minLength;
|
388 | }
|
389 |
|
390 | break;
|
391 | }
|
392 |
|
393 | default:
|
394 | break;
|
395 | }
|
396 |
|
397 |
|
398 | var value = callback(params);
|
399 |
|
400 | switch (type || schema.type) {
|
401 | case 'number':
|
402 | value = parseFloat(value);
|
403 | break;
|
404 |
|
405 | case 'integer':
|
406 | value = parseInt(value, 10);
|
407 | break;
|
408 |
|
409 | case 'boolean':
|
410 | value = !!value;
|
411 | break;
|
412 |
|
413 | case 'string':
|
414 | {
|
415 | value = String(value);
|
416 | var min$1 = Math.max(params.minLength || 0, 0);
|
417 | var max$1 = Math.min(params.maxLength || Infinity, Infinity);
|
418 |
|
419 | while (value.length < min$1) {
|
420 | value += " " + value;
|
421 | }
|
422 |
|
423 | if (value.length > max$1) {
|
424 | value = value.substr(0, max$1);
|
425 | }
|
426 |
|
427 | break;
|
428 | }
|
429 |
|
430 | default:
|
431 | break;
|
432 | }
|
433 |
|
434 | return value;
|
435 | }
|
436 |
|
437 | function merge(a, b) {
|
438 | Object.keys(b).forEach(function (key) {
|
439 | if (typeof b[key] !== 'object' || b[key] === null) {
|
440 | a[key] = b[key];
|
441 | } else if (Array.isArray(b[key])) {
|
442 | a[key] = a[key] || [];
|
443 |
|
444 | b[key].forEach(function (value) {
|
445 | if (a[key].indexOf(value) === -1) {
|
446 | a[key].push(value);
|
447 | }
|
448 | });
|
449 | } else if (typeof a[key] !== 'object' || a[key] === null || Array.isArray(a[key])) {
|
450 | a[key] = merge({}, b[key]);
|
451 | } else {
|
452 | a[key] = merge(a[key], b[key]);
|
453 | }
|
454 | });
|
455 | return a;
|
456 | }
|
457 |
|
458 | function short(schema) {
|
459 | var s = JSON.stringify(schema);
|
460 | var l = JSON.stringify(schema, null, 2);
|
461 | return s.length > 400 ? ((l.substr(0, 400)) + "...") : l;
|
462 | }
|
463 |
|
464 | function anyValue() {
|
465 | return random.pick([false, true, null, -1, NaN, Math.PI, Infinity, undefined, [], {}, Math.random(), Math.random().toString(36).substr(2)]);
|
466 | }
|
467 |
|
468 | function notValue(schema, parent) {
|
469 | var copy = merge({}, parent);
|
470 |
|
471 | if (typeof schema.minimum !== 'undefined') {
|
472 | copy.maximum = schema.minimum;
|
473 | copy.exclusiveMaximum = true;
|
474 | }
|
475 |
|
476 | if (typeof schema.maximum !== 'undefined') {
|
477 | copy.minimum = schema.maximum > copy.maximum ? 0 : schema.maximum;
|
478 | copy.exclusiveMinimum = true;
|
479 | }
|
480 |
|
481 | if (typeof schema.minLength !== 'undefined') {
|
482 | copy.maxLength = schema.minLength;
|
483 | }
|
484 |
|
485 | if (typeof schema.maxLength !== 'undefined') {
|
486 | copy.minLength = schema.maxLength > copy.maxLength ? 0 : schema.maxLength;
|
487 | }
|
488 |
|
489 | if (schema.type) {
|
490 | copy.type = random.pick(env.ALL_TYPES.filter(function (x) {
|
491 | var types = Array.isArray(schema.type) ? schema.type : [schema.type];
|
492 | return types.every(function (type) {
|
493 |
|
494 | if (x === 'number' || x === 'integer') {
|
495 | return type !== 'number' && type !== 'integer';
|
496 | }
|
497 |
|
498 | return x !== type;
|
499 | });
|
500 | }));
|
501 | } else if (schema.enum) {
|
502 | var value;
|
503 |
|
504 | do {
|
505 | value = anyValue();
|
506 | } while (schema.enum.indexOf(value) !== -1);
|
507 |
|
508 | copy.enum = [value];
|
509 | }
|
510 |
|
511 | if (schema.required && copy.properties) {
|
512 | schema.required.forEach(function (prop) {
|
513 | delete copy.properties[prop];
|
514 | });
|
515 | }
|
516 |
|
517 |
|
518 | return copy;
|
519 | }
|
520 |
|
521 |
|
522 | function validate(value, schemas) {
|
523 | return !schemas.every(function (x) {
|
524 | if (typeof x.minimum !== 'undefined' && value >= x.minimum) {
|
525 | return true;
|
526 | }
|
527 |
|
528 | if (typeof x.maximum !== 'undefined' && value <= x.maximum) {
|
529 | return true;
|
530 | }
|
531 |
|
532 | return false;
|
533 | });
|
534 | }
|
535 |
|
536 | function isKey(prop) {
|
537 | return ['enum', 'const', 'default', 'examples', 'required', 'definitions'].indexOf(prop) !== -1;
|
538 | }
|
539 |
|
540 | function omitProps(obj, props) {
|
541 | var copy = {};
|
542 | Object.keys(obj).forEach(function (k) {
|
543 | if (props.indexOf(k) === -1) {
|
544 | if (Array.isArray(obj[k])) {
|
545 | copy[k] = obj[k].slice();
|
546 | } else {
|
547 | copy[k] = typeof obj[k] === 'object' ? merge({}, obj[k]) : obj[k];
|
548 | }
|
549 | }
|
550 | });
|
551 | return copy;
|
552 | }
|
553 |
|
554 | function template(value, schema) {
|
555 | if (Array.isArray(value)) {
|
556 | return value.map(function (x) { return template(x, schema); });
|
557 | }
|
558 |
|
559 | if (typeof value === 'string') {
|
560 | value = value.replace(/#\{([\w.-]+)\}/g, function (_, $1) { return schema[$1]; });
|
561 | }
|
562 |
|
563 | return value;
|
564 | }
|
565 |
|
566 | var utils = {
|
567 | getSubAttribute: getSubAttribute,
|
568 | hasProperties: hasProperties,
|
569 | omitProps: omitProps,
|
570 | typecast: typecast,
|
571 | merge: merge,
|
572 | short: short,
|
573 | notValue: notValue,
|
574 | anyValue: anyValue,
|
575 | validate: validate,
|
576 | isKey: isKey,
|
577 | template: template
|
578 | };
|
579 |
|
580 | function proxy(gen) {
|
581 | return function (value, schema, property, rootSchema) {
|
582 | var fn = value;
|
583 | var args = [];
|
584 |
|
585 | if (typeof value === 'object') {
|
586 | fn = Object.keys(value)[0];
|
587 |
|
588 | if (Array.isArray(value[fn])) {
|
589 |
|
590 | args = value[fn];
|
591 | } else {
|
592 | args.push(value[fn]);
|
593 | }
|
594 | }
|
595 |
|
596 |
|
597 | var props = fn.split('.');
|
598 |
|
599 | var ctx = gen();
|
600 |
|
601 | while (props.length > 1) {
|
602 | ctx = ctx[props.shift()];
|
603 | }
|
604 |
|
605 |
|
606 | value = typeof ctx === 'object' ? ctx[props[0]] : ctx;
|
607 |
|
608 | if (typeof value === 'function') {
|
609 | value = value.apply(ctx, args.map(function (x) { return utils.template(x, rootSchema); }));
|
610 | }
|
611 |
|
612 |
|
613 | if (Object.prototype.toString.call(value) === '[object Object]') {
|
614 | Object.keys(value).forEach(function (key) {
|
615 | if (typeof value[key] === 'function') {
|
616 | throw new Error(("Cannot resolve value for '" + property + ": " + fn + "', given: " + value));
|
617 | }
|
618 | });
|
619 | }
|
620 |
|
621 | return value;
|
622 | };
|
623 | }
|
624 |
|
625 |
|
626 |
|
627 |
|
628 |
|
629 |
|
630 |
|
631 |
|
632 |
|
633 |
|
634 | var Container = function Container() {
|
635 |
|
636 |
|
637 | this.registry = {};
|
638 | this.support = {};
|
639 | };
|
640 |
|
641 |
|
642 |
|
643 |
|
644 |
|
645 |
|
646 | Container.prototype.reset = function reset (name) {
|
647 | if (!name) {
|
648 | this.registry = {};
|
649 | this.support = {};
|
650 | } else {
|
651 | delete this.registry[name];
|
652 | delete this.support[name];
|
653 | }
|
654 | };
|
655 |
|
656 |
|
657 |
|
658 |
|
659 |
|
660 |
|
661 |
|
662 | Container.prototype.extend = function extend (name, callback) {
|
663 | var this$1 = this;
|
664 |
|
665 | this.registry[name] = callback(this.registry[name]);
|
666 |
|
667 | if (!this.support[name]) {
|
668 | this.support[name] = proxy(function () { return this$1.registry[name]; });
|
669 | }
|
670 | };
|
671 |
|
672 |
|
673 |
|
674 |
|
675 |
|
676 |
|
677 |
|
678 | Container.prototype.define = function define (name, callback) {
|
679 | this.support[name] = callback;
|
680 | };
|
681 |
|
682 |
|
683 |
|
684 |
|
685 |
|
686 |
|
687 |
|
688 | Container.prototype.get = function get (name) {
|
689 | if (typeof this.registry[name] === 'undefined') {
|
690 | throw new ReferenceError(("'" + name + "' dependency doesn't exist."));
|
691 | }
|
692 |
|
693 | return this.registry[name];
|
694 | };
|
695 |
|
696 |
|
697 |
|
698 |
|
699 |
|
700 |
|
701 | Container.prototype.wrap = function wrap (schema) {
|
702 | var this$1 = this;
|
703 |
|
704 | var keys = Object.keys(schema);
|
705 | var context = {};
|
706 | var length = keys.length;
|
707 |
|
708 | var loop = function () {
|
709 |
|
710 | var fn = keys[length].replace(/^x-/, '');
|
711 | var gen = this$1.support[fn];
|
712 |
|
713 | if (typeof gen === 'function') {
|
714 | Object.defineProperty(schema, 'generate', {
|
715 | configurable: false,
|
716 | enumerable: false,
|
717 | writable: false,
|
718 | value: function (rootSchema) { return gen.call(context, schema[keys[length]], schema, keys[length], rootSchema); }
|
719 |
|
720 | });
|
721 | return 'break';
|
722 | }
|
723 | };
|
724 |
|
725 | while (length--) {
|
726 | var returned = loop();
|
727 |
|
728 | if ( returned === 'break' ) break;
|
729 | }
|
730 |
|
731 | return schema;
|
732 | };
|
733 |
|
734 | var registry$1 = new Registry();
|
735 |
|
736 |
|
737 |
|
738 |
|
739 |
|
740 |
|
741 |
|
742 |
|
743 |
|
744 | function formatAPI(nameOrFormatMap, callback) {
|
745 | if (typeof nameOrFormatMap === 'undefined') {
|
746 | return registry$1.list();
|
747 | } else if (typeof nameOrFormatMap === 'string') {
|
748 | if (typeof callback === 'function') {
|
749 | registry$1.register(nameOrFormatMap, callback);
|
750 | } else if (callback === null || callback === false) {
|
751 | registry$1.unregister(nameOrFormatMap);
|
752 | } else {
|
753 | return registry$1.get(nameOrFormatMap);
|
754 | }
|
755 | } else {
|
756 | registry$1.registerMany(nameOrFormatMap);
|
757 | }
|
758 | }
|
759 |
|
760 | var ParseError = (function (Error) {
|
761 | function ParseError(message, path) {
|
762 | Error.call(this);
|
763 |
|
764 | if (Error.captureStackTrace) {
|
765 | Error.captureStackTrace(this, this.constructor);
|
766 | }
|
767 |
|
768 | this.name = 'ParseError';
|
769 | this.message = message;
|
770 | this.path = path;
|
771 | }
|
772 |
|
773 | if ( Error ) ParseError.__proto__ = Error;
|
774 | ParseError.prototype = Object.create( Error && Error.prototype );
|
775 | ParseError.prototype.constructor = ParseError;
|
776 |
|
777 | return ParseError;
|
778 | }(Error));
|
779 |
|
780 | var inferredProperties = {
|
781 | array: ['additionalItems', 'items', 'maxItems', 'minItems', 'uniqueItems'],
|
782 | integer: ['exclusiveMaximum', 'exclusiveMinimum', 'maximum', 'minimum', 'multipleOf'],
|
783 | object: ['additionalProperties', 'dependencies', 'maxProperties', 'minProperties', 'patternProperties', 'properties', 'required'],
|
784 | string: ['maxLength', 'minLength', 'pattern', 'format']
|
785 | };
|
786 | inferredProperties.number = inferredProperties.integer;
|
787 | var subschemaProperties = ['additionalItems', 'items', 'additionalProperties', 'dependencies', 'patternProperties', 'properties'];
|
788 |
|
789 |
|
790 |
|
791 |
|
792 |
|
793 |
|
794 |
|
795 |
|
796 |
|
797 |
|
798 | function matchesType(obj, lastElementInPath, inferredTypeProperties) {
|
799 | return Object.keys(obj).filter(function (prop) {
|
800 | var isSubschema = subschemaProperties.indexOf(lastElementInPath) > -1;
|
801 | var inferredPropertyFound = inferredTypeProperties.indexOf(prop) > -1;
|
802 |
|
803 | if (inferredPropertyFound && !isSubschema) {
|
804 | return true;
|
805 | }
|
806 |
|
807 | return false;
|
808 | }).length > 0;
|
809 | }
|
810 |
|
811 |
|
812 |
|
813 |
|
814 |
|
815 |
|
816 |
|
817 |
|
818 | function inferType(obj, schemaPath) {
|
819 | var keys = Object.keys(inferredProperties);
|
820 |
|
821 | for (var i = 0; i < keys.length; i += 1) {
|
822 | var typeName = keys[i];
|
823 | var lastElementInPath = schemaPath[schemaPath.length - 1];
|
824 |
|
825 | if (matchesType(obj, lastElementInPath, inferredProperties[typeName])) {
|
826 | return typeName;
|
827 | }
|
828 | }
|
829 | }
|
830 |
|
831 |
|
832 |
|
833 |
|
834 |
|
835 |
|
836 |
|
837 | function booleanGenerator() {
|
838 | return optionAPI('random')() > 0.5;
|
839 | }
|
840 |
|
841 | var booleanType = booleanGenerator;
|
842 |
|
843 |
|
844 |
|
845 |
|
846 |
|
847 |
|
848 | function nullGenerator() {
|
849 | return null;
|
850 | }
|
851 |
|
852 | var nullType = nullGenerator;
|
853 |
|
854 | function unique(path, items, value, sample, resolve, traverseCallback) {
|
855 | var tmp = [];
|
856 | var seen = [];
|
857 |
|
858 | function walk(obj) {
|
859 | var json = JSON.stringify(obj);
|
860 |
|
861 | if (seen.indexOf(json) === -1) {
|
862 | seen.push(json);
|
863 | tmp.push(obj);
|
864 | }
|
865 | }
|
866 |
|
867 | items.forEach(walk);
|
868 |
|
869 | var limit = 100;
|
870 |
|
871 | while (tmp.length !== items.length) {
|
872 | walk(traverseCallback(value.items || sample, path, resolve));
|
873 |
|
874 | if (!limit) {
|
875 | limit -= 1;
|
876 | break;
|
877 | }
|
878 | }
|
879 |
|
880 | return tmp;
|
881 | }
|
882 |
|
883 |
|
884 | function arrayType(value, path, resolve, traverseCallback) {
|
885 | var items = [];
|
886 |
|
887 | if (!(value.items || value.additionalItems)) {
|
888 | if (utils.hasProperties(value, 'minItems', 'maxItems', 'uniqueItems')) {
|
889 | throw new ParseError(("missing items for " + (utils.short(value))), path);
|
890 | }
|
891 |
|
892 | return items;
|
893 | }
|
894 |
|
895 | if (Array.isArray(value.items)) {
|
896 | return value.items.map(function (item, key) {
|
897 | var itemSubpath = path.concat(['items', key]);
|
898 | return traverseCallback(item, itemSubpath, resolve);
|
899 | });
|
900 | }
|
901 |
|
902 | var minItems = value.minItems;
|
903 | var maxItems = value.maxItems;
|
904 |
|
905 | if (optionAPI('minItems')) {
|
906 |
|
907 | minItems = !maxItems ? optionAPI('minItems') : Math.min(optionAPI('minItems'), maxItems);
|
908 | }
|
909 |
|
910 | if (optionAPI('maxItems')) {
|
911 |
|
912 | if (maxItems && maxItems > optionAPI('maxItems')) {
|
913 | maxItems = optionAPI('maxItems');
|
914 | }
|
915 |
|
916 |
|
917 | if (minItems && minItems > optionAPI('maxItems')) {
|
918 | minItems = maxItems;
|
919 | }
|
920 | }
|
921 |
|
922 | var optionalsProbability = optionAPI('alwaysFakeOptionals') === true ? 1.0 : optionAPI('optionalsProbability');
|
923 | var fixedProbabilities = optionAPI('fixedProbabilities') || false;
|
924 | var length = random.number(minItems, maxItems, 1, 5);
|
925 |
|
926 | if (optionalsProbability !== false) {
|
927 | length = fixedProbabilities ? Math.round(maxItems * optionalsProbability) : random.number(minItems, maxItems * optionalsProbability);
|
928 | }
|
929 |
|
930 |
|
931 | var sample = typeof value.additionalItems === 'object' ? value.additionalItems : {};
|
932 |
|
933 | for (var current = items.length; current < length; current += 1) {
|
934 | var itemSubpath = path.concat(['items', current]);
|
935 | var element = traverseCallback(value.items || sample, itemSubpath, resolve);
|
936 | items.push(element);
|
937 | }
|
938 |
|
939 | if (value.uniqueItems) {
|
940 | return unique(path.concat(['items']), items, value, sample, resolve, traverseCallback);
|
941 | }
|
942 |
|
943 | return items;
|
944 | }
|
945 |
|
946 | function numberType(value) {
|
947 | var min = typeof value.minimum === 'undefined' ? env.MIN_INTEGER : value.minimum;
|
948 | var max = typeof value.maximum === 'undefined' ? env.MAX_INTEGER : value.maximum;
|
949 | var multipleOf = value.multipleOf;
|
950 |
|
951 | if (multipleOf) {
|
952 | max = Math.floor(max / multipleOf) * multipleOf;
|
953 | min = Math.ceil(min / multipleOf) * multipleOf;
|
954 | }
|
955 |
|
956 | if (value.exclusiveMinimum && min === value.minimum) {
|
957 | min += multipleOf || 1;
|
958 | }
|
959 |
|
960 | if (value.exclusiveMaximum && max === value.maximum) {
|
961 | max -= multipleOf || 1;
|
962 | }
|
963 |
|
964 | if (min > max) {
|
965 | return NaN;
|
966 | }
|
967 |
|
968 | if (multipleOf) {
|
969 | if (String(multipleOf).indexOf('.') === -1) {
|
970 | var base = random.number(Math.floor(min / multipleOf), Math.floor(max / multipleOf)) * multipleOf;
|
971 |
|
972 | while (base < min) {
|
973 | base += value.multipleOf;
|
974 | }
|
975 |
|
976 | return base;
|
977 | }
|
978 |
|
979 | var boundary = (max - min) / multipleOf;
|
980 | var num;
|
981 | var fix;
|
982 |
|
983 | do {
|
984 | num = random.number(0, boundary) * multipleOf;
|
985 | fix = num / multipleOf % 1;
|
986 | } while (fix !== 0);
|
987 |
|
988 |
|
989 | return num;
|
990 | }
|
991 |
|
992 | return random.number(min, max, undefined, undefined, true);
|
993 | }
|
994 |
|
995 |
|
996 |
|
997 |
|
998 | function integerType(value) {
|
999 | return numberType(Object.assign({
|
1000 | multipleOf: 1
|
1001 | }, value));
|
1002 | }
|
1003 |
|
1004 | var LIPSUM_WORDS = "Lorem ipsum dolor sit amet consectetur adipisicing elit sed do eiusmod tempor incididunt ut labore\net dolore magna aliqua Ut enim ad minim veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea\ncommodo consequat Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla\npariatur Excepteur sint occaecat cupidatat non proident sunt in culpa qui officia deserunt mollit anim id est\nlaborum".split(/\W/);
|
1005 |
|
1006 |
|
1007 |
|
1008 |
|
1009 |
|
1010 |
|
1011 |
|
1012 | function wordsGenerator(length) {
|
1013 | var words = random.shuffle(LIPSUM_WORDS);
|
1014 | return words.slice(0, length);
|
1015 | }
|
1016 |
|
1017 | var anyType = {
|
1018 | type: ['string', 'number', 'integer', 'boolean']
|
1019 | };
|
1020 |
|
1021 | function objectType(value, path, resolve, traverseCallback) {
|
1022 | var props = {};
|
1023 | var properties = value.properties || {};
|
1024 | var patternProperties = value.patternProperties || {};
|
1025 | var requiredProperties = (value.required || []).slice();
|
1026 | var allowsAdditional = value.additionalProperties !== false;
|
1027 | var propertyKeys = Object.keys(properties);
|
1028 | var patternPropertyKeys = Object.keys(patternProperties);
|
1029 | var optionalProperties = propertyKeys.concat(patternPropertyKeys).reduce(function (_response, _key) {
|
1030 | if (requiredProperties.indexOf(_key) === -1) { _response.push(_key); }
|
1031 | return _response;
|
1032 | }, []);
|
1033 | var allProperties = requiredProperties.concat(optionalProperties);
|
1034 | var additionalProperties = allowsAdditional
|
1035 | ? value.additionalProperties === true ? anyType : value.additionalProperties : null;
|
1036 |
|
1037 | if (!allowsAdditional && propertyKeys.length === 0 && patternPropertyKeys.length === 0 && utils.hasProperties(value, 'minProperties', 'maxProperties', 'dependencies', 'required')) {
|
1038 |
|
1039 | return {};
|
1040 | }
|
1041 |
|
1042 | if (optionAPI('requiredOnly') === true) {
|
1043 | requiredProperties.forEach(function (key) {
|
1044 | if (properties[key]) {
|
1045 | props[key] = properties[key];
|
1046 | }
|
1047 | });
|
1048 | return traverseCallback(props, path.concat(['properties']), resolve);
|
1049 | }
|
1050 |
|
1051 | var optionalsProbability = optionAPI('alwaysFakeOptionals') === true ? 1.0 : optionAPI('optionalsProbability');
|
1052 | var fixedProbabilities = optionAPI('fixedProbabilities') || false;
|
1053 | var ignoreProperties = optionAPI('ignoreProperties') || [];
|
1054 | var min = Math.max(value.minProperties || 0, requiredProperties.length);
|
1055 | var max = Math.min(value.maxProperties || allProperties.length, allProperties.length);
|
1056 | var neededExtras = Math.max(0, min - requiredProperties.length);
|
1057 |
|
1058 | if (allProperties.length === 1 && !requiredProperties.length) {
|
1059 | neededExtras = random.number(neededExtras, allProperties.length + (max - min));
|
1060 | }
|
1061 |
|
1062 | if (optionalsProbability !== false) {
|
1063 | if (fixedProbabilities === true) {
|
1064 | neededExtras = Math.round(min - requiredProperties.length + optionalsProbability * (max - min));
|
1065 | } else {
|
1066 | neededExtras = random.number(min - requiredProperties.length, optionalsProbability * (max - min));
|
1067 | }
|
1068 | }
|
1069 |
|
1070 | var extraPropertiesRandomOrder = random.shuffle(optionalProperties).slice(0, neededExtras);
|
1071 | var extraProperties = optionalProperties.filter(function (_item) {
|
1072 | return extraPropertiesRandomOrder.indexOf(_item) !== -1;
|
1073 | });
|
1074 |
|
1075 | var _props = requiredProperties.concat(extraProperties).slice(0, max);
|
1076 |
|
1077 | var skipped = [];
|
1078 | var missing = [];
|
1079 |
|
1080 | _props.forEach(function (key) {
|
1081 | for (var i = 0; i < ignoreProperties.length; i += 1) {
|
1082 | if (ignoreProperties[i] instanceof RegExp && ignoreProperties[i].test(key) || typeof ignoreProperties[i] === 'string' && ignoreProperties[i] === key || typeof ignoreProperties[i] === 'function' && ignoreProperties[i](properties[key], key)) {
|
1083 | skipped.push(key);
|
1084 | return;
|
1085 | }
|
1086 | }
|
1087 |
|
1088 |
|
1089 | if (properties[key]) {
|
1090 | props[key] = properties[key];
|
1091 | } else {
|
1092 | var found;
|
1093 |
|
1094 | patternPropertyKeys.forEach(function (_key) {
|
1095 | if (key.match(new RegExp(_key))) {
|
1096 | found = true;
|
1097 | props[random.randexp(key)] = patternProperties[_key];
|
1098 | }
|
1099 | });
|
1100 |
|
1101 | if (!found) {
|
1102 |
|
1103 | var subschema = patternProperties[key] || additionalProperties;
|
1104 |
|
1105 | if (subschema) {
|
1106 |
|
1107 | props[patternProperties[key] ? random.randexp(key) : key] = subschema;
|
1108 | } else {
|
1109 | missing.push(key);
|
1110 | }
|
1111 | }
|
1112 | }
|
1113 | });
|
1114 |
|
1115 | var fillProps = optionAPI('fillProperties');
|
1116 | var reuseProps = optionAPI('reuseProperties');
|
1117 |
|
1118 | var current = Object.keys(props).length + (fillProps ? 0 : skipped.length);
|
1119 |
|
1120 | function get() {
|
1121 | var one;
|
1122 |
|
1123 | do {
|
1124 | one = requiredProperties.shift();
|
1125 | } while (props[one]);
|
1126 |
|
1127 | return one;
|
1128 | }
|
1129 |
|
1130 | while (fillProps) {
|
1131 | if (!(patternPropertyKeys.length || allowsAdditional)) {
|
1132 | break;
|
1133 | }
|
1134 |
|
1135 | if (current >= min) {
|
1136 | break;
|
1137 | }
|
1138 |
|
1139 | if (allowsAdditional) {
|
1140 | if (reuseProps && propertyKeys.length - current > min) {
|
1141 | var count = 0;
|
1142 | var key = (void 0);
|
1143 |
|
1144 | do {
|
1145 | count += 1;
|
1146 |
|
1147 | if (count > 1000) {
|
1148 | break;
|
1149 | }
|
1150 |
|
1151 | key = get() || random.pick(propertyKeys);
|
1152 | } while (typeof props[key] !== 'undefined');
|
1153 |
|
1154 | if (typeof props[key] === 'undefined') {
|
1155 | props[key] = properties[key];
|
1156 | current += 1;
|
1157 | }
|
1158 | } else if (patternPropertyKeys.length && !additionalProperties) {
|
1159 | var prop = random.pick(patternPropertyKeys);
|
1160 | var word = random.randexp(prop);
|
1161 |
|
1162 | if (!props[word]) {
|
1163 | props[word] = patternProperties[prop];
|
1164 | current += 1;
|
1165 | }
|
1166 | } else {
|
1167 | var word$1 = get() || wordsGenerator(1) + random.randexp('[a-f\\d]{1,3}');
|
1168 |
|
1169 | if (!props[word$1]) {
|
1170 | props[word$1] = additionalProperties || anyType;
|
1171 | current += 1;
|
1172 | }
|
1173 | }
|
1174 | }
|
1175 |
|
1176 | for (var i = 0; current < min && i < patternPropertyKeys.length; i += 1) {
|
1177 | var _key = patternPropertyKeys[i];
|
1178 | var word$2 = random.randexp(_key);
|
1179 |
|
1180 | if (!props[word$2]) {
|
1181 | props[word$2] = patternProperties[_key];
|
1182 | current += 1;
|
1183 | }
|
1184 | }
|
1185 | }
|
1186 |
|
1187 | if (!allowsAdditional && current < min) {
|
1188 | if (missing.length) {
|
1189 | throw new ParseError(("properties '" + (missing.join(', ')) + "' were not found while additionalProperties is false:\n" + (utils.short(value))), path);
|
1190 | }
|
1191 |
|
1192 | throw new ParseError(("properties constraints were too strong to successfully generate a valid object for:\n" + (utils.short(value))), path);
|
1193 | }
|
1194 |
|
1195 | return traverseCallback(props, path.concat(['properties']), resolve);
|
1196 | }
|
1197 |
|
1198 |
|
1199 |
|
1200 |
|
1201 |
|
1202 |
|
1203 |
|
1204 | function produce() {
|
1205 | var length = random.number(1, 5);
|
1206 | return wordsGenerator(length).join(' ');
|
1207 | }
|
1208 |
|
1209 |
|
1210 |
|
1211 |
|
1212 |
|
1213 |
|
1214 |
|
1215 | function thunkGenerator(min, max) {
|
1216 | if ( min === void 0 ) min = 0;
|
1217 | if ( max === void 0 ) max = 140;
|
1218 |
|
1219 | var _min = Math.max(0, min);
|
1220 |
|
1221 | var _max = random.number(_min, max);
|
1222 |
|
1223 | var result = produce();
|
1224 |
|
1225 | while (result.length < _min) {
|
1226 | result += produce();
|
1227 | }
|
1228 |
|
1229 |
|
1230 | if (result.length > _max) {
|
1231 | result = result.substr(0, _max);
|
1232 | }
|
1233 |
|
1234 | return result;
|
1235 | }
|
1236 |
|
1237 |
|
1238 |
|
1239 |
|
1240 |
|
1241 |
|
1242 |
|
1243 | function ipv4Generator() {
|
1244 | return [0, 0, 0, 0].map(function () {
|
1245 | return random.number(0, 255);
|
1246 | }).join('.');
|
1247 | }
|
1248 |
|
1249 |
|
1250 |
|
1251 |
|
1252 |
|
1253 |
|
1254 |
|
1255 | function dateTimeGenerator() {
|
1256 | return random.date().toISOString();
|
1257 | }
|
1258 |
|
1259 |
|
1260 |
|
1261 |
|
1262 |
|
1263 |
|
1264 |
|
1265 | function dateGenerator() {
|
1266 | return dateTimeGenerator().slice(0, 10);
|
1267 | }
|
1268 |
|
1269 |
|
1270 |
|
1271 |
|
1272 |
|
1273 |
|
1274 |
|
1275 | function timeGenerator() {
|
1276 | return dateTimeGenerator().slice(11);
|
1277 | }
|
1278 |
|
1279 | var FRAGMENT = '[a-zA-Z][a-zA-Z0-9+-.]*';
|
1280 | var URI_PATTERN = "https?://{hostname}(?:" + FRAGMENT + ")+";
|
1281 | var PARAM_PATTERN = '(?:\\?([a-z]{1,7}(=\\w{1,5})?&){0,3})?';
|
1282 |
|
1283 |
|
1284 |
|
1285 |
|
1286 |
|
1287 | var regexps = {
|
1288 | email: '[a-zA-Z\\d][a-zA-Z\\d-]{1,13}[a-zA-Z\\d]@{hostname}',
|
1289 | hostname: '[a-zA-Z]{1,33}\\.[a-z]{2,4}',
|
1290 | ipv6: '[a-f\\d]{4}(:[a-f\\d]{4}){7}',
|
1291 | uri: URI_PATTERN,
|
1292 |
|
1293 | 'uri-reference': ("" + URI_PATTERN + PARAM_PATTERN),
|
1294 | 'uri-template': URI_PATTERN.replace('(?:', '(?:/\\{[a-z][:a-zA-Z0-9-]*\\}|'),
|
1295 | 'json-pointer': ("(/(?:" + (FRAGMENT.replace(']*', '/]*')) + "|~[01]))+"),
|
1296 |
|
1297 | uuid: '^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$'
|
1298 | };
|
1299 | regexps.iri = regexps['uri-reference'];
|
1300 | regexps['iri-reference'] = regexps['uri-reference'];
|
1301 | regexps['idn-email'] = regexps.email;
|
1302 | regexps['idn-hostname'] = regexps.hostname;
|
1303 | var ALLOWED_FORMATS = new RegExp(("\\{(" + (Object.keys(regexps).join('|')) + ")\\}"));
|
1304 |
|
1305 |
|
1306 |
|
1307 |
|
1308 |
|
1309 |
|
1310 |
|
1311 | function coreFormatGenerator(coreFormat) {
|
1312 | return random.randexp(regexps[coreFormat]).replace(ALLOWED_FORMATS, function (match, key) {
|
1313 | return random.randexp(regexps[key]);
|
1314 | });
|
1315 | }
|
1316 |
|
1317 | function generateFormat(value, invalid) {
|
1318 | var callback = formatAPI(value.format);
|
1319 |
|
1320 | if (typeof callback === 'function') {
|
1321 | return callback(value);
|
1322 | }
|
1323 |
|
1324 | switch (value.format) {
|
1325 | case 'date-time':
|
1326 | case 'datetime':
|
1327 | return dateTimeGenerator();
|
1328 |
|
1329 | case 'date':
|
1330 | return dateGenerator();
|
1331 |
|
1332 | case 'time':
|
1333 | return timeGenerator();
|
1334 |
|
1335 | case 'ipv4':
|
1336 | return ipv4Generator();
|
1337 |
|
1338 | case 'regex':
|
1339 |
|
1340 | return '.+?';
|
1341 |
|
1342 | case 'email':
|
1343 | case 'hostname':
|
1344 | case 'ipv6':
|
1345 | case 'uri':
|
1346 | case 'uri-reference':
|
1347 | case 'iri':
|
1348 | case 'iri-reference':
|
1349 | case 'idn-email':
|
1350 | case 'idn-hostname':
|
1351 | case 'json-pointer':
|
1352 | case 'uri-template':
|
1353 | case 'uuid':
|
1354 | return coreFormatGenerator(value.format);
|
1355 |
|
1356 | default:
|
1357 | if (typeof callback === 'undefined') {
|
1358 | if (optionAPI('failOnInvalidFormat')) {
|
1359 | throw new Error(("unknown registry key " + (utils.short(value.format))));
|
1360 | } else {
|
1361 | return invalid();
|
1362 | }
|
1363 | }
|
1364 |
|
1365 | throw new Error(("unsupported format '" + (value.format) + "'"));
|
1366 | }
|
1367 | }
|
1368 |
|
1369 | function stringType(value) {
|
1370 |
|
1371 | var output = utils.typecast('string', value, function (opts) {
|
1372 | if (value.format) {
|
1373 | return generateFormat(value, function () { return thunkGenerator(opts.minLength, opts.maxLength); });
|
1374 | }
|
1375 |
|
1376 | if (value.pattern) {
|
1377 | return random.randexp(value.pattern);
|
1378 | }
|
1379 |
|
1380 | return thunkGenerator(opts.minLength, opts.maxLength);
|
1381 | });
|
1382 | return output;
|
1383 | }
|
1384 |
|
1385 | var typeMap = {
|
1386 | boolean: booleanType,
|
1387 | null: nullType,
|
1388 | array: arrayType,
|
1389 | integer: integerType,
|
1390 | number: numberType,
|
1391 | object: objectType,
|
1392 | string: stringType
|
1393 | };
|
1394 |
|
1395 | function traverse(schema, path, resolve, rootSchema) {
|
1396 | schema = resolve(schema, undefined, path);
|
1397 |
|
1398 | if (!schema) {
|
1399 | return;
|
1400 | }
|
1401 |
|
1402 |
|
1403 | if (path[path.length - 1] !== 'properties') {
|
1404 |
|
1405 | if (optionAPI('useExamplesValue') && Array.isArray(schema.examples)) {
|
1406 |
|
1407 | var fixedExamples = schema.examples.concat('default' in schema ? [schema.default] : []);
|
1408 | return utils.typecast(null, schema, function () { return random.pick(fixedExamples); });
|
1409 | }
|
1410 |
|
1411 | if (optionAPI('useDefaultValue') && 'default' in schema) {
|
1412 | return schema.default;
|
1413 | }
|
1414 |
|
1415 | if ('template' in schema) {
|
1416 | return utils.template(schema.template, rootSchema);
|
1417 | }
|
1418 | }
|
1419 |
|
1420 | if (schema.not && typeof schema.not === 'object') {
|
1421 | schema = utils.notValue(schema.not, utils.omitProps(schema, ['not']));
|
1422 | }
|
1423 |
|
1424 | if ('const' in schema) {
|
1425 | return schema.const;
|
1426 | }
|
1427 |
|
1428 | if (Array.isArray(schema.enum)) {
|
1429 | return utils.typecast(null, schema, function () { return random.pick(schema.enum); });
|
1430 | }
|
1431 |
|
1432 |
|
1433 | if (typeof schema.thunk === 'function') {
|
1434 | return traverse(schema.thunk(), path, resolve);
|
1435 | }
|
1436 |
|
1437 | if (typeof schema.generate === 'function') {
|
1438 | return utils.typecast(null, schema, function () { return schema.generate(rootSchema); });
|
1439 | }
|
1440 |
|
1441 |
|
1442 | var type = schema.type;
|
1443 |
|
1444 | if (Array.isArray(type)) {
|
1445 | type = random.pick(type);
|
1446 | } else if (typeof type === 'undefined') {
|
1447 |
|
1448 | type = inferType(schema, path) || type;
|
1449 |
|
1450 | if (type) {
|
1451 | schema.type = type;
|
1452 | }
|
1453 | }
|
1454 |
|
1455 | if (typeof type === 'string') {
|
1456 | if (!typeMap[type]) {
|
1457 | if (optionAPI('failOnInvalidTypes')) {
|
1458 | throw new ParseError(("unknown primitive " + (utils.short(type))), path.concat(['type']));
|
1459 | } else {
|
1460 | return optionAPI('defaultInvalidTypeProduct');
|
1461 | }
|
1462 | } else {
|
1463 | try {
|
1464 | return typeMap[type](schema, path, resolve, traverse);
|
1465 | } catch (e) {
|
1466 | if (typeof e.path === 'undefined') {
|
1467 | throw new ParseError(e.message, path);
|
1468 | }
|
1469 |
|
1470 | throw e;
|
1471 | }
|
1472 | }
|
1473 | }
|
1474 |
|
1475 | var copy = {};
|
1476 |
|
1477 | if (Array.isArray(schema)) {
|
1478 | copy = [];
|
1479 | }
|
1480 |
|
1481 | Object.keys(schema).forEach(function (prop) {
|
1482 | if (typeof schema[prop] === 'object' && prop !== 'definitions') {
|
1483 | copy[prop] = traverse(schema[prop], path.concat([prop]), resolve, copy);
|
1484 | } else {
|
1485 | copy[prop] = schema[prop];
|
1486 | }
|
1487 | });
|
1488 | return copy;
|
1489 | }
|
1490 |
|
1491 | function pick$1(data) {
|
1492 | return Array.isArray(data) ? random.pick(data) : data;
|
1493 | }
|
1494 |
|
1495 | function cycle(data, reverse) {
|
1496 | if (!Array.isArray(data)) {
|
1497 | return data;
|
1498 | }
|
1499 |
|
1500 | var value = reverse ? data.pop() : data.shift();
|
1501 |
|
1502 | if (reverse) {
|
1503 | data.unshift(value);
|
1504 | } else {
|
1505 | data.push(value);
|
1506 | }
|
1507 |
|
1508 | return value;
|
1509 | }
|
1510 |
|
1511 | function resolve(obj, data, values, property) {
|
1512 | if (!obj || typeof obj !== 'object') {
|
1513 | return obj;
|
1514 | }
|
1515 |
|
1516 | if (!values) {
|
1517 | values = {};
|
1518 | }
|
1519 |
|
1520 | if (!data) {
|
1521 | data = obj;
|
1522 | }
|
1523 |
|
1524 | if (Array.isArray(obj)) {
|
1525 | return obj.map(function (x) { return resolve(x, data, values, property); });
|
1526 | }
|
1527 |
|
1528 | if (obj.jsonPath) {
|
1529 | var params = typeof obj.jsonPath !== 'object' ? {
|
1530 | path: obj.jsonPath
|
1531 | } : obj.jsonPath;
|
1532 | params.group = obj.group || params.group || property;
|
1533 | params.cycle = obj.cycle || params.cycle || false;
|
1534 | params.reverse = obj.reverse || params.reverse || false;
|
1535 | params.count = obj.count || params.count || 1;
|
1536 | var key = (params.group) + "__" + (params.path);
|
1537 |
|
1538 | if (!values[key]) {
|
1539 | if (params.count > 1) {
|
1540 | values[key] = jsonpath.query(data, params.path, params.count);
|
1541 | } else {
|
1542 | values[key] = jsonpath.query(data, params.path);
|
1543 | }
|
1544 | }
|
1545 |
|
1546 | if (params.cycle || params.reverse) {
|
1547 | return cycle(values[key], params.reverse);
|
1548 | }
|
1549 |
|
1550 | return pick$1(values[key]);
|
1551 | }
|
1552 |
|
1553 | Object.keys(obj).forEach(function (k) {
|
1554 | obj[k] = resolve(obj[k], data, values, k);
|
1555 | });
|
1556 | return obj;
|
1557 | }
|
1558 |
|
1559 |
|
1560 | function run(refs, schema, container) {
|
1561 | try {
|
1562 | var result = traverse(schema, [], function reduce(sub, maxReduceDepth, parentSchemaPath) {
|
1563 | if (typeof maxReduceDepth === 'undefined') {
|
1564 | maxReduceDepth = random.number(1, 3);
|
1565 | }
|
1566 |
|
1567 | if (!sub) {
|
1568 | return null;
|
1569 | }
|
1570 |
|
1571 | if (typeof sub.generate === 'function') {
|
1572 | return sub;
|
1573 | }
|
1574 |
|
1575 |
|
1576 | var _id = sub.$id || sub.id;
|
1577 |
|
1578 | if (typeof _id === 'string') {
|
1579 | delete sub.id;
|
1580 | delete sub.$id;
|
1581 | delete sub.$schema;
|
1582 | }
|
1583 |
|
1584 | if (typeof sub.$ref === 'string') {
|
1585 | if (sub.$ref === '#') {
|
1586 | delete sub.$ref;
|
1587 | return sub;
|
1588 | }
|
1589 |
|
1590 | var ref;
|
1591 |
|
1592 | if (sub.$ref.indexOf('#/') === -1) {
|
1593 | ref = refs[sub.$ref] || null;
|
1594 | }
|
1595 |
|
1596 | if (sub.$ref.indexOf('#/definitions/') === 0) {
|
1597 | ref = schema.definitions[sub.$ref.split('#/definitions/')[1]] || null;
|
1598 | }
|
1599 |
|
1600 | if (typeof ref !== 'undefined') {
|
1601 | if (!ref && optionAPI('ignoreMissingRefs') !== true) {
|
1602 | throw new Error(("Reference not found: " + (sub.$ref)));
|
1603 | }
|
1604 |
|
1605 | utils.merge(sub, ref || {});
|
1606 | }
|
1607 |
|
1608 |
|
1609 | delete sub.$ref;
|
1610 | return sub;
|
1611 | }
|
1612 |
|
1613 | if (Array.isArray(sub.allOf)) {
|
1614 | var schemas = sub.allOf;
|
1615 | delete sub.allOf;
|
1616 |
|
1617 |
|
1618 | schemas.forEach(function (subSchema) {
|
1619 | var _sub = reduce(subSchema, maxReduceDepth + 1, parentSchemaPath);
|
1620 |
|
1621 |
|
1622 | utils.merge(sub, typeof _sub.thunk === 'function' ? _sub.thunk() : _sub);
|
1623 | });
|
1624 | }
|
1625 |
|
1626 | if (Array.isArray(sub.oneOf || sub.anyOf)) {
|
1627 | var mix = sub.oneOf || sub.anyOf;
|
1628 |
|
1629 |
|
1630 | if (sub.enum && sub.oneOf) {
|
1631 | sub.enum = sub.enum.filter(function (x) { return utils.validate(x, mix); });
|
1632 | }
|
1633 |
|
1634 | return {
|
1635 | thunk: function thunk() {
|
1636 | var copy = utils.omitProps(sub, ['anyOf', 'oneOf']);
|
1637 | utils.merge(copy, random.pick(mix));
|
1638 | return copy;
|
1639 | }
|
1640 |
|
1641 | };
|
1642 | }
|
1643 |
|
1644 | Object.keys(sub).forEach(function (prop) {
|
1645 | if ((Array.isArray(sub[prop]) || typeof sub[prop] === 'object') && !utils.isKey(prop)) {
|
1646 | sub[prop] = reduce(sub[prop], maxReduceDepth, parentSchemaPath.concat(prop));
|
1647 | }
|
1648 | });
|
1649 |
|
1650 | if (parentSchemaPath) {
|
1651 | var lastProp = parentSchemaPath[parentSchemaPath.length - 1];
|
1652 |
|
1653 | if (lastProp === 'properties' || lastProp === 'items') {
|
1654 | return sub;
|
1655 | }
|
1656 | }
|
1657 |
|
1658 | return container.wrap(sub);
|
1659 | });
|
1660 |
|
1661 | if (optionAPI('resolveJsonPath')) {
|
1662 | return resolve(result);
|
1663 | }
|
1664 |
|
1665 | return result;
|
1666 | } catch (e) {
|
1667 | if (e.path) {
|
1668 | throw new Error(((e.message) + " in /" + (e.path.join('/'))));
|
1669 | } else {
|
1670 | throw e;
|
1671 | }
|
1672 | }
|
1673 | }
|
1674 |
|
1675 | var container = new Container();
|
1676 |
|
1677 | function setupKeywords() {
|
1678 |
|
1679 | container.define('pattern', random.randexp);
|
1680 |
|
1681 | container.define('autoIncrement', function autoIncrement(value, schema) {
|
1682 | if (!this.offset) {
|
1683 | var min = schema.minimum || 1;
|
1684 | var max = min + env.MAX_NUMBER;
|
1685 | var offset = value.initialOffset || schema.initialOffset;
|
1686 | this.offset = offset || random.number(min, max);
|
1687 | }
|
1688 |
|
1689 | if (value === true) {
|
1690 | return this.offset++;
|
1691 | }
|
1692 |
|
1693 | return schema;
|
1694 | });
|
1695 |
|
1696 | container.define('sequentialDate', function sequentialDate(value, schema) {
|
1697 | if (!this.now) {
|
1698 | this.now = random.date();
|
1699 | }
|
1700 |
|
1701 | if (value) {
|
1702 | schema = this.now.toISOString();
|
1703 | value = value === true ? 'days' : value;
|
1704 |
|
1705 | if (['seconds', 'minutes', 'hours', 'days', 'weeks', 'months', 'years'].indexOf(value) === -1) {
|
1706 | throw new Error(("Unsupported increment by " + (utils.short(value))));
|
1707 | }
|
1708 |
|
1709 | this.now.setTime(this.now.getTime() + random.date(value));
|
1710 | }
|
1711 |
|
1712 | return schema;
|
1713 | });
|
1714 | }
|
1715 |
|
1716 | function getRefs(refs) {
|
1717 | var $refs = {};
|
1718 |
|
1719 | if (Array.isArray(refs)) {
|
1720 | refs.forEach(function (schema) {
|
1721 | $refs[schema.$id || schema.id] = schema;
|
1722 | });
|
1723 | } else {
|
1724 | $refs = refs || {};
|
1725 | }
|
1726 |
|
1727 | return $refs;
|
1728 | }
|
1729 |
|
1730 | var jsf = function (schema, refs, cwd) {
|
1731 | console.log('[json-schema-faker] calling JsonSchemaFaker() is deprecated, call either .generate() or .resolve()');
|
1732 |
|
1733 | if (cwd) {
|
1734 | console.log('[json-schema-faker] references are only supported by calling .resolve()');
|
1735 | }
|
1736 |
|
1737 | return jsf.generate(schema, refs);
|
1738 | };
|
1739 |
|
1740 | jsf.generate = function (schema, refs) {
|
1741 | var $refs = getRefs(refs);
|
1742 | return run($refs, schema, container);
|
1743 | };
|
1744 |
|
1745 | jsf.resolve = function (schema, refs, cwd) {
|
1746 | if (typeof refs === 'string') {
|
1747 | cwd = refs;
|
1748 | refs = {};
|
1749 | }
|
1750 |
|
1751 |
|
1752 | cwd = cwd || (typeof process !== 'undefined' ? process.cwd() : '');
|
1753 | cwd = (cwd.replace(/\/+$/, '')) + "/";
|
1754 | var $refs = getRefs(refs);
|
1755 |
|
1756 | var fixedRefs = {
|
1757 | order: 300,
|
1758 | canRead: true,
|
1759 |
|
1760 | read: function read(file, callback) {
|
1761 | try {
|
1762 | callback(null, $refs[file.url] || $refs[file.url.split('/').pop()]);
|
1763 | } catch (e) {
|
1764 | callback(e);
|
1765 | }
|
1766 | }
|
1767 |
|
1768 | };
|
1769 | return $RefParser.dereference(cwd, schema, {
|
1770 | resolve: {
|
1771 | file: {
|
1772 | order: 100
|
1773 | },
|
1774 | http: {
|
1775 | order: 200
|
1776 | },
|
1777 | fixedRefs: fixedRefs
|
1778 | },
|
1779 | dereference: {
|
1780 | circular: 'ignore'
|
1781 | }
|
1782 | }).then(function (sub) { return run($refs, sub, container); });
|
1783 | };
|
1784 |
|
1785 | setupKeywords();
|
1786 | jsf.format = formatAPI;
|
1787 | jsf.option = optionAPI;
|
1788 | jsf.random = random;
|
1789 |
|
1790 | jsf.extend = function (name, cb) {
|
1791 | container.extend(name, cb);
|
1792 | return jsf;
|
1793 | };
|
1794 |
|
1795 | jsf.define = function (name, cb) {
|
1796 | container.define(name, cb);
|
1797 | return jsf;
|
1798 | };
|
1799 |
|
1800 | jsf.reset = function (name) {
|
1801 | container.reset(name);
|
1802 | setupKeywords();
|
1803 | return jsf;
|
1804 | };
|
1805 |
|
1806 | jsf.locate = function (name) {
|
1807 | return container.get(name);
|
1808 | };
|
1809 |
|
1810 | jsf.version = '0.5.0-rc16';
|
1811 |
|
1812 | export default jsf;
|