@takeshape/json-schema 8.87.0 → 8.87.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/schema-validator.js +43 -30
- package/lib/schema-validator.d.ts +5 -7
- package/lib/schema-validator.d.ts.map +1 -1
- package/lib/schema-validator.js +49 -30
- package/package.json +4 -3
package/es/schema-validator.js
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import Ajv from 'ajv';
|
|
2
2
|
import addFormats from 'ajv-formats';
|
|
3
3
|
import get from 'lodash/get';
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import set from 'lodash/set';
|
|
5
|
+
import unset from 'lodash/unset';
|
|
6
|
+
import isObject from 'lodash/isObject';
|
|
7
|
+
import isString from 'lodash/isString';
|
|
8
|
+
import isArray from 'lodash/isArray';
|
|
9
|
+
import { visit } from '@takeshape/util';
|
|
10
|
+
export function parseDataPath(instancePath) {
|
|
11
|
+
return instancePath.substr(1).split('/');
|
|
6
12
|
}
|
|
7
13
|
|
|
8
14
|
function getData(error, data) {
|
|
9
|
-
return get(data, parseDataPath(error.
|
|
15
|
+
return get(data, parseDataPath(error.instancePath));
|
|
10
16
|
}
|
|
11
17
|
|
|
12
18
|
function ignoreMissing(error) {
|
|
13
19
|
// ignore top level missing errors
|
|
14
|
-
return !(error.
|
|
20
|
+
return !(error.instancePath === '' && error.keyword === 'required');
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
function ignoreNull(error, data, schema) {
|
|
@@ -23,10 +29,10 @@ function getErrorFilter(params, data, schema) {
|
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
export function isInvalidPropertyRequired(schema, error) {
|
|
26
|
-
const
|
|
27
|
-
const parentDataPath =
|
|
32
|
+
const instancePath = parseDataPath(error.instancePath);
|
|
33
|
+
const parentDataPath = instancePath.slice(0, instancePath.length - 1);
|
|
28
34
|
const parentSchema = followSchemaPath(schema, parentDataPath);
|
|
29
|
-
const name = getName(error.
|
|
35
|
+
const name = getName(error.instancePath);
|
|
30
36
|
|
|
31
37
|
if (!parentSchema) {
|
|
32
38
|
throw new Error('Unexpected error cannot find parent schema');
|
|
@@ -57,11 +63,11 @@ function followRef(topLevelSchema, schema) {
|
|
|
57
63
|
return schema.$ref ? get(topLevelSchema, refToPath(schema.$ref)) : schema;
|
|
58
64
|
}
|
|
59
65
|
/**
|
|
60
|
-
* Given a schema object traverse it using a "
|
|
66
|
+
* Given a schema object traverse it using a "instancePath" and return the schema at that path
|
|
61
67
|
*/
|
|
62
68
|
|
|
63
69
|
|
|
64
|
-
export function followSchemaPath(topLevelSchema,
|
|
70
|
+
export function followSchemaPath(topLevelSchema, instancePath) {
|
|
65
71
|
const followPath = (schema, path) => {
|
|
66
72
|
var _schema, _schema$properties;
|
|
67
73
|
|
|
@@ -96,7 +102,7 @@ export function followSchemaPath(topLevelSchema, dataPath) {
|
|
|
96
102
|
}
|
|
97
103
|
};
|
|
98
104
|
|
|
99
|
-
return followPath(topLevelSchema,
|
|
105
|
+
return followPath(topLevelSchema, instancePath);
|
|
100
106
|
}
|
|
101
107
|
|
|
102
108
|
function isSchemaObject(schema) {
|
|
@@ -140,6 +146,7 @@ export function validate(ajv, id, data, options) {
|
|
|
140
146
|
export { Ajv };
|
|
141
147
|
export function createAjv(options) {
|
|
142
148
|
const ajv = new Ajv({
|
|
149
|
+
discriminator: true,
|
|
143
150
|
allErrors: true,
|
|
144
151
|
unevaluated: true,
|
|
145
152
|
strict: false,
|
|
@@ -169,35 +176,41 @@ function isValidRegex(str) {
|
|
|
169
176
|
}
|
|
170
177
|
}
|
|
171
178
|
/**
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
* This should be fixed in ajv see the comment here
|
|
175
|
-
* https://github.com/ajv-validator/ajv/blob/9f1c3eaa4b91ca17b72b122cdac9b108d1ac30cb/lib/vocabularies/validation/pattern.ts#L21
|
|
179
|
+
* Apply various fixes to the schema to work around AJV issues and bugs.
|
|
180
|
+
* See inline comments for more.
|
|
176
181
|
*/
|
|
177
182
|
|
|
178
183
|
|
|
179
184
|
export function fixSchema(schema) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
185
|
+
visit(schema, ['pattern', 'oneOf'], (value, path) => {
|
|
186
|
+
const key = path.slice(-1)[0];
|
|
187
|
+
const parent = get(schema, path.slice(0, -1));
|
|
188
|
+
/**
|
|
189
|
+
* Fix schema by removing any broken regexes that will cause ajv to throw a compile error.
|
|
190
|
+
* It is better to remove the invalid regex rather than forgo validation altogether
|
|
191
|
+
* This should be fixed in ajv see the comment here
|
|
192
|
+
* https://github.com/ajv-validator/ajv/blob/9f1c3eaa4b91ca17b72b122cdac9b108d1ac30cb/lib/vocabularies/validation/pattern.ts#L21
|
|
193
|
+
*/
|
|
194
|
+
|
|
195
|
+
if (key === 'pattern') {
|
|
196
|
+
if (parent.type === 'string' && (!isString(value) || !isValidRegex(value))) {
|
|
197
|
+
unset(schema, path);
|
|
198
|
+
}
|
|
199
|
+
} // Inline $refs inside definitions that use discriminator
|
|
200
|
+
// https://github.com/ajv-validator/ajv/issues/1899
|
|
184
201
|
|
|
185
|
-
if (obj && typeof obj === 'object') {
|
|
186
|
-
const result = {};
|
|
187
202
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
203
|
+
if (key === 'oneOf' && isArray(value)) {
|
|
204
|
+
if (isObject(parent.discriminator) && path[0] === 'definitions') {
|
|
205
|
+
for (const [index, subschema] of value.entries()) {
|
|
206
|
+
if (subschema.$ref) {
|
|
207
|
+
set(schema, [...path, index], get(schema, subschema.$ref.substr(2).split('/')));
|
|
208
|
+
}
|
|
191
209
|
}
|
|
192
210
|
}
|
|
193
|
-
|
|
194
|
-
return result;
|
|
195
211
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
return normalize(schema);
|
|
212
|
+
});
|
|
213
|
+
return schema;
|
|
201
214
|
}
|
|
202
215
|
export function createSchemaValidator(schema, metaSchemas = [], options = {}) {
|
|
203
216
|
const schemas = Array.isArray(schema) ? schema : [schema];
|
|
@@ -12,22 +12,20 @@ export interface ValidateResult {
|
|
|
12
12
|
errors: ErrorObject[];
|
|
13
13
|
}
|
|
14
14
|
export declare type Validator = (data: Data, options?: Partial<ValidateParams>) => ValidateResult;
|
|
15
|
-
export declare function parseDataPath(
|
|
15
|
+
export declare function parseDataPath(instancePath: string): string[];
|
|
16
16
|
export declare function isInvalidPropertyRequired(schema: SchemaObject, error: ErrorObject): boolean;
|
|
17
17
|
export declare function refToPath(ref: string): string[];
|
|
18
18
|
/**
|
|
19
|
-
* Given a schema object traverse it using a "
|
|
19
|
+
* Given a schema object traverse it using a "instancePath" and return the schema at that path
|
|
20
20
|
*/
|
|
21
|
-
export declare function followSchemaPath(topLevelSchema: SchemaObject,
|
|
21
|
+
export declare function followSchemaPath(topLevelSchema: SchemaObject, instancePath: string[]): SchemaObject | undefined;
|
|
22
22
|
export declare type MinimalAjv = Pick<Ajv, 'validate' | 'errors' | 'getSchema' | 'errorsText'>;
|
|
23
23
|
export declare function validate(ajv: MinimalAjv, id: string, data: Data, options?: Partial<ValidateParams>): ValidateResult;
|
|
24
24
|
export { Ajv, ErrorObject };
|
|
25
25
|
export declare function createAjv(options?: Options): Ajv;
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* This should be fixed in ajv see the comment here
|
|
30
|
-
* https://github.com/ajv-validator/ajv/blob/9f1c3eaa4b91ca17b72b122cdac9b108d1ac30cb/lib/vocabularies/validation/pattern.ts#L21
|
|
27
|
+
* Apply various fixes to the schema to work around AJV issues and bugs.
|
|
28
|
+
* See inline comments for more.
|
|
31
29
|
*/
|
|
32
30
|
export declare function fixSchema(schema: SchemaObject): SchemaObject;
|
|
33
31
|
export declare function createSchemaValidator(schema: SchemaObject | SchemaObject[], metaSchemas?: SchemaObject[], options?: Options): Validator;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-validator.d.ts","sourceRoot":"","sources":["../../src/schema-validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,WAAW,EAAE,OAAO,EAAE,YAAY,EAAC,MAAM,KAAK,CAAC;AAC5D,OAAO,GAAG,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"schema-validator.d.ts","sourceRoot":"","sources":["../../src/schema-validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,WAAW,EAAE,OAAO,EAAE,YAAY,EAAC,MAAM,KAAK,CAAC;AAC5D,OAAO,GAAG,MAAM,KAAK,CAAC;AAUtB,oBAAY,IAAI,GAAG,GAAG,CAAC;AAEvB,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAED,oBAAY,SAAS,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,KAAK,cAAc,CAAC;AAE1F,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,CAE5D;AAwBD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAW3F;AAcD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAE/C;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,YAAY,GAAG,SAAS,CA6B/G;AAED,oBAAY,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,YAAY,CAAC,CAAC;AAMvF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CA2BnH;AAED,OAAO,EAAC,GAAG,EAAE,WAAW,EAAC,CAAC;AAC1B,wBAAgB,SAAS,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,GAAG,CAmBhD;AAeD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CA+B5D;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,YAAY,GAAG,YAAY,EAAE,EACrC,WAAW,GAAE,YAAY,EAAO,EAChC,OAAO,GAAE,OAAY,GACpB,SAAS,CAqBX"}
|
package/lib/schema-validator.js
CHANGED
|
@@ -24,19 +24,31 @@ var _ajvFormats = _interopRequireDefault(require("ajv-formats"));
|
|
|
24
24
|
|
|
25
25
|
var _get = _interopRequireDefault(require("lodash/get"));
|
|
26
26
|
|
|
27
|
+
var _set = _interopRequireDefault(require("lodash/set"));
|
|
28
|
+
|
|
29
|
+
var _unset = _interopRequireDefault(require("lodash/unset"));
|
|
30
|
+
|
|
31
|
+
var _isObject = _interopRequireDefault(require("lodash/isObject"));
|
|
32
|
+
|
|
33
|
+
var _isString = _interopRequireDefault(require("lodash/isString"));
|
|
34
|
+
|
|
35
|
+
var _isArray = _interopRequireDefault(require("lodash/isArray"));
|
|
36
|
+
|
|
37
|
+
var _util = require("@takeshape/util");
|
|
38
|
+
|
|
27
39
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
28
40
|
|
|
29
|
-
function parseDataPath(
|
|
30
|
-
return
|
|
41
|
+
function parseDataPath(instancePath) {
|
|
42
|
+
return instancePath.substr(1).split('/');
|
|
31
43
|
}
|
|
32
44
|
|
|
33
45
|
function getData(error, data) {
|
|
34
|
-
return (0, _get.default)(data, parseDataPath(error.
|
|
46
|
+
return (0, _get.default)(data, parseDataPath(error.instancePath));
|
|
35
47
|
}
|
|
36
48
|
|
|
37
49
|
function ignoreMissing(error) {
|
|
38
50
|
// ignore top level missing errors
|
|
39
|
-
return !(error.
|
|
51
|
+
return !(error.instancePath === '' && error.keyword === 'required');
|
|
40
52
|
}
|
|
41
53
|
|
|
42
54
|
function ignoreNull(error, data, schema) {
|
|
@@ -48,10 +60,10 @@ function getErrorFilter(params, data, schema) {
|
|
|
48
60
|
}
|
|
49
61
|
|
|
50
62
|
function isInvalidPropertyRequired(schema, error) {
|
|
51
|
-
const
|
|
52
|
-
const parentDataPath =
|
|
63
|
+
const instancePath = parseDataPath(error.instancePath);
|
|
64
|
+
const parentDataPath = instancePath.slice(0, instancePath.length - 1);
|
|
53
65
|
const parentSchema = followSchemaPath(schema, parentDataPath);
|
|
54
|
-
const name = getName(error.
|
|
66
|
+
const name = getName(error.instancePath);
|
|
55
67
|
|
|
56
68
|
if (!parentSchema) {
|
|
57
69
|
throw new Error('Unexpected error cannot find parent schema');
|
|
@@ -82,11 +94,11 @@ function followRef(topLevelSchema, schema) {
|
|
|
82
94
|
return schema.$ref ? (0, _get.default)(topLevelSchema, refToPath(schema.$ref)) : schema;
|
|
83
95
|
}
|
|
84
96
|
/**
|
|
85
|
-
* Given a schema object traverse it using a "
|
|
97
|
+
* Given a schema object traverse it using a "instancePath" and return the schema at that path
|
|
86
98
|
*/
|
|
87
99
|
|
|
88
100
|
|
|
89
|
-
function followSchemaPath(topLevelSchema,
|
|
101
|
+
function followSchemaPath(topLevelSchema, instancePath) {
|
|
90
102
|
const followPath = (schema, path) => {
|
|
91
103
|
var _schema, _schema$properties;
|
|
92
104
|
|
|
@@ -121,7 +133,7 @@ function followSchemaPath(topLevelSchema, dataPath) {
|
|
|
121
133
|
}
|
|
122
134
|
};
|
|
123
135
|
|
|
124
|
-
return followPath(topLevelSchema,
|
|
136
|
+
return followPath(topLevelSchema, instancePath);
|
|
125
137
|
}
|
|
126
138
|
|
|
127
139
|
function isSchemaObject(schema) {
|
|
@@ -165,6 +177,7 @@ function validate(ajv, id, data, options) {
|
|
|
165
177
|
|
|
166
178
|
function createAjv(options) {
|
|
167
179
|
const ajv = new _ajv.default({
|
|
180
|
+
discriminator: true,
|
|
168
181
|
allErrors: true,
|
|
169
182
|
unevaluated: true,
|
|
170
183
|
strict: false,
|
|
@@ -195,35 +208,41 @@ function isValidRegex(str) {
|
|
|
195
208
|
}
|
|
196
209
|
}
|
|
197
210
|
/**
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
* This should be fixed in ajv see the comment here
|
|
201
|
-
* https://github.com/ajv-validator/ajv/blob/9f1c3eaa4b91ca17b72b122cdac9b108d1ac30cb/lib/vocabularies/validation/pattern.ts#L21
|
|
211
|
+
* Apply various fixes to the schema to work around AJV issues and bugs.
|
|
212
|
+
* See inline comments for more.
|
|
202
213
|
*/
|
|
203
214
|
|
|
204
215
|
|
|
205
216
|
function fixSchema(schema) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
217
|
+
(0, _util.visit)(schema, ['pattern', 'oneOf'], (value, path) => {
|
|
218
|
+
const key = path.slice(-1)[0];
|
|
219
|
+
const parent = (0, _get.default)(schema, path.slice(0, -1));
|
|
220
|
+
/**
|
|
221
|
+
* Fix schema by removing any broken regexes that will cause ajv to throw a compile error.
|
|
222
|
+
* It is better to remove the invalid regex rather than forgo validation altogether
|
|
223
|
+
* This should be fixed in ajv see the comment here
|
|
224
|
+
* https://github.com/ajv-validator/ajv/blob/9f1c3eaa4b91ca17b72b122cdac9b108d1ac30cb/lib/vocabularies/validation/pattern.ts#L21
|
|
225
|
+
*/
|
|
226
|
+
|
|
227
|
+
if (key === 'pattern') {
|
|
228
|
+
if (parent.type === 'string' && (!(0, _isString.default)(value) || !isValidRegex(value))) {
|
|
229
|
+
(0, _unset.default)(schema, path);
|
|
230
|
+
}
|
|
231
|
+
} // Inline $refs inside definitions that use discriminator
|
|
232
|
+
// https://github.com/ajv-validator/ajv/issues/1899
|
|
210
233
|
|
|
211
|
-
if (obj && typeof obj === 'object') {
|
|
212
|
-
const result = {};
|
|
213
234
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
235
|
+
if (key === 'oneOf' && (0, _isArray.default)(value)) {
|
|
236
|
+
if ((0, _isObject.default)(parent.discriminator) && path[0] === 'definitions') {
|
|
237
|
+
for (const [index, subschema] of value.entries()) {
|
|
238
|
+
if (subschema.$ref) {
|
|
239
|
+
(0, _set.default)(schema, [...path, index], (0, _get.default)(schema, subschema.$ref.substr(2).split('/')));
|
|
240
|
+
}
|
|
217
241
|
}
|
|
218
242
|
}
|
|
219
|
-
|
|
220
|
-
return result;
|
|
221
243
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
return normalize(schema);
|
|
244
|
+
});
|
|
245
|
+
return schema;
|
|
227
246
|
}
|
|
228
247
|
|
|
229
248
|
function createSchemaValidator(schema, metaSchemas = [], options = {}) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@takeshape/json-schema",
|
|
3
|
-
"version": "8.87.
|
|
3
|
+
"version": "8.87.1",
|
|
4
4
|
"description": "JSON Schema validator",
|
|
5
5
|
"homepage": "https://www.takeshape.io",
|
|
6
6
|
"repository": {
|
|
@@ -20,8 +20,9 @@
|
|
|
20
20
|
"es"
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"
|
|
24
|
-
"ajv
|
|
23
|
+
"@takeshape/util": "8.87.1",
|
|
24
|
+
"ajv": "^8.10.0",
|
|
25
|
+
"ajv-formats": "^2.1.1",
|
|
25
26
|
"lodash": "^4.17.21"
|
|
26
27
|
},
|
|
27
28
|
"devDependencies": {
|