-
-
Notifications
You must be signed in to change notification settings - Fork 240
/
ajv.ts
90 lines (83 loc) · 2.66 KB
/
ajv.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import Ajv, { _, ValidateFunction } from 'ajv';
import names from 'ajv/dist/compile/names';
import addFormats from 'ajv-formats';
import addErrors from 'ajv-errors';
import * as ruleSchema from '../meta/rule.schema.json';
import * as shared from '../meta/shared.json';
import * as rulesetSchema from '../meta/ruleset.schema.json';
import * as jsExtensions from '../meta/js-extensions.json';
import * as jsonExtensions from '../meta/json-extensions.json';
import { validateAlias } from './validators/alias';
import { validateFunction } from './validators/function';
const validators: { [key in 'js' | 'json']: null | ValidateFunction } = {
js: null,
json: null,
};
export function createValidator(format: 'js' | 'json'): ValidateFunction {
const existingValidator = validators[format];
if (existingValidator !== null) {
return existingValidator;
}
const ajv = new Ajv({
allErrors: true,
strict: true,
strictRequired: false,
keywords: ['$anchor'],
schemas: [ruleSchema, shared],
passContext: true,
});
addFormats(ajv);
addErrors(ajv);
ajv.addKeyword({
keyword: 'x-spectral-runtime',
schemaType: 'string',
error: {
message(cxt) {
return _`${cxt.params?.message !== void 0 ? cxt.params.message : ''}`;
},
params(cxt) {
return _`{ errors: ${cxt.params?.errors !== void 0 && cxt.params.errors} || [] }`;
},
},
code(cxt) {
const { data } = cxt;
switch (cxt.schema as unknown) {
case 'format':
cxt.fail(_`typeof ${data} !== "function"`);
break;
case 'ruleset-function': {
const fn = cxt.gen.const(
'spectralFunction',
_`this.validateFunction(${data}.function, ${data}.functionOptions === void 0 ? null : ${data}.functionOptions, ${names.instancePath})`,
);
cxt.gen.if(_`${fn} !== void 0`);
cxt.error(false, { errors: fn });
cxt.gen.endIf();
break;
}
case 'alias': {
const alias = cxt.gen.const(
'spectralAlias',
_`this.validateAlias(${names.rootData}, ${data}, ${names.instancePath})`,
);
cxt.gen.if(_`${alias} !== void 0`);
cxt.error(false, { errors: alias });
cxt.gen.endIf();
break;
}
}
},
});
if (format === 'js') {
ajv.addSchema(jsExtensions);
} else {
ajv.addSchema(jsonExtensions);
}
const validator = new Proxy(ajv.compile(rulesetSchema), {
apply(target, thisArg, args: unknown[]): unknown {
return Reflect.apply(target, { validateAlias, validateFunction }, args);
},
});
validators[format] = validator;
return validator;
}