/
index.ts
243 lines (201 loc) · 7.04 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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
import * as URI from "uri-js"
import type {CodeGen, Code, Name, ScopeValueSets, ValueScopeName} from "../compile/codegen"
import type {SchemaEnv, SchemaCxt, SchemaObjCxt} from "../compile"
import type {JSONType} from "../compile/rules"
import type {KeywordCxt} from "../compile/validate"
import type Ajv from "../core"
interface _SchemaObject {
id?: string
$id?: string
$schema?: string
[x: string]: any // TODO
}
export interface SchemaObject extends _SchemaObject {
id?: string
$id?: string
$schema?: string
$async?: false
[x: string]: any // TODO
}
export interface AsyncSchema extends _SchemaObject {
$async: true
}
export type AnySchemaObject = SchemaObject | AsyncSchema
export type Schema = SchemaObject | boolean
export type AnySchema = Schema | AsyncSchema
export type SchemaMap = {[Key in string]?: AnySchema}
export interface SourceCode {
validateName: ValueScopeName
validateCode: string
scopeValues: ScopeValueSets
evaluated?: Code
}
export interface DataValidationCxt<T extends string | number = string | number> {
instancePath: string
parentData: {[K in T]: any} // object or array
parentDataProperty: T // string or number
rootData: Record<string, any> | any[]
dynamicAnchors: {[Ref in string]?: ValidateFunction}
}
export interface ValidateFunction<T = unknown> {
(this: Ajv | any, data: any, dataCxt?: DataValidationCxt): data is T
errors?: null | ErrorObject[]
evaluated?: Evaluated
schema: AnySchema
schemaEnv: SchemaEnv
source?: SourceCode
}
export interface JTDParser<T = unknown> {
(json: string): T | undefined
message?: string
position?: number
}
export type EvaluatedProperties = {[K in string]?: true} | true
export type EvaluatedItems = number | true
export interface Evaluated {
// determined at compile time if staticProps/Items is true
props?: EvaluatedProperties
items?: EvaluatedItems
// whether props/items determined at compile time
dynamicProps: boolean
dynamicItems: boolean
}
export interface AsyncValidateFunction<T = unknown> extends ValidateFunction<T> {
(...args: Parameters<ValidateFunction<T>>): Promise<T>
$async: true
}
export type AnyValidateFunction<T = any> = ValidateFunction<T> | AsyncValidateFunction<T>
export interface ErrorObject<K extends string = string, P = Record<string, any>, S = unknown> {
keyword: K
instancePath: string
schemaPath: string
params: P
// Added to validation errors of "propertyNames" keyword schema
propertyName?: string
// Excluded if option `messages` set to false.
message?: string
// These are added with the `verbose` option.
schema?: S
parentSchema?: AnySchemaObject
data?: unknown
}
export type ErrorNoParams<K extends string, S = unknown> = ErrorObject<K, Record<string, never>, S>
interface _KeywordDef {
keyword: string | string[]
type?: JSONType | JSONType[] // data types that keyword applies to
schemaType?: JSONType | JSONType[] // allowed type(s) of keyword value in the schema
allowUndefined?: boolean // used for keywords that can be invoked by other keywords, not being present in the schema
$data?: boolean // keyword supports [$data reference](../../docs/guide/combining-schemas.md#data-reference)
implements?: string[] // other schema keywords that this keyword implements
before?: string // keyword should be executed before this keyword (should be applicable to the same type)
post?: boolean // keyword should be executed after other keywords without post flag
metaSchema?: AnySchemaObject // meta-schema for keyword schema value - it is better to use schemaType where applicable
validateSchema?: AnyValidateFunction // compiled keyword metaSchema - should not be passed
dependencies?: string[] // keywords that must be present in the same schema
error?: KeywordErrorDefinition
$dataError?: KeywordErrorDefinition
}
export interface CodeKeywordDefinition extends _KeywordDef {
code: (cxt: KeywordCxt, ruleType?: string) => void
trackErrors?: boolean
}
export type MacroKeywordFunc = (
schema: any,
parentSchema: AnySchemaObject,
it: SchemaCxt
) => AnySchema
export type CompileKeywordFunc = (
schema: any,
parentSchema: AnySchemaObject,
it: SchemaObjCxt
) => DataValidateFunction
export interface DataValidateFunction {
(...args: Parameters<ValidateFunction>): boolean | Promise<any>
errors?: Partial<ErrorObject>[]
}
export interface SchemaValidateFunction {
(
schema: any,
data: any,
parentSchema?: AnySchemaObject,
dataCxt?: DataValidationCxt
): boolean | Promise<any>
errors?: Partial<ErrorObject>[]
}
export interface FuncKeywordDefinition extends _KeywordDef {
validate?: SchemaValidateFunction | DataValidateFunction
compile?: CompileKeywordFunc
// schema: false makes validate not to expect schema (DataValidateFunction)
schema?: boolean // requires "validate"
modifying?: boolean
async?: boolean
valid?: boolean
errors?: boolean | "full"
}
export interface MacroKeywordDefinition extends FuncKeywordDefinition {
macro: MacroKeywordFunc
}
export type KeywordDefinition =
| CodeKeywordDefinition
| FuncKeywordDefinition
| MacroKeywordDefinition
export type AddedKeywordDefinition = KeywordDefinition & {
type: JSONType[]
schemaType: JSONType[]
}
export interface KeywordErrorDefinition {
message: string | Code | ((cxt: KeywordErrorCxt) => string | Code)
params?: Code | ((cxt: KeywordErrorCxt) => Code)
}
export type Vocabulary = (KeywordDefinition | string)[]
export interface KeywordErrorCxt {
gen: CodeGen
keyword: string
data: Name
$data?: string | false
schema: any // TODO
parentSchema?: AnySchemaObject
schemaCode: Code | number | boolean
schemaValue: Code | number | boolean
schemaType?: JSONType[]
errsCount?: Name
params: KeywordCxtParams
it: SchemaCxt
}
export type KeywordCxtParams = {[P in string]?: Code | string | number}
export type FormatValidator<T extends string | number> = (data: T) => boolean
export type FormatCompare<T extends string | number> = (data1: T, data2: T) => number | undefined
export type AsyncFormatValidator<T extends string | number> = (data: T) => Promise<boolean>
export interface FormatDefinition<T extends string | number> {
type?: T extends string ? "string" | undefined : "number"
validate: FormatValidator<T> | (T extends string ? string | RegExp : never)
async?: false | undefined
compare?: FormatCompare<T>
}
export interface AsyncFormatDefinition<T extends string | number> {
type?: T extends string ? "string" | undefined : "number"
validate: AsyncFormatValidator<T>
async: true
compare?: FormatCompare<T>
}
export type AddedFormat =
| true
| RegExp
| FormatValidator<string>
| FormatDefinition<string>
| FormatDefinition<number>
| AsyncFormatDefinition<string>
| AsyncFormatDefinition<number>
export type Format = AddedFormat | string
export interface RegExpEngine {
(pattern: string, u: string): RegExpLike
code: string
}
export interface RegExpLike {
test: (s: string) => boolean
}
export interface UriResolver {
parse(uri: string): URI.URIComponents
resolve(base: string, path: string): string
serialize(component: URI.URIComponents): string
}