forked from APIDevTools/json-schema-ref-parser
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathoptions.ts
202 lines (187 loc) · 6.98 KB
/
options.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
import jsonParser from "./parsers/json.js";
import yamlParser from "./parsers/yaml.js";
import textParser from "./parsers/text.js";
import binaryParser from "./parsers/binary.js";
import fileResolver from "./resolvers/file.js";
import httpResolver from "./resolvers/http.js";
import cloneDeep from "lodash.clonedeep";
import type { HTTPResolverOptions, JSONSchemaObject, Plugin, ResolverOptions } from "./types/index.js";
type DeepPartial<T> = T extends object
? {
[P in keyof T]?: DeepPartial<T[P]>;
}
: T;
/**
* Options that determine how JSON schemas are parsed, resolved, and dereferenced.
*
* @param [options] - Overridden options
* @class
*/
interface $RefParserOptions {
/**
* The `parse` options determine how different types of files will be parsed.
*
* JSON Schema `$Ref` Parser comes with built-in JSON, YAML, plain-text, and binary parsers, any of which you can configure or disable. You can also add your own custom parsers if you want.
*/
parse: {
json?: Plugin | boolean;
yaml?: Plugin | boolean;
binary?: Plugin | boolean;
text?: (Plugin & { encoding?: string }) | boolean;
[key: string]: Plugin | boolean | undefined;
};
/**
* The `resolve` options control how JSON Schema $Ref Parser will resolve file paths and URLs, and how those files will be read/downloaded.
*
* JSON Schema `$Ref` Parser comes with built-in support for HTTP and HTTPS, as well as support for local files (when running in Node.js). You can configure or disable either of these built-in resolvers. You can also add your own custom resolvers if you want.
*/
resolve: {
/**
* Determines whether external $ref pointers will be resolved. If this option is disabled, then external `$ref` pointers will simply be ignored.
*/
external?: boolean;
file?: Partial<ResolverOptions> | boolean;
http?: HTTPResolverOptions | boolean;
} & {
[key: string]: Partial<ResolverOptions> | HTTPResolverOptions | boolean | undefined;
};
/**
* By default, JSON Schema $Ref Parser throws the first error it encounters. Setting `continueOnError` to `true`
* causes it to keep processing as much as possible and then throw a single error that contains all errors
* that were encountered.
*/
continueOnError: boolean;
/**
* The `dereference` options control how JSON Schema `$Ref` Parser will dereference `$ref` pointers within the JSON schema.
*/
dereference: {
/**
* Determines whether circular `$ref` pointers are handled.
*
* If set to `false`, then a `ReferenceError` will be thrown if the schema contains any circular references.
*
* If set to `"ignore"`, then circular references will simply be ignored. No error will be thrown, but the `$Refs.circular` property will still be set to `true`.
*/
circular?: boolean | "ignore";
/**
* A function, called for each path, which can return true to stop this path and all
* subpaths from being dereferenced further. This is useful in schemas where some
* subpaths contain literal $ref keys that should not be dereferenced.
*/
excludedPathMatcher?(path: string): boolean;
/**
* Callback invoked during dereferencing.
*
* @argument {string} path The path being dereferenced (ie. the `$ref` string).
* @argument {JSONSchemaObject} object The JSON-Schema that the `$ref` resolved to.
*/
onDereference?(path: string, value: JSONSchemaObject): void;
};
}
const getDefaults = () => {
const defaults = {
/**
* Determines how different types of files will be parsed.
*
* You can add additional parsers of your own, replace an existing one with
* your own implementation, or disable any parser by setting it to false.
*/
parse: {
json: jsonParser,
yaml: yamlParser,
text: textParser,
binary: binaryParser,
},
/**
* Determines how JSON References will be resolved.
*
* You can add additional resolvers of your own, replace an existing one with
* your own implementation, or disable any resolver by setting it to false.
*/
resolve: {
file: fileResolver,
http: httpResolver,
/**
* Determines whether external $ref pointers will be resolved.
* If this option is disabled, then none of above resolvers will be called.
* Instead, external $ref pointers will simply be ignored.
*
* @type {boolean}
*/
external: true,
},
/**
* By default, JSON Schema $Ref Parser throws the first error it encounters. Setting `continueOnError` to `true`
* causes it to keep processing as much as possible and then throw a single error that contains all errors
* that were encountered.
*/
continueOnError: false,
/**
* Determines the types of JSON references that are allowed.
*/
dereference: {
/**
* Dereference circular (recursive) JSON references?
* If false, then a {@link ReferenceError} will be thrown if a circular reference is found.
* If "ignore", then circular references will not be dereferenced.
*
* @type {boolean|string}
*/
circular: true,
/**
* A function, called for each path, which can return true to stop this path and all
* subpaths from being dereferenced further. This is useful in schemas where some
* subpaths contain literal $ref keys that should not be dereferenced.
*
* @type {function}
*/
excludedPathMatcher: () => false,
},
};
return cloneDeep(defaults);
};
export const getNewOptions = (options: DeepPartial<$RefParserOptions>): $RefParserOptions => {
const newOptions = getDefaults();
if (options) {
merge(newOptions, options);
}
return newOptions;
};
export type Options = $RefParserOptions;
export type ParserOptions = DeepPartial<$RefParserOptions>;
/**
* Merges the properties of the source object into the target object.
*
* @param target - The object that we're populating
* @param source - The options that are being merged
* @returns
*/
function merge(target: any, source: any) {
if (isMergeable(source)) {
const keys = Object.keys(source);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const sourceSetting = source[key];
const targetSetting = target[key];
if (isMergeable(sourceSetting)) {
// It's a nested object, so merge it recursively
target[key] = merge(targetSetting || {}, sourceSetting);
} else if (sourceSetting !== undefined) {
// It's a scalar value, function, or array. No merging necessary. Just overwrite the target value.
target[key] = sourceSetting;
}
}
}
return target;
}
/**
* Determines whether the given value can be merged,
* or if it is a scalar value that should just override the target value.
*
* @param val
* @returns
*/
function isMergeable(val: any) {
return val && typeof val === "object" && !Array.isArray(val) && !(val instanceof RegExp) && !(val instanceof Date);
}
export default $RefParserOptions;