@squiz/dx-json-schema-lib 1.79.0 → 1.80.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +6 -0
- package/jest.config.ts +13 -2
- package/lib/JsonSchemaService.d.ts +34 -0
- package/lib/JsonSchemaService.js +140 -0
- package/lib/JsonSchemaService.js.map +1 -0
- package/lib/JsonSchemaService.spec.d.ts +1 -0
- package/lib/JsonSchemaService.spec.js +1807 -0
- package/lib/JsonSchemaService.spec.js.map +1 -0
- package/lib/JsonValidationService.d.ts +11 -33
- package/lib/JsonValidationService.js +43 -194
- package/lib/JsonValidationService.js.map +1 -1
- package/lib/JsonValidationService.spec.js +19 -1800
- package/lib/JsonValidationService.spec.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/jsonTypeResolution/TypeResolver.d.ts +0 -1
- package/lib/jsonTypeResolution/TypeResolver.js +0 -3
- package/lib/jsonTypeResolution/TypeResolver.js.map +1 -1
- package/lib/jsonTypeResolution/TypeResolver.spec.js +10 -0
- package/lib/jsonTypeResolution/TypeResolver.spec.js.map +1 -1
- package/lib/manifest/v1/DxComponentInputSchema.spec.js +18 -0
- package/lib/manifest/v1/DxComponentInputSchema.spec.js.map +1 -1
- package/lib/manifest/v1/DxContentMetaSchema.json +24 -32
- package/lib/manifest/v1/JobV1.d.ts +23 -18
- package/lib/manifest/v1/__test__/schemas/invalidUiMetadata.json +31 -0
- package/lib/manifest/v1/v1.d.ts +23 -18
- package/lib/manifest/v1/v1.spec.js +3 -66
- package/lib/manifest/v1/v1.spec.js.map +1 -1
- package/lib/processValidationResult.d.ts +2 -0
- package/lib/processValidationResult.js +24 -0
- package/lib/processValidationResult.js.map +1 -0
- package/lib/validators/customKeywordValidators.d.ts +2 -0
- package/lib/validators/customKeywordValidators.js +47 -0
- package/lib/validators/customKeywordValidators.js.map +1 -0
- package/lib/validators/customKeywordValidators.spec.d.ts +1 -0
- package/lib/validators/customKeywordValidators.spec.js +100 -0
- package/lib/validators/customKeywordValidators.spec.js.map +1 -0
- package/package.json +1 -1
- package/src/JsonSchemaService.spec.ts +2198 -0
- package/src/JsonSchemaService.ts +159 -0
- package/src/JsonValidationService.spec.ts +26 -2195
- package/src/JsonValidationService.ts +64 -226
- package/src/index.ts +1 -0
- package/src/jsonTypeResolution/TypeResolver.spec.ts +12 -0
- package/src/jsonTypeResolution/TypeResolver.ts +0 -4
- package/src/manifest/v1/DxComponentInputSchema.spec.ts +21 -0
- package/src/manifest/v1/DxContentMetaSchema.json +24 -32
- package/src/manifest/v1/JobV1.ts +23 -23
- package/src/manifest/v1/__test__/schemas/invalidUiMetadata.json +31 -0
- package/src/manifest/v1/v1.spec.ts +3 -73
- package/src/manifest/v1/v1.ts +23 -23
- package/src/processValidationResult.ts +20 -0
- package/src/validators/customKeywordValidators.spec.ts +171 -0
- package/src/validators/customKeywordValidators.ts +53 -0
- package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,159 @@
|
|
1
|
+
import JSONQuery, { Input } from '@sagold/json-query';
|
2
|
+
|
3
|
+
import DxComponentInputSchema from './manifest/v1/DxComponentInputSchema.json';
|
4
|
+
import DxComponentIcons from './manifest/v1/DxComponentIcons.json';
|
5
|
+
import DxContentMetaSchema from './manifest/v1/DxContentMetaSchema.json';
|
6
|
+
import MatrixAssetSchema from './manifest/v1/MatrixAssetSchema.json';
|
7
|
+
|
8
|
+
import Draft07Schema from './manifest/v1/Draft-07.json';
|
9
|
+
|
10
|
+
import JobV1 from './manifest/v1/JobV1.json';
|
11
|
+
import v1 from './manifest/v1/v1.json';
|
12
|
+
import { JSONSchema, Draft } from '@squiz/json-schema-library';
|
13
|
+
|
14
|
+
import { draft07Config } from '@squiz/json-schema-library';
|
15
|
+
import { AnyPrimitiveType, AnyResolvableType, TypeResolver } from './jsonTypeResolution/TypeResolver';
|
16
|
+
import { JsonResolutionError } from './errors/JsonResolutionError';
|
17
|
+
import { processValidationResult } from './processValidationResult';
|
18
|
+
import { defaultConfig } from '.';
|
19
|
+
|
20
|
+
export const ComponentInputMetaSchema: MetaSchemaInput = {
|
21
|
+
root: DxComponentInputSchema,
|
22
|
+
remotes: {
|
23
|
+
'DxComponentInputSchema.json/DxContentMetaSchema.json': DxContentMetaSchema,
|
24
|
+
},
|
25
|
+
};
|
26
|
+
|
27
|
+
export const RenderInputMetaSchema: MetaSchemaInput = {
|
28
|
+
root: Draft07Schema,
|
29
|
+
};
|
30
|
+
|
31
|
+
export const ManifestV1MetaSchema: MetaSchemaInput = {
|
32
|
+
root: v1,
|
33
|
+
remotes: {
|
34
|
+
'DxComponentInputSchema.json/DxContentMetaSchema.json': DxContentMetaSchema,
|
35
|
+
'/DxComponentInputSchema.json': DxComponentInputSchema,
|
36
|
+
'/DxComponentIcons.json': DxComponentIcons,
|
37
|
+
'/MatrixAssetSchema.json': MatrixAssetSchema,
|
38
|
+
'http://json-schema.org/draft-07/schema': Draft07Schema,
|
39
|
+
'http://json-schema.org/draft-07/schema#': Draft07Schema,
|
40
|
+
},
|
41
|
+
};
|
42
|
+
|
43
|
+
export const JobV1MetaSchema: MetaSchemaInput = {
|
44
|
+
root: JobV1,
|
45
|
+
remotes: {
|
46
|
+
'DxComponentInputSchema.json/DxContentMetaSchema.json': DxContentMetaSchema,
|
47
|
+
'/DxComponentInputSchema.json': DxComponentInputSchema,
|
48
|
+
'http://json-schema.org/draft-07/schema': Draft07Schema,
|
49
|
+
'http://json-schema.org/draft-07/schema#': Draft07Schema,
|
50
|
+
},
|
51
|
+
};
|
52
|
+
|
53
|
+
interface MetaSchemaInput {
|
54
|
+
root: JSONSchema;
|
55
|
+
remotes?: Record<string, JSONSchema>;
|
56
|
+
}
|
57
|
+
/**
|
58
|
+
* A service that can be used to validate and resolve JSON against a schema.
|
59
|
+
*/
|
60
|
+
export class JSONSchemaService<P extends AnyPrimitiveType, R extends AnyResolvableType> {
|
61
|
+
schema: Draft;
|
62
|
+
constructor(private typeResolver: TypeResolver<P, R>, metaSchema: MetaSchemaInput) {
|
63
|
+
this.schema = new Draft(
|
64
|
+
{
|
65
|
+
...defaultConfig,
|
66
|
+
resolveRef: (schema, rootSchema) => this.doResolveRef(schema, rootSchema),
|
67
|
+
validate: (core, data, schema, pointer) => defaultConfig.validate(core, data, schema, pointer),
|
68
|
+
resolveOneOf: (core, data, schema, pointer) => defaultConfig.resolveOneOf(core, data, schema, pointer),
|
69
|
+
},
|
70
|
+
metaSchema.root,
|
71
|
+
);
|
72
|
+
|
73
|
+
for (const [key, value] of Object.entries(metaSchema.remotes || {})) {
|
74
|
+
this.schema.addRemoteSchema(key, value);
|
75
|
+
}
|
76
|
+
|
77
|
+
for (const schema of this.typeResolver.validationSchemaDefinitions) {
|
78
|
+
// Please find a better way of doing this.
|
79
|
+
this.schema.addRemoteSchema(`/${schema.title}.json`, schema as JSONSchema);
|
80
|
+
this.schema.addRemoteSchema(`#/${schema.title}.json`, schema as JSONSchema);
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
private doResolveRef(schema: JSONSchema, rootSchema: JSONSchema): JSONSchema {
|
85
|
+
const initialRef = draft07Config.resolveRef(schema, rootSchema);
|
86
|
+
if (!initialRef) return initialRef;
|
87
|
+
if (!this.typeResolver.isPrimitiveType(initialRef.type)) return initialRef;
|
88
|
+
|
89
|
+
const validationSchemas = this.typeResolver.getValidationSchemaForPrimitive(initialRef.type);
|
90
|
+
// All validation schemas are pre-compiled as remote schemas and are referenced below
|
91
|
+
const fullValidationSchema = {
|
92
|
+
oneOf: validationSchemas.map((schema) => ({ $ref: `${schema.title}.json` })),
|
93
|
+
};
|
94
|
+
return this.schema.compileSchema(fullValidationSchema);
|
95
|
+
}
|
96
|
+
|
97
|
+
/**
|
98
|
+
* Validate an input value against a specified schema
|
99
|
+
* @throws {SchemaValidationError} if the input is invalid
|
100
|
+
* @returns true if the input is valid
|
101
|
+
*/
|
102
|
+
public validateInput(input: unknown, inputSchema: JSONSchema = this.schema.rootSchema): true | never {
|
103
|
+
inputSchema = this.schema.compileSchema(inputSchema);
|
104
|
+
const errors = this.schema.validate(input, inputSchema);
|
105
|
+
return processValidationResult(errors);
|
106
|
+
}
|
107
|
+
|
108
|
+
/**
|
109
|
+
* Resolve an input object by replacing all resolvable shapes with their resolved values
|
110
|
+
* @param input any input object which matches the input schema
|
111
|
+
* @param inputSchema a JSONSchema which provides type information about the input object
|
112
|
+
* @returns the input object with all resolvable shapes resolved
|
113
|
+
*/
|
114
|
+
public async resolveInput(input: Input, inputSchema: JSONSchema) {
|
115
|
+
const setters: Array<Promise<(input: Input) => Input>> = [];
|
116
|
+
this.schema.each(
|
117
|
+
input,
|
118
|
+
async (schema, value, pointer) => {
|
119
|
+
// Bug in library for Array item schemas which won't resolve the oneOf schema
|
120
|
+
if (Array.isArray(schema?.oneOf)) {
|
121
|
+
const oldSchema = schema;
|
122
|
+
schema = this.schema.resolveOneOf(value, schema);
|
123
|
+
schema.oneOfSchema = oldSchema;
|
124
|
+
}
|
125
|
+
if (!this.typeResolver.isResolvableSchema(schema)) return;
|
126
|
+
// If its a resolvable schema, it should exist in a oneOf array with other schemas
|
127
|
+
// Including a primitive schema
|
128
|
+
const allPossibleSchemaTitles: Array<string> = schema.oneOfSchema.oneOf.map((o: JSONSchema) =>
|
129
|
+
o.$ref.replace('.json', ''),
|
130
|
+
);
|
131
|
+
|
132
|
+
const primitiveSchema = allPossibleSchemaTitles.find((title) => this.typeResolver.isPrimitiveType(title));
|
133
|
+
if (!primitiveSchema) return;
|
134
|
+
const resolver = this.typeResolver.tryGetResolver(primitiveSchema, schema as any);
|
135
|
+
if (!resolver) return;
|
136
|
+
const setResolvedData = Promise.resolve()
|
137
|
+
.then(() => resolver(value))
|
138
|
+
.then((resolvedData) => (item: typeof input) => JSONQuery.set(item, pointer, resolvedData, 'replace' as any))
|
139
|
+
.catch((e) => Promise.reject(new JsonResolutionError(e, pointer, value)));
|
140
|
+
setters.push(setResolvedData);
|
141
|
+
},
|
142
|
+
inputSchema,
|
143
|
+
);
|
144
|
+
|
145
|
+
const potentialResolutionErrors = [];
|
146
|
+
for (const resolveResult of await Promise.allSettled(setters)) {
|
147
|
+
if (resolveResult.status === 'rejected') {
|
148
|
+
potentialResolutionErrors.push(resolveResult.reason);
|
149
|
+
continue;
|
150
|
+
}
|
151
|
+
|
152
|
+
input = resolveResult.value(input);
|
153
|
+
}
|
154
|
+
if (potentialResolutionErrors.length) {
|
155
|
+
throw new Error(`Error(s) occurred when resolving JSON:\n${potentialResolutionErrors.join('\n')}`);
|
156
|
+
}
|
157
|
+
return input;
|
158
|
+
}
|
159
|
+
}
|