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