1 |
|
2 | type StrictNullChecksWrapper<Name extends string, Type> = undefined extends null
|
3 | ? `strictNullChecks must be true in tsconfig to use ${Name}`
|
4 | : Type
|
5 |
|
6 | type UnionToIntersection<U> = (U extends any ? (_: U) => void : never) extends (_: infer I) => void
|
7 | ? I
|
8 | : never
|
9 |
|
10 | export type SomeJSONSchema = UncheckedJSONSchemaType<Known, true>
|
11 |
|
12 | type UncheckedPartialSchema<T> = Partial<UncheckedJSONSchemaType<T, true>>
|
13 |
|
14 | export type PartialSchema<T> = StrictNullChecksWrapper<"PartialSchema", UncheckedPartialSchema<T>>
|
15 |
|
16 | type JSONType<T extends string, IsPartial extends boolean> = IsPartial extends true
|
17 | ? T | undefined
|
18 | : T
|
19 |
|
20 | interface NumberKeywords {
|
21 | minimum?: number
|
22 | maximum?: number
|
23 | exclusiveMinimum?: number
|
24 | exclusiveMaximum?: number
|
25 | multipleOf?: number
|
26 | format?: string
|
27 | }
|
28 |
|
29 | interface StringKeywords {
|
30 | minLength?: number
|
31 | maxLength?: number
|
32 | pattern?: string
|
33 | format?: string
|
34 | }
|
35 |
|
36 | type UncheckedJSONSchemaType<T, IsPartial extends boolean> = (
|
37 | |
|
38 | {
|
39 | anyOf: readonly UncheckedJSONSchemaType<T, IsPartial>[]
|
40 | }
|
41 | | {
|
42 | oneOf: readonly UncheckedJSONSchemaType<T, IsPartial>[]
|
43 | }
|
44 |
|
45 | | ({
|
46 | type: readonly (T extends number
|
47 | ? JSONType<"number" | "integer", IsPartial>
|
48 | : T extends string
|
49 | ? JSONType<"string", IsPartial>
|
50 | : T extends boolean
|
51 | ? JSONType<"boolean", IsPartial>
|
52 | : never)[]
|
53 | } & UnionToIntersection<
|
54 | T extends number
|
55 | ? NumberKeywords
|
56 | : T extends string
|
57 | ? StringKeywords
|
58 | : T extends boolean
|
59 | ?
|
60 | {}
|
61 | : never
|
62 | >)
|
63 |
|
64 | | ((T extends number
|
65 | ? {
|
66 | type: JSONType<"number" | "integer", IsPartial>
|
67 | } & NumberKeywords
|
68 | : T extends string
|
69 | ? {
|
70 | type: JSONType<"string", IsPartial>
|
71 | } & StringKeywords
|
72 | : T extends boolean
|
73 | ? {
|
74 | type: JSONType<"boolean", IsPartial>
|
75 | }
|
76 | : T extends readonly [any, ...any[]]
|
77 | ? {
|
78 |
|
79 | type: JSONType<"array", IsPartial>
|
80 | items: {
|
81 | readonly [K in keyof T]-?: UncheckedJSONSchemaType<T[K], false> & Nullable<T[K]>
|
82 | } & {length: T["length"]}
|
83 | minItems: T["length"]
|
84 | } & ({maxItems: T["length"]} | {additionalItems: false})
|
85 | : T extends readonly any[]
|
86 | ? {
|
87 | type: JSONType<"array", IsPartial>
|
88 | items: UncheckedJSONSchemaType<T[0], false>
|
89 | contains?: UncheckedPartialSchema<T[0]>
|
90 | minItems?: number
|
91 | maxItems?: number
|
92 | minContains?: number
|
93 | maxContains?: number
|
94 | uniqueItems?: true
|
95 | additionalItems?: never
|
96 | }
|
97 | : T extends Record<string, any>
|
98 | ? {
|
99 |
|
100 |
|
101 |
|
102 |
|
103 | type: JSONType<"object", IsPartial>
|
104 | additionalProperties?: boolean | UncheckedJSONSchemaType<T[string], false>
|
105 | unevaluatedProperties?: boolean | UncheckedJSONSchemaType<T[string], false>
|
106 | properties?: IsPartial extends true
|
107 | ? Partial<UncheckedPropertiesSchema<T>>
|
108 | : UncheckedPropertiesSchema<T>
|
109 | patternProperties?: Record<string, UncheckedJSONSchemaType<T[string], false>>
|
110 | propertyNames?: Omit<UncheckedJSONSchemaType<string, false>, "type"> & {type?: "string"}
|
111 | dependencies?: {[K in keyof T]?: Readonly<(keyof T)[]> | UncheckedPartialSchema<T>}
|
112 | dependentRequired?: {[K in keyof T]?: Readonly<(keyof T)[]>}
|
113 | dependentSchemas?: {[K in keyof T]?: UncheckedPartialSchema<T>}
|
114 | minProperties?: number
|
115 | maxProperties?: number
|
116 | } & (IsPartial extends true
|
117 | ? {required: Readonly<(keyof T)[]>}
|
118 | : [UncheckedRequiredMembers<T>] extends [never]
|
119 | ? {required?: Readonly<UncheckedRequiredMembers<T>[]>}
|
120 | : {required: Readonly<UncheckedRequiredMembers<T>[]>})
|
121 | : T extends null
|
122 | ? {
|
123 | type: JSONType<"null", IsPartial>
|
124 | nullable: true
|
125 | }
|
126 | : never) & {
|
127 | allOf?: Readonly<UncheckedPartialSchema<T>[]>
|
128 | anyOf?: Readonly<UncheckedPartialSchema<T>[]>
|
129 | oneOf?: Readonly<UncheckedPartialSchema<T>[]>
|
130 | if?: UncheckedPartialSchema<T>
|
131 | then?: UncheckedPartialSchema<T>
|
132 | else?: UncheckedPartialSchema<T>
|
133 | not?: UncheckedPartialSchema<T>
|
134 | })
|
135 | ) & {
|
136 | [keyword: string]: any
|
137 | $id?: string
|
138 | $ref?: string
|
139 | $defs?: Record<string, UncheckedJSONSchemaType<Known, true>>
|
140 | definitions?: Record<string, UncheckedJSONSchemaType<Known, true>>
|
141 | }
|
142 |
|
143 | export type JSONSchemaType<T> = StrictNullChecksWrapper<
|
144 | "JSONSchemaType",
|
145 | UncheckedJSONSchemaType<T, false>
|
146 | >
|
147 |
|
148 | type Known =
|
149 | | {[key: string]: Known}
|
150 | | [Known, ...Known[]]
|
151 | | Known[]
|
152 | | number
|
153 | | string
|
154 | | boolean
|
155 | | null
|
156 |
|
157 | type UncheckedPropertiesSchema<T> = {
|
158 | [K in keyof T]-?: (UncheckedJSONSchemaType<T[K], false> & Nullable<T[K]>) | {$ref: string}
|
159 | }
|
160 |
|
161 | export type PropertiesSchema<T> = StrictNullChecksWrapper<
|
162 | "PropertiesSchema",
|
163 | UncheckedPropertiesSchema<T>
|
164 | >
|
165 |
|
166 | type UncheckedRequiredMembers<T> = {
|
167 | [K in keyof T]-?: undefined extends T[K] ? never : K
|
168 | }[keyof T]
|
169 |
|
170 | export type RequiredMembers<T> = StrictNullChecksWrapper<
|
171 | "RequiredMembers",
|
172 | UncheckedRequiredMembers<T>
|
173 | >
|
174 |
|
175 | type Nullable<T> = undefined extends T
|
176 | ? {
|
177 | nullable: true
|
178 | const?: null
|
179 | enum?: Readonly<(T | null)[]>
|
180 | default?: T | null
|
181 | }
|
182 | : {
|
183 | const?: T
|
184 | enum?: Readonly<T[]>
|
185 | default?: T
|
186 | }
|