rapidoc 9.3.7 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +193 -61
- package/dist/rapidoc-min.js +279 -3912
- package/package.json +24 -47
- package/.babelrc.json +0 -42
- package/.eslintrc +0 -53
- package/.github/FUNDING.yml +0 -13
- package/.github/workflow/words.yaml +0 -22
- package/CONTRIBUTING.md +0 -35
- package/dist/index.html +0 -6
- package/dist/index.html.gz +0 -0
- package/dist/rapidoc-min.js.LICENSE.txt +0 -64
- package/dist/rapidoc-min.js.LICENSE.txt.gz +0 -0
- package/dist/rapidoc-min.js.gz +0 -0
- package/dist/rapidoc-min.js.map +0 -1
- package/dist/rapidoc-min.js.map.gz +0 -0
- package/dist/rapidoc.js +0 -21594
- package/dist/report.html +0 -39
- package/index-hashroute.html +0 -65
- package/index.html +0 -249
- package/index1.html +0 -244
- package/jsconfig.json +0 -11
- package/logo.png +0 -0
- package/performance.html +0 -31
- package/src/components/api-request.js +0 -1787
- package/src/components/api-response.js +0 -335
- package/src/components/dialog-box.js +0 -73
- package/src/components/json-tree.js +0 -145
- package/src/components/schema-table.js +0 -358
- package/src/components/schema-tree.js +0 -378
- package/src/components/tag-input.js +0 -135
- package/src/index.js +0 -7
- package/src/json-schema-viewer.js +0 -345
- package/src/oauth-receiver.js +0 -56
- package/src/rapidoc-mini.js +0 -380
- package/src/rapidoc.js +0 -1082
- package/src/styles/border-styles.js +0 -24
- package/src/styles/custom-styles.js +0 -10
- package/src/styles/dialog-box-styles.js +0 -75
- package/src/styles/endpoint-styles.js +0 -202
- package/src/styles/flex-styles.js +0 -15
- package/src/styles/font-styles.js +0 -268
- package/src/styles/info-styles.js +0 -21
- package/src/styles/input-styles.js +0 -202
- package/src/styles/nav-styles.js +0 -198
- package/src/styles/prism-styles.js +0 -105
- package/src/styles/schema-styles.js +0 -121
- package/src/styles/tab-styles.js +0 -47
- package/src/styles/table-styles.js +0 -58
- package/src/templates/advance-search-template.js +0 -72
- package/src/templates/callback-template.js +0 -73
- package/src/templates/code-samples-template.js +0 -34
- package/src/templates/components-template.js +0 -76
- package/src/templates/endpoint-template.js +0 -249
- package/src/templates/expanded-endpoint-template.js +0 -197
- package/src/templates/focused-endpoint-template.js +0 -110
- package/src/templates/header-template.js +0 -66
- package/src/templates/json-schema-viewer-template.js +0 -185
- package/src/templates/logo-template.js +0 -18
- package/src/templates/main-body-template.js +0 -121
- package/src/templates/navbar-template.js +0 -272
- package/src/templates/overview-template.js +0 -79
- package/src/templates/security-scheme-template.js +0 -610
- package/src/templates/server-template.js +0 -115
- package/src/utils/color-utils.js +0 -59
- package/src/utils/common-utils.js +0 -168
- package/src/utils/schema-utils.js +0 -1086
- package/src/utils/spec-parser.js +0 -462
- package/src/utils/theme.js +0 -288
- package/webpack.config.js +0 -142
|
@@ -1,1086 +0,0 @@
|
|
|
1
|
-
import RandExp from 'randexp';
|
|
2
|
-
|
|
3
|
-
// Make RandExp determinist
|
|
4
|
-
RandExp.prototype.randInt = (from) => from;
|
|
5
|
-
|
|
6
|
-
// Takes a value as input and provides a printable string to replresent null values, spaces, blankstring etc
|
|
7
|
-
export function getPrintableVal(val) {
|
|
8
|
-
if (val === undefined) {
|
|
9
|
-
return '';
|
|
10
|
-
}
|
|
11
|
-
if (val === null) {
|
|
12
|
-
return 'null';
|
|
13
|
-
}
|
|
14
|
-
if (val === '') {
|
|
15
|
-
return '∅';
|
|
16
|
-
}
|
|
17
|
-
if (typeof val === 'boolean' || typeof val === 'number') {
|
|
18
|
-
return `${val}`;
|
|
19
|
-
}
|
|
20
|
-
if (Array.isArray(val)) {
|
|
21
|
-
return val.map((v) => (v === null ? 'null' : v === '' ? '∅' : v.toString().replace(/^ +| +$/g, (m) => '●'.repeat(m.length)) || '')).join(', ');
|
|
22
|
-
}
|
|
23
|
-
if (typeof val === 'object') {
|
|
24
|
-
const keys = Object.keys(val);
|
|
25
|
-
return `{ ${keys[0]}:${val[keys[0]]}${keys.length > 1 ? ',' : ''} ... }`;
|
|
26
|
-
}
|
|
27
|
-
return val.toString().replace(/^ +| +$/g, (m) => '●'.repeat(m.length)) || '';
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/* Generates an schema object containing type and constraint info */
|
|
31
|
-
export function getTypeInfo(schema) {
|
|
32
|
-
if (!schema) {
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
let dataType = '';
|
|
36
|
-
let constrain = '';
|
|
37
|
-
// let examples;
|
|
38
|
-
|
|
39
|
-
if (schema.$ref) {
|
|
40
|
-
const n = schema.$ref.lastIndexOf('/');
|
|
41
|
-
const schemaNode = schema.$ref.substring(n + 1);
|
|
42
|
-
dataType = `{recursive: ${schemaNode}} `;
|
|
43
|
-
} else if (schema.type) {
|
|
44
|
-
dataType = Array.isArray(schema.type) ? schema.type.join(schema.length === 2 ? ' or ' : '┃') : schema.type;
|
|
45
|
-
if (schema.format || schema.enum || schema.const) {
|
|
46
|
-
dataType = dataType.replace('string', schema.enum ? 'enum' : schema.const ? 'const' : schema.format);
|
|
47
|
-
}
|
|
48
|
-
if (schema.nullable) {
|
|
49
|
-
dataType += '┃null';
|
|
50
|
-
}
|
|
51
|
-
} else if (schema.const) {
|
|
52
|
-
dataType = 'const';
|
|
53
|
-
} else if (Object.keys(schema).length === 0) {
|
|
54
|
-
dataType = 'any';
|
|
55
|
-
} else {
|
|
56
|
-
dataType = '{missing-type-info}';
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const info = {
|
|
60
|
-
type: dataType,
|
|
61
|
-
format: schema.format || '',
|
|
62
|
-
pattern: (schema.pattern && !schema.enum) ? schema.pattern : '',
|
|
63
|
-
readOrWriteOnly: (schema.readOnly ? '🆁' : schema.writeOnly ? '🆆' : ''),
|
|
64
|
-
deprecated: schema.deprecated ? '❌' : '',
|
|
65
|
-
examples: schema.examples || schema.example,
|
|
66
|
-
default: getPrintableVal(schema.default),
|
|
67
|
-
description: schema.description || '',
|
|
68
|
-
constrain: '',
|
|
69
|
-
allowedValues: '',
|
|
70
|
-
arrayType: '',
|
|
71
|
-
html: '',
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
if (info.type === '{recursive}') {
|
|
75
|
-
info.description = schema.$ref.substring(schema.$ref.lastIndexOf('/') + 1);
|
|
76
|
-
} else if (info.type === '{missing-type-info}' || info.type === 'any') {
|
|
77
|
-
info.description = info.description || '';
|
|
78
|
-
}
|
|
79
|
-
// Set Allowed Values
|
|
80
|
-
info.allowedValues = schema.const
|
|
81
|
-
? schema.const
|
|
82
|
-
: Array.isArray(schema.enum)
|
|
83
|
-
? schema.enum.map((v) => (getPrintableVal(v))).join('┃')
|
|
84
|
-
: '';
|
|
85
|
-
|
|
86
|
-
if (dataType === 'array' && schema.items) {
|
|
87
|
-
const arrayItemType = schema.items?.type;
|
|
88
|
-
const arrayItemDefault = getPrintableVal(schema.items.default);
|
|
89
|
-
|
|
90
|
-
info.arrayType = `${schema.type} of ${Array.isArray(arrayItemType) ? arrayItemType.join('') : arrayItemType}`;
|
|
91
|
-
info.default = arrayItemDefault;
|
|
92
|
-
info.allowedValues = schema.items.const
|
|
93
|
-
? schema.const
|
|
94
|
-
: Array.isArray(schema.items?.enum)
|
|
95
|
-
? schema.items.enum.map((v) => (getPrintableVal(v))).join('┃')
|
|
96
|
-
: '';
|
|
97
|
-
}
|
|
98
|
-
if (dataType.match(/integer|number/g)) {
|
|
99
|
-
if (schema.minimum !== undefined || schema.exclusiveMinimum !== undefined) {
|
|
100
|
-
constrain += schema.minimum !== undefined ? `Min ${schema.minimum}` : `More than ${schema.exclusiveMinimum}`;
|
|
101
|
-
}
|
|
102
|
-
if (schema.maximum !== undefined || schema.exclusiveMaximum !== undefined) {
|
|
103
|
-
constrain += schema.maximum !== undefined ? `${constrain ? '┃' : ''}Max ${schema.maximum}` : `${constrain ? '┃' : ''}Less than ${schema.exclusiveMaximum}`;
|
|
104
|
-
}
|
|
105
|
-
if (schema.multipleOf !== undefined) {
|
|
106
|
-
constrain += `${constrain ? '┃' : ''} multiple of ${schema.multipleOf}`;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
if (dataType.match(/string/g)) {
|
|
110
|
-
if (schema.minLength !== undefined && schema.maxLength !== undefined) {
|
|
111
|
-
constrain += `${constrain ? '┃' : ''}${schema.minLength} to ${schema.maxLength} chars`;
|
|
112
|
-
} else if (schema.minLength !== undefined) {
|
|
113
|
-
constrain += `${constrain ? '┃' : ''}Min ${schema.minLength} chars`;
|
|
114
|
-
} else if (schema.maxLength !== undefined) {
|
|
115
|
-
constrain += `Max ${constrain ? '┃' : ''}${schema.maxLength} chars`;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
info.constrain = constrain;
|
|
119
|
-
info.html = `${info.type}~|~${info.readOrWriteOnly}~|~${info.constrain}~|~${info.default}~|~${info.allowedValues}~|~${info.pattern}~|~${info.description}~|~${schema.title || ''}~|~${info.deprecated ? 'deprecated' : ''}`;
|
|
120
|
-
return info;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
*
|
|
125
|
-
* @param {*} ex if the value
|
|
126
|
-
* - Is an Object with 'value' property like
|
|
127
|
-
* { 'value': 'example_val1', 'description': 'some description' }
|
|
128
|
-
* Returns >>>
|
|
129
|
-
* {
|
|
130
|
-
* 'Example': { 'value' : 'example_val1', 'description': 'some description' },
|
|
131
|
-
* }
|
|
132
|
-
* - Is an object where each key represents a valid example object (i,e has a value property)
|
|
133
|
-
* {
|
|
134
|
-
* 'example1': { 'value' : 'example_val1', 'description': 'some description' },
|
|
135
|
-
* 'example2': { 'value' : 'example_val2', 'description': 'some other description' },
|
|
136
|
-
* 'invalid': { 'description': 'invalid example object without any value property' }
|
|
137
|
-
* }
|
|
138
|
-
* Returns >>>
|
|
139
|
-
* {
|
|
140
|
-
* 'example1': { 'value' : 'example_val1', 'description': 'some description' },
|
|
141
|
-
* 'example2': { 'value' : 'example_val2', 'description': 'some other description' }
|
|
142
|
-
* }
|
|
143
|
-
* if none of the keys represents an object with 'value' property then return undefined
|
|
144
|
-
* - Is an array of premitive values
|
|
145
|
-
* ['example_val1', 'example_val2']
|
|
146
|
-
* Returns >>>
|
|
147
|
-
* {
|
|
148
|
-
* 'Example1': {value:'value1'}
|
|
149
|
-
* 'Example2': {value:'value2'}
|
|
150
|
-
* }
|
|
151
|
-
* - Is a premitive value
|
|
152
|
-
* 'example_val1'
|
|
153
|
-
* Returns >>>
|
|
154
|
-
* {
|
|
155
|
-
* 'Example': { 'value': 'example_val1' }
|
|
156
|
-
* }
|
|
157
|
-
* - Is undefined
|
|
158
|
-
* returns undefined
|
|
159
|
-
* @returns
|
|
160
|
-
*/
|
|
161
|
-
|
|
162
|
-
export function standardizeExample(ex) {
|
|
163
|
-
if (typeof ex === 'object' && !Array.isArray(ex)) {
|
|
164
|
-
if (ex.value !== undefined) {
|
|
165
|
-
// Case 1: Single object with 'value' property
|
|
166
|
-
return { Example: { ...ex } };
|
|
167
|
-
}
|
|
168
|
-
// Case 2: Object where each key is an object with a 'value' property
|
|
169
|
-
const filteredEntries = Object.entries(ex).filter(([_, obj]) => obj.value !== undefined); // eslint-disable-line
|
|
170
|
-
// If no valid entries found, return JSON.stringify of the input
|
|
171
|
-
if (filteredEntries.length === 0) {
|
|
172
|
-
return undefined;
|
|
173
|
-
}
|
|
174
|
-
return Object.fromEntries(filteredEntries);
|
|
175
|
-
} if (Array.isArray(ex)) {
|
|
176
|
-
// Case 3: Array of primitive values
|
|
177
|
-
return ex.reduce((acc, value, index) => {
|
|
178
|
-
acc[`Example${index + 1}`] = { value };
|
|
179
|
-
return acc;
|
|
180
|
-
}, {});
|
|
181
|
-
}
|
|
182
|
-
// Case 4: Single primitive value
|
|
183
|
-
return ex ? { Example: { value: ex } } : undefined;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Normalize example object in the following format (List of object which is used to render example links and fill the input boxes)
|
|
188
|
-
* [{
|
|
189
|
-
* exampleVal : 'value to be rendered on the input control (text-box)',
|
|
190
|
-
* exampleList : [
|
|
191
|
-
* value : '',
|
|
192
|
-
* printableValue: '',
|
|
193
|
-
* summary : '',
|
|
194
|
-
* description : ''
|
|
195
|
-
* ]
|
|
196
|
-
* }]
|
|
197
|
-
* */
|
|
198
|
-
export function normalizeExamples(examples, dataType = 'string') {
|
|
199
|
-
if (!examples) {
|
|
200
|
-
return {
|
|
201
|
-
exampleVal: '',
|
|
202
|
-
exampleList: [],
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
if (examples.constructor === Object) {
|
|
206
|
-
const exampleList = Object.values(examples)
|
|
207
|
-
.filter((v) => (v['x-example-show-value'] !== false))
|
|
208
|
-
.map((v) => ({
|
|
209
|
-
value: (typeof v.value === 'boolean' || typeof v.value === 'number' ? `${v.value}` : (v.value || '')),
|
|
210
|
-
printableValue: getPrintableVal(v.value),
|
|
211
|
-
summary: v.summary || '',
|
|
212
|
-
description: v.description || '',
|
|
213
|
-
}));
|
|
214
|
-
const exampleVal = exampleList.length > 0
|
|
215
|
-
? exampleList[0].value
|
|
216
|
-
: '';
|
|
217
|
-
return { exampleVal, exampleList };
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// This is non-standard way to provide example but will support for now
|
|
221
|
-
if (!Array.isArray(examples)) {
|
|
222
|
-
examples = examples ? [examples] : [];
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (examples.length === 0) {
|
|
226
|
-
return {
|
|
227
|
-
exampleVal: '',
|
|
228
|
-
exampleList: [],
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
if (dataType === 'array') {
|
|
233
|
-
const [exampleVal] = examples;
|
|
234
|
-
const exampleList = examples.map((v) => ({
|
|
235
|
-
value: v,
|
|
236
|
-
printableValue: getPrintableVal(v),
|
|
237
|
-
}));
|
|
238
|
-
return { exampleVal, exampleList };
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
const exampleVal = examples[0].toString();
|
|
242
|
-
const exampleList = examples.map((v) => ({
|
|
243
|
-
value: v.toString(),
|
|
244
|
-
printableValue: getPrintableVal(v),
|
|
245
|
-
}));
|
|
246
|
-
return { exampleVal, exampleList };
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
export function anyExampleWithSummaryOrDescription(examples) {
|
|
250
|
-
return examples.some((x) => x.summary?.length > 0 || x.description?.length > 0);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
export function getSampleValueByType(schemaObj) {
|
|
254
|
-
const example = schemaObj.examples
|
|
255
|
-
? schemaObj.examples[0]
|
|
256
|
-
: schemaObj.example === null
|
|
257
|
-
? null
|
|
258
|
-
: schemaObj.example || undefined;
|
|
259
|
-
if (example === '') { return ''; }
|
|
260
|
-
if (example === null) { return null; }
|
|
261
|
-
if (example === 0) { return 0; }
|
|
262
|
-
if (example === false) { return false; }
|
|
263
|
-
if (example instanceof Date) {
|
|
264
|
-
switch (schemaObj.format.toLowerCase()) {
|
|
265
|
-
case 'date':
|
|
266
|
-
return example.toISOString().split('T')[0];
|
|
267
|
-
case 'time':
|
|
268
|
-
return example.toISOString().split('T')[1];
|
|
269
|
-
default:
|
|
270
|
-
return example.toISOString();
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
if (example) { return example; }
|
|
274
|
-
|
|
275
|
-
if (Object.keys(schemaObj).length === 0) {
|
|
276
|
-
return null;
|
|
277
|
-
}
|
|
278
|
-
if (schemaObj.$ref) {
|
|
279
|
-
// Indicates a Circular ref
|
|
280
|
-
return {};
|
|
281
|
-
}
|
|
282
|
-
if (schemaObj.const === false || schemaObj.const === 0 || schemaObj.const === null || schemaObj.const === '') {
|
|
283
|
-
return schemaObj.const;
|
|
284
|
-
}
|
|
285
|
-
if (schemaObj.const) {
|
|
286
|
-
return schemaObj.const;
|
|
287
|
-
}
|
|
288
|
-
if (schemaObj.default) {
|
|
289
|
-
return schemaObj.default;
|
|
290
|
-
}
|
|
291
|
-
const typeValue = Array.isArray(schemaObj.type) ? schemaObj.type[0] : schemaObj.type;
|
|
292
|
-
if (!typeValue) {
|
|
293
|
-
return null;
|
|
294
|
-
}
|
|
295
|
-
if (typeValue.match(/^integer|^number/g)) {
|
|
296
|
-
const multipleOf = Number.isNaN(Number(schemaObj.multipleOf)) ? undefined : Number(schemaObj.multipleOf);
|
|
297
|
-
const maximum = Number.isNaN(Number(schemaObj.maximum)) ? undefined : Number(schemaObj.maximum);
|
|
298
|
-
const minimumPossibleVal = Number.isNaN(Number(schemaObj.minimum))
|
|
299
|
-
? Number.isNaN(Number(schemaObj.exclusiveMinimum))
|
|
300
|
-
? maximum || 0
|
|
301
|
-
: Number(schemaObj.exclusiveMinimum) + (typeValue.startsWith('integer') ? 1 : 0.001)
|
|
302
|
-
: Number(schemaObj.minimum);
|
|
303
|
-
const finalVal = multipleOf
|
|
304
|
-
? multipleOf >= minimumPossibleVal
|
|
305
|
-
? multipleOf
|
|
306
|
-
: minimumPossibleVal % multipleOf === 0
|
|
307
|
-
? minimumPossibleVal
|
|
308
|
-
: Math.ceil(minimumPossibleVal / multipleOf) * multipleOf
|
|
309
|
-
: minimumPossibleVal;
|
|
310
|
-
return finalVal;
|
|
311
|
-
}
|
|
312
|
-
if (typeValue.match(/^boolean/g)) { return false; }
|
|
313
|
-
if (typeValue.match(/^null/g)) { return null; }
|
|
314
|
-
if (typeValue.match(/^string/g)) {
|
|
315
|
-
if (schemaObj.enum) { return schemaObj.enum[0]; }
|
|
316
|
-
if (schemaObj.const) { return schemaObj.const; }
|
|
317
|
-
if (schemaObj.pattern) {
|
|
318
|
-
try {
|
|
319
|
-
return new RandExp(schemaObj.pattern).gen();
|
|
320
|
-
} catch {
|
|
321
|
-
return schemaObj.pattern;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
if (schemaObj.format) {
|
|
325
|
-
const u = `${Date.now().toString(16)}${Math.random().toString(16)}0`.repeat(16);
|
|
326
|
-
switch (schemaObj.format.toLowerCase()) {
|
|
327
|
-
case 'url':
|
|
328
|
-
case 'uri':
|
|
329
|
-
return 'http://example.com';
|
|
330
|
-
case 'date':
|
|
331
|
-
return (new Date(0)).toISOString().split('T')[0];
|
|
332
|
-
case 'time':
|
|
333
|
-
return (new Date(0)).toISOString().split('T')[1];
|
|
334
|
-
case 'date-time':
|
|
335
|
-
return (new Date(0)).toISOString();
|
|
336
|
-
case 'duration':
|
|
337
|
-
return 'P3Y6M4DT12H30M5S'; // P=Period 3-Years 6-Months 4-Days 12-Hours 30-Minutes 5-Seconds
|
|
338
|
-
case 'email':
|
|
339
|
-
case 'idn-email':
|
|
340
|
-
return 'user@example.com';
|
|
341
|
-
case 'hostname':
|
|
342
|
-
case 'idn-hostname':
|
|
343
|
-
return 'www.example.com';
|
|
344
|
-
case 'ipv4':
|
|
345
|
-
return '198.51.100.42';
|
|
346
|
-
case 'ipv6':
|
|
347
|
-
return '2001:0db8:5b96:0000:0000:426f:8e17:642a';
|
|
348
|
-
case 'uuid':
|
|
349
|
-
return [u.substring(0, 8), u.substring(8, 12), `4000-8${u.substring(13, 16)}`, u.substring(16, 28)].join('-');
|
|
350
|
-
case 'byte':
|
|
351
|
-
return 'ZXhhbXBsZQ=='; // 'example' base64 encoded. See https://spec.openapis.org/oas/v3.0.0#data-types
|
|
352
|
-
default:
|
|
353
|
-
return '';
|
|
354
|
-
}
|
|
355
|
-
} else {
|
|
356
|
-
const minLength = Number.isNaN(schemaObj.minLength) ? undefined : Number(schemaObj.minLength);
|
|
357
|
-
const maxLength = Number.isNaN(schemaObj.maxLength) ? undefined : Number(schemaObj.maxLength);
|
|
358
|
-
const finalLength = minLength || (maxLength > 6 ? 6 : maxLength || undefined);
|
|
359
|
-
return finalLength ? 'A'.repeat(finalLength) : 'string';
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
// If type cannot be determined
|
|
363
|
-
return null;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/*
|
|
367
|
-
json2xml- TestCase
|
|
368
|
-
{
|
|
369
|
-
'prop1' : 'one',
|
|
370
|
-
'prop2' : 'two',
|
|
371
|
-
'prop3' : [ 'a', 'b', 'c' ],
|
|
372
|
-
'prop4' : {
|
|
373
|
-
'ob1' : 'val-1',
|
|
374
|
-
'ob2' : 'val-2'
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
<root>
|
|
378
|
-
<prop1>simple</prop1>
|
|
379
|
-
<prop2>
|
|
380
|
-
<0>a</0>
|
|
381
|
-
<1>b</1>
|
|
382
|
-
<2>c</2>
|
|
383
|
-
</prop2>
|
|
384
|
-
<prop3>
|
|
385
|
-
<ob1>val-1</ob1>
|
|
386
|
-
<ob2>val-2</ob2>
|
|
387
|
-
</prop3>
|
|
388
|
-
</root>
|
|
389
|
-
*/
|
|
390
|
-
export function json2xml(obj, level = 1) {
|
|
391
|
-
const indent = ' '.repeat(level);
|
|
392
|
-
let xmlText = '';
|
|
393
|
-
if (level === 1 && typeof obj !== 'object') {
|
|
394
|
-
return `\n${indent}${obj.toString()}`;
|
|
395
|
-
}
|
|
396
|
-
for (const prop in obj) {
|
|
397
|
-
const tagNameOrProp = (obj[prop]['::XML_TAG'] || prop);
|
|
398
|
-
let tagName = '';
|
|
399
|
-
if (Array.isArray(obj[prop])) {
|
|
400
|
-
tagName = tagNameOrProp[0]['::XML_TAG'] || `${prop}`;
|
|
401
|
-
} else {
|
|
402
|
-
tagName = tagNameOrProp;
|
|
403
|
-
}
|
|
404
|
-
if (prop.startsWith('::')) {
|
|
405
|
-
continue;
|
|
406
|
-
}
|
|
407
|
-
if (Array.isArray(obj[prop])) {
|
|
408
|
-
xmlText = `${xmlText}\n${indent}<${tagName}>${json2xml(obj[prop], level + 1)}\n${indent}</${tagName}>`;
|
|
409
|
-
} else if (typeof obj[prop] === 'object') {
|
|
410
|
-
xmlText = `${xmlText}\n${indent}<${tagName}>${json2xml(obj[prop], level + 1)}\n${indent}</${tagName}>`;
|
|
411
|
-
} else {
|
|
412
|
-
xmlText = `${xmlText}\n${indent}<${tagName}>${obj[prop].toString()}</${tagName}>`;
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
return xmlText;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
function addSchemaInfoToExample(schema, obj) {
|
|
419
|
-
if (typeof obj !== 'object' || obj === null) {
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
if (schema.title) {
|
|
423
|
-
obj['::TITLE'] = schema.title;
|
|
424
|
-
}
|
|
425
|
-
if (schema.description) {
|
|
426
|
-
obj['::DESCRIPTION'] = schema.description;
|
|
427
|
-
}
|
|
428
|
-
if (schema.xml?.name) {
|
|
429
|
-
obj['::XML_TAG'] = schema.xml?.name;
|
|
430
|
-
}
|
|
431
|
-
if (schema.xml?.wrapped) {
|
|
432
|
-
obj['::XML_WRAP'] = schema.xml?.wrapped.toString();
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
function removeTitlesAndDescriptions(obj) {
|
|
437
|
-
if (typeof obj !== 'object' || obj === null) {
|
|
438
|
-
return;
|
|
439
|
-
}
|
|
440
|
-
delete obj['::TITLE'];
|
|
441
|
-
delete obj['::DESCRIPTION'];
|
|
442
|
-
delete obj['::XML_TAG'];
|
|
443
|
-
delete obj['::XML_WRAP'];
|
|
444
|
-
for (const k in obj) {
|
|
445
|
-
removeTitlesAndDescriptions(obj[k]);
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
function addPropertyExampleToObjectExamples(example, obj, propertyKey) {
|
|
450
|
-
for (const key in obj) {
|
|
451
|
-
obj[key][propertyKey] = example;
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
function mergePropertyExamples(obj, propertyName, propExamples) {
|
|
456
|
-
// Create an example for each variant of the propertyExample, merging them with the current (parent) example
|
|
457
|
-
let i = 0;
|
|
458
|
-
const maxCombinations = 10;
|
|
459
|
-
const mergedObj = {};
|
|
460
|
-
for (const exampleKey in obj) {
|
|
461
|
-
for (const propExampleKey in propExamples) {
|
|
462
|
-
mergedObj[`example-${i}`] = { ...obj[exampleKey] };
|
|
463
|
-
mergedObj[`example-${i}`][propertyName] = propExamples[propExampleKey];
|
|
464
|
-
i++;
|
|
465
|
-
if (i >= maxCombinations) {
|
|
466
|
-
break;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
if (i >= maxCombinations) {
|
|
470
|
-
break;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
return mergedObj;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
/* For changing JSON-Schema to a Sample Object, as per the schema (to generate examples based on schema) */
|
|
477
|
-
export function schemaToSampleObj(schema, config = { }) {
|
|
478
|
-
let obj = {};
|
|
479
|
-
if (!schema) {
|
|
480
|
-
return;
|
|
481
|
-
}
|
|
482
|
-
if (schema.allOf) {
|
|
483
|
-
const objWithAllProps = {};
|
|
484
|
-
|
|
485
|
-
if (schema.allOf.length === 1 && !schema.allOf[0]?.properties && !schema.allOf[0]?.items) {
|
|
486
|
-
// If allOf has single item and the type is not an object or array, then its a primitive
|
|
487
|
-
if (schema.allOf[0].$ref) {
|
|
488
|
-
return '{ }';
|
|
489
|
-
}
|
|
490
|
-
if (schema.allOf[0].readOnly && config.includeReadOnly) {
|
|
491
|
-
const tempSchema = schema.allOf[0];
|
|
492
|
-
return getSampleValueByType(tempSchema);
|
|
493
|
-
}
|
|
494
|
-
return;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
schema.allOf.forEach((v) => {
|
|
498
|
-
if (v.type === 'object' || v.properties || v.allOf || v.anyOf || v.oneOf) {
|
|
499
|
-
const partialObj = schemaToSampleObj(v, config);
|
|
500
|
-
Object.assign(objWithAllProps, partialObj);
|
|
501
|
-
} else if (v.type === 'array' || v.items) {
|
|
502
|
-
const partialObj = [schemaToSampleObj(v, config)];
|
|
503
|
-
Object.assign(objWithAllProps, partialObj);
|
|
504
|
-
} else if (v.type) {
|
|
505
|
-
const prop = `prop${Object.keys(objWithAllProps).length}`;
|
|
506
|
-
objWithAllProps[prop] = getSampleValueByType(v);
|
|
507
|
-
} else {
|
|
508
|
-
return '';
|
|
509
|
-
}
|
|
510
|
-
});
|
|
511
|
-
|
|
512
|
-
obj = objWithAllProps;
|
|
513
|
-
} else if (schema.oneOf) {
|
|
514
|
-
// 1. First create example with scheme.properties
|
|
515
|
-
const objWithSchemaProps = {};
|
|
516
|
-
if (schema.properties) {
|
|
517
|
-
for (const propertyName in schema.properties) {
|
|
518
|
-
if (schema.properties[propertyName].properties || schema.properties[propertyName].properties?.items) {
|
|
519
|
-
objWithSchemaProps[propertyName] = schemaToSampleObj(schema.properties[propertyName], config);
|
|
520
|
-
} else {
|
|
521
|
-
objWithSchemaProps[propertyName] = getSampleValueByType(schema.properties[propertyName]);
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
if (schema.oneOf.length > 0) {
|
|
527
|
-
/*
|
|
528
|
-
oneOf:
|
|
529
|
-
- type: object
|
|
530
|
-
properties:
|
|
531
|
-
option1_PropA:
|
|
532
|
-
type: string
|
|
533
|
-
option1_PropB:
|
|
534
|
-
type: string
|
|
535
|
-
- type: object
|
|
536
|
-
properties:
|
|
537
|
-
option2_PropX:
|
|
538
|
-
type: string
|
|
539
|
-
properties:
|
|
540
|
-
prop1:
|
|
541
|
-
type: string
|
|
542
|
-
prop2:
|
|
543
|
-
type: string
|
|
544
|
-
minLength: 10
|
|
545
|
-
|
|
546
|
-
The aboove Schem should generate the following 2 examples
|
|
547
|
-
|
|
548
|
-
Example-1
|
|
549
|
-
{
|
|
550
|
-
prop1: 'string',
|
|
551
|
-
prop2: 'AAAAAAAAAA', <-- min-length 10
|
|
552
|
-
option1_PropA: 'string',
|
|
553
|
-
option1_PropB: 'string'
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
Example-2
|
|
557
|
-
{
|
|
558
|
-
prop1: 'string',
|
|
559
|
-
prop2: 'AAAAAAAAAA', <-- min-length 10
|
|
560
|
-
option2_PropX: 'string'
|
|
561
|
-
}
|
|
562
|
-
*/
|
|
563
|
-
let i = 0;
|
|
564
|
-
// Merge all examples of each oneOf-schema
|
|
565
|
-
for (const key in schema.oneOf) {
|
|
566
|
-
const oneOfSamples = schemaToSampleObj(schema.oneOf[key], config);
|
|
567
|
-
for (const sampleKey in oneOfSamples) {
|
|
568
|
-
// 2. In the final example include a one-of item along with properties
|
|
569
|
-
let finalExample;
|
|
570
|
-
if (Object.keys(objWithSchemaProps).length > 0) {
|
|
571
|
-
if (oneOfSamples[sampleKey] === null || typeof oneOfSamples[sampleKey] !== 'object') {
|
|
572
|
-
// This doesn't really make sense since every oneOf schema _should_ be an object if there are common properties, so we'll skip this
|
|
573
|
-
continue;
|
|
574
|
-
} else {
|
|
575
|
-
finalExample = Object.assign(oneOfSamples[sampleKey], objWithSchemaProps);
|
|
576
|
-
}
|
|
577
|
-
} else {
|
|
578
|
-
finalExample = oneOfSamples[sampleKey];
|
|
579
|
-
}
|
|
580
|
-
obj[`example-${i}`] = finalExample;
|
|
581
|
-
addSchemaInfoToExample(schema.oneOf[key], obj[`example-${i}`]);
|
|
582
|
-
i++;
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
} else if (schema.anyOf) {
|
|
587
|
-
// First generate values for regular properties
|
|
588
|
-
let commonObj;
|
|
589
|
-
if (schema.type === 'object' || schema.properties) {
|
|
590
|
-
commonObj = { 'example-0': {} };
|
|
591
|
-
for (const propertyName in schema.properties) {
|
|
592
|
-
if (schema.example) {
|
|
593
|
-
commonObj = schema;
|
|
594
|
-
break;
|
|
595
|
-
}
|
|
596
|
-
if (schema.properties[propertyName].deprecated && !config.includeDeprecated) { continue; }
|
|
597
|
-
if (schema.properties[propertyName].readOnly && !config.includeReadOnly) { continue; }
|
|
598
|
-
if (schema.properties[propertyName].writeOnly && !config.includeWriteOnly) { continue; }
|
|
599
|
-
commonObj = mergePropertyExamples(commonObj, propertyName, schemaToSampleObj(schema.properties[propertyName], config));
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
// Combine every variant of the regular properties with every variant of the anyOf samples
|
|
604
|
-
let i = 0;
|
|
605
|
-
for (const key in schema.anyOf) {
|
|
606
|
-
const anyOfSamples = schemaToSampleObj(schema.anyOf[key], config);
|
|
607
|
-
for (const sampleKey in anyOfSamples) {
|
|
608
|
-
if (typeof commonObj !== 'undefined') {
|
|
609
|
-
for (const commonKey in commonObj) {
|
|
610
|
-
obj[`example-${i}`] = { ...commonObj[commonKey], ...anyOfSamples[sampleKey] };
|
|
611
|
-
}
|
|
612
|
-
} else {
|
|
613
|
-
obj[`example-${i}`] = anyOfSamples[sampleKey];
|
|
614
|
-
}
|
|
615
|
-
addSchemaInfoToExample(schema.anyOf[key], obj[`example-${i}`]);
|
|
616
|
-
i++;
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
} else if (schema.type === 'object' || schema.properties) {
|
|
620
|
-
obj['example-0'] = {};
|
|
621
|
-
addSchemaInfoToExample(schema, obj['example-0']);
|
|
622
|
-
if (schema.example) {
|
|
623
|
-
obj['example-0'] = schema.example;
|
|
624
|
-
} else {
|
|
625
|
-
for (const propertyName in schema.properties) {
|
|
626
|
-
if (schema.properties[propertyName]?.deprecated && !config.includeDeprecated) { continue; }
|
|
627
|
-
if (schema.properties[propertyName]?.readOnly && !config.includeReadOnly) { continue; }
|
|
628
|
-
if (schema.properties[propertyName]?.writeOnly && !config.includeWriteOnly) { continue; }
|
|
629
|
-
if (schema.properties[propertyName]?.type === 'array' || schema.properties[propertyName]?.items) {
|
|
630
|
-
if (schema.properties[propertyName].example) {
|
|
631
|
-
addPropertyExampleToObjectExamples(schema.properties[propertyName].example, obj, propertyName);
|
|
632
|
-
} else if (schema.properties[propertyName]?.items?.example) { // schemas and properties support single example but not multiple examples.
|
|
633
|
-
addPropertyExampleToObjectExamples([schema.properties[propertyName].items.example], obj, propertyName);
|
|
634
|
-
} else {
|
|
635
|
-
const itemSamples = schemaToSampleObj(schema.properties[propertyName].items, config);
|
|
636
|
-
if (config.useXmlTagForProp) {
|
|
637
|
-
const xmlTagName = schema.properties[propertyName].xml?.name || propertyName;
|
|
638
|
-
if (schema.properties[propertyName].xml?.wrapped) {
|
|
639
|
-
const wrappedItemSample = JSON.parse(`{ "${xmlTagName}" : { "${xmlTagName}" : ${JSON.stringify(itemSamples['example-0'])} } }`);
|
|
640
|
-
obj = mergePropertyExamples(obj, xmlTagName, wrappedItemSample);
|
|
641
|
-
} else {
|
|
642
|
-
obj = mergePropertyExamples(obj, xmlTagName, itemSamples);
|
|
643
|
-
}
|
|
644
|
-
} else {
|
|
645
|
-
const arraySamples = [];
|
|
646
|
-
for (const key in itemSamples) {
|
|
647
|
-
arraySamples[key] = [itemSamples[key]];
|
|
648
|
-
}
|
|
649
|
-
obj = mergePropertyExamples(obj, propertyName, arraySamples);
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
continue;
|
|
653
|
-
}
|
|
654
|
-
obj = mergePropertyExamples(obj, propertyName, schemaToSampleObj(schema.properties[propertyName], config));
|
|
655
|
-
}
|
|
656
|
-
if (typeof schema.additionalProperties === 'object') {
|
|
657
|
-
const propertyName = schema.additionalProperties['x-additionalPropertiesName'] || 'property';
|
|
658
|
-
obj = mergePropertyExamples(obj, `${propertyName}1`, schemaToSampleObj(schema.additionalProperties, config));
|
|
659
|
-
obj = mergePropertyExamples(obj, `${propertyName}2`, schemaToSampleObj(schema.additionalProperties, config));
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
} else if (schema.type === 'array' || schema.items) {
|
|
663
|
-
if (schema.items || schema.example) {
|
|
664
|
-
if (schema.example) {
|
|
665
|
-
obj['example-0'] = schema.example;
|
|
666
|
-
} else if (schema.items?.example) { // schemas and properties support single example but not multiple examples.
|
|
667
|
-
obj['example-0'] = [schema.items.example];
|
|
668
|
-
} else {
|
|
669
|
-
const samples = schemaToSampleObj(schema.items, config);
|
|
670
|
-
let i = 0;
|
|
671
|
-
for (const key in samples) {
|
|
672
|
-
obj[`example-${i}`] = [samples[key]];
|
|
673
|
-
addSchemaInfoToExample(schema.items, obj[`example-${i}`]);
|
|
674
|
-
i++;
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
} else {
|
|
678
|
-
obj['example-0'] = [];
|
|
679
|
-
}
|
|
680
|
-
} else {
|
|
681
|
-
return { 'example-0': getSampleValueByType(schema) };
|
|
682
|
-
}
|
|
683
|
-
return obj;
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
function generateMarkdownForArrayAndObjectDescription(schema, level = 0) {
|
|
687
|
-
let markdown = ((schema.description || schema.title) && (schema.minItems || schema.maxItems)) ? '<span class="descr-expand-toggle">➔</span>' : '';
|
|
688
|
-
if (schema.title) {
|
|
689
|
-
if (schema.description) {
|
|
690
|
-
markdown = `${markdown} <b>${schema.title}:</b> ${schema.description}<br/>`;
|
|
691
|
-
} else {
|
|
692
|
-
markdown = `${markdown} ${schema.title}<br/>`;
|
|
693
|
-
}
|
|
694
|
-
} else if (schema.description) {
|
|
695
|
-
markdown = `${markdown} ${schema.description}<br/>`;
|
|
696
|
-
}
|
|
697
|
-
if (schema.minItems) {
|
|
698
|
-
markdown = `${markdown} <b>Min Items:</b> ${schema.minItems}`;
|
|
699
|
-
}
|
|
700
|
-
if (schema.maxItems) {
|
|
701
|
-
markdown = `${markdown} <b>Max Items:</b> ${schema.maxItems}`;
|
|
702
|
-
}
|
|
703
|
-
if (level > 0 && schema.items?.description) {
|
|
704
|
-
let itemsMarkdown = '';
|
|
705
|
-
if (schema.items.minProperties) {
|
|
706
|
-
itemsMarkdown = `<b>Min Properties:</b> ${schema.items.minProperties}`;
|
|
707
|
-
}
|
|
708
|
-
if (schema.items.maxProperties) {
|
|
709
|
-
itemsMarkdown = `${itemsMarkdown} <b>Max Properties:</b> ${schema.items.maxProperties}`;
|
|
710
|
-
}
|
|
711
|
-
markdown = `${markdown} ⮕ ${itemsMarkdown} [ ${schema.items.description} ] `;
|
|
712
|
-
}
|
|
713
|
-
return markdown;
|
|
714
|
-
}
|
|
715
|
-
/**
|
|
716
|
-
* For changing OpenAPI-Schema to an Object Notation,
|
|
717
|
-
* This Object would further be an input to UI Components to generate an Object-Tree
|
|
718
|
-
* @param {object} schema - Schema object from OpenAPI spec
|
|
719
|
-
* @param {object} obj - recursivly pass this object to generate object notation
|
|
720
|
-
* @param {number} level - recursion level
|
|
721
|
-
* @param {string} suffix - used for suffixing property names to avoid duplicate props during object composion
|
|
722
|
-
*/
|
|
723
|
-
export function schemaInObjectNotation(schema, obj, level = 0, suffix = '') {
|
|
724
|
-
if (!schema) {
|
|
725
|
-
return;
|
|
726
|
-
}
|
|
727
|
-
if (schema.allOf) {
|
|
728
|
-
const objWithAllProps = {};
|
|
729
|
-
if (schema.allOf.length === 1 && !schema.allOf[0].properties && !schema.allOf[0].items) {
|
|
730
|
-
// If allOf has single item and the type is not an object or array, then its a primitive
|
|
731
|
-
const tempSchema = schema.allOf[0];
|
|
732
|
-
return `${getTypeInfo(tempSchema).html}`;
|
|
733
|
-
}
|
|
734
|
-
// If allOf is an array of multiple elements, then all the keys makes a single object
|
|
735
|
-
schema.allOf.map((v, i) => {
|
|
736
|
-
if (v.type === 'object' || v.properties || v.allOf || v.anyOf || v.oneOf) {
|
|
737
|
-
const propSuffix = (v.anyOf || v.oneOf) && i > 0 ? i : '';
|
|
738
|
-
const partialObj = schemaInObjectNotation(v, {}, (level + 1), propSuffix);
|
|
739
|
-
Object.assign(objWithAllProps, partialObj);
|
|
740
|
-
} else if (v.type === 'array' || v.items) {
|
|
741
|
-
const partialObj = schemaInObjectNotation(v, {}, (level + 1));
|
|
742
|
-
Object.assign(objWithAllProps, partialObj);
|
|
743
|
-
} else if (v.type) {
|
|
744
|
-
const prop = `prop${Object.keys(objWithAllProps).length}`;
|
|
745
|
-
const typeObj = getTypeInfo(v);
|
|
746
|
-
objWithAllProps[prop] = `${typeObj.html}`;
|
|
747
|
-
} else {
|
|
748
|
-
return '';
|
|
749
|
-
}
|
|
750
|
-
});
|
|
751
|
-
obj = objWithAllProps;
|
|
752
|
-
} else if (schema.anyOf || schema.oneOf) {
|
|
753
|
-
obj['::description'] = schema.description || '';
|
|
754
|
-
// 1. First iterate the regular properties
|
|
755
|
-
if (schema.type === 'object' || schema.properties) {
|
|
756
|
-
obj['::description'] = schema.description || '';
|
|
757
|
-
obj['::type'] = 'object';
|
|
758
|
-
// obj['::deprecated'] = schema.deprecated || false;
|
|
759
|
-
for (const key in schema.properties) {
|
|
760
|
-
if (schema.required && schema.required.includes(key)) {
|
|
761
|
-
obj[`${key}*`] = schemaInObjectNotation(schema.properties[key], {}, (level + 1));
|
|
762
|
-
} else {
|
|
763
|
-
obj[key] = schemaInObjectNotation(schema.properties[key], {}, (level + 1));
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
// 2. Then show allof/anyof objects
|
|
768
|
-
const objWithAnyOfProps = {};
|
|
769
|
-
const xxxOf = schema.anyOf ? 'anyOf' : 'oneOf';
|
|
770
|
-
schema[xxxOf].forEach((v, index) => {
|
|
771
|
-
if (v.type === 'object' || v.properties || v.allOf || v.anyOf || v.oneOf) {
|
|
772
|
-
const partialObj = schemaInObjectNotation(v, {});
|
|
773
|
-
objWithAnyOfProps[`::OPTION~${index + 1}${v.title ? `~${v.title}` : ''}`] = partialObj;
|
|
774
|
-
objWithAnyOfProps[`::OPTION~${index + 1}${v.title ? `~${v.title}` : ''}`]['::readwrite'] = ''; // xxx-options cannot be read or write only
|
|
775
|
-
objWithAnyOfProps['::type'] = 'xxx-of-option';
|
|
776
|
-
} else if (v.type === 'array' || v.items) {
|
|
777
|
-
// This else-if block never seems to get executed
|
|
778
|
-
const partialObj = schemaInObjectNotation(v, {});
|
|
779
|
-
objWithAnyOfProps[`::OPTION~${index + 1}${v.title ? `~${v.title}` : ''}`] = partialObj;
|
|
780
|
-
objWithAnyOfProps[`::OPTION~${index + 1}${v.title ? `~${v.title}` : ''}`]['::readwrite'] = ''; // xxx-options cannot be read or write only
|
|
781
|
-
objWithAnyOfProps['::type'] = 'xxx-of-array';
|
|
782
|
-
} else {
|
|
783
|
-
const prop = `::OPTION~${index + 1}${v.title ? `~${v.title}` : ''}`;
|
|
784
|
-
objWithAnyOfProps[prop] = `${getTypeInfo(v).html}`;
|
|
785
|
-
objWithAnyOfProps['::type'] = 'xxx-of-option';
|
|
786
|
-
}
|
|
787
|
-
});
|
|
788
|
-
obj[(schema.anyOf ? `::ANY~OF ${suffix}` : `::ONE~OF ${suffix}`)] = objWithAnyOfProps;
|
|
789
|
-
// obj['::type'] = 'object';
|
|
790
|
-
obj['::type'] = 'object';
|
|
791
|
-
} else if (Array.isArray(schema.type)) {
|
|
792
|
-
// When a property has multiple types, then check further if any of the types are array or object, if yes then modify the schema using one-of
|
|
793
|
-
// Clone the schema - as it will be modified to replace multi-data-types with one-of;
|
|
794
|
-
const subSchema = JSON.parse(JSON.stringify(schema));
|
|
795
|
-
const primitiveType = [];
|
|
796
|
-
const complexTypes = [];
|
|
797
|
-
subSchema.type.forEach((v) => {
|
|
798
|
-
if (v.match(/integer|number|string|null|boolean/g)) {
|
|
799
|
-
primitiveType.push(v);
|
|
800
|
-
} else if (v === 'array' && typeof subSchema.items?.type === 'string' && subSchema.items?.type.match(/integer|number|string|null|boolean/g)) {
|
|
801
|
-
// Array with primitive types should also be treated as primitive type
|
|
802
|
-
if (subSchema.items.type === 'string' && subSchema.items.format) {
|
|
803
|
-
primitiveType.push(`[${subSchema.items.format}]`);
|
|
804
|
-
} else {
|
|
805
|
-
primitiveType.push(`[${subSchema.items.type}]`);
|
|
806
|
-
}
|
|
807
|
-
} else {
|
|
808
|
-
complexTypes.push(v);
|
|
809
|
-
}
|
|
810
|
-
});
|
|
811
|
-
let multiPrimitiveTypes;
|
|
812
|
-
if (primitiveType.length > 0) {
|
|
813
|
-
subSchema.type = primitiveType.join(primitiveType.length === 2 ? ' or ' : '┃');
|
|
814
|
-
multiPrimitiveTypes = getTypeInfo(subSchema);
|
|
815
|
-
if (complexTypes.length === 0) {
|
|
816
|
-
return `${multiPrimitiveTypes?.html || ''}`;
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
if (complexTypes.length > 0) {
|
|
820
|
-
obj['::type'] = 'object';
|
|
821
|
-
const multiTypeOptions = {
|
|
822
|
-
'::type': 'xxx-of-option',
|
|
823
|
-
};
|
|
824
|
-
|
|
825
|
-
// Generate ONE-OF options for complexTypes
|
|
826
|
-
complexTypes.forEach((v, i) => {
|
|
827
|
-
if (v === 'null') {
|
|
828
|
-
multiTypeOptions[`::OPTION~${i + 1}`] = 'NULL~|~~|~~|~~|~~|~~|~~|~~|~';
|
|
829
|
-
} else if ('integer, number, string, boolean,'.includes(`${v},`)) {
|
|
830
|
-
subSchema.type = Array.isArray(v) ? v.join('┃') : v;
|
|
831
|
-
const primitiveTypeInfo = getTypeInfo(subSchema);
|
|
832
|
-
multiTypeOptions[`::OPTION~${i + 1}`] = primitiveTypeInfo.html;
|
|
833
|
-
} else if (v === 'object') {
|
|
834
|
-
// If object type iterate all the properties and create an object-type-option
|
|
835
|
-
const objTypeOption = {
|
|
836
|
-
'::title': schema.title || '',
|
|
837
|
-
'::description': schema.description || '',
|
|
838
|
-
'::type': 'object',
|
|
839
|
-
'::deprecated': schema.deprecated || false,
|
|
840
|
-
};
|
|
841
|
-
for (const key in schema.properties) {
|
|
842
|
-
if (schema.required && schema.required.includes(key)) {
|
|
843
|
-
objTypeOption[`${key}*`] = schemaInObjectNotation(schema.properties[key], {}, (level + 1));
|
|
844
|
-
} else {
|
|
845
|
-
objTypeOption[key] = schemaInObjectNotation(schema.properties[key], {}, (level + 1));
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
multiTypeOptions[`::OPTION~${i + 1}`] = objTypeOption;
|
|
849
|
-
} else if (v === 'array') {
|
|
850
|
-
multiTypeOptions[`::OPTION~${i + 1}`] = {
|
|
851
|
-
'::title': schema.title || '',
|
|
852
|
-
'::description': schema.description || '',
|
|
853
|
-
'::type': 'array',
|
|
854
|
-
'::props': schemaInObjectNotation(schema.items, {}, (level + 1)),
|
|
855
|
-
};
|
|
856
|
-
}
|
|
857
|
-
});
|
|
858
|
-
multiTypeOptions[`::OPTION~${complexTypes.length + 1}`] = multiPrimitiveTypes?.html || '';
|
|
859
|
-
obj['::ONE~OF'] = multiTypeOptions;
|
|
860
|
-
}
|
|
861
|
-
} else if (schema.type === 'object' || schema.properties) { // If Object
|
|
862
|
-
obj['::title'] = schema.title || '';
|
|
863
|
-
obj['::description'] = generateMarkdownForArrayAndObjectDescription(schema, level);
|
|
864
|
-
obj['::type'] = 'object';
|
|
865
|
-
if ((Array.isArray(schema.type) && schema.type.includes('null')) || schema.nullable) {
|
|
866
|
-
obj['::dataTypeLabel'] = 'object or null';
|
|
867
|
-
obj['::nullable'] = true;
|
|
868
|
-
}
|
|
869
|
-
obj['::deprecated'] = schema.deprecated || false;
|
|
870
|
-
obj['::readwrite'] = schema.readOnly ? 'readonly' : schema.writeOnly ? 'writeonly' : '';
|
|
871
|
-
for (const key in schema.properties) {
|
|
872
|
-
if (schema.required && schema.required.includes(key)) {
|
|
873
|
-
obj[`${key}*`] = schemaInObjectNotation(schema.properties[key], {}, (level + 1));
|
|
874
|
-
} else {
|
|
875
|
-
obj[key] = schemaInObjectNotation(schema.properties[key], {}, (level + 1));
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
for (const key in schema.patternProperties) {
|
|
879
|
-
obj[`[pattern: ${key}]`] = schemaInObjectNotation(schema.patternProperties[key], obj, (level + 1));
|
|
880
|
-
}
|
|
881
|
-
if (schema.additionalProperties) {
|
|
882
|
-
obj['[any-key]'] = schemaInObjectNotation(schema.additionalProperties, {});
|
|
883
|
-
}
|
|
884
|
-
} else if (schema.type === 'array' || schema.items) { // If Array
|
|
885
|
-
obj['::title'] = schema.title || '';
|
|
886
|
-
obj['::description'] = generateMarkdownForArrayAndObjectDescription(schema, level);
|
|
887
|
-
obj['::type'] = 'array';
|
|
888
|
-
if ((Array.isArray(schema.type) && schema.type.includes('null')) || schema.nullable) {
|
|
889
|
-
obj['::dataTypeLabel'] = 'array or null';
|
|
890
|
-
obj['::nullable'] = true;
|
|
891
|
-
}
|
|
892
|
-
obj['::deprecated'] = schema.deprecated || false;
|
|
893
|
-
obj['::readwrite'] = schema.readOnly ? 'readonly' : schema.writeOnly ? 'writeonly' : '';
|
|
894
|
-
if (schema.items?.items) {
|
|
895
|
-
obj['::array-type'] = schema.items.items.type;
|
|
896
|
-
}
|
|
897
|
-
obj['::props'] = schemaInObjectNotation(schema.items, {}, (level + 1));
|
|
898
|
-
} else {
|
|
899
|
-
const typeObj = getTypeInfo(schema);
|
|
900
|
-
if (typeObj?.html) {
|
|
901
|
-
return `${typeObj.html}`;
|
|
902
|
-
}
|
|
903
|
-
return '';
|
|
904
|
-
}
|
|
905
|
-
return obj;
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
/* Create Example object */
|
|
909
|
-
export function generateExample(schema, mimeType, examples = {}, example = {}, includeReadOnly = true, includeWriteOnly = true, outputType = 'json', includeGeneratedExample = false) {
|
|
910
|
-
const finalExamples = [];
|
|
911
|
-
// First check if examples is provided
|
|
912
|
-
if (examples) {
|
|
913
|
-
for (const eg in examples) {
|
|
914
|
-
let egContent = '';
|
|
915
|
-
let egFormat = 'json';
|
|
916
|
-
if (mimeType?.toLowerCase().includes('json')) {
|
|
917
|
-
if (outputType === 'text') {
|
|
918
|
-
egContent = typeof examples[eg].value === 'string' ? examples[eg].value : JSON.stringify(examples[eg].value, undefined, 2);
|
|
919
|
-
egFormat = 'text';
|
|
920
|
-
} else {
|
|
921
|
-
egContent = examples[eg].value;
|
|
922
|
-
if (typeof examples[eg].value === 'string') {
|
|
923
|
-
try {
|
|
924
|
-
// const fixedJsonString = examples[eg].value.replace((/([\w]+)(:)/g), '"$1"$2').replace((/'/g), '"');
|
|
925
|
-
const fixedJsonString = examples[eg].value;
|
|
926
|
-
egContent = JSON.parse(fixedJsonString);
|
|
927
|
-
egFormat = 'json';
|
|
928
|
-
} catch {
|
|
929
|
-
egFormat = 'text';
|
|
930
|
-
egContent = examples[eg].value;
|
|
931
|
-
}
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
} else {
|
|
935
|
-
egContent = examples[eg].value;
|
|
936
|
-
egFormat = 'text';
|
|
937
|
-
}
|
|
938
|
-
|
|
939
|
-
finalExamples.push({
|
|
940
|
-
exampleId: eg,
|
|
941
|
-
exampleSummary: examples[eg].summary || eg,
|
|
942
|
-
exampleDescription: examples[eg].description || '',
|
|
943
|
-
exampleType: mimeType,
|
|
944
|
-
exampleValue: egContent,
|
|
945
|
-
exampleFormat: egFormat,
|
|
946
|
-
});
|
|
947
|
-
}
|
|
948
|
-
} else if (example) {
|
|
949
|
-
let egContent = '';
|
|
950
|
-
let egFormat = 'json';
|
|
951
|
-
if (mimeType?.toLowerCase().includes('json')) {
|
|
952
|
-
if (outputType === 'text') {
|
|
953
|
-
egContent = typeof example === 'string' ? example : JSON.stringify(example, undefined, 2);
|
|
954
|
-
egFormat = 'text';
|
|
955
|
-
} else if (typeof example === 'object') {
|
|
956
|
-
egContent = example;
|
|
957
|
-
egFormat = 'json';
|
|
958
|
-
} else if (typeof example === 'string') {
|
|
959
|
-
try {
|
|
960
|
-
egContent = JSON.parse(example);
|
|
961
|
-
egFormat = 'json';
|
|
962
|
-
} catch {
|
|
963
|
-
egFormat = 'text';
|
|
964
|
-
egContent = example;
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
} else {
|
|
968
|
-
egContent = example;
|
|
969
|
-
egFormat = 'text';
|
|
970
|
-
}
|
|
971
|
-
finalExamples.push({
|
|
972
|
-
exampleId: 'Example',
|
|
973
|
-
exampleSummary: '',
|
|
974
|
-
exampleDescription: '',
|
|
975
|
-
exampleType: mimeType,
|
|
976
|
-
exampleValue: egContent,
|
|
977
|
-
exampleFormat: egFormat,
|
|
978
|
-
});
|
|
979
|
-
}
|
|
980
|
-
// If schema-level examples are not provided or includeGeneratedExample === true then generate one based on the schema field types
|
|
981
|
-
if (finalExamples.length === 0 || includeGeneratedExample === true) {
|
|
982
|
-
if (schema) {
|
|
983
|
-
if (schema.example) {
|
|
984
|
-
// Note: Deprecated: The 'example' property has been deprecated in 3.1.0 in favor of the JSON Schema 'examples' keyword
|
|
985
|
-
finalExamples.push({
|
|
986
|
-
exampleId: 'Example',
|
|
987
|
-
exampleSummary: '',
|
|
988
|
-
exampleDescription: '',
|
|
989
|
-
exampleType: mimeType,
|
|
990
|
-
exampleValue: schema.example,
|
|
991
|
-
exampleFormat: ((mimeType?.toLowerCase().includes('json') && typeof schema.example === 'object') ? 'json' : 'text'),
|
|
992
|
-
});
|
|
993
|
-
} else if (mimeType?.toLowerCase().includes('json') || mimeType?.toLowerCase().includes('text') || mimeType?.toLowerCase().includes('*/*') || mimeType?.toLowerCase().includes('xml')) {
|
|
994
|
-
let xmlRootStart = '';
|
|
995
|
-
let xmlRootEnd = '';
|
|
996
|
-
let exampleFormat = '';
|
|
997
|
-
let exampleValue = '';
|
|
998
|
-
if (mimeType?.toLowerCase().includes('xml')) {
|
|
999
|
-
xmlRootStart = schema.xml?.name ? `<${schema.xml.name} ${schema.xml.namespace ? `xmlns="${schema.xml.namespace}"` : ''}>` : '<root>';
|
|
1000
|
-
xmlRootEnd = schema.xml?.name ? `</${schema.xml.name}>` : '</root>';
|
|
1001
|
-
exampleFormat = 'text';
|
|
1002
|
-
} else {
|
|
1003
|
-
exampleFormat = outputType;
|
|
1004
|
-
}
|
|
1005
|
-
const samples = schemaToSampleObj(schema, { includeReadOnly, includeWriteOnly, deprecated: true, useXmlTagForProp: mimeType?.toLowerCase().includes('xml') });
|
|
1006
|
-
let i = 0;
|
|
1007
|
-
for (const samplesKey in samples) {
|
|
1008
|
-
if (!samples[samplesKey]) {
|
|
1009
|
-
continue;
|
|
1010
|
-
}
|
|
1011
|
-
const summary = samples[samplesKey]['::TITLE'] || `Example ${++i}`;
|
|
1012
|
-
const description = samples[samplesKey]['::DESCRIPTION'] || '';
|
|
1013
|
-
if (mimeType?.toLowerCase().includes('xml')) {
|
|
1014
|
-
exampleValue = `<?xml version="1.0" encoding="UTF-8"?>\n${xmlRootStart}${json2xml(samples[samplesKey], 1)}\n${xmlRootEnd}`;
|
|
1015
|
-
} else {
|
|
1016
|
-
removeTitlesAndDescriptions(samples[samplesKey]);
|
|
1017
|
-
exampleValue = outputType === 'text' ? JSON.stringify(samples[samplesKey], null, 2) : samples[samplesKey];
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
finalExamples.push({
|
|
1021
|
-
exampleId: samplesKey,
|
|
1022
|
-
exampleSummary: summary,
|
|
1023
|
-
exampleDescription: description,
|
|
1024
|
-
exampleType: mimeType,
|
|
1025
|
-
exampleFormat,
|
|
1026
|
-
exampleValue,
|
|
1027
|
-
});
|
|
1028
|
-
}
|
|
1029
|
-
} else if (mimeType?.toLowerCase().includes('jose')) {
|
|
1030
|
-
finalExamples.push({
|
|
1031
|
-
exampleId: 'Example',
|
|
1032
|
-
exampleSummary: 'Base64 Encoded',
|
|
1033
|
-
exampleDescription: '',
|
|
1034
|
-
exampleType: mimeType,
|
|
1035
|
-
exampleValue: schema.pattern || 'bXJpbg==',
|
|
1036
|
-
exampleFormat: 'text',
|
|
1037
|
-
});
|
|
1038
|
-
} else {
|
|
1039
|
-
finalExamples.push({
|
|
1040
|
-
exampleId: 'Example',
|
|
1041
|
-
exampleSummary: '',
|
|
1042
|
-
exampleDescription: '',
|
|
1043
|
-
exampleType: mimeType,
|
|
1044
|
-
exampleValue: '',
|
|
1045
|
-
exampleFormat: 'text',
|
|
1046
|
-
});
|
|
1047
|
-
}
|
|
1048
|
-
} else {
|
|
1049
|
-
// No Example or Schema provided (should never reach here)
|
|
1050
|
-
finalExamples.push({
|
|
1051
|
-
exampleId: 'Example',
|
|
1052
|
-
exampleSummary: '',
|
|
1053
|
-
exampleDescription: '',
|
|
1054
|
-
exampleType: mimeType,
|
|
1055
|
-
exampleValue: '',
|
|
1056
|
-
exampleFormat: 'text',
|
|
1057
|
-
});
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
return finalExamples;
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1063
|
-
function getSerializeStyleForContentType(contentType) {
|
|
1064
|
-
if (contentType === 'application/json') {
|
|
1065
|
-
return 'json';
|
|
1066
|
-
}
|
|
1067
|
-
if (contentType === 'application/xml') {
|
|
1068
|
-
return 'xml';
|
|
1069
|
-
}
|
|
1070
|
-
return null;
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
export function getSchemaFromParam(param) {
|
|
1074
|
-
if (param.schema) {
|
|
1075
|
-
return [param.schema, null, null];
|
|
1076
|
-
}
|
|
1077
|
-
if (param.content) {
|
|
1078
|
-
// we gonna use the first content-encoding
|
|
1079
|
-
for (const contentType of Object.keys(param.content)) {
|
|
1080
|
-
if (param.content[contentType].schema) {
|
|
1081
|
-
return [param.content[contentType].schema, getSerializeStyleForContentType(contentType), param.content[contentType]];
|
|
1082
|
-
}
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
return [null, null, null];
|
|
1086
|
-
}
|