forked from sagold/json-schema-library
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
201 lines (179 loc) · 7.57 KB
/
index.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
import step from "../step";
import validate from "../validate";
import resolveOneOf from "../resolveOneOf.strict";
import resolveRef from "../resolveRef.strict";
import resolveAllOf from "../resolveAllOf";
import resolveAnyOf from "../resolveAnyOf";
import getTemplate, { TemplateOptions } from "../getTemplate";
import getChildSchemaSelection from "../getChildSchemaSelection";
import getSchema from "../getSchema";
import { each, EachCallback } from "../each";
import isValid from "../isValid";
import { eachSchema, EachSchemaCallback } from "../eachSchema";
import createSchemaOf from "../createSchemaOf";
import compileSchema from "../compileSchema";
import { CreateError } from "../utils/createCustomError";
import addRemoteSchema from "../addRemoteSchema";
import { JSONSchema, JSONPointer, JSONValidator, JSONTypeValidator, JSONError } from "../types";
export type DraftConfig = {
/** error creators by id */
errors: Record<string, CreateError>;
/** map for valid keywords of a type */
typeKeywords: Record<string, string[]>;
/** keyword validators */
validateKeyword: Record<string, JSONValidator>;
/** type validators */
validateType: Record<string, JSONTypeValidator>;
/** format validators */
validateFormat: Record<string, JSONValidator>;
addRemoteSchema: typeof addRemoteSchema;
compileSchema: typeof compileSchema;
createSchemaOf: typeof createSchemaOf;
each: typeof each;
eachSchema: typeof eachSchema;
getChildSchemaSelection: typeof getChildSchemaSelection;
getSchema: typeof getSchema;
getTemplate: typeof getTemplate;
isValid: typeof isValid;
resolveAllOf: typeof resolveAllOf;
resolveAnyOf: typeof resolveAnyOf;
resolveOneOf: typeof resolveOneOf;
resolveRef: typeof resolveRef;
step: typeof step;
validate: typeof validate;
};
export class Draft {
readonly config: DraftConfig;
/** entry point of schema */
private __rootSchema: JSONSchema;
/** cache for remote schemas */
remotes: Record<string, JSONSchema> = {};
/** error creators by id */
readonly errors: Record<string, CreateError> = {};
/** map for valid keywords of a type */
readonly typeKeywords: Record<string, string[]> = {};
/** keyword validators */
readonly validateKeyword: Record<string, JSONValidator> = {};
/** type validators */
readonly validateType: Record<string, JSONTypeValidator> = {};
/** format validators */
readonly validateFormat: Record<string, JSONValidator> = {};
constructor(config: DraftConfig, schema?: JSONSchema) {
this.config = config;
this.typeKeywords = JSON.parse(JSON.stringify(config.typeKeywords));
this.validateKeyword = Object.assign({}, config.validateKeyword);
this.validateType = Object.assign({}, config.validateType);
this.validateFormat = Object.assign({}, config.validateFormat);
this.errors = Object.assign({}, config.errors);
this.setSchema(schema);
}
get rootSchema() {
return this.__rootSchema;
}
set rootSchema(rootSchema: JSONSchema) {
if (rootSchema == null) {
return;
}
this.__rootSchema = this.config.compileSchema(this, rootSchema);
}
/**
* register a json-schema to be referenced from another json-schema
* @param url - base-url of json-schema (aka id)
* @param schema - json-schema root
*/
addRemoteSchema(url: string, schema: JSONSchema): void {
this.config.addRemoteSchema(this, url, schema);
}
compileSchema(schema: JSONSchema): JSONSchema {
return this.config.compileSchema(this, schema, this.rootSchema ?? schema);
}
createSchemaOf(data: unknown) {
return this.config.createSchemaOf(data);
}
/**
* Iterates over data, retrieving its schema
*
* @param data - the data to iterate
* @param callback - will be called with (schema, data, pointer) on each item
* @param [schema] - the schema matching the data. Defaults to rootSchema
* @param [pointer] - pointer to current data. Default to rootPointer
*/
each(data: any, callback: EachCallback, schema?: JSONSchema, pointer?: JSONPointer) {
return this.config.each(this, data, callback, schema, pointer);
}
eachSchema(callback: EachSchemaCallback, schema = this.rootSchema) {
return this.config.eachSchema(schema, callback);
}
getChildSchemaSelection(property: string | number, schema?: JSONSchema) {
return this.config.getChildSchemaSelection(this, property, schema);
}
/**
* Returns the json-schema of a data-json-pointer.
* Notes
* - Uses core.step to walk through data and schema
*
* @param pointer - json pointer in data to get the json schema for
* @param [data] - the data object, which includes the json pointers value. This is optional, as
* long as no oneOf, anyOf, etc statement is part of the pointers schema
* @param [schema] - the json schema to iterate. Defaults to core.rootSchema
* @return json schema object of the json-pointer or an error
*/
getSchema(pointer: JSONPointer = "#", data?: any, schema?: JSONSchema): JSONSchema | JSONError {
return this.config.getSchema(this, pointer, data, schema);
}
/**
* Create data object matching the given schema
*
* @param [data] - optional template data
* @param [schema] - json schema, defaults to rootSchema
* @return created template data
*/
getTemplate(data?: unknown, schema?: JSONSchema, opts?: TemplateOptions) {
return this.config.getTemplate(this, data, schema, opts);
}
isValid(data: any, schema?: JSONSchema, pointer?: JSONPointer): boolean {
return this.config.isValid(this, data, schema, pointer);
}
resolveAnyOf(data: any, schema: JSONSchema, pointer?: JSONPointer): JSONSchema {
return this.config.resolveAnyOf(this, data, schema, pointer);
}
resolveAllOf(data: any, schema: JSONSchema, pointer?: JSONPointer): JSONSchema {
return this.config.resolveAllOf(this, data, schema, pointer);
}
resolveRef(schema: JSONSchema): JSONSchema {
return this.config.resolveRef(schema, this.rootSchema);
}
resolveOneOf(data: any, schema: JSONSchema, pointer?: JSONPointer): JSONSchema {
return this.config.resolveOneOf(this, data, schema, pointer);
}
setSchema(schema: JSONSchema) {
this.rootSchema = schema;
}
/**
* Returns the json-schema of the given object property or array item.
* e.g. it steps by one key into the data
*
* This helper determines the location of the property within the schema (additional properties, oneOf, ...) and
* returns the correct schema.
*
* @param key - property-name or array-index
* @param schema - json schema of current data
* @param data - parent of key
* @param [pointer] - pointer to schema and data (parent of key)
* @return Schema or Error if failed resolving key
*/
step(key: string | number, schema: JSONSchema, data: any, pointer?: JSONPointer): JSONSchema {
return this.config.step(this, key, schema, data, pointer);
}
/**
* Validate data by a json schema
*
* @param value - value to validate
* @param [schema] - json schema, defaults to rootSchema
* @param [pointer] - json pointer pointing to value (used for error-messages only)
* @return list of errors or empty
*/
validate(data: unknown, schema?: JSONSchema, pointer?: JSONPointer): JSONError[] {
return this.config.validate(this, data, schema, pointer);
}
}