diff --git a/package.json b/package.json index c4a544c73..4b0e024ae 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ }, "dependencies": { "ajv": "^8.17.1", + "ajv-draft-04": "^1.0.0", "lodash": "4.17.21", "prettier": "^3.5.0", "request-light": "^0.5.7", diff --git a/src/languageservice/services/yamlSchemaService.ts b/src/languageservice/services/yamlSchemaService.ts index 0cd199b3b..8ae730f47 100644 --- a/src/languageservice/services/yamlSchemaService.ts +++ b/src/languageservice/services/yamlSchemaService.ts @@ -28,9 +28,11 @@ import { JSONSchemaDescriptionExt } from '../../requestTypes'; import { SchemaVersions } from '../yamlTypes'; import Ajv, { DefinedError } from 'ajv'; +import Ajv4 from 'ajv-draft-04'; import { getSchemaTitle } from '../utils/schemaUtils'; const ajv = new Ajv(); +const ajv4 = new Ajv4(); const localize = nls.loadMessageBundle(); @@ -39,6 +41,11 @@ const localize = nls.loadMessageBundle(); const jsonSchema07 = require('ajv/dist/refs/json-schema-draft-07.json'); const schema07Validator = ajv.compile(jsonSchema07); +// eslint-disable-next-line @typescript-eslint/no-var-requires +const jsonSchema04 = require('ajv-draft-04/dist/refs/json-schema-draft-04.json'); +const schema04Validator = ajv4.compile(jsonSchema04); +const SCHEMA_04_URI_WITH_HTTPS = ajv4.defaultMeta().replace('http://', 'https://'); + export declare type CustomSchemaProvider = (uri: string) => Promise; export enum MODIFICATION_ACTIONS { @@ -164,9 +171,13 @@ export class YAMLSchemaService extends JSONSchemaService { let schema: JSONSchema = schemaToResolve.schema; const contextService = this.contextService; - if (!schema07Validator(schema)) { + const validator = + this.normalizeId(schema.$schema) === ajv4.defaultMeta() || this.normalizeId(schema.$schema) === SCHEMA_04_URI_WITH_HTTPS + ? schema04Validator + : schema07Validator; + if (!validator(schema)) { const errs: string[] = []; - for (const err of schema07Validator.errors as DefinedError[]) { + for (const err of validator.errors as DefinedError[]) { errs.push(`${err.instancePath} : ${err.message}`); } resolveErrors.push(`Schema '${getSchemaTitle(schemaToResolve.schema, schemaURL)}' is not valid:\n${errs.join('\n')}`); diff --git a/test/schemaValidation.test.ts b/test/schemaValidation.test.ts index 5cd9231b3..edb73810f 100644 --- a/test/schemaValidation.test.ts +++ b/test/schemaValidation.test.ts @@ -2151,4 +2151,66 @@ obj: result = await parseSetup(content); expect(result.length).to.eq(0); }); + + it('draft-04 schema', async () => { + const schema: JSONSchema = { + $schema: 'http://json-schema.org/draft-04/schema#', + type: 'object', + properties: { + myProperty: { + $ref: '#/definitions/Interface%3Ctype%3E', + }, + }, + definitions: { + 'Interface': { + type: 'object', + properties: { + foo: { + type: 'string', + }, + multipleOf: { + type: 'number', + minimum: 0, + exclusiveMinimum: true, + }, + }, + }, + }, + }; + schemaProvider.addSchema(SCHEMA_ID, schema); + const content = `myProperty:\n foo: bar\n multipleOf: 1`; + const result = await parseSetup(content); + assert.equal(result.length, 0); + }); + + it('draft-04 schema with https in metaschema URI', async () => { + const schema: JSONSchema = { + $schema: 'https://json-schema.org/draft-04/schema#', + type: 'object', + properties: { + myProperty: { + $ref: '#/definitions/Interface%3Ctype%3E', + }, + }, + definitions: { + 'Interface': { + type: 'object', + properties: { + foo: { + type: 'string', + }, + multipleOf: { + type: 'number', + minimum: 0, + exclusiveMinimum: true, + }, + }, + }, + }, + }; + schemaProvider.addSchema(SCHEMA_ID, schema); + const content = `myProperty:\n foo: bar\n multipleOf: 1`; + const result = await parseSetup(content); + assert.equal(result.length, 0); + }); }); diff --git a/yarn.lock b/yarn.lock index ce1c8eaa5..877c50d06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -681,6 +681,11 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" +ajv-draft-04@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz#3b64761b268ba0b9e668f0b41ba53fce0ad77fc8" + integrity sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw== + ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz"