@aws-cdk/cloud-assembly-schema 40.0.7 → 40.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,978 +0,0 @@
1
- 'use strict';
2
-
3
- var helpers = require('./helpers');
4
-
5
- /** @type ValidatorResult */
6
- var ValidatorResult = helpers.ValidatorResult;
7
- /** @type SchemaError */
8
- var SchemaError = helpers.SchemaError;
9
-
10
- var attribute = {};
11
-
12
- attribute.ignoreProperties = {
13
- // informative properties
14
- 'id': true,
15
- 'default': true,
16
- 'description': true,
17
- 'title': true,
18
- // arguments to other properties
19
- 'additionalItems': true,
20
- 'then': true,
21
- 'else': true,
22
- // special-handled properties
23
- '$schema': true,
24
- '$ref': true,
25
- 'extends': true,
26
- };
27
-
28
- /**
29
- * @name validators
30
- */
31
- var validators = attribute.validators = {};
32
-
33
- /**
34
- * Validates whether the instance if of a certain type
35
- * @param instance
36
- * @param schema
37
- * @param options
38
- * @param ctx
39
- * @return {ValidatorResult|null}
40
- */
41
- validators.type = function validateType (instance, schema, options, ctx) {
42
- // Ignore undefined instances
43
- if (instance === undefined) {
44
- return null;
45
- }
46
- var result = new ValidatorResult(instance, schema, options, ctx);
47
- var types = Array.isArray(schema.type) ? schema.type : [schema.type];
48
- if (!types.some(this.testType.bind(this, instance, schema, options, ctx))) {
49
- var list = types.map(function (v) {
50
- if(!v) return;
51
- var id = v.$id || v.id;
52
- return id ? ('<' + id + '>') : (v+'');
53
- });
54
- result.addError({
55
- name: 'type',
56
- argument: list,
57
- message: "is not of a type(s) " + list,
58
- });
59
- }
60
- return result;
61
- };
62
-
63
- function testSchemaNoThrow(instance, options, ctx, callback, schema){
64
- var throwError = options.throwError;
65
- var throwAll = options.throwAll;
66
- options.throwError = false;
67
- options.throwAll = false;
68
- var res = this.validateSchema(instance, schema, options, ctx);
69
- options.throwError = throwError;
70
- options.throwAll = throwAll;
71
-
72
- if (!res.valid && callback instanceof Function) {
73
- callback(res);
74
- }
75
- return res.valid;
76
- }
77
-
78
- /**
79
- * Validates whether the instance matches some of the given schemas
80
- * @param instance
81
- * @param schema
82
- * @param options
83
- * @param ctx
84
- * @return {ValidatorResult|null}
85
- */
86
- validators.anyOf = function validateAnyOf (instance, schema, options, ctx) {
87
- // Ignore undefined instances
88
- if (instance === undefined) {
89
- return null;
90
- }
91
- var result = new ValidatorResult(instance, schema, options, ctx);
92
- var inner = new ValidatorResult(instance, schema, options, ctx);
93
- if (!Array.isArray(schema.anyOf)){
94
- throw new SchemaError("anyOf must be an array");
95
- }
96
- if (!schema.anyOf.some(
97
- testSchemaNoThrow.bind(
98
- this, instance, options, ctx, function(res){inner.importErrors(res);}
99
- ))) {
100
- var list = schema.anyOf.map(function (v, i) {
101
- var id = v.$id || v.id;
102
- if(id) return '<' + id + '>';
103
- return(v.title && JSON.stringify(v.title)) || (v['$ref'] && ('<' + v['$ref'] + '>')) || '[subschema '+i+']';
104
- });
105
- if (options.nestedErrors) {
106
- result.importErrors(inner);
107
- }
108
- result.addError({
109
- name: 'anyOf',
110
- argument: list,
111
- message: "is not any of " + list.join(','),
112
- });
113
- }
114
- return result;
115
- };
116
-
117
- /**
118
- * Validates whether the instance matches every given schema
119
- * @param instance
120
- * @param schema
121
- * @param options
122
- * @param ctx
123
- * @return {String|null}
124
- */
125
- validators.allOf = function validateAllOf (instance, schema, options, ctx) {
126
- // Ignore undefined instances
127
- if (instance === undefined) {
128
- return null;
129
- }
130
- if (!Array.isArray(schema.allOf)){
131
- throw new SchemaError("allOf must be an array");
132
- }
133
- var result = new ValidatorResult(instance, schema, options, ctx);
134
- var self = this;
135
- schema.allOf.forEach(function(v, i){
136
- var valid = self.validateSchema(instance, v, options, ctx);
137
- if(!valid.valid){
138
- var id = v.$id || v.id;
139
- var msg = id || (v.title && JSON.stringify(v.title)) || (v['$ref'] && ('<' + v['$ref'] + '>')) || '[subschema '+i+']';
140
- result.addError({
141
- name: 'allOf',
142
- argument: { id: msg, length: valid.errors.length, valid: valid },
143
- message: 'does not match allOf schema ' + msg + ' with ' + valid.errors.length + ' error[s]:',
144
- });
145
- result.importErrors(valid);
146
- }
147
- });
148
- return result;
149
- };
150
-
151
- /**
152
- * Validates whether the instance matches exactly one of the given schemas
153
- * @param instance
154
- * @param schema
155
- * @param options
156
- * @param ctx
157
- * @return {String|null}
158
- */
159
- validators.oneOf = function validateOneOf (instance, schema, options, ctx) {
160
- // Ignore undefined instances
161
- if (instance === undefined) {
162
- return null;
163
- }
164
- if (!Array.isArray(schema.oneOf)){
165
- throw new SchemaError("oneOf must be an array");
166
- }
167
- var result = new ValidatorResult(instance, schema, options, ctx);
168
- var inner = new ValidatorResult(instance, schema, options, ctx);
169
- var count = schema.oneOf.filter(
170
- testSchemaNoThrow.bind(
171
- this, instance, options, ctx, function(res) {inner.importErrors(res);}
172
- ) ).length;
173
- var list = schema.oneOf.map(function (v, i) {
174
- var id = v.$id || v.id;
175
- return id || (v.title && JSON.stringify(v.title)) || (v['$ref'] && ('<' + v['$ref'] + '>')) || '[subschema '+i+']';
176
- });
177
- if (count!==1) {
178
- if (options.nestedErrors) {
179
- result.importErrors(inner);
180
- }
181
- result.addError({
182
- name: 'oneOf',
183
- argument: list,
184
- message: "is not exactly one from " + list.join(','),
185
- });
186
- }
187
- return result;
188
- };
189
-
190
- /**
191
- * Validates "then" or "else" depending on the result of validating "if"
192
- * @param instance
193
- * @param schema
194
- * @param options
195
- * @param ctx
196
- * @return {String|null}
197
- */
198
- validators.if = function validateIf (instance, schema, options, ctx) {
199
- // Ignore undefined instances
200
- if (instance === undefined) return null;
201
- if (!helpers.isSchema(schema.if)) throw new Error('Expected "if" keyword to be a schema');
202
- var ifValid = testSchemaNoThrow.call(this, instance, options, ctx, null, schema.if);
203
- var result = new ValidatorResult(instance, schema, options, ctx);
204
- var res;
205
- if(ifValid){
206
- if (schema.then === undefined) return;
207
- if (!helpers.isSchema(schema.then)) throw new Error('Expected "then" keyword to be a schema');
208
- res = this.validateSchema(instance, schema.then, options, ctx.makeChild(schema.then));
209
- result.importErrors(res);
210
- }else{
211
- if (schema.else === undefined) return;
212
- if (!helpers.isSchema(schema.else)) throw new Error('Expected "else" keyword to be a schema');
213
- res = this.validateSchema(instance, schema.else, options, ctx.makeChild(schema.else));
214
- result.importErrors(res);
215
- }
216
- return result;
217
- };
218
-
219
- function getEnumerableProperty(object, key){
220
- // Determine if `key` shows up in `for(var key in object)`
221
- // First test Object.hasOwnProperty.call as an optimization: that guarantees it does
222
- if(Object.hasOwnProperty.call(object, key)) return object[key];
223
- // Test `key in object` as an optimization; false means it won't
224
- if(!(key in object)) return;
225
- while( (object = Object.getPrototypeOf(object)) ){
226
- if(Object.propertyIsEnumerable.call(object, key)) return object[key];
227
- }
228
- }
229
-
230
- /**
231
- * Validates propertyNames
232
- * @param instance
233
- * @param schema
234
- * @param options
235
- * @param ctx
236
- * @return {String|null|ValidatorResult}
237
- */
238
- validators.propertyNames = function validatePropertyNames (instance, schema, options, ctx) {
239
- if(!this.types.object(instance)) return;
240
- var result = new ValidatorResult(instance, schema, options, ctx);
241
- var subschema = schema.propertyNames!==undefined ? schema.propertyNames : {};
242
- if(!helpers.isSchema(subschema)) throw new SchemaError('Expected "propertyNames" to be a schema (object or boolean)');
243
-
244
- for (var property in instance) {
245
- if(getEnumerableProperty(instance, property) !== undefined){
246
- var res = this.validateSchema(property, subschema, options, ctx.makeChild(subschema));
247
- result.importErrors(res);
248
- }
249
- }
250
-
251
- return result;
252
- };
253
-
254
- /**
255
- * Validates properties
256
- * @param instance
257
- * @param schema
258
- * @param options
259
- * @param ctx
260
- * @return {String|null|ValidatorResult}
261
- */
262
- validators.properties = function validateProperties (instance, schema, options, ctx) {
263
- if(!this.types.object(instance)) return;
264
- var result = new ValidatorResult(instance, schema, options, ctx);
265
- var properties = schema.properties || {};
266
- for (var property in properties) {
267
- var subschema = properties[property];
268
- if(subschema===undefined){
269
- continue;
270
- }else if(subschema===null){
271
- throw new SchemaError('Unexpected null, expected schema in "properties"');
272
- }
273
- if (typeof options.preValidateProperty == 'function') {
274
- options.preValidateProperty(instance, property, subschema, options, ctx);
275
- }
276
- var prop = getEnumerableProperty(instance, property);
277
- var res = this.validateSchema(prop, subschema, options, ctx.makeChild(subschema, property));
278
- if(res.instance !== result.instance[property]) result.instance[property] = res.instance;
279
- result.importErrors(res);
280
- }
281
- return result;
282
- };
283
-
284
- /**
285
- * Test a specific property within in instance against the additionalProperties schema attribute
286
- * This ignores properties with definitions in the properties schema attribute, but no other attributes.
287
- * If too many more types of property-existence tests pop up they may need their own class of tests (like `type` has)
288
- * @private
289
- * @return {boolean}
290
- */
291
- function testAdditionalProperty (instance, schema, options, ctx, property, result) {
292
- if(!this.types.object(instance)) return;
293
- if (schema.properties && schema.properties[property] !== undefined) {
294
- return;
295
- }
296
- if (schema.additionalProperties === false) {
297
- result.addError({
298
- name: 'additionalProperties',
299
- argument: property,
300
- message: "is not allowed to have the additional property " + JSON.stringify(property),
301
- });
302
- } else {
303
- var additionalProperties = schema.additionalProperties || {};
304
-
305
- if (typeof options.preValidateProperty == 'function') {
306
- options.preValidateProperty(instance, property, additionalProperties, options, ctx);
307
- }
308
-
309
- var res = this.validateSchema(instance[property], additionalProperties, options, ctx.makeChild(additionalProperties, property));
310
- if(res.instance !== result.instance[property]) result.instance[property] = res.instance;
311
- result.importErrors(res);
312
- }
313
- }
314
-
315
- /**
316
- * Validates patternProperties
317
- * @param instance
318
- * @param schema
319
- * @param options
320
- * @param ctx
321
- * @return {String|null|ValidatorResult}
322
- */
323
- validators.patternProperties = function validatePatternProperties (instance, schema, options, ctx) {
324
- if(!this.types.object(instance)) return;
325
- var result = new ValidatorResult(instance, schema, options, ctx);
326
- var patternProperties = schema.patternProperties || {};
327
-
328
- for (var property in instance) {
329
- var test = true;
330
- for (var pattern in patternProperties) {
331
- var subschema = patternProperties[pattern];
332
- if(subschema===undefined){
333
- continue;
334
- }else if(subschema===null){
335
- throw new SchemaError('Unexpected null, expected schema in "patternProperties"');
336
- }
337
- try {
338
- var regexp = new RegExp(pattern, 'u');
339
- } catch(_e) {
340
- // In the event the stricter handling causes an error, fall back on the forgiving handling
341
- // DEPRECATED
342
- regexp = new RegExp(pattern);
343
- }
344
- if (!regexp.test(property)) {
345
- continue;
346
- }
347
- test = false;
348
-
349
- if (typeof options.preValidateProperty == 'function') {
350
- options.preValidateProperty(instance, property, subschema, options, ctx);
351
- }
352
-
353
- var res = this.validateSchema(instance[property], subschema, options, ctx.makeChild(subschema, property));
354
- if(res.instance !== result.instance[property]) result.instance[property] = res.instance;
355
- result.importErrors(res);
356
- }
357
- if (test) {
358
- testAdditionalProperty.call(this, instance, schema, options, ctx, property, result);
359
- }
360
- }
361
-
362
- return result;
363
- };
364
-
365
- /**
366
- * Validates additionalProperties
367
- * @param instance
368
- * @param schema
369
- * @param options
370
- * @param ctx
371
- * @return {String|null|ValidatorResult}
372
- */
373
- validators.additionalProperties = function validateAdditionalProperties (instance, schema, options, ctx) {
374
- if(!this.types.object(instance)) return;
375
- // if patternProperties is defined then we'll test when that one is called instead
376
- if (schema.patternProperties) {
377
- return null;
378
- }
379
- var result = new ValidatorResult(instance, schema, options, ctx);
380
- for (var property in instance) {
381
- testAdditionalProperty.call(this, instance, schema, options, ctx, property, result);
382
- }
383
- return result;
384
- };
385
-
386
- /**
387
- * Validates whether the instance value is at least of a certain length, when the instance value is a string.
388
- * @param instance
389
- * @param schema
390
- * @return {String|null}
391
- */
392
- validators.minProperties = function validateMinProperties (instance, schema, options, ctx) {
393
- if (!this.types.object(instance)) return;
394
- var result = new ValidatorResult(instance, schema, options, ctx);
395
- var keys = Object.keys(instance);
396
- if (!(keys.length >= schema.minProperties)) {
397
- result.addError({
398
- name: 'minProperties',
399
- argument: schema.minProperties,
400
- message: "does not meet minimum property length of " + schema.minProperties,
401
- });
402
- }
403
- return result;
404
- };
405
-
406
- /**
407
- * Validates whether the instance value is at most of a certain length, when the instance value is a string.
408
- * @param instance
409
- * @param schema
410
- * @return {String|null}
411
- */
412
- validators.maxProperties = function validateMaxProperties (instance, schema, options, ctx) {
413
- if (!this.types.object(instance)) return;
414
- var result = new ValidatorResult(instance, schema, options, ctx);
415
- var keys = Object.keys(instance);
416
- if (!(keys.length <= schema.maxProperties)) {
417
- result.addError({
418
- name: 'maxProperties',
419
- argument: schema.maxProperties,
420
- message: "does not meet maximum property length of " + schema.maxProperties,
421
- });
422
- }
423
- return result;
424
- };
425
-
426
- /**
427
- * Validates items when instance is an array
428
- * @param instance
429
- * @param schema
430
- * @param options
431
- * @param ctx
432
- * @return {String|null|ValidatorResult}
433
- */
434
- validators.items = function validateItems (instance, schema, options, ctx) {
435
- var self = this;
436
- if (!this.types.array(instance)) return;
437
- if (schema.items===undefined) return;
438
- var result = new ValidatorResult(instance, schema, options, ctx);
439
- instance.every(function (value, i) {
440
- if(Array.isArray(schema.items)){
441
- var items = schema.items[i]===undefined ? schema.additionalItems : schema.items[i];
442
- }else{
443
- var items = schema.items;
444
- }
445
- if (items === undefined) {
446
- return true;
447
- }
448
- if (items === false) {
449
- result.addError({
450
- name: 'items',
451
- message: "additionalItems not permitted",
452
- });
453
- return false;
454
- }
455
- var res = self.validateSchema(value, items, options, ctx.makeChild(items, i));
456
- if(res.instance !== result.instance[i]) result.instance[i] = res.instance;
457
- result.importErrors(res);
458
- return true;
459
- });
460
- return result;
461
- };
462
-
463
- /**
464
- * Validates the "contains" keyword
465
- * @param instance
466
- * @param schema
467
- * @param options
468
- * @param ctx
469
- * @return {String|null|ValidatorResult}
470
- */
471
- validators.contains = function validateContains (instance, schema, options, ctx) {
472
- var self = this;
473
- if (!this.types.array(instance)) return;
474
- if (schema.contains===undefined) return;
475
- if (!helpers.isSchema(schema.contains)) throw new Error('Expected "contains" keyword to be a schema');
476
- var result = new ValidatorResult(instance, schema, options, ctx);
477
- var count = instance.some(function (value, i) {
478
- var res = self.validateSchema(value, schema.contains, options, ctx.makeChild(schema.contains, i));
479
- return res.errors.length===0;
480
- });
481
- if(count===false){
482
- result.addError({
483
- name: 'contains',
484
- argument: schema.contains,
485
- message: "must contain an item matching given schema",
486
- });
487
- }
488
- return result;
489
- };
490
-
491
- /**
492
- * Validates minimum and exclusiveMinimum when the type of the instance value is a number.
493
- * @param instance
494
- * @param schema
495
- * @return {String|null}
496
- */
497
- validators.minimum = function validateMinimum (instance, schema, options, ctx) {
498
- if (!this.types.number(instance)) return;
499
- var result = new ValidatorResult(instance, schema, options, ctx);
500
- if (schema.exclusiveMinimum && schema.exclusiveMinimum === true) {
501
- if(!(instance > schema.minimum)){
502
- result.addError({
503
- name: 'minimum',
504
- argument: schema.minimum,
505
- message: "must be greater than " + schema.minimum,
506
- });
507
- }
508
- } else {
509
- if(!(instance >= schema.minimum)){
510
- result.addError({
511
- name: 'minimum',
512
- argument: schema.minimum,
513
- message: "must be greater than or equal to " + schema.minimum,
514
- });
515
- }
516
- }
517
- return result;
518
- };
519
-
520
- /**
521
- * Validates maximum and exclusiveMaximum when the type of the instance value is a number.
522
- * @param instance
523
- * @param schema
524
- * @return {String|null}
525
- */
526
- validators.maximum = function validateMaximum (instance, schema, options, ctx) {
527
- if (!this.types.number(instance)) return;
528
- var result = new ValidatorResult(instance, schema, options, ctx);
529
- if (schema.exclusiveMaximum && schema.exclusiveMaximum === true) {
530
- if(!(instance < schema.maximum)){
531
- result.addError({
532
- name: 'maximum',
533
- argument: schema.maximum,
534
- message: "must be less than " + schema.maximum,
535
- });
536
- }
537
- } else {
538
- if(!(instance <= schema.maximum)){
539
- result.addError({
540
- name: 'maximum',
541
- argument: schema.maximum,
542
- message: "must be less than or equal to " + schema.maximum,
543
- });
544
- }
545
- }
546
- return result;
547
- };
548
-
549
- /**
550
- * Validates the number form of exclusiveMinimum when the type of the instance value is a number.
551
- * @param instance
552
- * @param schema
553
- * @return {String|null}
554
- */
555
- validators.exclusiveMinimum = function validateExclusiveMinimum (instance, schema, options, ctx) {
556
- // Support the boolean form of exclusiveMinimum, which is handled by the "minimum" keyword.
557
- if(typeof schema.exclusiveMinimum === 'boolean') return;
558
- if (!this.types.number(instance)) return;
559
- var result = new ValidatorResult(instance, schema, options, ctx);
560
- var valid = instance > schema.exclusiveMinimum;
561
- if (!valid) {
562
- result.addError({
563
- name: 'exclusiveMinimum',
564
- argument: schema.exclusiveMinimum,
565
- message: "must be strictly greater than " + schema.exclusiveMinimum,
566
- });
567
- }
568
- return result;
569
- };
570
-
571
- /**
572
- * Validates the number form of exclusiveMaximum when the type of the instance value is a number.
573
- * @param instance
574
- * @param schema
575
- * @return {String|null}
576
- */
577
- validators.exclusiveMaximum = function validateExclusiveMaximum (instance, schema, options, ctx) {
578
- // Support the boolean form of exclusiveMaximum, which is handled by the "maximum" keyword.
579
- if(typeof schema.exclusiveMaximum === 'boolean') return;
580
- if (!this.types.number(instance)) return;
581
- var result = new ValidatorResult(instance, schema, options, ctx);
582
- var valid = instance < schema.exclusiveMaximum;
583
- if (!valid) {
584
- result.addError({
585
- name: 'exclusiveMaximum',
586
- argument: schema.exclusiveMaximum,
587
- message: "must be strictly less than " + schema.exclusiveMaximum,
588
- });
589
- }
590
- return result;
591
- };
592
-
593
- /**
594
- * Perform validation for multipleOf and divisibleBy, which are essentially the same.
595
- * @param instance
596
- * @param schema
597
- * @param validationType
598
- * @param errorMessage
599
- * @returns {String|null}
600
- */
601
- var validateMultipleOfOrDivisbleBy = function validateMultipleOfOrDivisbleBy (instance, schema, options, ctx, validationType, errorMessage) {
602
- if (!this.types.number(instance)) return;
603
-
604
- var validationArgument = schema[validationType];
605
- if (validationArgument == 0) {
606
- throw new SchemaError(validationType + " cannot be zero");
607
- }
608
-
609
- var result = new ValidatorResult(instance, schema, options, ctx);
610
-
611
- var instanceDecimals = helpers.getDecimalPlaces(instance);
612
- var divisorDecimals = helpers.getDecimalPlaces(validationArgument);
613
-
614
- var maxDecimals = Math.max(instanceDecimals , divisorDecimals);
615
- var multiplier = Math.pow(10, maxDecimals);
616
-
617
- if (Math.round(instance * multiplier) % Math.round(validationArgument * multiplier) !== 0) {
618
- result.addError({
619
- name: validationType,
620
- argument: validationArgument,
621
- message: errorMessage + JSON.stringify(validationArgument),
622
- });
623
- }
624
-
625
- return result;
626
- };
627
-
628
- /**
629
- * Validates divisibleBy when the type of the instance value is a number.
630
- * @param instance
631
- * @param schema
632
- * @return {String|null}
633
- */
634
- validators.multipleOf = function validateMultipleOf (instance, schema, options, ctx) {
635
- return validateMultipleOfOrDivisbleBy.call(this, instance, schema, options, ctx, "multipleOf", "is not a multiple of (divisible by) ");
636
- };
637
-
638
- /**
639
- * Validates multipleOf when the type of the instance value is a number.
640
- * @param instance
641
- * @param schema
642
- * @return {String|null}
643
- */
644
- validators.divisibleBy = function validateDivisibleBy (instance, schema, options, ctx) {
645
- return validateMultipleOfOrDivisbleBy.call(this, instance, schema, options, ctx, "divisibleBy", "is not divisible by (multiple of) ");
646
- };
647
-
648
- /**
649
- * Validates whether the instance value is present.
650
- * @param instance
651
- * @param schema
652
- * @return {String|null}
653
- */
654
- validators.required = function validateRequired (instance, schema, options, ctx) {
655
- var result = new ValidatorResult(instance, schema, options, ctx);
656
- if (instance === undefined && schema.required === true) {
657
- // A boolean form is implemented for reverse-compatibility with schemas written against older drafts
658
- result.addError({
659
- name: 'required',
660
- message: "is required",
661
- });
662
- } else if (this.types.object(instance) && Array.isArray(schema.required)) {
663
- schema.required.forEach(function(n){
664
- if(getEnumerableProperty(instance, n)===undefined){
665
- result.addError({
666
- name: 'required',
667
- argument: n,
668
- message: "requires property " + JSON.stringify(n),
669
- });
670
- }
671
- });
672
- }
673
- return result;
674
- };
675
-
676
- /**
677
- * Validates whether the instance value matches the regular expression, when the instance value is a string.
678
- * @param instance
679
- * @param schema
680
- * @return {String|null}
681
- */
682
- validators.pattern = function validatePattern (instance, schema, options, ctx) {
683
- if (!this.types.string(instance)) return;
684
- var result = new ValidatorResult(instance, schema, options, ctx);
685
- var pattern = schema.pattern;
686
- try {
687
- var regexp = new RegExp(pattern, 'u');
688
- } catch(_e) {
689
- // In the event the stricter handling causes an error, fall back on the forgiving handling
690
- // DEPRECATED
691
- regexp = new RegExp(pattern);
692
- }
693
- if (!instance.match(regexp)) {
694
- result.addError({
695
- name: 'pattern',
696
- argument: schema.pattern,
697
- message: "does not match pattern " + JSON.stringify(schema.pattern.toString()),
698
- });
699
- }
700
- return result;
701
- };
702
-
703
- /**
704
- * Validates whether the instance value is of a certain defined format or a custom
705
- * format.
706
- * The following formats are supported for string types:
707
- * - date-time
708
- * - date
709
- * - time
710
- * - ip-address
711
- * - ipv6
712
- * - uri
713
- * - color
714
- * - host-name
715
- * - alpha
716
- * - alpha-numeric
717
- * - utc-millisec
718
- * @param instance
719
- * @param schema
720
- * @param [options]
721
- * @param [ctx]
722
- * @return {String|null}
723
- */
724
- validators.format = function validateFormat (instance, schema, options, ctx) {
725
- if (instance===undefined) return;
726
- var result = new ValidatorResult(instance, schema, options, ctx);
727
- if (!result.disableFormat && !helpers.isFormat(instance, schema.format, this)) {
728
- result.addError({
729
- name: 'format',
730
- argument: schema.format,
731
- message: "does not conform to the " + JSON.stringify(schema.format) + " format",
732
- });
733
- }
734
- return result;
735
- };
736
-
737
- /**
738
- * Validates whether the instance value is at least of a certain length, when the instance value is a string.
739
- * @param instance
740
- * @param schema
741
- * @return {String|null}
742
- */
743
- validators.minLength = function validateMinLength (instance, schema, options, ctx) {
744
- if (!this.types.string(instance)) return;
745
- var result = new ValidatorResult(instance, schema, options, ctx);
746
- var hsp = instance.match(/[\uDC00-\uDFFF]/g);
747
- var length = instance.length - (hsp ? hsp.length : 0);
748
- if (!(length >= schema.minLength)) {
749
- result.addError({
750
- name: 'minLength',
751
- argument: schema.minLength,
752
- message: "does not meet minimum length of " + schema.minLength,
753
- });
754
- }
755
- return result;
756
- };
757
-
758
- /**
759
- * Validates whether the instance value is at most of a certain length, when the instance value is a string.
760
- * @param instance
761
- * @param schema
762
- * @return {String|null}
763
- */
764
- validators.maxLength = function validateMaxLength (instance, schema, options, ctx) {
765
- if (!this.types.string(instance)) return;
766
- var result = new ValidatorResult(instance, schema, options, ctx);
767
- // TODO if this was already computed in "minLength", use that value instead of re-computing
768
- var hsp = instance.match(/[\uDC00-\uDFFF]/g);
769
- var length = instance.length - (hsp ? hsp.length : 0);
770
- if (!(length <= schema.maxLength)) {
771
- result.addError({
772
- name: 'maxLength',
773
- argument: schema.maxLength,
774
- message: "does not meet maximum length of " + schema.maxLength,
775
- });
776
- }
777
- return result;
778
- };
779
-
780
- /**
781
- * Validates whether instance contains at least a minimum number of items, when the instance is an Array.
782
- * @param instance
783
- * @param schema
784
- * @return {String|null}
785
- */
786
- validators.minItems = function validateMinItems (instance, schema, options, ctx) {
787
- if (!this.types.array(instance)) return;
788
- var result = new ValidatorResult(instance, schema, options, ctx);
789
- if (!(instance.length >= schema.minItems)) {
790
- result.addError({
791
- name: 'minItems',
792
- argument: schema.minItems,
793
- message: "does not meet minimum length of " + schema.minItems,
794
- });
795
- }
796
- return result;
797
- };
798
-
799
- /**
800
- * Validates whether instance contains no more than a maximum number of items, when the instance is an Array.
801
- * @param instance
802
- * @param schema
803
- * @return {String|null}
804
- */
805
- validators.maxItems = function validateMaxItems (instance, schema, options, ctx) {
806
- if (!this.types.array(instance)) return;
807
- var result = new ValidatorResult(instance, schema, options, ctx);
808
- if (!(instance.length <= schema.maxItems)) {
809
- result.addError({
810
- name: 'maxItems',
811
- argument: schema.maxItems,
812
- message: "does not meet maximum length of " + schema.maxItems,
813
- });
814
- }
815
- return result;
816
- };
817
-
818
- /**
819
- * Deep compares arrays for duplicates
820
- * @param v
821
- * @param i
822
- * @param a
823
- * @private
824
- * @return {boolean}
825
- */
826
- function testArrays (v, i, a) {
827
- var j, len = a.length;
828
- for (j = i + 1, len; j < len; j++) {
829
- if (helpers.deepCompareStrict(v, a[j])) {
830
- return false;
831
- }
832
- }
833
- return true;
834
- }
835
-
836
- /**
837
- * Validates whether there are no duplicates, when the instance is an Array.
838
- * @param instance
839
- * @return {String|null}
840
- */
841
- validators.uniqueItems = function validateUniqueItems (instance, schema, options, ctx) {
842
- if (schema.uniqueItems!==true) return;
843
- if (!this.types.array(instance)) return;
844
- var result = new ValidatorResult(instance, schema, options, ctx);
845
- if (!instance.every(testArrays)) {
846
- result.addError({
847
- name: 'uniqueItems',
848
- message: "contains duplicate item",
849
- });
850
- }
851
- return result;
852
- };
853
-
854
- /**
855
- * Validate for the presence of dependency properties, if the instance is an object.
856
- * @param instance
857
- * @param schema
858
- * @param options
859
- * @param ctx
860
- * @return {null|ValidatorResult}
861
- */
862
- validators.dependencies = function validateDependencies (instance, schema, options, ctx) {
863
- if (!this.types.object(instance)) return;
864
- var result = new ValidatorResult(instance, schema, options, ctx);
865
- for (var property in schema.dependencies) {
866
- if (instance[property] === undefined) {
867
- continue;
868
- }
869
- var dep = schema.dependencies[property];
870
- var childContext = ctx.makeChild(dep, property);
871
- if (typeof dep == 'string') {
872
- dep = [dep];
873
- }
874
- if (Array.isArray(dep)) {
875
- dep.forEach(function (prop) {
876
- if (instance[prop] === undefined) {
877
- result.addError({
878
- // FIXME there's two different "dependencies" errors here with slightly different outputs
879
- // Can we make these the same? Or should we create different error types?
880
- name: 'dependencies',
881
- argument: childContext.propertyPath,
882
- message: "property " + prop + " not found, required by " + childContext.propertyPath,
883
- });
884
- }
885
- });
886
- } else {
887
- var res = this.validateSchema(instance, dep, options, childContext);
888
- if(result.instance !== res.instance) result.instance = res.instance;
889
- if (res && res.errors.length) {
890
- result.addError({
891
- name: 'dependencies',
892
- argument: childContext.propertyPath,
893
- message: "does not meet dependency required by " + childContext.propertyPath,
894
- });
895
- result.importErrors(res);
896
- }
897
- }
898
- }
899
- return result;
900
- };
901
-
902
- /**
903
- * Validates whether the instance value is one of the enumerated values.
904
- *
905
- * @param instance
906
- * @param schema
907
- * @return {ValidatorResult|null}
908
- */
909
- validators['enum'] = function validateEnum (instance, schema, options, ctx) {
910
- if (instance === undefined) {
911
- return null;
912
- }
913
- if (!Array.isArray(schema['enum'])) {
914
- throw new SchemaError("enum expects an array", schema);
915
- }
916
- var result = new ValidatorResult(instance, schema, options, ctx);
917
- if (!schema['enum'].some(helpers.deepCompareStrict.bind(null, instance))) {
918
- result.addError({
919
- name: 'enum',
920
- argument: schema['enum'],
921
- message: "is not one of enum values: " + schema['enum'].map(String).join(','),
922
- });
923
- }
924
- return result;
925
- };
926
-
927
- /**
928
- * Validates whether the instance exactly matches a given value
929
- *
930
- * @param instance
931
- * @param schema
932
- * @return {ValidatorResult|null}
933
- */
934
- validators['const'] = function validateEnum (instance, schema, options, ctx) {
935
- if (instance === undefined) {
936
- return null;
937
- }
938
- var result = new ValidatorResult(instance, schema, options, ctx);
939
- if (!helpers.deepCompareStrict(schema['const'], instance)) {
940
- result.addError({
941
- name: 'const',
942
- argument: schema['const'],
943
- message: "does not exactly match expected constant: " + schema['const'],
944
- });
945
- }
946
- return result;
947
- };
948
-
949
- /**
950
- * Validates whether the instance if of a prohibited type.
951
- * @param instance
952
- * @param schema
953
- * @param options
954
- * @param ctx
955
- * @return {null|ValidatorResult}
956
- */
957
- validators.not = validators.disallow = function validateNot (instance, schema, options, ctx) {
958
- var self = this;
959
- if(instance===undefined) return null;
960
- var result = new ValidatorResult(instance, schema, options, ctx);
961
- var notTypes = schema.not || schema.disallow;
962
- if(!notTypes) return null;
963
- if(!Array.isArray(notTypes)) notTypes=[notTypes];
964
- notTypes.forEach(function (type) {
965
- if (self.testType(instance, schema, options, ctx, type)) {
966
- var id = type && (type.$id || type.id);
967
- var schemaId = id || type;
968
- result.addError({
969
- name: 'not',
970
- argument: schemaId,
971
- message: "is of prohibited type " + schemaId,
972
- });
973
- }
974
- });
975
- return result;
976
- };
977
-
978
- module.exports = attribute;