From e15f543dbda7fc539817f2b9b2820f6db2e3986f Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Sun, 26 Nov 2017 10:11:55 +0000 Subject: [PATCH] refactor: remove patternGroups keyword, #614 --- KEYWORDS.md | 36 ----- lib/ajv.d.ts | 10 +- lib/ajv.js | 2 - lib/dot/errors.def | 3 - lib/dot/properties.jst | 83 ---------- lib/dot/validate.jst | 3 - lib/patternGroups.js | 36 ----- spec/extras.spec.js | 1 - spec/extras/patternGroups.json | 271 --------------------------------- spec/options.spec.js | 70 --------- 10 files changed, 2 insertions(+), 513 deletions(-) delete mode 100644 lib/patternGroups.js delete mode 100644 spec/extras/patternGroups.json diff --git a/KEYWORDS.md b/KEYWORDS.md index 0c280de..e5b330e 100644 --- a/KEYWORDS.md +++ b/KEYWORDS.md @@ -31,7 +31,6 @@ The keywords and their values define what rules the data should satisfy to be va - [additionalProperties](#additionalproperties) - [dependencies](#dependencies) - [propertyNames](#propertynames) (added in draft-06) - - [patternGroups](#patterngroups-deprecated) (deprecated) - [patternRequired](#patternrequired-proposed) (proposed) - [Keywords for all types](#keywords-for-all-types) - [enum](#enum) @@ -617,41 +616,6 @@ _invalid_: `{"foo": "any value"}` -### `patternGroups` (deprecated) - -This keyword is only provided for backward compatibility, it will be removed in the next major version. To use it, pass option `patternGroups: true`. - -The value of this keyword should be a map where keys should be regular expressions and the values should be objects with the following properties: - -- `schema` (required) - should be a JSON Schema. For data object to be valid the values in data object properties that match regular expression(s) should be valid according to the corresponding `schema`(s). -- `maximum` / `minimum` (optional) - should be integers. For data object to be valid the number of properties that match regular expression(s) should be within limits set by `minimum`(s) and `maximum`(s). - - -__Example__ - -_schema_: - -```json -{ - "patternGroups": { - "^[a-z]+$": { - "minimum": 1, - "schema": { "type": "string" } - }, - "^[0-9]+$": { - "minimum": 1, - "schema": { "type": "integer" } - } - } -} -``` - -_valid_: `{ "foo": "bar", "1": "2" }`, any non-object - -_invalid_: `{}`, `{ "foo": "bar" }`, `{ "1": "2" }` - - - ### `patternRequired` (proposed) Defined in [ajv-keywords](https://github.com/epoberezkin/ajv-keywords) package. diff --git a/lib/ajv.d.ts b/lib/ajv.d.ts index b687f78..d34b7f9 100644 --- a/lib/ajv.d.ts +++ b/lib/ajv.d.ts @@ -225,8 +225,8 @@ declare namespace ajv { DependenciesParams | FormatParams | ComparisonParams | MultipleOfParams | PatternParams | RequiredParams | TypeParams | UniqueItemsParams | CustomParams | - PatternGroupsParams | PatternRequiredParams | - PropertyNamesParams | SwitchParams | NoParams | EnumParams; + PatternRequiredParams | PropertyNamesParams | + SwitchParams | NoParams | EnumParams; interface RefParams { ref: string; @@ -282,12 +282,6 @@ declare namespace ajv { keyword: string; } - interface PatternGroupsParams { - reason: string; - limit: number; - pattern: string; - } - interface PatternRequiredParams { missingPattern: string; } diff --git a/lib/ajv.js b/lib/ajv.js index 4d93848..531d814 100644 --- a/lib/ajv.js +++ b/lib/ajv.js @@ -8,7 +8,6 @@ var compileSchema = require('./compile') , formats = require('./compile/formats') , rules = require('./compile/rules') , $dataMetaSchema = require('./data') - , patternGroups = require('./patternGroups') , util = require('./compile/util'); module.exports = Ajv; @@ -74,7 +73,6 @@ function Ajv(opts) { addDraft6MetaSchema(this); if (typeof opts.meta == 'object') this.addMetaSchema(opts.meta); addInitialSchemas(this); - if (opts.patternGroups) patternGroups(this); } diff --git a/lib/dot/errors.def b/lib/dot/errors.def index 562052c..855b882 100644 --- a/lib/dot/errors.def +++ b/lib/dot/errors.def @@ -111,7 +111,6 @@ not: "'should NOT be valid'", oneOf: "'should match exactly one schema in oneOf'", pattern: "'should match pattern \"{{#def.concatSchemaEQ}}\"'", - patternGroups: "'should NOT have {{=$moreOrLess}} than {{=$limit}} properties matching pattern \"{{=it.util.escapeQuotes($pgProperty)}}\"'", propertyNames: "'property name \\'{{=$invalidName}}\\' is invalid'", required: "'{{? it.opts._errorDataPathProperty }}is a required property{{??}}should have required property \\'{{=$missingProperty}}\\'{{?}}'", type: "'should be {{? $typeIsArray }}{{= $typeSchema.join(\",\") }}{{??}}{{=$typeSchema}}{{?}}'", @@ -148,7 +147,6 @@ not: "validate.schema{{=$schemaPath}}", oneOf: "validate.schema{{=$schemaPath}}", pattern: "{{#def.schemaRefOrQS}}", - patternGroups: "validate.schema{{=$schemaPath}}", propertyNames: "validate.schema{{=$schemaPath}}", required: "validate.schema{{=$schemaPath}}", type: "validate.schema{{=$schemaPath}}", @@ -184,7 +182,6 @@ not: "{}", oneOf: "{ passingSchemas: {{=$passingSchemas}} }", pattern: "{ pattern: {{#def.schemaValueQS}} }", - patternGroups: "{ reason: '{{=$reason}}', limit: {{=$limit}}, pattern: '{{=it.util.escapeQuotes($pgProperty)}}' }", propertyNames: "{ propertyName: '{{=$invalidName}}' }", required: "{ missingProperty: '{{=$missingProperty}}' }", type: "{ type: '{{? $typeIsArray }}{{= $typeSchema.join(\",\") }}{{??}}{{=$typeSchema}}{{?}}' }", diff --git a/lib/dot/properties.jst b/lib/dot/properties.jst index 8d56324..dc8ab7b 100644 --- a/lib/dot/properties.jst +++ b/lib/dot/properties.jst @@ -44,11 +44,6 @@ var $required = it.schema.required; if ($required && !(it.opts.v5 && $required.$data) && $required.length < it.opts.loopRequired) var $requiredHash = it.util.toHash($required); - - if (it.opts.patternGroups) { - var $pgProperties = it.schema.patternGroups || {} - , $pgPropertyKeys = Object.keys($pgProperties); - } }} @@ -76,11 +71,6 @@ var {{=$nextValid}} = true; || {{= it.usePattern($pProperty) }}.test({{=$key}}) {{~}} {{?}} - {{? it.opts.patternGroups && $pgPropertyKeys.length }} - {{~ $pgPropertyKeys:$pgProperty:$i }} - || {{= it.usePattern($pgProperty) }}.test({{=$key}}) - {{~}} - {{?}} ); if (isAdditional{{=$lvl}}) { @@ -246,79 +236,6 @@ var {{=$nextValid}} = true; {{?}} -{{? it.opts.patternGroups && $pgPropertyKeys.length }} - {{~ $pgPropertyKeys:$pgProperty }} - {{ - var $pgSchema = $pgProperties[$pgProperty] - , $sch = $pgSchema.schema; - }} - - {{? {{# def.nonEmptySchema:$sch}} }} - {{ - $it.schema = $sch; - $it.schemaPath = it.schemaPath + '.patternGroups' + it.util.getProperty($pgProperty) + '.schema'; - $it.errSchemaPath = it.errSchemaPath + '/patternGroups/' - + it.util.escapeFragment($pgProperty) - + '/schema'; - }} - - var pgPropCount{{=$lvl}} = 0; - - {{# def.iterateProperties }} - if ({{= it.usePattern($pgProperty) }}.test({{=$key}})) { - pgPropCount{{=$lvl}}++; - - {{ - $it.errorPath = it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); - var $passData = $data + '[' + $key + ']'; - $it.dataPathArr[$dataNxt] = $key; - }} - - {{# def.generateSubschemaCode }} - {{# def.optimizeValidate }} - - {{? $breakOnError }} if (!{{=$nextValid}}) break; {{?}} - } - {{? $breakOnError }} else {{=$nextValid}} = true; {{?}} - } - - {{# def.ifResultValid }} - - {{ - var $pgMin = $pgSchema.minimum - , $pgMax = $pgSchema.maximum; - }} - {{? $pgMin !== undefined || $pgMax !== undefined }} - var {{=$valid}} = true; - - {{ var $currErrSchemaPath = $errSchemaPath; }} - - {{? $pgMin !== undefined }} - {{ var $limit = $pgMin, $reason = 'minimum', $moreOrLess = 'less'; }} - {{=$valid}} = pgPropCount{{=$lvl}} >= {{=$pgMin}}; - {{ $errSchemaPath = it.errSchemaPath + '/patternGroups/minimum'; }} - {{# def.checkError:'patternGroups' }} - {{? $pgMax !== undefined }} - else - {{?}} - {{?}} - - {{? $pgMax !== undefined }} - {{ var $limit = $pgMax, $reason = 'maximum', $moreOrLess = 'more'; }} - {{=$valid}} = pgPropCount{{=$lvl}} <= {{=$pgMax}}; - {{ $errSchemaPath = it.errSchemaPath + '/patternGroups/maximum'; }} - {{# def.checkError:'patternGroups' }} - {{?}} - - {{ $errSchemaPath = $currErrSchemaPath; }} - - {{# def.ifValid }} - {{?}} - {{?}} {{ /* def.nonEmptySchema */ }} - {{~}} -{{?}} - - {{? $breakOnError }} {{= $closingBraces }} if ({{=$errs}} == errors) { diff --git a/lib/dot/validate.jst b/lib/dot/validate.jst index 5918f73..27393cf 100644 --- a/lib/dot/validate.jst +++ b/lib/dot/validate.jst @@ -162,9 +162,6 @@ {{ $closingBraces2 += '}'; }} {{?}} {{??}} - {{? it.opts.v5 && it.schema.patternGroups }} - {{ it.logger.warn('keyword "patternGroups" is deprecated and disabled. Use option patternGroups: true to enable.'); }} - {{?}} {{~ it.RULES:$rulesGroup }} {{? $shouldUseGroup($rulesGroup) }} {{? $rulesGroup.type }} diff --git a/lib/patternGroups.js b/lib/patternGroups.js deleted file mode 100644 index 79abc2a..0000000 --- a/lib/patternGroups.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; - -var META_SCHEMA_ID = 'http://json-schema.org/draft-07/schema'; - -module.exports = function (ajv) { - var defaultMeta = ajv._opts.defaultMeta; - var metaSchemaRef = typeof defaultMeta == 'string' - ? { $ref: defaultMeta } - : ajv.getSchema(META_SCHEMA_ID) - ? { $ref: META_SCHEMA_ID } - : {}; - - ajv.addKeyword('patternGroups', { - // implemented in properties.jst - metaSchema: { - type: 'object', - additionalProperties: { - type: 'object', - required: [ 'schema' ], - properties: { - maximum: { - type: 'integer', - minimum: 0 - }, - minimum: { - type: 'integer', - minimum: 0 - }, - schema: metaSchemaRef - }, - additionalProperties: false - } - } - }); - ajv.RULES.all.properties.implements.push('patternGroups'); -}; diff --git a/spec/extras.spec.js b/spec/extras.spec.js index dcf1713..15c51a6 100644 --- a/spec/extras.spec.js +++ b/spec/extras.spec.js @@ -8,7 +8,6 @@ var jsonSchemaTest = require('json-schema-test') var instances = getAjvInstances(options, { $data: true, - patternGroups: true, unknownFormats: ['allowedUnknown'] }); diff --git a/spec/extras/patternGroups.json b/spec/extras/patternGroups.json deleted file mode 100644 index 94eea5b..0000000 --- a/spec/extras/patternGroups.json +++ /dev/null @@ -1,271 +0,0 @@ -[ - { - "description": "patternGroups validates properties matching a regex (equivalent to the test from draft 4)", - "schema": { - "patternGroups": { - "f.*o": { - "schema": {"type": "integer"} - } - } - }, - "tests": [ - { - "description": "a single valid match is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "multiple valid matches is valid", - "data": {"foo": 1, "foooooo" : 2}, - "valid": true - }, - { - "description": "a single invalid match is invalid", - "data": {"foo": "bar", "fooooo": 2}, - "valid": false - }, - { - "description": "multiple invalid matches is invalid", - "data": {"foo": "bar", "foooooo" : "baz"}, - "valid": false - }, - { - "description": "ignores non-objects", - "data": 12, - "valid": true - } - ] - }, - { - "description": "multiple simultaneous patternGroups are validated (equivalent to the test from draft 4)", - "schema": { - "patternGroups": { - "a*": { - "schema": {"type": "integer"} - }, - "aaa*": { - "schema": {"maximum": 20} - } - } - }, - "tests": [ - { - "description": "a single valid match is valid", - "data": {"a": 21}, - "valid": true - }, - { - "description": "a simultaneous match is valid", - "data": {"aaaa": 18}, - "valid": true - }, - { - "description": "multiple matches is valid", - "data": {"a": 21, "aaaa": 18}, - "valid": true - }, - { - "description": "an invalid due to one is invalid", - "data": {"a": "bar"}, - "valid": false - }, - { - "description": "an invalid due to the other is invalid", - "data": {"aaaa": 31}, - "valid": false - }, - { - "description": "an invalid due to both is invalid", - "data": {"aaa": "foo", "aaaa": 31}, - "valid": false - } - ] - }, - { - "description": "regexes in patternGroups are not anchored by default and are case sensitive (equivalent to the test from draft 4)", - "schema": { - "patternGroups": { - "[0-9]{2,}": { - "schema": { "type": "boolean" } - }, - "X_": { - "schema": { "type": "string" } - } - } - }, - "tests": [ - { - "description": "non recognized members are ignored", - "data": { "answer 1": "42" }, - "valid": true - }, - { - "description": "recognized members are accounted for", - "data": { "a31b": null }, - "valid": false - }, - { - "description": "regexes are case sensitive", - "data": { "a_x_3": 3 }, - "valid": true - }, - { - "description": "regexes are case sensitive, 2", - "data": { "a_X_3": 3 }, - "valid": false - } - ] - }, - { - "description": - "patternGroups validates that the number of properties matching a regex is within limit", - "schema": { - "patternGroups": { - "f.*o": { - "schema": {"type": "integer"}, - "minimum": 1, - "maximum": 2 - } - } - }, - "tests": [ - { - "description": "a single valid match is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "2 valid matches are valid", - "data": {"foo": 1, "foooo" : 2}, - "valid": true - }, - { - "description": "no valid matches are invalid", - "data": {}, - "valid": false - }, - { - "description": "more than 2 valid matches are invalid", - "data": {"foo": 1, "foooo" : 2, "foooooo" : 3}, - "valid": false - }, - { - "description": "sinlge invalid match is invalid", - "data": {"foo": 1, "foooooo" : "baz"}, - "valid": false - } - ] - }, - { - "description": "multiple simultaneous patternGroups are validated for number of matching properties", - "schema": { - "patternGroups": { - "a*": { - "schema": {"type": "integer"}, - "minimum": 1 - }, - "aaa*": { - "schema": {"maximum": 20}, - "maximum": 1 - } - } - }, - "tests": [ - { - "description": "a single first match is valid", - "data": {"a": 21}, - "valid": true - }, - { - "description": "no first match is invalid", - "data": {}, - "valid": false - }, - { - "description": "simultaneous match is valid", - "data": {"aaaa": 18}, - "valid": true - }, - { - "description": "multiple matches is valid", - "data": {"a": 21, "aaaa": 18}, - "valid": true - }, - { - "description": "two second matches are invalid", - "data": {"aaa": 17, "aaaa": 18}, - "valid": false - }, - { - "description": "invalid due to the first is invalid", - "data": {"a": "bar"}, - "valid": false - }, - { - "description": "invalid due to the second is invalid", - "data": {"a": 21, "aaaa": 31}, - "valid": false - }, - { - "description": "invalid due to both is invalid", - "data": {"a": "foo", "aaaa": 31}, - "valid": false - } - ] - }, - { - "description": "properties, patternGroups, additionalProperties interaction (equivalent to the test from draft 4)", - "schema": { - "properties": { - "foo": {"type": "array", "maxItems": 3}, - "bar": {"type": "array"} - }, - "patternGroups": { - "f.o": { "schema": {"minItems": 2} } - }, - "additionalProperties": {"type": "integer"} - }, - "tests": [ - { - "description": "property validates property", - "data": {"foo": [1, 2]}, - "valid": true - }, - { - "description": "property invalidates property", - "data": {"foo": [1, 2, 3, 4]}, - "valid": false - }, - { - "description": "patternGroups invalidates property", - "data": {"foo": []}, - "valid": false - }, - { - "description": "patternGroups validates nonproperty", - "data": {"fxo": [1, 2]}, - "valid": true - }, - { - "description": "patternGroups invalidates nonproperty", - "data": {"fxo": []}, - "valid": false - }, - { - "description": "additionalProperty ignores property", - "data": {"bar": []}, - "valid": true - }, - { - "description": "additionalProperty validates others", - "data": {"quux": 3}, - "valid": true - }, - { - "description": "additionalProperty invalidates others", - "data": {"quux": "foo"}, - "valid": false - } - ] - } -] diff --git a/spec/options.spec.js b/spec/options.spec.js index 84a5d64..5ae18dd 100644 --- a/spec/options.spec.js +++ b/spec/options.spec.js @@ -222,21 +222,6 @@ describe('Ajv Options', function () { test(schema, obj, proto); }); - it('should only validate own properties with patternGroups', function() { - ajv = new Ajv({ allErrors: true, patternGroups: true }); - ajvOP = new Ajv({ ownProperties: true, allErrors: true, patternGroups: true }); - - var schema = { - patternGroups: { - 'f.*o': { schema: { type: 'integer' } } - } - }; - - var obj = { fooo: 1 }; - var proto = { foo: 'not a number' }; - test(schema, obj, proto); - }); - it('should only validate own properties with propertyNames', function() { var schema = { propertyNames: { @@ -1148,61 +1133,6 @@ describe('Ajv Options', function () { }); - describe('patternGroups without draft-07 meta-schema', function() { - it('should use default meta-schema', function() { - var ajv = new Ajv({ - patternGroups: true, - meta: require('../lib/refs/json-schema-draft-04.json') - }); - - ajv.compile({ - patternGroups: { - '^foo': { - schema: { type: 'number' }, - minimum: 1 - } - } - }); - - should.throw(function() { - ajv.compile({ - patternGroups: { - '^foo': { - schema: { type: 'wrong_type' }, - minimum: 1 - } - } - }); - }); - }); - - it('should not use meta-schema if not available', function() { - var ajv = new Ajv({ - patternGroups: true, - meta: false - }); - - ajv.compile({ - patternGroups: { - '^foo': { - schema: { type: 'number' }, - minimum: 1 - } - } - }); - - ajv.compile({ - patternGroups: { - '^foo': { - schema: { type: 'wrong_type' }, - minimum: 1 - } - } - }); - }); - }); - - describe('schemaId', function() { describe('= undefined (default)', function() { it('should throw if both id and $id are available and different', function() {