1
>
/*---------------------------------------------------------------------------------------------
jsonSchema.ts
2
>
* Copyright (c) Microsoft Corporation. All rights reserved.
3
>
* Licensed under the MIT License. See License.txt in the project root for license information.
4
>
*--------------------------------------------------------------------------------------------*/
5
>
6
>
export type JSONSchemaType = 'string' | 'number' | 'integer' | 'boolean' | 'null' | 'array' | 'object';
7
>
8
>
export interface IJSONSchema {
9
>
id?: string;
10
>
$id?: string;
11
>
$schema?: string;
12
>
type?: JSONSchemaType | JSONSchemaType[];
13
>
title?: string;
14
>
default?: any;
15
>
definitions?: IJSONSchemaMap;
16
>
description?: string;
17
>
properties?: IJSONSchemaMap;
18
>
patternProperties?: IJSONSchemaMap;
19
>
additionalProperties?: boolean | IJSONSchema;
20
>
minProperties?: number;
21
>
maxProperties?: number;
22
>
dependencies?: IJSONSchemaMap | { [prop: string]: string[] };
23
>
items?: IJSONSchema | IJSONSchema[];
24
>
minItems?: number;
25
>
maxItems?: number;
26
>
uniqueItems?: boolean;
27
>
additionalItems?: boolean | IJSONSchema;
28
>
pattern?: string;
29
>
minLength?: number;
30
>
maxLength?: number;
31
>
minimum?: number;
32
>
maximum?: number;
33
>
exclusiveMinimum?: boolean | number;
34
>
exclusiveMaximum?: boolean | number;
35
>
multipleOf?: number;
36
>
required?: string[];
37
>
$ref?: string;
38
>
anyOf?: IJSONSchema[];
39
>
allOf?: IJSONSchema[];
40
>
oneOf?: IJSONSchema[];
41
>
not?: IJSONSchema;
42
>
enum?: any[];
43
>
format?: string;
44
>
45
>
// schema draft 06
46
>
const?: any;
47
>
contains?: IJSONSchema;
48
>
propertyNames?: IJSONSchema;
49
>
examples?: any[];
50
>
51
>
// schema draft 07
52
>
$comment?: string;
53
>
if?: IJSONSchema;
54
>
then?: IJSONSchema;
55
>
else?: IJSONSchema;
56
>
57
>
// schema 2019-09
58
>
unevaluatedProperties?: boolean | IJSONSchema;
59
>
unevaluatedItems?: boolean | IJSONSchema;
60
>
minContains?: number;
61
>
maxContains?: number;
62
>
deprecated?: boolean;
63
>
dependentRequired?: { [prop: string]: string[] };
64
>
dependentSchemas?: IJSONSchemaMap;
65
>
$defs?: { [name: string]: IJSONSchema };
66
>
$anchor?: string;
67
>
$recursiveRef?: string;
68
>
$recursiveAnchor?: string;
69
>
$vocabulary?: any;
70
>
71
>
// schema 2020-12
72
>
prefixItems?: IJSONSchema[];
73
>
$dynamicRef?: string;
74
>
$dynamicAnchor?: string;
75
>
76
>
// VSCode extensions
77
>
78
>
defaultSnippets?: IJSONSchemaSnippet[];
79
>
errorMessage?: string;
80
>
patternErrorMessage?: string;
81
>
deprecationMessage?: string;
82
>
markdownDeprecationMessage?: string;
83
>
enumDescriptions?: string[];
84
>
markdownEnumDescriptions?: string[];
85
>
markdownDescription?: string;
86
>
doNotSuggest?: boolean;
87
>
suggestSortText?: string;
88
>
allowComments?: boolean;
89
>
allowTrailingCommas?: boolean;
90
>
secret?: boolean;
91
>
}
92
>
93
>
export interface IJSONSchemaMap {
94
>
[name: string]: IJSONSchema;
95
>
}
96
>
97
>
export interface IJSONSchemaSnippet {
98
>
label?: string;
99
>
description?: string;
100
>
body?: any; // a object that will be JSON stringified
101
>
bodyText?: string; // an already stringified JSON object that can contain new lines (\n) and tabs (\t)
102
>
}
103
>
104
>
/**
105
>
* Converts a basic JSON schema to a TypeScript type.
106
>
*/
107
>
export type TypeFromJsonSchema<T> =
108
>
// enum
109
>
T extends { enum: infer EnumValues }
110
>
? UnionOf<EnumValues>
111
>
112
>
// Object with list of required properties.
113
>
// Values are required or optional based on `required` list.
114
>
: T extends { type: 'object'; properties: infer P; required: infer RequiredList }
115
>
? {
116
>
[K in keyof P]: IsRequired<K, RequiredList> extends true ? TypeFromJsonSchema<P[K]> : TypeFromJsonSchema<P[K]> | undefined;
117
>
} & AdditionalPropertiesType<T>
118
>
119
>
// Object with no required properties.
120
>
// All values are optional
121
>
: T extends { type: 'object'; properties: infer P }
122
>
? { [K in keyof P]: TypeFromJsonSchema<P[K]> | undefined } & AdditionalPropertiesType<T>
123
>
124
>
// Array
125
>
: T extends { type: 'array'; items: infer Items }
126
>
? Items extends [...infer R]
127
>
// If items is an array, we treat it like a tuple
128
>
? { [K in keyof R]: TypeFromJsonSchema<Items[K]> }
129
>
: Array<TypeFromJsonSchema<Items>>
130
>
131
>
// oneOf / anyof
132
>
// These are handled the same way as they both represent a union type.
133
>
// However at the validation level, they have different semantics.
134
>
: T extends { oneOf: infer I }
135
>
? MapSchemaToType<I>
136
>
: T extends { anyOf: infer I }
137
>
? MapSchemaToType<I>
138
>
139
>
// Primitive types
140
>
: T extends { type: infer Type }
141
>
// Basic type
142
>
? Type extends 'string' | 'number' | 'integer' | 'boolean' | 'null'
143
>
? SchemaPrimitiveTypeNameToType<Type>
144
>
// Union of primitive types
145
>
: Type extends [...infer R]
146
>
? UnionOf<{ [K in keyof R]: SchemaPrimitiveTypeNameToType<R[K]> }>
147
>
: never
148
>
149
>
// Fallthrough
150
>
: never;
151
>
152
>
type SchemaPrimitiveTypeNameToType<T> =
153
>
T extends 'string' ? string :
154
>
T extends 'number' | 'integer' ? number :
155
>
T extends 'boolean' ? boolean :
156
>
T extends 'null' ? null :
157
>
never;
158
>
159
>
type UnionOf<T> =
160
>
T extends [infer First, ...infer Rest]
161
>
? First | UnionOf<Rest>
162
>
: never;
163
>
164
>
type IsRequired<K, RequiredList> =
165
>
RequiredList extends []
166
>
? false
167
>
168
>
: RequiredList extends [K, ...infer _]
169
>
? true
170
>
171
>
: RequiredList extends [infer _, ...infer R]
172
>
? IsRequired<K, R>
173
>
174
>
: false;
175
>
176
>
type AdditionalPropertiesType<Schema> =
177
>
Schema extends { additionalProperties: infer AP }
178
>
? AP extends false ? {} : { [key: string]: TypeFromJsonSchema<Schema['additionalProperties']> }
179
>
: {};
180
>
181
>
type MapSchemaToType<T> = T extends [infer First, ...infer Rest]
182
>
? TypeFromJsonSchema<First> | MapSchemaToType<Rest>
183
>
: never;
184
>
185
>
interface Equals { schemas: IJSONSchema[]; id?: string }
186
>
187
>
export function getCompressedContent(schema: IJSONSchema): string {
188
let hasDups = false;
189