Skip to content

Commit fce910a

Browse files
authored
Support draft-04 schemas (#1065)
This helps to support the schema for openapi 3.0.0, among others, that use an older draft of JSON schema that has some type differences that make it incompatible with JSON schema draft 07. See #1006 , I think the root cause for the issues that PR caused is that we were trying to download and cache the metaschema from the "URL" instead of using the copy that's bundled with `ajv`. Fixes #780, Fixes #752 (and many, many duplicates we'll have to find and clean up) Signed-off-by: David Thompson <[email protected]>
1 parent 4370b5c commit fce910a

File tree

4 files changed

+81
-2
lines changed

4 files changed

+81
-2
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
},
2828
"dependencies": {
2929
"ajv": "^8.17.1",
30+
"ajv-draft-04": "^1.0.0",
3031
"lodash": "4.17.21",
3132
"prettier": "^3.5.0",
3233
"request-light": "^0.5.7",

src/languageservice/services/yamlSchemaService.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ import { JSONSchemaDescriptionExt } from '../../requestTypes';
2828
import { SchemaVersions } from '../yamlTypes';
2929

3030
import Ajv, { DefinedError } from 'ajv';
31+
import Ajv4 from 'ajv-draft-04';
3132
import { getSchemaTitle } from '../utils/schemaUtils';
3233

3334
const ajv = new Ajv();
35+
const ajv4 = new Ajv4();
3436

3537
const localize = nls.loadMessageBundle();
3638

@@ -39,6 +41,11 @@ const localize = nls.loadMessageBundle();
3941
const jsonSchema07 = require('ajv/dist/refs/json-schema-draft-07.json');
4042
const schema07Validator = ajv.compile(jsonSchema07);
4143

44+
// eslint-disable-next-line @typescript-eslint/no-var-requires
45+
const jsonSchema04 = require('ajv-draft-04/dist/refs/json-schema-draft-04.json');
46+
const schema04Validator = ajv4.compile(jsonSchema04);
47+
const SCHEMA_04_URI_WITH_HTTPS = ajv4.defaultMeta().replace('http://', 'https://');
48+
4249
export declare type CustomSchemaProvider = (uri: string) => Promise<string | string[]>;
4350

4451
export enum MODIFICATION_ACTIONS {
@@ -164,9 +171,13 @@ export class YAMLSchemaService extends JSONSchemaService {
164171
let schema: JSONSchema = schemaToResolve.schema;
165172
const contextService = this.contextService;
166173

167-
if (!schema07Validator(schema)) {
174+
const validator =
175+
this.normalizeId(schema.$schema) === ajv4.defaultMeta() || this.normalizeId(schema.$schema) === SCHEMA_04_URI_WITH_HTTPS
176+
? schema04Validator
177+
: schema07Validator;
178+
if (!validator(schema)) {
168179
const errs: string[] = [];
169-
for (const err of schema07Validator.errors as DefinedError[]) {
180+
for (const err of validator.errors as DefinedError[]) {
170181
errs.push(`${err.instancePath} : ${err.message}`);
171182
}
172183
resolveErrors.push(`Schema '${getSchemaTitle(schemaToResolve.schema, schemaURL)}' is not valid:\n${errs.join('\n')}`);

test/schemaValidation.test.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2151,4 +2151,66 @@ obj:
21512151
result = await parseSetup(content);
21522152
expect(result.length).to.eq(0);
21532153
});
2154+
2155+
it('draft-04 schema', async () => {
2156+
const schema: JSONSchema = {
2157+
$schema: 'http://json-schema.org/draft-04/schema#',
2158+
type: 'object',
2159+
properties: {
2160+
myProperty: {
2161+
$ref: '#/definitions/Interface%3Ctype%3E',
2162+
},
2163+
},
2164+
definitions: {
2165+
'Interface<type>': {
2166+
type: 'object',
2167+
properties: {
2168+
foo: {
2169+
type: 'string',
2170+
},
2171+
multipleOf: {
2172+
type: 'number',
2173+
minimum: 0,
2174+
exclusiveMinimum: true,
2175+
},
2176+
},
2177+
},
2178+
},
2179+
};
2180+
schemaProvider.addSchema(SCHEMA_ID, schema);
2181+
const content = `myProperty:\n foo: bar\n multipleOf: 1`;
2182+
const result = await parseSetup(content);
2183+
assert.equal(result.length, 0);
2184+
});
2185+
2186+
it('draft-04 schema with https in metaschema URI', async () => {
2187+
const schema: JSONSchema = {
2188+
$schema: 'https://json-schema.org/draft-04/schema#',
2189+
type: 'object',
2190+
properties: {
2191+
myProperty: {
2192+
$ref: '#/definitions/Interface%3Ctype%3E',
2193+
},
2194+
},
2195+
definitions: {
2196+
'Interface<type>': {
2197+
type: 'object',
2198+
properties: {
2199+
foo: {
2200+
type: 'string',
2201+
},
2202+
multipleOf: {
2203+
type: 'number',
2204+
minimum: 0,
2205+
exclusiveMinimum: true,
2206+
},
2207+
},
2208+
},
2209+
},
2210+
};
2211+
schemaProvider.addSchema(SCHEMA_ID, schema);
2212+
const content = `myProperty:\n foo: bar\n multipleOf: 1`;
2213+
const result = await parseSetup(content);
2214+
assert.equal(result.length, 0);
2215+
});
21542216
});

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,11 @@ aggregate-error@^3.0.0:
681681
clean-stack "^2.0.0"
682682
indent-string "^4.0.0"
683683

684+
ajv-draft-04@^1.0.0:
685+
version "1.0.0"
686+
resolved "https://registry.yarnpkg.com/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz#3b64761b268ba0b9e668f0b41ba53fce0ad77fc8"
687+
integrity sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==
688+
684689
ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4:
685690
version "6.12.6"
686691
resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz"

0 commit comments

Comments
 (0)