From e8a515c726e08e4783da0c3f932586f5cf42671a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Lal?= Date: Thu, 21 Dec 2023 14:49:57 +0100 Subject: [PATCH] Support $defs and deprecate definitions --- lib/model/AjvValidator.js | 10 +++++++ tests/unit/model/AjvValidator.js | 47 ++++++++++++++++++++++++++++++++ typings/objection/index.d.ts | 8 ++++++ 3 files changed, 65 insertions(+) diff --git a/lib/model/AjvValidator.js b/lib/model/AjvValidator.js index 97b8f3af2..4e0dee42f 100644 --- a/lib/model/AjvValidator.js +++ b/lib/model/AjvValidator.js @@ -265,6 +265,16 @@ function jsonSchemaWithoutRequired(jsonSchema) { ), } : {}, + jsonSchema && jsonSchema.$defs && Object.keys(jsonSchema.$defs).length > 0 + ? { + $defs: Object.assign( + ...Object.keys(jsonSchema.$defs).map((prop) => ({ + [prop]: jsonSchemaWithoutRequired(jsonSchema.$defs[prop]), + })), + ), + } + : {}, + jsonSchema.discriminator && jsonSchema.discriminator.propertyName ? { required: [jsonSchema.discriminator.propertyName] } : {}, diff --git a/tests/unit/model/AjvValidator.js b/tests/unit/model/AjvValidator.js index 24a14786c..6c67d4c94 100644 --- a/tests/unit/model/AjvValidator.js +++ b/tests/unit/model/AjvValidator.js @@ -35,6 +35,26 @@ describe('AjvValidator', () => { anyOf: [{ $ref: '#/definitions/TestRef1' }, { $ref: '#/definitions/TestRef2' }], }; + const schemaBis = { + $defs: { + TestRef1: { + type: 'object', + properties: { + aRequiredProp1: { type: 'string' }, + }, + required: ['aRequiredProp1'], + }, + TestRef2: { + type: 'object', + properties: { + aRequiredProp2: { type: 'string' }, + }, + required: ['aRequiredProp2'], + }, + }, + anyOf: [{ $ref: '#/$defs/TestRef1' }, { $ref: '#/$defs/TestRef2' }], + }; + const schema2 = { type: 'object', discriminator: { propertyName: 'foo' }, @@ -102,6 +122,15 @@ describe('AjvValidator', () => { definitions.forEach((d) => expect(d.required).to.be(undefined)); }); + it('should remove required fields from $defs', () => { + const validator = new AjvValidator({ onCreateAjv: () => {} }); + const validators = validator.getValidator(modelClass('test', schemaBis), schemaBis, true); + const $defs = Object.entries(validators.schema.$defs); + + expect($defs.length).to.be(2); + $defs.forEach((d) => expect(d.required).to.be(undefined)); + }); + it('should not remove required fields if there is a discriminator', () => { const validator = new AjvValidator({ onCreateAjv: () => {}, @@ -156,5 +185,23 @@ describe('AjvValidator', () => { true, ); }); + + it('should handle empty $defs', () => { + const emptyDefinitionsSchema = { + type: 'object', + required: ['a'], + $defs: {}, + additionalProperties: false, + properties: { + a: { type: 'string' }, + }, + }; + const validator = new AjvValidator({ onCreateAjv: () => {} }); + validator.getValidator( + modelClass('test', emptyDefinitionsSchema), + emptyDefinitionsSchema, + true, + ); + }); }); }); diff --git a/typings/objection/index.d.ts b/typings/objection/index.d.ts index 848bdca10..44120111b 100644 --- a/typings/objection/index.d.ts +++ b/typings/objection/index.d.ts @@ -1869,6 +1869,13 @@ declare namespace Objection { $schema?: JSONSchemaVersion; $comment?: string; + /** + * @see https://json-schema.org/draft/2019-09/release-notes + */ + $defs?: { + [key: string]: JSONSchemaDefinition; + }; + /** * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.1 */ @@ -1948,6 +1955,7 @@ declare namespace Objection { /** * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-9 + * @deprecated Rename to $defs */ definitions?: { [key: string]: JSONSchemaDefinition;