rapidoc 9.1.3 → 9.1.4
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/dist/index.html +1 -1
- package/dist/index.html.gz +0 -0
- package/dist/rapidoc-min.js +2 -2
- package/dist/rapidoc-min.js.LICENSE.txt +17 -1
- package/dist/rapidoc-min.js.LICENSE.txt.gz +0 -0
- package/dist/rapidoc-min.js.gz +0 -0
- package/dist/report.html +6 -5
- package/docker/Dockerfile +5 -5
- package/docs/api.html +12 -5
- package/docs/examples/dynamic-query-params.html +1 -0
- package/docs/examples/readwrite.html +40 -0
- package/docs/examples.html +3 -2
- package/docs/index.html +2 -2
- package/docs/list.html +6 -2
- package/docs/quickstart.html +1 -1
- package/docs/rapidoc-min.js +2 -2
- package/docs/specs/code-highlight.yaml +1 -1
- package/docs/specs/data-types.yaml +0 -1
- package/docs/specs/examples.yaml +11 -0
- package/docs/specs/petstore_extended.yaml +1 -1
- package/docs/specs/readwrite.yaml +90 -0
- package/docs/specs/temp.json +24 -105
- package/docs/specs/temp.yaml +20 -282
- package/docs/welcome.html +3 -3
- package/index.html +8 -5
- package/package.json +22 -21
- package/src/components/api-request.js +78 -41
- package/src/components/api-response.js +10 -10
- package/src/components/schema-table.js +51 -14
- package/src/components/schema-tree.js +59 -18
- package/src/components/tag-input.js +8 -1
- package/src/json-schema-viewer.js +1 -1
- package/src/rapidoc-mini.js +5 -1
- package/src/rapidoc.js +5 -1
- package/src/styles/font-styles.js +3 -2
- package/src/styles/nav-styles.js +2 -2
- package/src/templates/components-template.js +5 -5
- package/src/templates/endpoint-template.js +1 -1
- package/src/templates/expanded-endpoint-template.js +1 -1
- package/src/templates/focused-endpoint-template.js +1 -1
- package/src/templates/header-template.js +1 -1
- package/src/templates/json-schema-viewer-template.js +8 -8
- package/src/templates/main-body-template.js +4 -1
- package/src/templates/navbar-template.js +2 -2
- package/src/templates/overview-template.js +5 -2
- package/src/templates/security-scheme-template.js +48 -13
- package/src/templates/server-template.js +1 -1
- package/src/utils/common-utils.js +2 -1
- package/src/utils/schema-utils.js +14 -9
- package/src/utils/spec-parser.js +3 -3
- package/webpack.config.js +1 -0
- package/docs/specs/tenants.json +0 -12
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LitElement, html, css } from 'lit-element';
|
|
2
|
-
import marked from 'marked';
|
|
2
|
+
import { marked } from 'marked';
|
|
3
3
|
import { unsafeHTML } from 'lit-html/directives/unsafe-html';
|
|
4
4
|
import FontStyles from '~/styles/font-styles';
|
|
5
5
|
import SchemaStyles from '~/styles/schema-styles';
|
|
@@ -115,7 +115,6 @@ export default class SchemaTree extends LitElement {
|
|
|
115
115
|
this.data['::type'] === 'array' ? this.data['::props'] : this.data,
|
|
116
116
|
this.data['::type'],
|
|
117
117
|
this.data['::array-type'] || '',
|
|
118
|
-
|
|
119
118
|
)}`
|
|
120
119
|
: html`<span class='mono-font' style='color:var(--red)'> Schema not found </span>`
|
|
121
120
|
}
|
|
@@ -123,7 +122,28 @@ export default class SchemaTree extends LitElement {
|
|
|
123
122
|
`;
|
|
124
123
|
}
|
|
125
124
|
|
|
126
|
-
generateTree(data, dataType = 'object', arrayType = '', key = '', description = '', schemaLevel = 0, indentLevel = 0) {
|
|
125
|
+
generateTree(data, dataType = 'object', arrayType = '', key = '', description = '', schemaLevel = 0, indentLevel = 0, readOrWrite = '') {
|
|
126
|
+
if (this.schemaHideReadOnly === 'true') {
|
|
127
|
+
if (dataType === 'array') {
|
|
128
|
+
if (readOrWrite === 'readonly') {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (data['::readwrite'] === 'readonly') {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (this.schemaHideWriteOnly === 'true') {
|
|
137
|
+
if (dataType === 'array') {
|
|
138
|
+
if (readOrWrite === 'writeonly') {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (data['::readwrite'] === 'writeonly') {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
127
147
|
if (!data) {
|
|
128
148
|
return html`<div class="null" style="display:inline;">null</div>`;
|
|
129
149
|
}
|
|
@@ -189,13 +209,13 @@ export default class SchemaTree extends LitElement {
|
|
|
189
209
|
<div class="td key ${data['::deprecated'] ? 'deprecated' : ''}" style='min-width:${minFieldColWidth}px'>
|
|
190
210
|
${data['::type'] === 'xxx-of-option' || data['::type'] === 'xxx-of-array' || key.startsWith('::OPTION')
|
|
191
211
|
? html`<span class='key-label xxx-of-key'>${keyLabel}</span><span class="xxx-of-descr">${keyDescr}</span>`
|
|
192
|
-
: keyLabel
|
|
193
|
-
?
|
|
194
|
-
:
|
|
195
|
-
? ''
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
212
|
+
: keyLabel === '::props' || keyLabel === '::ARRAY~OF'
|
|
213
|
+
? ''
|
|
214
|
+
: schemaLevel > 0
|
|
215
|
+
? html`<span class="key-label" title="${readOrWrite === 'readonly' ? 'Read-Only' : readOrWrite === 'writeonly' ? 'Write-Only' : ''}">
|
|
216
|
+
${keyLabel.replace(/\*$/, '')}${keyLabel.endsWith('*') ? html`<span style="color:var(--red)">*</span>` : ''}${readOrWrite === 'readonly' ? html` 🆁` : readOrWrite === 'writeonly' ? html` 🆆` : readOrWrite}:
|
|
217
|
+
</span>`
|
|
218
|
+
: ''
|
|
199
219
|
}
|
|
200
220
|
${data['::type'] === 'xxx-of' && dataType === 'array' ? html`<span style="color:var(--primary-color)">ARRAY</span>` : ''}
|
|
201
221
|
${openBracket}
|
|
@@ -204,10 +224,10 @@ export default class SchemaTree extends LitElement {
|
|
|
204
224
|
</div>
|
|
205
225
|
<div class='inside-bracket ${data['::type'] || 'no-type-info'}' style='padding-left:${data['::type'] === 'xxx-of-option' || data['::type'] === 'xxx-of-array' ? 0 : leftPadding}px;'>
|
|
206
226
|
${Array.isArray(data) && data[0]
|
|
207
|
-
? html`${this.generateTree(data[0], 'xxx-of-option', '', '::ARRAY~OF', '', newSchemaLevel, newIndentLevel)}`
|
|
227
|
+
? html`${this.generateTree(data[0], 'xxx-of-option', '', '::ARRAY~OF', '', newSchemaLevel, newIndentLevel, data[0]['::readwrite'])}`
|
|
208
228
|
: html`
|
|
209
229
|
${Object.keys(data).map((dataKey) => html`
|
|
210
|
-
${['::description', '::type', '::props', '::deprecated', '::array-type'].includes(dataKey)
|
|
230
|
+
${['::description', '::type', '::props', '::deprecated', '::array-type', '::readwrite'].includes(dataKey)
|
|
211
231
|
? data[dataKey]['::type'] === 'array' || data[dataKey]['::type'] === 'object'
|
|
212
232
|
? html`${this.generateTree(
|
|
213
233
|
data[dataKey]['::type'] === 'array' ? data[dataKey]['::props'] : data[dataKey],
|
|
@@ -217,6 +237,7 @@ export default class SchemaTree extends LitElement {
|
|
|
217
237
|
data[dataKey]['::description'],
|
|
218
238
|
newSchemaLevel,
|
|
219
239
|
newIndentLevel,
|
|
240
|
+
data[dataKey]['::readwrite'] ? data[dataKey]['::readwrite'] : '',
|
|
220
241
|
)}`
|
|
221
242
|
: ''
|
|
222
243
|
: html`${this.generateTree(
|
|
@@ -227,6 +248,7 @@ export default class SchemaTree extends LitElement {
|
|
|
227
248
|
data[dataKey]['::description'],
|
|
228
249
|
newSchemaLevel,
|
|
229
250
|
newIndentLevel,
|
|
251
|
+
data[dataKey]['::readwrite'] ? data[dataKey]['::readwrite'] : '',
|
|
230
252
|
)}`
|
|
231
253
|
}
|
|
232
254
|
`)}
|
|
@@ -240,15 +262,34 @@ export default class SchemaTree extends LitElement {
|
|
|
240
262
|
`;
|
|
241
263
|
}
|
|
242
264
|
|
|
243
|
-
// For Primitive
|
|
244
|
-
const [type,
|
|
245
|
-
if (
|
|
265
|
+
// For Primitive types and array of Primitives
|
|
266
|
+
const [type, primitiveReadOrWrite, constraint, defaultValue, allowedValues, pattern, schemaDescription, , deprecated] = data.split('~|~');
|
|
267
|
+
if (primitiveReadOrWrite === '🆁' && this.schemaHideReadOnly === 'true') {
|
|
246
268
|
return;
|
|
247
269
|
}
|
|
248
|
-
if (
|
|
270
|
+
if (primitiveReadOrWrite === '🆆' && this.schemaHideWriteOnly === 'true') {
|
|
249
271
|
return;
|
|
250
272
|
}
|
|
251
273
|
const dataTypeCss = type.replace(/┃.*/g, '').replace(/[^a-zA-Z0-9+]/g, '').substring(0, 4).toLowerCase();
|
|
274
|
+
|
|
275
|
+
let finalReadWriteText = '';
|
|
276
|
+
let finalReadWriteTip = '';
|
|
277
|
+
if (dataType === 'array') {
|
|
278
|
+
if (readOrWrite === 'readonly') {
|
|
279
|
+
finalReadWriteText = '🆁';
|
|
280
|
+
finalReadWriteTip = 'Read-Only';
|
|
281
|
+
} else if (readOrWrite === 'writeonly') {
|
|
282
|
+
finalReadWriteText = '🆆';
|
|
283
|
+
finalReadWriteTip = 'Write-Only';
|
|
284
|
+
}
|
|
285
|
+
} else if (primitiveReadOrWrite === '🆁') {
|
|
286
|
+
finalReadWriteText = '🆁';
|
|
287
|
+
finalReadWriteTip = 'Read-Only';
|
|
288
|
+
} else if (primitiveReadOrWrite === '🆆') {
|
|
289
|
+
finalReadWriteText = '🆆';
|
|
290
|
+
finalReadWriteTip = 'Write-Only';
|
|
291
|
+
}
|
|
292
|
+
|
|
252
293
|
return html`
|
|
253
294
|
<div class = "tr primitive">
|
|
254
295
|
<div class="td key ${deprecated}" style='min-width:${minFieldColWidth}px' >
|
|
@@ -258,9 +299,9 @@ export default class SchemaTree extends LitElement {
|
|
|
258
299
|
? html`<span class='key-label xxx-of-key'>${keyLabel}</span><span class="xxx-of-descr">${keyDescr}</span>`
|
|
259
300
|
: html`<span class="key-label">${keyLabel}:</span>`
|
|
260
301
|
}
|
|
261
|
-
<span class="${dataTypeCss}" >
|
|
302
|
+
<span class="${dataTypeCss}" title="${finalReadWriteTip}">
|
|
262
303
|
${dataType === 'array' ? `[${type}]` : `${type}`}
|
|
263
|
-
${
|
|
304
|
+
${finalReadWriteText}
|
|
264
305
|
</span>
|
|
265
306
|
</div>
|
|
266
307
|
<div class='td key-descr'>
|
|
@@ -38,7 +38,14 @@ export default class TagInput extends LitElement {
|
|
|
38
38
|
afterPaste(e) {
|
|
39
39
|
const clipboardData = e.clipboardData || window.clipboardData;
|
|
40
40
|
const pastedData = clipboardData.getData('Text');
|
|
41
|
-
|
|
41
|
+
const pastedArray = pastedData ? pastedData.split(',').filter((v) => v.trim() !== '') : '';
|
|
42
|
+
if (pastedArray) {
|
|
43
|
+
if (Array.isArray(this.value)) {
|
|
44
|
+
this.value = [...this.value, ...pastedArray];
|
|
45
|
+
} else {
|
|
46
|
+
this.value = pastedArray;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
42
49
|
e.preventDefault();
|
|
43
50
|
}
|
|
44
51
|
|
package/src/rapidoc-mini.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { css, LitElement } from 'lit-element';
|
|
2
|
-
import marked from 'marked';
|
|
2
|
+
import { marked } from 'marked';
|
|
3
3
|
import Prism from 'prismjs';
|
|
4
4
|
import 'prismjs/components/prism-css';
|
|
5
5
|
import 'prismjs/components/prism-yaml';
|
|
@@ -49,6 +49,7 @@ export default class RapiDocMini extends LitElement {
|
|
|
49
49
|
responseAreaHeight: { type: String, attribute: 'response-area-height' },
|
|
50
50
|
showSummaryWhenCollapsed: { type: String, attribute: 'show-summary-when-collapsed' },
|
|
51
51
|
fillRequestFieldsWithExample: { type: String, attribute: 'fill-request-fields-with-example' },
|
|
52
|
+
persistAuth: { type: String, attribute: 'persist-auth' },
|
|
52
53
|
|
|
53
54
|
// Schema Styles
|
|
54
55
|
schemaStyle: { type: String, attribute: 'schema-style' },
|
|
@@ -166,6 +167,7 @@ export default class RapiDocMini extends LitElement {
|
|
|
166
167
|
if (!this.schemaExpandLevel || this.schemaExpandLevel < 1) { this.schemaExpandLevel = 99999; }
|
|
167
168
|
if (!this.schemaDescriptionExpanded || !'true, false,'.includes(`${this.schemaDescriptionExpanded},`)) { this.schemaDescriptionExpanded = 'false'; }
|
|
168
169
|
if (!this.fillRequestFieldsWithExample || !'true, false,'.includes(`${this.fillRequestFieldsWithExample},`)) { this.fillRequestFieldsWithExample = 'true'; }
|
|
170
|
+
if (!this.persistAuth || !'true, false,'.includes(`${this.persistAuth},`)) { this.persistAuth = 'false'; }
|
|
169
171
|
if (!this.responseAreaHeight) { this.responseAreaHeight = '300px'; }
|
|
170
172
|
|
|
171
173
|
if (!this.allowTry || !'true, false,'.includes(`${this.allowTry},`)) { this.allowTry = 'true'; }
|
|
@@ -318,6 +320,8 @@ export default class RapiDocMini extends LitElement {
|
|
|
318
320
|
}
|
|
319
321
|
}
|
|
320
322
|
this.requestUpdate();
|
|
323
|
+
// eslint-disable-next-line no-await-in-loop
|
|
324
|
+
while (!await this.updateComplete);
|
|
321
325
|
const specLoadedEvent = new CustomEvent('spec-loaded', { detail: spec });
|
|
322
326
|
this.dispatchEvent(specLoadedEvent);
|
|
323
327
|
}
|
package/src/rapidoc.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { css, LitElement, unsafeCSS } from 'lit-element';
|
|
2
|
-
import marked from 'marked';
|
|
2
|
+
import { marked } from 'marked';
|
|
3
3
|
import Prism from 'prismjs';
|
|
4
4
|
import 'prismjs/components/prism-css';
|
|
5
5
|
import 'prismjs/components/prism-yaml';
|
|
@@ -63,6 +63,7 @@ export default class RapiDoc extends LitElement {
|
|
|
63
63
|
defaultSchemaTab: { type: String, attribute: 'default-schema-tab' },
|
|
64
64
|
responseAreaHeight: { type: String, attribute: 'response-area-height' },
|
|
65
65
|
fillRequestFieldsWithExample: { type: String, attribute: 'fill-request-fields-with-example' },
|
|
66
|
+
persistAuth: { type: String, attribute: 'persist-auth' },
|
|
66
67
|
onNavTagClick: { type: String, attribute: 'on-nav-tag-click' },
|
|
67
68
|
|
|
68
69
|
// Schema Styles
|
|
@@ -434,6 +435,7 @@ export default class RapiDoc extends LitElement {
|
|
|
434
435
|
this.schemaHideReadOnly += ['get', 'head', 'delete', 'options'];
|
|
435
436
|
this.schemaHideWriteOnly = this.schemaHideWriteOnly !== 'never';
|
|
436
437
|
if (!this.fillRequestFieldsWithExample || !'true, false,'.includes(`${this.fillRequestFieldsWithExample},`)) { this.fillRequestFieldsWithExample = 'true'; }
|
|
438
|
+
if (!this.persistAuth || !'true, false,'.includes(`${this.persistAuth},`)) { this.persistAuth = 'false'; }
|
|
437
439
|
if (!this.onNavTagClick || !'expand-collapse, show-description,'.includes(`${this.onNavTagClick},`)) { this.onNavTagClick = 'expand-collapse'; }
|
|
438
440
|
if (!this.responseAreaHeight) {
|
|
439
441
|
this.responseAreaHeight = '300px';
|
|
@@ -709,6 +711,8 @@ export default class RapiDoc extends LitElement {
|
|
|
709
711
|
}
|
|
710
712
|
}
|
|
711
713
|
this.requestUpdate();
|
|
714
|
+
// eslint-disable-next-line no-await-in-loop
|
|
715
|
+
while (!await this.updateComplete);
|
|
712
716
|
const specLoadedEvent = new CustomEvent('spec-loaded', { detail: spec });
|
|
713
717
|
this.dispatchEvent(specLoadedEvent);
|
|
714
718
|
|
|
@@ -88,8 +88,9 @@ export default css`
|
|
|
88
88
|
font-size: var(--font-size-regular);
|
|
89
89
|
line-height:calc(var(--font-size-regular) + 8px);
|
|
90
90
|
}
|
|
91
|
-
.m-markdown li{
|
|
92
|
-
|
|
91
|
+
.m-markdown li {
|
|
92
|
+
font-size: var(--font-size-regular);
|
|
93
|
+
line-height:calc(var(--font-size-regular) + 10px);
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
.m-markdown-small p,
|
package/src/styles/nav-styles.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { html } from 'lit-element';
|
|
2
2
|
import { unsafeHTML } from 'lit-html/directives/unsafe-html';
|
|
3
|
-
import marked from 'marked';
|
|
3
|
+
import { marked } from 'marked';
|
|
4
4
|
import { schemaInObjectNotation } from '~/utils/schema-utils';
|
|
5
5
|
import '~/components/json-tree';
|
|
6
6
|
import '~/components/schema-tree';
|
|
@@ -19,8 +19,8 @@ function schemaBodyTemplate(sComponent) {
|
|
|
19
19
|
schema-expand-level = "${this.schemaExpandLevel}"
|
|
20
20
|
schema-description-expanded = "${this.schemaDescriptionExpanded}"
|
|
21
21
|
allow-schema-description-expand-toggle = "${this.allowSchemaDescriptionExpandToggle}",
|
|
22
|
-
schema-hide-read-only = false
|
|
23
|
-
schema-hide-write-only = ${this.schemaHideWriteOnly}
|
|
22
|
+
schema-hide-read-only = "false"
|
|
23
|
+
schema-hide-write-only = "${this.schemaHideWriteOnly}"
|
|
24
24
|
> </schema-tree> `
|
|
25
25
|
: html`
|
|
26
26
|
<schema-tree
|
|
@@ -29,8 +29,8 @@ function schemaBodyTemplate(sComponent) {
|
|
|
29
29
|
schema-expand-level = "${this.schemaExpandLevel}"
|
|
30
30
|
schema-description-expanded = "${this.schemaDescriptionExpanded}"
|
|
31
31
|
allow-schema-description-expand-toggle = "${this.allowSchemaDescriptionExpandToggle}",
|
|
32
|
-
schema-hide-read-only = false
|
|
33
|
-
schema-hide-write-only = ${this.schemaHideWriteOnly}
|
|
32
|
+
schema-hide-read-only = "false"
|
|
33
|
+
schema-hide-write-only = "${this.schemaHideWriteOnly}"
|
|
34
34
|
> </schema-tree>`
|
|
35
35
|
}
|
|
36
36
|
</div>`;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { html } from 'lit-element';
|
|
2
2
|
import { unsafeHTML } from 'lit-html/directives/unsafe-html';
|
|
3
|
-
import marked from 'marked';
|
|
3
|
+
import { marked } from 'marked';
|
|
4
4
|
import '~/components/api-request';
|
|
5
5
|
import '~/components/api-response';
|
|
6
6
|
import codeSamplesTemplate from '~/templates/code-samples-template';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { html } from 'lit-element';
|
|
2
2
|
import { unsafeHTML } from 'lit-html/directives/unsafe-html';
|
|
3
|
-
import marked from 'marked';
|
|
3
|
+
import { marked } from 'marked';
|
|
4
4
|
import { rapidocApiKey } from '~/utils/common-utils';
|
|
5
5
|
import { pathSecurityTemplate } from '~/templates/security-scheme-template';
|
|
6
6
|
import codeSamplesTemplate from '~/templates/code-samples-template';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { html } from 'lit-element';
|
|
2
2
|
import { unsafeHTML } from 'lit-html/directives/unsafe-html';
|
|
3
|
-
import marked from 'marked';
|
|
3
|
+
import { marked } from 'marked';
|
|
4
4
|
import { expandedEndpointBodyTemplate } from '~/templates/expanded-endpoint-template';
|
|
5
5
|
import '~/components/api-request';
|
|
6
6
|
import '~/components/api-response';
|
|
@@ -52,7 +52,7 @@ export default function headerTemplate() {
|
|
|
52
52
|
`
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
${(this.
|
|
55
|
+
${(this.allowAdvancedSearch === 'false' || 'read focused'.includes(this.renderStyle))
|
|
56
56
|
? ''
|
|
57
57
|
: html`
|
|
58
58
|
<button class="m-btn primary only-large-screen" part="btn btn-fill btn-search" style="margin-left:10px;" @click="${this.onShowSearchModalClicked}">
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { html } from 'lit-element';
|
|
2
|
-
import marked from 'marked';
|
|
2
|
+
import { marked } from 'marked';
|
|
3
3
|
import { unsafeHTML } from 'lit-html/directives/unsafe-html';
|
|
4
4
|
|
|
5
5
|
// Templates
|
|
@@ -49,7 +49,7 @@ function jsonSchemaBodyTemplate() {
|
|
|
49
49
|
${this.showInfo === 'true' ? overviewTemplate.call(this) : ''}
|
|
50
50
|
<div style="font-size:var(--font-size-regular);">
|
|
51
51
|
${this.resolvedSpec.schemaAndExamples.map((jSchemaBody) => {
|
|
52
|
-
const examplesObj = generateExample(jSchemaBody.
|
|
52
|
+
const examplesObj = generateExample(jSchemaBody.schema, 'json', jSchemaBody.examples, jSchemaBody.example, true, false, 'json', true);
|
|
53
53
|
jSchemaBody.selectedExample = examplesObj[0]?.exampleId;
|
|
54
54
|
return html`
|
|
55
55
|
<section id='${jSchemaBody.elementId}' class='json-schema-and-example regular-font' style="display:flex; flex-direction: column; border:1px solid var(--border-color); margin-bottom:32px; border-top: 5px solid var(--border-color)">
|
|
@@ -60,12 +60,12 @@ function jsonSchemaBodyTemplate() {
|
|
|
60
60
|
<div style="display:flex; flex-direction: row; gap:16px;">
|
|
61
61
|
<div class="json-schema-def" style="flex:1; padding:16px 0 16px 16px; ">
|
|
62
62
|
<schema-tree
|
|
63
|
-
.data =
|
|
63
|
+
.data = "${schemaInObjectNotation(jSchemaBody.schema, {})}"
|
|
64
64
|
schema-expand-level = "${this.schemaExpandLevel}"
|
|
65
65
|
schema-description-expanded = "${this.schemaDescriptionExpanded}"
|
|
66
66
|
allow-schema-description-expand-toggle = "${this.allowSchemaDescriptionExpandToggle}",
|
|
67
|
-
schema-hide-read-only = false
|
|
68
|
-
schema-hide-write-only = false
|
|
67
|
+
schema-hide-read-only = "false"
|
|
68
|
+
schema-hide-write-only = "false"
|
|
69
69
|
> </schema-tree>
|
|
70
70
|
</div>
|
|
71
71
|
<div class="json-schema-example-panel" style="width:400px; background-color: var(--input-bg); padding:16px 0 16px 16px; border-left: 1px dashed var(--border-color);">
|
|
@@ -81,9 +81,9 @@ function jsonSchemaBodyTemplate() {
|
|
|
81
81
|
}
|
|
82
82
|
${examplesObj.map((v) => html`
|
|
83
83
|
<json-tree
|
|
84
|
-
.data="${v.exampleValue}"
|
|
85
|
-
data-example =
|
|
86
|
-
class =
|
|
84
|
+
.data = "${v.exampleValue}"
|
|
85
|
+
data-example = "${v.exampleId}"
|
|
86
|
+
class = "example"
|
|
87
87
|
style = "margin-top:16px; display: ${v.exampleId === jSchemaBody.selectedExample ? 'flex' : 'none'}"
|
|
88
88
|
></json-tree>`)
|
|
89
89
|
}
|
|
@@ -6,7 +6,7 @@ import focusedEndpointTemplate from '~/templates/focused-endpoint-template';
|
|
|
6
6
|
import overviewTemplate from '~/templates/overview-template';
|
|
7
7
|
import endpointTemplate from '~/templates/endpoint-template';
|
|
8
8
|
import serverTemplate from '~/templates/server-template';
|
|
9
|
-
import securitySchemeTemplate from '~/templates/security-scheme-template';
|
|
9
|
+
import securitySchemeTemplate, { recoverPersistedApiKeys } from '~/templates/security-scheme-template';
|
|
10
10
|
import headerTemplate from '~/templates/header-template';
|
|
11
11
|
import navbarTemplate from '~/templates/navbar-template';
|
|
12
12
|
import advancedSearchTemplate from '~/templates/advance-search-template';
|
|
@@ -17,6 +17,9 @@ export default function mainBodyTemplate(isMini = false, showExpandCollapse = tr
|
|
|
17
17
|
if (!this.resolvedSpec) {
|
|
18
18
|
return '';
|
|
19
19
|
}
|
|
20
|
+
if (this.persistAuth === 'true') {
|
|
21
|
+
recoverPersistedApiKeys.call(this);
|
|
22
|
+
}
|
|
20
23
|
const newTheme = {
|
|
21
24
|
bg1: isValidHexColor(this.bgColor) ? this.bgColor : '',
|
|
22
25
|
fg1: isValidHexColor(this.textColor) ? this.textColor : '',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { html } from 'lit-element';
|
|
2
|
-
import marked from 'marked';
|
|
2
|
+
import { marked } from 'marked';
|
|
3
3
|
import { pathIsInSearch } from '~/utils/common-utils';
|
|
4
4
|
|
|
5
5
|
export function expandCollapseNavBarTag(navLinkEl, action = 'toggle') {
|
|
@@ -50,7 +50,7 @@ export default function navbarTemplate() {
|
|
|
50
50
|
${(this.allowSearch === 'false' && this.allowAdvancedSearch === 'false')
|
|
51
51
|
? ''
|
|
52
52
|
: html`
|
|
53
|
-
<div style="display:flex; flex-direction:row; justify-content:center; align-items:center; padding:24px; ${this.allowAdvancedSearch === 'false' ? 'border-bottom: 1px solid var(--nav-hover-bg-color)' : ''}">
|
|
53
|
+
<div style="display:flex; flex-direction:row; justify-content:center; align-items:center; padding:8px 24px 12px 24px; ${this.allowAdvancedSearch === 'false' ? 'border-bottom: 1px solid var(--nav-hover-bg-color)' : ''}">
|
|
54
54
|
${this.allowSearch === 'false'
|
|
55
55
|
? ''
|
|
56
56
|
: html`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { html } from 'lit-element';
|
|
2
2
|
import { unsafeHTML } from 'lit-html/directives/unsafe-html';
|
|
3
|
-
import marked from 'marked';
|
|
3
|
+
import { marked } from 'marked';
|
|
4
4
|
import { downloadResource, viewResource } from '~/utils/common-utils';
|
|
5
5
|
|
|
6
6
|
/* eslint-disable indent */
|
|
@@ -51,7 +51,10 @@ export default function overviewTemplate() {
|
|
|
51
51
|
? html`
|
|
52
52
|
<div style="display:flex; margin:12px 0; gap:8px; justify-content: start;">
|
|
53
53
|
<button class="m-btn thin-border" style="width:170px" part="btn btn-outline" @click='${(e) => { downloadResource(this.specUrl, 'openapi-spec', e); }}'>Download OpenAPI spec</button>
|
|
54
|
-
|
|
54
|
+
${this.specUrl?.trim().toLowerCase().endsWith('json')
|
|
55
|
+
? html`<button class="m-btn thin-border" style="width:200px" part="btn btn-outline" @click='${(e) => { viewResource(this.specUrl, e); }}'>View OpenAPI spec (New Tab)</button>`
|
|
56
|
+
: ''
|
|
57
|
+
}
|
|
55
58
|
</div>`
|
|
56
59
|
: ''
|
|
57
60
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/* eslint-disable arrow-body-style */
|
|
2
2
|
import { html } from 'lit-element';
|
|
3
3
|
import { unsafeHTML } from 'lit-html/directives/unsafe-html';
|
|
4
|
-
import marked from 'marked';
|
|
4
|
+
import { marked } from 'marked';
|
|
5
5
|
|
|
6
6
|
const codeVerifier = '731DB1C3F7EA533B85E29492D26AA-1234567890-1234567890';
|
|
7
7
|
const codeChallenge = '4FatVDBJKPAo4JgLLaaQFMUcQPn5CrPRvLlaob9PTYc'; // Base64 encoded SHA-256
|
|
8
8
|
|
|
9
|
+
const localStorageKey = 'rapidoc';
|
|
10
|
+
|
|
9
11
|
export function applyApiKey(securitySchemeId, username = '', password = '', providedApikeyVal = '') {
|
|
10
12
|
const securityObj = this.resolvedSpec.securitySchemes?.find((v) => (v.securitySchemeId === securitySchemeId));
|
|
11
13
|
if (!securityObj) {
|
|
@@ -17,7 +19,8 @@ export function applyApiKey(securitySchemeId, username = '', password = '', prov
|
|
|
17
19
|
finalApiKeyValue = `Basic ${btoa(`${username}:${password}`)}`;
|
|
18
20
|
}
|
|
19
21
|
} else if (providedApikeyVal) {
|
|
20
|
-
|
|
22
|
+
securityObj.value = providedApikeyVal;
|
|
23
|
+
finalApiKeyValue = `${securityObj.scheme?.toLowerCase() === 'bearer' ? 'Bearer ' : ''}${providedApikeyVal}`;
|
|
21
24
|
}
|
|
22
25
|
if (finalApiKeyValue) {
|
|
23
26
|
securityObj.finalKeyValue = finalApiKeyValue;
|
|
@@ -37,6 +40,21 @@ export function onClearAllApiKeys() {
|
|
|
37
40
|
this.requestUpdate();
|
|
38
41
|
}
|
|
39
42
|
|
|
43
|
+
function getPersistedApiKeys() {
|
|
44
|
+
return JSON.parse(localStorage.getItem(localStorageKey)) || {};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function setPersistedApiKeys(obj) {
|
|
48
|
+
localStorage.setItem(localStorageKey, JSON.stringify(obj));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function recoverPersistedApiKeys() {
|
|
52
|
+
const rapidocLs = getPersistedApiKeys.call(this);
|
|
53
|
+
Object.values(rapidocLs).forEach((p) => {
|
|
54
|
+
applyApiKey.call(this, p.securitySchemeId, p.username, p.password, p.value);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
40
58
|
function onApiKeyChange(securitySchemeId) {
|
|
41
59
|
let apiKeyValue = '';
|
|
42
60
|
const securityObj = this.resolvedSpec.securitySchemes.find((v) => (v.securitySchemeId === securitySchemeId));
|
|
@@ -51,12 +69,17 @@ function onApiKeyChange(securitySchemeId) {
|
|
|
51
69
|
apiKeyValue = trEl.querySelector('.api-key-input').value.trim();
|
|
52
70
|
applyApiKey.call(this, securitySchemeId, '', '', apiKeyValue);
|
|
53
71
|
}
|
|
72
|
+
if (this.persistAuth === 'true') {
|
|
73
|
+
const rapidocLs = getPersistedApiKeys.call(this);
|
|
74
|
+
rapidocLs[securitySchemeId] = securityObj;
|
|
75
|
+
setPersistedApiKeys.call(this, rapidocLs);
|
|
76
|
+
}
|
|
54
77
|
}
|
|
55
78
|
}
|
|
56
79
|
}
|
|
57
80
|
|
|
58
81
|
// Updates the OAuth Access Token (API key), so it reflects in UI and gets used in TRY calls
|
|
59
|
-
function updateOAuthKey(securitySchemeId, tokenType = 'Bearer'
|
|
82
|
+
function updateOAuthKey(securitySchemeId, accessToken, tokenType = 'Bearer') {
|
|
60
83
|
const securityObj = this.resolvedSpec.securitySchemes.find((v) => (v.securitySchemeId === securitySchemeId));
|
|
61
84
|
securityObj.finalKeyValue = `${(tokenType.toLowerCase() === 'bearer' ? 'Bearer' : (tokenType.toLowerCase() === 'mac' ? 'MAC' : tokenType))} ${accessToken}`;
|
|
62
85
|
this.requestUpdate();
|
|
@@ -64,7 +87,7 @@ function updateOAuthKey(securitySchemeId, tokenType = 'Bearer', accessToken) {
|
|
|
64
87
|
|
|
65
88
|
/* eslint-disable no-console */
|
|
66
89
|
// Gets Access-Token in exchange of Authorization Code
|
|
67
|
-
async function fetchAccessToken(tokenUrl, clientId, clientSecret, redirectUrl, grantType, authCode, sendClientSecretIn = 'header',
|
|
90
|
+
async function fetchAccessToken(tokenUrl, clientId, clientSecret, redirectUrl, grantType, authCode, securitySchemeId, authFlowDivEl, sendClientSecretIn = 'header', scopes = null, username = null, password = null) {
|
|
68
91
|
const respDisplayEl = authFlowDivEl ? authFlowDivEl.querySelector('.oauth-resp-display') : undefined;
|
|
69
92
|
const urlFormParams = new URLSearchParams();
|
|
70
93
|
const headers = new Headers();
|
|
@@ -95,7 +118,7 @@ async function fetchAccessToken(tokenUrl, clientId, clientSecret, redirectUrl, g
|
|
|
95
118
|
const tokenResp = await resp.json();
|
|
96
119
|
if (resp.ok) {
|
|
97
120
|
if (tokenResp.token_type && tokenResp.access_token) {
|
|
98
|
-
updateOAuthKey.call(this, securitySchemeId, tokenResp.
|
|
121
|
+
updateOAuthKey.call(this, securitySchemeId, tokenResp.access_token, tokenResp.token_type);
|
|
99
122
|
if (respDisplayEl) {
|
|
100
123
|
respDisplayEl.innerHTML = '<span style="color:var(--green)">Access Token Received</span>';
|
|
101
124
|
}
|
|
@@ -131,10 +154,10 @@ async function onWindowMessageEvent(msgEvent, winObj, tokenUrl, clientId, client
|
|
|
131
154
|
if (msgEvent.data) {
|
|
132
155
|
if (msgEvent.data.responseType === 'code') {
|
|
133
156
|
// Authorization Code flow
|
|
134
|
-
fetchAccessToken.call(this, tokenUrl, clientId, clientSecret, redirectUrl, grantType, msgEvent.data.code,
|
|
157
|
+
fetchAccessToken.call(this, tokenUrl, clientId, clientSecret, redirectUrl, grantType, msgEvent.data.code, securitySchemeId, authFlowDivEl, sendClientSecretIn);
|
|
135
158
|
} else if (msgEvent.data.responseType === 'token') {
|
|
136
159
|
// Implicit flow
|
|
137
|
-
updateOAuthKey.call(this, securitySchemeId, msgEvent.data.
|
|
160
|
+
updateOAuthKey.call(this, securitySchemeId, msgEvent.data.access_token, msgEvent.data.token_type);
|
|
138
161
|
}
|
|
139
162
|
}
|
|
140
163
|
}
|
|
@@ -218,11 +241,11 @@ async function onInvokeOAuthFlow(securitySchemeId, flowType, authUrl, tokenUrl,
|
|
|
218
241
|
} else if (flowType === 'clientCredentials') {
|
|
219
242
|
grantType = 'client_credentials';
|
|
220
243
|
const selectedScopes = checkedScopeEls.map((v) => v.value).join(' ');
|
|
221
|
-
fetchAccessToken.call(this, tokenUrl, clientId, clientSecret, redirectUrlObj.toString(), grantType, '',
|
|
244
|
+
fetchAccessToken.call(this, tokenUrl, clientId, clientSecret, redirectUrlObj.toString(), grantType, '', securitySchemeId, authFlowDivEl, sendClientSecretIn, selectedScopes);
|
|
222
245
|
} else if (flowType === 'password') {
|
|
223
246
|
grantType = 'password';
|
|
224
247
|
const selectedScopes = checkedScopeEls.map((v) => v.value).join(' ');
|
|
225
|
-
fetchAccessToken.call(this, tokenUrl, clientId, clientSecret, redirectUrlObj.toString(), grantType, '',
|
|
248
|
+
fetchAccessToken.call(this, tokenUrl, clientId, clientSecret, redirectUrlObj.toString(), grantType, '', securitySchemeId, authFlowDivEl, sendClientSecretIn, selectedScopes, username, password);
|
|
226
249
|
}
|
|
227
250
|
}
|
|
228
251
|
/* eslint-enable no-console */
|
|
@@ -339,6 +362,20 @@ function oAuthFlowTemplate(flowName, clientId, clientSecret, securitySchemeId, a
|
|
|
339
362
|
`;
|
|
340
363
|
}
|
|
341
364
|
|
|
365
|
+
function removeApiKey(securitySchemeId) {
|
|
366
|
+
const securityObj = this.resolvedSpec.securitySchemes?.find((v) => (v.securitySchemeId === securitySchemeId));
|
|
367
|
+
securityObj.user = '';
|
|
368
|
+
securityObj.password = '';
|
|
369
|
+
securityObj.value = '';
|
|
370
|
+
securityObj.finalKeyValue = '';
|
|
371
|
+
if (this.persistAuth === 'true') {
|
|
372
|
+
const rapidocLs = getPersistedApiKeys.call(this);
|
|
373
|
+
delete rapidocLs[securityObj.securitySchemeId];
|
|
374
|
+
setPersistedApiKeys.call(this, rapidocLs);
|
|
375
|
+
}
|
|
376
|
+
this.requestUpdate();
|
|
377
|
+
}
|
|
378
|
+
|
|
342
379
|
export default function securitySchemeTemplate() {
|
|
343
380
|
if (!this.resolvedSpec) { return ''; }
|
|
344
381
|
const providedApiKeys = this.resolvedSpec.securitySchemes?.filter((v) => (v.finalKeyValue));
|
|
@@ -369,7 +406,7 @@ export default function securitySchemeTemplate() {
|
|
|
369
406
|
${v.finalKeyValue
|
|
370
407
|
? html`
|
|
371
408
|
<span class='blue-text'> ${v.finalKeyValue ? 'Key Applied' : ''} </span>
|
|
372
|
-
<button class="m-btn thin-border small" part="btn btn-outline" @click=${() => {
|
|
409
|
+
<button class="m-btn thin-border small" part="btn btn-outline" @click=${() => { removeApiKey.call(this, v.securitySchemeId); }}>REMOVE</button>
|
|
373
410
|
`
|
|
374
411
|
: ''
|
|
375
412
|
}
|
|
@@ -427,9 +464,7 @@ export default function securitySchemeTemplate() {
|
|
|
427
464
|
? html`
|
|
428
465
|
<tr>
|
|
429
466
|
<td style="border:none; padding-left:48px">
|
|
430
|
-
${Object.keys(v.flows).map((f) => oAuthFlowTemplate.call(
|
|
431
|
-
this, f, v['x-client-id'], v['x-client-secret'], v.securitySchemeId, v.flows[f],
|
|
432
|
-
))}
|
|
467
|
+
${Object.keys(v.flows).map((f) => oAuthFlowTemplate.call(this, f, v['x-client-id'], v['x-client-secret'], v.securitySchemeId, v.flows[f]))}
|
|
433
468
|
</td>
|
|
434
469
|
</tr>
|
|
435
470
|
`
|
|
@@ -10,10 +10,11 @@ export function debounce(fn, delay) {
|
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export const invalidCharsRegEx =
|
|
13
|
+
export const invalidCharsRegEx = /[\s#:?&={}]/g; // used for generating valid html element ids by replacing the invalid chars with hyphen (-)
|
|
14
14
|
export const rapidocApiKey = '_rapidoc_api_key';
|
|
15
15
|
|
|
16
16
|
export function sleep(ms) {
|
|
17
|
+
// eslint-disable-next-line no-promise-executor-return
|
|
17
18
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
18
19
|
}
|
|
19
20
|
|