From ef7b753c997deec3a90b7f3dc106e4cc66eb1f7b Mon Sep 17 00:00:00 2001 From: ronyhe Date: Thu, 24 Mar 2022 10:57:20 +0200 Subject: [PATCH 1/8] Initial naive implementation --- lib/core.ts | 1 + lib/vocabularies/unevaluated/unevaluatedProperties.ts | 6 +++++- package.json | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/core.ts b/lib/core.ts index 3686ffe76..f7dd4fdee 100644 --- a/lib/core.ts +++ b/lib/core.ts @@ -117,6 +117,7 @@ export interface CurrentOptions { loadSchema?: (uri: string) => Promise // options to modify validated data: removeAdditional?: boolean | "all" | "failing" + removeUnevaluated?: boolean useDefaults?: boolean | "empty" coerceTypes?: boolean | "array" // advanced options: diff --git a/lib/vocabularies/unevaluated/unevaluatedProperties.ts b/lib/vocabularies/unevaluated/unevaluatedProperties.ts index 0e6868fa3..fec2f9171 100644 --- a/lib/vocabularies/unevaluated/unevaluatedProperties.ts +++ b/lib/vocabularies/unevaluated/unevaluatedProperties.ts @@ -29,7 +29,7 @@ const def: CodeKeywordDefinition = { const {gen, schema, data, errsCount, it} = cxt /* istanbul ignore if */ if (!errsCount) throw new Error("ajv implementation error") - const {allErrors, props} = it + const {allErrors, props, opts} = it if (props instanceof Name) { gen.if(_`${props} !== true`, () => gen.forIn("key", data, (key: Name) => @@ -66,6 +66,10 @@ const def: CodeKeywordDefinition = { ) if (!allErrors) gen.if(not(valid), () => gen.break()) } + + if (opts.removeUnevaluated) { + gen.code(_`delete ${data}[${key}]`) + } } function unevaluatedDynamic(evaluatedProps: Name, key: Name): Code { diff --git a/package.json b/package.json index c277d94d6..026477639 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "prettier:write": "prettier --write \"./**/*.{json,yaml,js,ts}\"", "prettier:check": "prettier --list-different \"./**/*.{json,yaml,js,ts}\"", "test-spec": "cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot", + "myTest": "cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/options/removeUnevaluated.spec.ts\"", "test-codegen": "nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec", "test-debug": "npm run test-spec -- --inspect-brk", "test-cov": "nyc npm run test-spec", From b98df74b3f9398f82527d35b0b7c2506f6852f0b Mon Sep 17 00:00:00 2001 From: ronyhe Date: Thu, 24 Mar 2022 10:57:26 +0200 Subject: [PATCH 2/8] Initial naive implementation --- spec/options/removeUnevaluated.spec.ts | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 spec/options/removeUnevaluated.spec.ts diff --git a/spec/options/removeUnevaluated.spec.ts b/spec/options/removeUnevaluated.spec.ts new file mode 100644 index 000000000..5bc481fcd --- /dev/null +++ b/spec/options/removeUnevaluated.spec.ts @@ -0,0 +1,27 @@ +import _Ajv from "../ajv2019" +import chai from "../chai" +chai.should() + +describe("removeAdditional option", () => { + it("should remove all additional properties", () => { + const ajv = new _Ajv({removeUnevaluated: true, unevaluated: true}) + + ajv.addSchema({ + $id: "//test/fooBar", + type: "object", + properties: {foo: {type: "string"}, bar: {type: "string"}}, + unevaluatedProperties: true + }) + + const object = { + foo: "foo", + bar: "bar", + baz: "baz-to-be-removed", + } + + ajv.validate("//test/fooBar", object).should.equal(true) + object.should.have.property("foo") + object.should.have.property("bar") + object.should.not.have.property("baz") + }) +}) From 21ec0af74dabd2787763b521dc11e15b841c340d Mon Sep 17 00:00:00 2001 From: ronyhe Date: Thu, 24 Mar 2022 10:58:02 +0200 Subject: [PATCH 3/8] description fix --- spec/options/removeUnevaluated.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/options/removeUnevaluated.spec.ts b/spec/options/removeUnevaluated.spec.ts index 5bc481fcd..3843866e2 100644 --- a/spec/options/removeUnevaluated.spec.ts +++ b/spec/options/removeUnevaluated.spec.ts @@ -3,7 +3,7 @@ import chai from "../chai" chai.should() describe("removeAdditional option", () => { - it("should remove all additional properties", () => { + it("should remove unevaluated properties", () => { const ajv = new _Ajv({removeUnevaluated: true, unevaluated: true}) ajv.addSchema({ From c91b9c06f67adc2bac31a0ff32d0111ebaf9a1eb Mon Sep 17 00:00:00 2001 From: ronyhe Date: Thu, 24 Mar 2022 11:04:25 +0200 Subject: [PATCH 4/8] add test --- spec/options/removeUnevaluated.spec.ts | 33 ++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/spec/options/removeUnevaluated.spec.ts b/spec/options/removeUnevaluated.spec.ts index 3843866e2..23bc3ff0d 100644 --- a/spec/options/removeUnevaluated.spec.ts +++ b/spec/options/removeUnevaluated.spec.ts @@ -24,4 +24,37 @@ describe("removeAdditional option", () => { object.should.have.property("bar") object.should.not.have.property("baz") }) + + it('should remove redundant properties in oneOf situations', () => { + const ajv = new _Ajv({removeUnevaluated: true, unevaluated: true}) + ajv.addSchema({ + $id: "//test/fooBar", + type: "object", + oneOf: [ + { + required: ['a', 'b'], + properties: { + a: {type: 'number'}, + b: {type: 'number'}, + } + }, + { + properties: { + c: {type: 'number'}, + d: {type: 'number'} + } + } + ], + unevaluatedProperties: true + }) + const object = { + b: 2, + c: 3, + d: 4 + } + ajv.validate("//test/fooBar", object).should.equal(true) + object.should.not.have.property('b') + object.should.have.property('c') + object.should.have.property('d') + }) }) From f0dcc8304f3b3ad45443c433a59e1528ffa72020 Mon Sep 17 00:00:00 2001 From: ronyhe Date: Thu, 24 Mar 2022 11:09:03 +0200 Subject: [PATCH 5/8] failing test --- spec/options/removeUnevaluated.spec.ts | 38 ++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/spec/options/removeUnevaluated.spec.ts b/spec/options/removeUnevaluated.spec.ts index 23bc3ff0d..2e6694a82 100644 --- a/spec/options/removeUnevaluated.spec.ts +++ b/spec/options/removeUnevaluated.spec.ts @@ -57,4 +57,42 @@ describe("removeAdditional option", () => { object.should.have.property('c') object.should.have.property('d') }) + + // Still failing + it.skip('should remove redundant properties in anyOf situations', () => { + const ajv = new _Ajv({removeUnevaluated: true, unevaluated: true}) + ajv.addSchema({ + $id: "//test/fooBar", + type: "object", + anyOf: [ + { + required: ['a', 'b'], + properties: { + a: {type: 'number'}, + b: {type: 'number'}, + // unevaluatedProperties: true -> This makes it pass + }, + }, + { + required: ['c', 'd'], + properties: { + c: {type: 'number'}, + d: {type: 'number'} + } + } + ], + unevaluatedProperties: true + }) + const object = { + a: 1, + b: 2, + c: 3, + d: 4 + } + ajv.validate("//test/fooBar", object).should.equal(true) + object.should.have.property('a') + object.should.have.property('b') + object.should.not.have.property('c') + object.should.not.have.property('d') + }) }) From 53c2db3753dec89da299c3ceb1c7be165314df26 Mon Sep 17 00:00:00 2001 From: ronyhe Date: Thu, 24 Mar 2022 11:11:21 +0200 Subject: [PATCH 6/8] Prettier --- spec/options/removeUnevaluated.spec.ts | 60 +++++++++++++------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/spec/options/removeUnevaluated.spec.ts b/spec/options/removeUnevaluated.spec.ts index 2e6694a82..0b473d77e 100644 --- a/spec/options/removeUnevaluated.spec.ts +++ b/spec/options/removeUnevaluated.spec.ts @@ -10,7 +10,7 @@ describe("removeAdditional option", () => { $id: "//test/fooBar", type: "object", properties: {foo: {type: "string"}, bar: {type: "string"}}, - unevaluatedProperties: true + unevaluatedProperties: true, }) const object = { @@ -25,74 +25,74 @@ describe("removeAdditional option", () => { object.should.not.have.property("baz") }) - it('should remove redundant properties in oneOf situations', () => { + it("should remove redundant properties in oneOf situations", () => { const ajv = new _Ajv({removeUnevaluated: true, unevaluated: true}) ajv.addSchema({ $id: "//test/fooBar", type: "object", oneOf: [ { - required: ['a', 'b'], + required: ["a", "b"], properties: { - a: {type: 'number'}, - b: {type: 'number'}, - } + a: {type: "number"}, + b: {type: "number"}, + }, }, { properties: { - c: {type: 'number'}, - d: {type: 'number'} - } - } + c: {type: "number"}, + d: {type: "number"}, + }, + }, ], - unevaluatedProperties: true + unevaluatedProperties: true, }) const object = { b: 2, c: 3, - d: 4 + d: 4, } ajv.validate("//test/fooBar", object).should.equal(true) - object.should.not.have.property('b') - object.should.have.property('c') - object.should.have.property('d') + object.should.not.have.property("b") + object.should.have.property("c") + object.should.have.property("d") }) // Still failing - it.skip('should remove redundant properties in anyOf situations', () => { + it.skip("should remove redundant properties in anyOf situations", () => { const ajv = new _Ajv({removeUnevaluated: true, unevaluated: true}) ajv.addSchema({ $id: "//test/fooBar", type: "object", anyOf: [ { - required: ['a', 'b'], + required: ["a", "b"], properties: { - a: {type: 'number'}, - b: {type: 'number'}, + a: {type: "number"}, + b: {type: "number"}, // unevaluatedProperties: true -> This makes it pass }, }, { - required: ['c', 'd'], + required: ["c", "d"], properties: { - c: {type: 'number'}, - d: {type: 'number'} - } - } + c: {type: "number"}, + d: {type: "number"}, + }, + }, ], - unevaluatedProperties: true + unevaluatedProperties: true, }) const object = { a: 1, b: 2, c: 3, - d: 4 + d: 4, } ajv.validate("//test/fooBar", object).should.equal(true) - object.should.have.property('a') - object.should.have.property('b') - object.should.not.have.property('c') - object.should.not.have.property('d') + object.should.have.property("a") + object.should.have.property("b") + object.should.not.have.property("c") + object.should.not.have.property("d") }) }) From 86dced135895706a83aaf092a232fe3c38dcff26 Mon Sep 17 00:00:00 2001 From: ronyhe Date: Wed, 11 May 2022 15:51:01 +0300 Subject: [PATCH 7/8] More tests --- spec/options/removeUnevaluated.spec.ts | 42 ++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/spec/options/removeUnevaluated.spec.ts b/spec/options/removeUnevaluated.spec.ts index 0b473d77e..753b3e010 100644 --- a/spec/options/removeUnevaluated.spec.ts +++ b/spec/options/removeUnevaluated.spec.ts @@ -58,8 +58,7 @@ describe("removeAdditional option", () => { object.should.have.property("d") }) - // Still failing - it.skip("should remove redundant properties in anyOf situations", () => { + it("should remove redundant properties in anyOf situations, for the first alternative", () => { const ajv = new _Ajv({removeUnevaluated: true, unevaluated: true}) ajv.addSchema({ $id: "//test/fooBar", @@ -70,8 +69,8 @@ describe("removeAdditional option", () => { properties: { a: {type: "number"}, b: {type: "number"}, - // unevaluatedProperties: true -> This makes it pass }, + unevaluatedProperties: true }, { required: ["c", "d"], @@ -95,4 +94,41 @@ describe("removeAdditional option", () => { object.should.not.have.property("c") object.should.not.have.property("d") }) + + it("should remove redundant properties in anyOf situations, for subsequent alternatives", () => { + const ajv = new _Ajv({removeUnevaluated: true, unevaluated: true}) + ajv.addSchema({ + $id: "//test/fooBar", + type: "object", + anyOf: [ + { + required: ["a", "b"], + properties: { + a: {type: "number"}, + b: {type: "number"}, + }, + unevaluatedProperties: true + }, + { + required: ["c", "d"], + properties: { + c: {type: "number"}, + d: {type: "number"}, + }, + }, + ], + unevaluatedProperties: true, + }) + const object = { + b: 2, + c: 3, + d: 4, + } + ajv.validate("//test/fooBar", object).should.equal(true) + object.should.not.have.property("a") + object.should.not.have.property("b") + object.should.have.property("c") + object.should.have.property("d") + }) + }) From 2189b65f804daeb6226846ba3c99de554751bd99 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 16:15:28 +0000 Subject: [PATCH 8/8] build(deps-dev): bump eslint from 7.32.0 to 8.35.0 Bumps [eslint](https://github.com/eslint/eslint) from 7.32.0 to 8.35.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v7.32.0...v8.35.0) --- updated-dependencies: - dependency-name: eslint dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 026477639..dc1b8bebf 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "cross-env": "^7.0.2", "dayjs": "^1.10.4", "dayjs-plugin-utc": "^0.1.2", - "eslint": "^7.8.1", + "eslint": "^8.35.0", "eslint-config-prettier": "^7.0.0", "fast-uri": "^1.0.0", "glob": "^7.0.0",