UNPKG

16.8 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.selectSchemaType = exports.searchAllSubSchema = exports.setId = exports.getId = exports.getSubSchema = void 0;
4const tslib_1 = require("tslib");
5const JsonPointer = tslib_1.__importStar(require("../jsonPointer"));
6const schemaId_1 = tslib_1.__importDefault(require("./schemaId"));
7const type_1 = require("./type");
8const utils_1 = require("./utils");
9function getSubSchema(rootSchema, pointer, id) {
10 const content = JsonPointer.get(rootSchema.content, JsonPointer.parse(pointer));
11 if (id == null) {
12 const subId = typeof content === 'boolean'
13 ? undefined
14 : getId(rootSchema.type, content);
15 const getParentIds = (s, result) => {
16 result.push(s.id.getAbsoluteId());
17 return s.rootSchema == null
18 ? result
19 : getParentIds(s.rootSchema, result);
20 };
21 if (subId) {
22 id = new schemaId_1.default(subId, getParentIds(rootSchema, []));
23 }
24 else {
25 id = new schemaId_1.default(pointer, getParentIds(rootSchema, []));
26 }
27 }
28 return {
29 type: rootSchema.type,
30 id,
31 content,
32 rootSchema,
33 };
34}
35exports.getSubSchema = getSubSchema;
36const Draft04Id = 'id';
37const Draft07Id = '$id';
38function getId(type, content) {
39 var _a, _b;
40 if ((0, type_1.isJsonSchemaDraft04)(content, type)) {
41 return (_a = content[Draft04Id]) !== null && _a !== void 0 ? _a : '';
42 }
43 else {
44 return (_b = content[Draft07Id]) !== null && _b !== void 0 ? _b : '';
45 }
46}
47exports.getId = getId;
48function setId(type, content, id) {
49 var _a, _b;
50 if ((0, type_1.isJsonSchemaDraft04)(content, type)) {
51 (_a = content[Draft04Id]) !== null && _a !== void 0 ? _a : (content[Draft04Id] = id);
52 }
53 else {
54 (_b = content[Draft07Id]) !== null && _b !== void 0 ? _b : (content[Draft07Id] = id);
55 }
56}
57exports.setId = setId;
58function searchAllSubSchema(schema, onFoundSchema, onFoundReference) {
59 const walkArray = (array, paths, parentIds) => {
60 if (array == null) {
61 return;
62 }
63 array.forEach((item, index) => {
64 walk(item, paths.concat(index.toString()), parentIds);
65 });
66 };
67 const walkObject = (obj, paths, parentIds) => {
68 if (obj == null) {
69 return;
70 }
71 Object.keys(obj).forEach((key) => {
72 const sub = obj[key];
73 if (sub != null) {
74 walk(sub, paths.concat(key), parentIds);
75 }
76 });
77 };
78 const walkMaybeArray = (item, paths, parentIds) => {
79 if (Array.isArray(item)) {
80 walkArray(item, paths, parentIds);
81 }
82 else {
83 walk(item, paths, parentIds);
84 }
85 };
86 const walk = (s, paths, parentIds) => {
87 if (s == null || typeof s !== 'object') {
88 return;
89 }
90 const id = getId(schema.type, s);
91 if (id && typeof id === 'string') {
92 const schemaId = new schemaId_1.default(id, parentIds);
93 const subSchema = {
94 type: schema.type,
95 id: schemaId,
96 content: s,
97 rootSchema: schema,
98 };
99 onFoundSchema(subSchema);
100 parentIds = parentIds.concat([schemaId.getAbsoluteId()]);
101 }
102 if (typeof s.$ref === 'string') {
103 const schemaId = new schemaId_1.default(s.$ref, parentIds);
104 s.$ref = schemaId.getAbsoluteId();
105 onFoundReference(schemaId);
106 }
107 walkArray(s.allOf, paths.concat('allOf'), parentIds);
108 walkArray(s.anyOf, paths.concat('anyOf'), parentIds);
109 walkArray(s.oneOf, paths.concat('oneOf'), parentIds);
110 walk(s.not, paths.concat('not'), parentIds);
111 walkMaybeArray(s.items, paths.concat('items'), parentIds);
112 walk(s.additionalItems, paths.concat('additionalItems'), parentIds);
113 walk(s.additionalProperties, paths.concat('additionalProperties'), parentIds);
114 walkObject(s.definitions, paths.concat('definitions'), parentIds);
115 walkObject(s.properties, paths.concat('properties'), parentIds);
116 walkObject(s.patternProperties, paths.concat('patternProperties'), parentIds);
117 walkMaybeArray(s.dependencies, paths.concat('dependencies'), parentIds);
118 if (schema.type === 'Draft07') {
119 if ('propertyNames' in s) {
120 walk(s.propertyNames, paths.concat('propertyNames'), parentIds);
121 walk(s.contains, paths.concat('contains'), parentIds);
122 walk(s.if, paths.concat('if'), parentIds);
123 walk(s.then, paths.concat('then'), parentIds);
124 walk(s.else, paths.concat('else'), parentIds);
125 }
126 }
127 };
128 function searchOpenApiSubSchema(openApi) {
129 function createId(paths) {
130 return '#/' + paths.join('/');
131 }
132 function convertKeyToTypeName(key) {
133 key = key.replace(/\/(.)/g, (_match, p1) => {
134 return p1.toUpperCase();
135 });
136 return key
137 .replace(/}/g, '')
138 .replace(/{/g, '$')
139 .replace(/^\//, '')
140 .replace(/[^0-9A-Za-z_$]+/g, '_');
141 }
142 function setSubIdToAnyObject(f, obj, keys) {
143 if (obj == null) {
144 return;
145 }
146 Object.keys(obj).forEach((key) => {
147 const item = obj[key];
148 if (item != null) {
149 f(item, keys.concat(convertKeyToTypeName(key)));
150 }
151 });
152 }
153 function setSubIdToParameterObject(obj, keys) {
154 if (obj == null) {
155 return;
156 }
157 addParameterSchema(Object.entries(obj), keys);
158 }
159 function setSubIdToParameters(array, keys) {
160 if (array == null) {
161 return;
162 }
163 addParameterSchema(array.map((item, index) => {
164 const key = 'name' in item ? item.name : `${index}`;
165 return [key, item];
166 }), keys);
167 }
168 function addParameterSchema(input, keys) {
169 const map = new Map();
170 const pushItem = (key, po) => {
171 let work = map.get(key);
172 if (work == null) {
173 work = [];
174 map.set(key, work);
175 }
176 work.push(po);
177 };
178 for (const [key, item] of input) {
179 if ('schema' in item) {
180 setSubId(item.schema, keys.concat(key));
181 pushItem(item.in, [key, item]);
182 }
183 if ('content' in item) {
184 setSubIdToMediaTypes(item.content, keys.concat(key));
185 pushItem(item.in, [key, item]);
186 }
187 if ('$ref' in item) {
188 setSubId(item, keys.concat(key));
189 }
190 if ('type' in item && item.in !== undefined) {
191 setSubId(item, keys.concat(key));
192 pushItem(item.in, [key, item]);
193 }
194 }
195 for (const [key, params] of map) {
196 const [paths, obj] = buildParameterSchema(key, params, keys);
197 setSubId(obj, paths);
198 }
199 }
200 function buildParameterSchema(inType, params, keys) {
201 const paths = keys
202 .slice(0, keys.length - 1)
203 .concat(inType + 'Parameters');
204 const properties = {};
205 params.forEach(([key, _]) => {
206 properties[key] = {
207 $ref: createId(keys.concat(key)),
208 };
209 });
210 return [
211 paths,
212 {
213 id: createId(paths),
214 type: 'object',
215 properties,
216 required: params
217 .filter(([_, item]) => item.required === true)
218 .map(([_, item]) => item.name),
219 },
220 ];
221 }
222 const setSubIdToResponsesV2 = (responses, keys) => setSubIdToAnyObject(setSubIdToResponseV2, responses, keys);
223 function setSubIdToResponseV2(response, keys) {
224 if (response == null) {
225 return;
226 }
227 if ('schema' in response) {
228 const s = response.schema;
229 if (s != null && s.type === 'file') {
230 return;
231 }
232 setSubId(s, keys);
233 }
234 }
235 function setSubIdToOperationV2(ops, keys) {
236 if (ops == null) {
237 return;
238 }
239 const operationId = ops.operationId;
240 if (operationId) {
241 keys = [keys[0], convertKeyToTypeName(operationId)];
242 }
243 setSubIdToParameters(ops.parameters, keys.concat('parameters'));
244 setSubIdToResponsesV2(ops.responses, keys.concat('responses'));
245 }
246 const setSubIdToPathsV2 = (paths, keys) => setSubIdToAnyObject(setSubIdToPathItemV2, paths, keys);
247 function setSubIdToPathItemV2(pathItem, keys) {
248 setSubIdToParameters(pathItem.parameters, keys.concat('parameters'));
249 setSubIdToOperationV2(pathItem.get, keys.concat('get'));
250 setSubIdToOperationV2(pathItem.put, keys.concat('put'));
251 setSubIdToOperationV2(pathItem.post, keys.concat('post'));
252 setSubIdToOperationV2(pathItem.delete, keys.concat('delete'));
253 setSubIdToOperationV2(pathItem.options, keys.concat('options'));
254 setSubIdToOperationV2(pathItem.head, keys.concat('head'));
255 setSubIdToOperationV2(pathItem.patch, keys.concat('patch'));
256 }
257 function setSubIdToMediaTypes(types, keys) {
258 if (types == null) {
259 return;
260 }
261 for (const mime of Object.keys(types)) {
262 if ((0, utils_1.checkValidMIMEType)(mime)) {
263 const mt = types[mime];
264 if (mt != null) {
265 setSubId(mt.schema, keys);
266 }
267 }
268 }
269 }
270 const setSubIdToRequestBodies = (bodies, keys) => setSubIdToAnyObject(setSubIdToRequestBody, bodies, keys);
271 function setSubIdToRequestBody(body, keys) {
272 if (body == null) {
273 return;
274 }
275 if ('content' in body) {
276 setSubIdToMediaTypes(body.content, keys);
277 }
278 else if ('$ref' in body) {
279 setSubId(body, keys);
280 }
281 else {
282 setSubId({ type: 'object' }, keys);
283 }
284 }
285 const setSubIdToResponsesV3 = (responses, keys) => setSubIdToAnyObject(setSubIdToResponseV3, responses, keys);
286 function setSubIdToResponseV3(response, keys) {
287 if (response == null) {
288 return;
289 }
290 if ('content' in response) {
291 setSubIdToMediaTypes(response.content, keys);
292 }
293 else if ('$ref' in response) {
294 setSubId(response, keys);
295 }
296 else {
297 setSubId({ type: 'object' }, keys);
298 }
299 }
300 function setSubIdToOperationV3(ops, keys) {
301 if (ops == null) {
302 return;
303 }
304 const operationId = ops.operationId;
305 if (operationId) {
306 keys = [keys[0], convertKeyToTypeName(operationId)];
307 }
308 setSubIdToParameters(ops.parameters, keys.concat('parameters'));
309 setSubIdToRequestBody(ops.requestBody, keys.concat('requestBody'));
310 setSubIdToResponsesV3(ops.responses, keys.concat('responses'));
311 }
312 const setSubIdToPathsV3 = (paths, keys) => setSubIdToAnyObject(setSubIdToPathItemV3, paths, keys);
313 function setSubIdToPathItemV3(pathItem, keys) {
314 setSubIdToParameters(pathItem.parameters, keys.concat('parameters'));
315 setSubIdToOperationV3(pathItem.get, keys.concat('get'));
316 setSubIdToOperationV3(pathItem.put, keys.concat('put'));
317 setSubIdToOperationV3(pathItem.post, keys.concat('post'));
318 setSubIdToOperationV3(pathItem.delete, keys.concat('delete'));
319 setSubIdToOperationV3(pathItem.options, keys.concat('options'));
320 setSubIdToOperationV3(pathItem.head, keys.concat('head'));
321 setSubIdToOperationV3(pathItem.patch, keys.concat('patch'));
322 setSubIdToOperationV3(pathItem.trace, keys.concat('trace'));
323 }
324 function setSubIdToObject(obj, paths) {
325 if (obj == null) {
326 return;
327 }
328 Object.keys(obj).forEach((key) => {
329 const sub = obj[key];
330 setSubId(sub, paths.concat(key));
331 });
332 }
333 function setSubId(s, paths) {
334 switch (typeof s) {
335 case 'object': {
336 const id = createId(paths);
337 setId(schema.type, s, id);
338 walk(s, paths, []);
339 break;
340 }
341 case 'boolean': {
342 const id = createId(paths);
343 const schemaId = new schemaId_1.default(id, []);
344 const subSchema = {
345 type: schema.type,
346 id: schemaId,
347 content: s,
348 rootSchema: schema,
349 };
350 onFoundSchema(subSchema);
351 break;
352 }
353 }
354 }
355 if ('swagger' in openApi) {
356 setSubIdToObject(openApi.definitions, ['definitions']);
357 setSubIdToParameterObject(openApi.parameters, ['parameters']);
358 setSubIdToResponsesV2(openApi.responses, ['responses']);
359 setSubIdToPathsV2(openApi.paths, ['paths']);
360 }
361 else {
362 if (openApi.components) {
363 const components = openApi.components;
364 setSubIdToObject(components.schemas, ['components', 'schemas']);
365 setSubIdToResponsesV3(components.responses, [
366 'components',
367 'responses',
368 ]);
369 setSubIdToParameterObject(components.parameters, [
370 'components',
371 'parameters',
372 ]);
373 setSubIdToRequestBodies(components.requestBodies, [
374 'components',
375 'requestBodies',
376 ]);
377 }
378 setSubIdToPathsV3(openApi.paths, ['paths']);
379 }
380 }
381 if (schema.openApiVersion != null) {
382 const obj = schema.content;
383 searchOpenApiSubSchema(obj);
384 return;
385 }
386 walk(schema.content, ['#'], []);
387}
388exports.searchAllSubSchema = searchAllSubSchema;
389function selectSchemaType(content) {
390 var _a;
391 if (typeof content === 'boolean') {
392 return { type: 'Draft07' };
393 }
394 if (typeof content !== 'object') {
395 throw new Error(`expect parameter of type object, received ${typeof content}`);
396 }
397 if ('$schema' in content) {
398 const schema = (_a = content.$schema) !== null && _a !== void 0 ? _a : '';
399 if (/^https?:\/\/json-schema.org\/schema#?$/.test(schema)) {
400 return { type: 'Latest' };
401 }
402 const match = /^https?:\/\/json-schema\.org\/(?:draft\/(\d{4}-\d{2})|draft-(\d+))\/schema#?$/.exec(schema);
403 if (match) {
404 if (match[1] != null) {
405 switch (match[1]) {
406 case '2019-09':
407 return { type: '2019-09' };
408 case '2020-12':
409 return { type: '2020-12' };
410 }
411 }
412 const version = Number(match[2]);
413 if (version <= 4) {
414 return { type: 'Draft04' };
415 }
416 else {
417 return { type: 'Draft07' };
418 }
419 }
420 }
421 if ('swagger' in content && content.swagger === '2.0') {
422 return {
423 type: 'Draft04',
424 openApiVersion: 2,
425 };
426 }
427 if ('openapi' in content && content.openapi) {
428 const { openapi } = content;
429 if (/^3\.\d+\.\d+$/.test(openapi)) {
430 return {
431 type: 'Draft07',
432 openApiVersion: 3,
433 };
434 }
435 }
436 return { type: 'Draft04' };
437}
438exports.selectSchemaType = selectSchemaType;