Skip to content

Commit 0400d2a

Browse files
committed
Support draft-04 schemas
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 1be76fb commit 0400d2a

File tree

4 files changed

+61
-5
lines changed

4 files changed

+61
-5
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: 23 additions & 5 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,10 @@ 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+
4248
export declare type CustomSchemaProvider = (uri: string) => Promise<string | string[]>;
4349

4450
export enum MODIFICATION_ACTIONS {
@@ -164,12 +170,24 @@ export class YAMLSchemaService extends JSONSchemaService {
164170
let schema: JSONSchema = schemaToResolve.schema;
165171
const contextService = this.contextService;
166172

167-
if (!schema07Validator(schema)) {
168-
const errs: string[] = [];
169-
for (const err of schema07Validator.errors as DefinedError[]) {
170-
errs.push(`${err.instancePath} : ${err.message}`);
173+
if (schema.$schema === 'http://json-schema.org/draft-04/schema#') {
174+
if (!schema04Validator(schema)) {
175+
if (!schema07Validator(schema)) {
176+
const errs: string[] = [];
177+
for (const err of schema07Validator.errors as DefinedError[]) {
178+
errs.push(`${err.instancePath} : ${err.message}`);
179+
}
180+
resolveErrors.push(`Schema '${getSchemaTitle(schemaToResolve.schema, schemaURL)}' is not valid:\n${errs.join('\n')}`);
181+
}
182+
}
183+
} else {
184+
if (!schema07Validator(schema)) {
185+
const errs: string[] = [];
186+
for (const err of schema07Validator.errors as DefinedError[]) {
187+
errs.push(`${err.instancePath} : ${err.message}`);
188+
}
189+
resolveErrors.push(`Schema '${getSchemaTitle(schemaToResolve.schema, schemaURL)}' is not valid:\n${errs.join('\n')}`);
171190
}
172-
resolveErrors.push(`Schema '${getSchemaTitle(schemaToResolve.schema, schemaURL)}' is not valid:\n${errs.join('\n')}`);
173191
}
174192

175193
const findSection = (schema: JSONSchema, path: string): JSONSchema => {

test/schemaValidation.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2094,4 +2094,36 @@ obj:
20942094
const result = await parseSetup(content);
20952095
assert.equal(result.length, 0);
20962096
});
2097+
2098+
it('draft-04 schema', async () => {
2099+
const schema: JSONSchema = {
2100+
$schema: 'http://json-schema.org/draft-04/schema#',
2101+
type: 'object',
2102+
properties: {
2103+
myProperty: {
2104+
$ref: '#/definitions/Interface%3Ctype%3E',
2105+
},
2106+
},
2107+
definitions: {
2108+
'Interface<type>': {
2109+
type: 'object',
2110+
properties: {
2111+
foo: {
2112+
type: 'string',
2113+
},
2114+
multipleOf: {
2115+
type: 'number',
2116+
minimum: 0,
2117+
exclusiveMinimum: true,
2118+
},
2119+
},
2120+
},
2121+
},
2122+
};
2123+
schemaProvider.addSchema(SCHEMA_ID, schema);
2124+
const content = `myProperty:\n foo: bar\n multipleOf: 1`;
2125+
const result = await parseSetup(content);
2126+
console.log(result);
2127+
assert.equal(result.length, 0);
2128+
});
20972129
});

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)