massive update, probably broken
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / table / node_modules / ajv / lib / types / jtd-schema.ts
1 /** numeric strings */
2 type NumberType = "float32" | "float64" | "int8" | "uint8" | "int16" | "uint16" | "int32" | "uint32"
3
4 /** string strings */
5 type StringType = "string" | "timestamp"
6
7 /** Generic JTD Schema without inference of the represented type */
8 export type SomeJTDSchemaType = (
9   | // ref
10   {ref: string}
11   // primitives
12   | {type: NumberType | StringType | "boolean"}
13   // enum
14   | {enum: string[]}
15   // elements
16   | {elements: SomeJTDSchemaType}
17   // values
18   | {values: SomeJTDSchemaType}
19   // properties
20   | {
21       properties: Record<string, SomeJTDSchemaType>
22       optionalProperties?: Record<string, SomeJTDSchemaType>
23       additionalProperties?: boolean
24     }
25   | {
26       properties?: Record<string, SomeJTDSchemaType>
27       optionalProperties: Record<string, SomeJTDSchemaType>
28       additionalProperties?: boolean
29     }
30   // discriminator
31   | {discriminator: string; mapping: Record<string, SomeJTDSchemaType>}
32   // empty
33   // NOTE see the end of
34   // https://github.com/typescript-eslint/typescript-eslint/issues/2063#issuecomment-675156492
35   // eslint-disable-next-line @typescript-eslint/ban-types
36   | {}
37 ) & {
38   nullable?: boolean
39   metadata?: Record<string, unknown>
40   definitions?: Record<string, SomeJTDSchemaType>
41 }
42
43 /** required keys of an object, not undefined */
44 type RequiredKeys<T> = {
45   [K in keyof T]-?: undefined extends T[K] ? never : K
46 }[keyof T]
47
48 /** optional or undifined-able keys of an object */
49 type OptionalKeys<T> = {
50   [K in keyof T]-?: undefined extends T[K] ? K : never
51 }[keyof T]
52
53 /** type is true if T is a union type */
54 type IsUnion_<T, U extends T = T> = false extends (
55   T extends unknown ? ([U] extends [T] ? false : true) : never
56 )
57   ? false
58   : true
59 type IsUnion<T> = IsUnion_<T>
60
61 /** type is true if T is identically E */
62 type TypeEquality<T, E> = [T] extends [E] ? ([E] extends [T] ? true : false) : false
63
64 /** type is true if T or null is identically E or null*/
65 type NullTypeEquality<T, E> = TypeEquality<T | null, E | null>
66
67 /** gets only the string literals of a type or null if a type isn't a string literal */
68 type EnumString<T> = [T] extends [never]
69   ? null
70   : T extends string
71   ? string extends T
72     ? null
73     : T
74   : null
75
76 /** true if type is a union of string literals */
77 type IsEnum<T> = null extends EnumString<Exclude<T, null>> ? false : true
78
79 /** true only if all types are array types (not tuples) */
80 // NOTE relies on the fact that tuples don't have an index at 0.5, but arrays
81 // have an index at every number
82 type IsElements<T> = false extends IsUnion<T>
83   ? [T] extends [readonly unknown[]]
84     ? undefined extends T[0.5]
85       ? false
86       : true
87     : false
88   : false
89
90 /** true if the the type is a values type */
91 type IsValues<T> = false extends IsUnion<Exclude<T, null>>
92   ? TypeEquality<keyof Exclude<T, null>, string>
93   : false
94
95 /** true if type is a proeprties type and Union is false, or type is a discriminator type and Union is true */
96 type IsRecord<T, Union extends boolean> = Union extends IsUnion<Exclude<T, null>>
97   ? null extends EnumString<keyof Exclude<T, null>>
98     ? false
99     : true
100   : false
101
102 /** actual schema */
103 export type JTDSchemaType<T, D extends Record<string, unknown> = Record<string, never>> = (
104   | // refs - where null wasn't specified, must match exactly
105   (null extends EnumString<keyof D>
106       ? never
107       :
108           | ({[K in keyof D]: [T] extends [D[K]] ? {ref: K} : never}[keyof D] & {nullable?: false})
109           // nulled refs - if ref is nullable and nullable is specified, then it can
110           // match either null or non-null definitions
111           | (null extends T
112               ? {
113                   [K in keyof D]: [Exclude<T, null>] extends [Exclude<D[K], null>]
114                     ? {ref: K}
115                     : never
116                 }[keyof D] & {nullable: true}
117               : never))
118   // empty - empty schemas also treat nullable differently in that it's now fully ignored
119   | (unknown extends T ? {nullable?: boolean} : never)
120   // all other types
121   | ((// numbers - only accepts the type number
122     true extends NullTypeEquality<T, number>
123       ? {type: NumberType}
124       : // booleans - accepts the type boolean
125       true extends NullTypeEquality<T, boolean>
126       ? {type: "boolean"}
127       : // strings - only accepts the type string
128       true extends NullTypeEquality<T, string>
129       ? {type: StringType}
130       : // strings - only accepts the type Date
131       true extends NullTypeEquality<T, Date>
132       ? {type: "timestamp"}
133       : // enums - only accepts union of string literals
134       // TODO we can't actually check that everything in the union was specified
135       true extends IsEnum<T>
136       ? {enum: EnumString<Exclude<T, null>>[]}
137       : // arrays - only accepts arrays, could be array of unions to be resolved later
138       true extends IsElements<Exclude<T, null>>
139       ? T extends readonly (infer E)[]
140         ? {
141             elements: JTDSchemaType<E, D>
142           }
143         : never
144       : // values
145       true extends IsValues<T>
146       ? T extends Record<string, infer V>
147         ? {
148             values: JTDSchemaType<V, D>
149           }
150         : never
151       : // properties
152       true extends IsRecord<T, false>
153       ? ([RequiredKeys<Exclude<T, null>>] extends [never]
154           ? {
155               properties?: Record<string, never>
156             }
157           : {
158               properties: {[K in RequiredKeys<T>]: JTDSchemaType<T[K], D>}
159             }) &
160           ([OptionalKeys<Exclude<T, null>>] extends [never]
161             ? {
162                 optionalProperties?: Record<string, never>
163               }
164             : {
165                 optionalProperties: {
166                   [K in OptionalKeys<T>]: JTDSchemaType<Exclude<T[K], undefined>, D>
167                 }
168               }) & {
169             additionalProperties?: boolean
170           }
171       : // discriminator
172       true extends IsRecord<T, true>
173       ? {
174           [K in keyof Exclude<T, null>]-?: Exclude<T, null>[K] extends string
175             ? {
176                 discriminator: K
177                 mapping: {
178                   // TODO currently allows descriminator to be present in schema
179                   [M in Exclude<T, null>[K]]: JTDSchemaType<
180                     Omit<T extends {[C in K]: M} ? T : never, K>,
181                     D
182                   >
183                 }
184               }
185             : never
186         }[keyof Exclude<T, null>]
187       : never) &
188       (null extends T
189         ? {
190             nullable: true
191           }
192         : {nullable?: false}))
193 ) & {
194   // extra properties
195   metadata?: Record<string, unknown>
196   // TODO these should only be allowed at the top level
197   definitions?: {[K in keyof D]: JTDSchemaType<D[K], D>}
198 }
199
200 type JTDDataDef<S, D extends Record<string, unknown>> =
201   | (// ref
202     S extends {ref: string}
203       ? D extends {[K in S["ref"]]: infer V}
204         ? JTDDataDef<V, D>
205         : never
206       : // type
207       S extends {type: NumberType}
208       ? number
209       : S extends {type: "boolean"}
210       ? boolean
211       : S extends {type: "string"}
212       ? string
213       : S extends {type: "timestamp"}
214       ? string | Date
215       : // enum
216       S extends {enum: readonly (infer E)[]}
217       ? string extends E
218         ? never
219         : [E] extends [string]
220         ? E
221         : never
222       : // elements
223       S extends {elements: infer E}
224       ? JTDDataDef<E, D>[]
225       : // properties
226       S extends {
227           properties: Record<string, unknown>
228           optionalProperties?: Record<string, unknown>
229           additionalProperties?: boolean
230         }
231       ? {-readonly [K in keyof S["properties"]]-?: JTDDataDef<S["properties"][K], D>} & {
232           -readonly [K in keyof S["optionalProperties"]]+?: JTDDataDef<
233             S["optionalProperties"][K],
234             D
235           >
236         } & ([S["additionalProperties"]] extends [true] ? Record<string, unknown> : unknown)
237       : S extends {
238           properties?: Record<string, unknown>
239           optionalProperties: Record<string, unknown>
240           additionalProperties?: boolean
241         }
242       ? {-readonly [K in keyof S["properties"]]-?: JTDDataDef<S["properties"][K], D>} & {
243           -readonly [K in keyof S["optionalProperties"]]+?: JTDDataDef<
244             S["optionalProperties"][K],
245             D
246           >
247         } & ([S["additionalProperties"]] extends [true] ? Record<string, unknown> : unknown)
248       : // values
249       S extends {values: infer V}
250       ? Record<string, JTDDataDef<V, D>>
251       : // discriminator
252       S extends {discriminator: infer M; mapping: Record<string, unknown>}
253       ? [M] extends [string]
254         ? {
255             [K in keyof S["mapping"]]: JTDDataDef<S["mapping"][K], D> & {[KM in M]: K}
256           }[keyof S["mapping"]]
257         : never
258       : // empty
259         unknown)
260   | (S extends {nullable: true} ? null : never)
261
262 export type JTDDataType<S> = S extends {definitions: Record<string, unknown>}
263   ? JTDDataDef<S, S["definitions"]>
264   : JTDDataDef<S, Record<string, never>>