openapi-explorer 0.9.310 → 0.9.314

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.
Files changed (121) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/dist/{openapi-explorer.min.js → browser/openapi-explorer.min.js} +3 -3
  3. package/dist/{openapi-explorer.min.js.map → browser/openapi-explorer.min.js.map} +0 -0
  4. package/dist/es/components/api-request.js +936 -0
  5. package/dist/es/components/api-response.js +184 -0
  6. package/dist/es/components/json-tree.js +67 -0
  7. package/{src → dist/es}/components/mime-types.js +11 -17
  8. package/dist/es/components/schema-table.js +156 -0
  9. package/dist/es/components/schema-tree.js +191 -0
  10. package/dist/es/components/tag-input.js +67 -0
  11. package/{src → dist/es}/openapi-explorer-oauth-handler.js +2 -2
  12. package/{src → dist/es}/openapi-explorer.js +364 -371
  13. package/dist/es/styles/advanced-search-styles.js +2 -0
  14. package/dist/es/styles/api-request-styles.js +2 -0
  15. package/dist/es/styles/border-styles.js +2 -0
  16. package/dist/es/styles/endpoint-styles.js +2 -0
  17. package/dist/es/styles/flex-styles.js +2 -0
  18. package/dist/es/styles/font-styles.js +2 -0
  19. package/dist/es/styles/info-styles.js +2 -0
  20. package/dist/es/styles/input-styles.js +4 -0
  21. package/dist/es/styles/nav-styles.js +2 -0
  22. package/dist/es/styles/prism-styles.js +2 -0
  23. package/dist/es/styles/schema-styles.js +2 -0
  24. package/dist/es/styles/tab-styles.js +2 -0
  25. package/dist/es/styles/table-styles.js +2 -0
  26. package/dist/es/templates/advance-search-template.js +37 -0
  27. package/dist/es/templates/callback-template.js +7 -0
  28. package/dist/es/templates/code-samples-template.js +26 -0
  29. package/dist/es/templates/components-template.js +17 -0
  30. package/dist/es/templates/endpoint-template.js +94 -0
  31. package/dist/es/templates/expanded-endpoint-template.js +32 -0
  32. package/{src → dist/es}/templates/focused-endpoint-template.js +15 -15
  33. package/dist/es/templates/navbar-template.js +46 -0
  34. package/dist/es/templates/overview-template.js +9 -0
  35. package/dist/es/templates/responsiveViewMainBodyTemplate.js +30 -0
  36. package/dist/es/templates/security-scheme-template.js +330 -0
  37. package/dist/es/templates/server-template.js +42 -0
  38. package/{src → dist/es}/utils/color-utils.js +53 -16
  39. package/{src → dist/es}/utils/common-utils.js +18 -18
  40. package/{src → dist/es}/utils/schema-utils.js +248 -124
  41. package/{src → dist/es}/utils/spec-parser.js +112 -71
  42. package/dist/es/utils/theme.js +75 -0
  43. package/{src → dist/es}/utils/xml/xml.js +41 -38
  44. package/dist/lib/components/api-request.js +957 -0
  45. package/dist/lib/components/api-response.js +206 -0
  46. package/dist/lib/components/json-tree.js +82 -0
  47. package/dist/lib/components/mime-types.js +70 -0
  48. package/dist/lib/components/schema-table.js +170 -0
  49. package/dist/lib/components/schema-tree.js +206 -0
  50. package/dist/lib/components/tag-input.js +76 -0
  51. package/dist/lib/openapi-explorer-oauth-handler.js +19 -0
  52. package/dist/lib/openapi-explorer.js +817 -0
  53. package/dist/lib/styles/advanced-search-styles.js +10 -0
  54. package/dist/lib/styles/api-request-styles.js +10 -0
  55. package/dist/lib/styles/border-styles.js +10 -0
  56. package/dist/lib/styles/endpoint-styles.js +10 -0
  57. package/dist/lib/styles/flex-styles.js +10 -0
  58. package/dist/lib/styles/font-styles.js +10 -0
  59. package/dist/lib/styles/info-styles.js +10 -0
  60. package/dist/lib/styles/input-styles.js +11 -0
  61. package/dist/lib/styles/nav-styles.js +10 -0
  62. package/dist/lib/styles/prism-styles.js +10 -0
  63. package/dist/lib/styles/schema-styles.js +10 -0
  64. package/dist/lib/styles/tab-styles.js +10 -0
  65. package/dist/lib/styles/table-styles.js +10 -0
  66. package/dist/lib/templates/advance-search-template.js +42 -0
  67. package/dist/lib/templates/callback-template.js +12 -0
  68. package/dist/lib/templates/code-samples-template.js +36 -0
  69. package/dist/lib/templates/components-template.js +27 -0
  70. package/dist/lib/templates/endpoint-template.js +111 -0
  71. package/dist/lib/templates/expanded-endpoint-template.js +48 -0
  72. package/dist/lib/templates/focused-endpoint-template.js +95 -0
  73. package/dist/lib/templates/navbar-template.js +54 -0
  74. package/dist/lib/templates/overview-template.js +16 -0
  75. package/dist/lib/templates/responsiveViewMainBodyTemplate.js +47 -0
  76. package/dist/lib/templates/security-scheme-template.js +342 -0
  77. package/dist/lib/templates/server-template.js +49 -0
  78. package/dist/lib/utils/color-utils.js +112 -0
  79. package/dist/lib/utils/common-utils.js +156 -0
  80. package/dist/lib/utils/schema-utils.js +743 -0
  81. package/dist/lib/utils/spec-parser.js +361 -0
  82. package/dist/lib/utils/theme.js +84 -0
  83. package/dist/lib/utils/xml/xml.js +239 -0
  84. package/package.json +19 -6
  85. package/dist/openapi-explorer.min.js.LICENSE.txt +0 -71
  86. package/dist/openapi-explorer.min.js.LICENSE.txt.gz +0 -0
  87. package/dist/openapi-explorer.min.js.gz +0 -0
  88. package/dist/openapi-explorer.min.js.map.gz +0 -0
  89. package/dist/report.html +0 -38
  90. package/src/components/api-request.js +0 -1244
  91. package/src/components/api-response.js +0 -340
  92. package/src/components/json-tree.js +0 -129
  93. package/src/components/schema-table.js +0 -250
  94. package/src/components/schema-tree.js +0 -280
  95. package/src/components/tag-input.js +0 -109
  96. package/src/styles/advanced-search-styles.js +0 -84
  97. package/src/styles/api-request-styles.js +0 -111
  98. package/src/styles/border-styles.js +0 -24
  99. package/src/styles/css/main.css +0 -24
  100. package/src/styles/endpoint-styles.js +0 -222
  101. package/src/styles/flex-styles.js +0 -15
  102. package/src/styles/font-styles.js +0 -266
  103. package/src/styles/info-styles.js +0 -20
  104. package/src/styles/input-styles.js +0 -236
  105. package/src/styles/nav-styles.js +0 -141
  106. package/src/styles/prism-styles.js +0 -107
  107. package/src/styles/schema-styles.js +0 -121
  108. package/src/styles/tab-styles.js +0 -44
  109. package/src/styles/table-styles.js +0 -48
  110. package/src/templates/advance-search-template.js +0 -81
  111. package/src/templates/callback-template.js +0 -63
  112. package/src/templates/code-samples-template.js +0 -35
  113. package/src/templates/components-template.js +0 -43
  114. package/src/templates/endpoint-template.js +0 -175
  115. package/src/templates/expanded-endpoint-template.js +0 -104
  116. package/src/templates/navbar-template.js +0 -175
  117. package/src/templates/overview-template.js +0 -58
  118. package/src/templates/responsiveViewMainBodyTemplate.js +0 -72
  119. package/src/templates/security-scheme-template.js +0 -487
  120. package/src/templates/server-template.js +0 -106
  121. package/src/utils/theme.js +0 -163
@@ -1,487 +0,0 @@
1
- import { html } from 'lit-element';
2
- import { unsafeHTML } from 'lit-html/directives/unsafe-html';
3
- import { marked } from 'marked';
4
- import base64url from 'base64url';
5
-
6
- function onApiKeyChange(apiKeyId, e) {
7
- let apiKeyValue = '';
8
- const securityObj = this.resolvedSpec.securitySchemes.find((v) => (v.apiKeyId === apiKeyId));
9
- if (!securityObj) {
10
- return;
11
- }
12
-
13
- const trEl = e.target.closest('tr');
14
- if (securityObj.type && securityObj.type === 'http' && securityObj.scheme && securityObj.scheme.toLowerCase() === 'basic') {
15
- const userVal = trEl.querySelector('.api-key-user').value.trim();
16
- const passwordVal = trEl.querySelector('.api-key-password').value.trim();
17
- if (passwordVal) {
18
- apiKeyValue = `Basic ${btoa(`${userVal}:${passwordVal}`)}`;
19
- }
20
- } else {
21
- apiKeyValue = trEl.querySelector('.api-key-input').value.trim();
22
- if (apiKeyValue) {
23
- if (securityObj.scheme && securityObj.scheme.toLowerCase() === 'bearer') {
24
- apiKeyValue = `Bearer ${apiKeyValue.replace(/^Bearer\s+/i, '')}`;
25
- }
26
- }
27
- }
28
-
29
- securityObj.finalKeyValue = apiKeyValue;
30
- this.requestUpdate();
31
- }
32
-
33
- function onClearAllApiKeys() {
34
- this.resolvedSpec.securitySchemes.forEach((v) => {
35
- v.user = '';
36
- v.password = '';
37
- v.value = '';
38
- v.finalKeyValue = '';
39
- });
40
- this.requestUpdate();
41
- }
42
-
43
- // Updates the OAuth Access Token (API key), so it reflects in UI and gets used in TRY calls
44
- function updateOAuthKey(apiKeyId, tokenType = 'Bearer', accessToken) {
45
- const securityObj = this.resolvedSpec.securitySchemes.find((v) => (v.apiKeyId === apiKeyId));
46
- const tokenPrefix = tokenType && tokenType.toLowerCase() === 'bearer' ? 'Bearer' : tokenType;
47
- securityObj.finalKeyValue = `${tokenPrefix}${tokenPrefix ? ' ' : ''}${accessToken}`;
48
- this.requestUpdate();
49
- }
50
-
51
- // Gets Access-Token in exchange of Authorization Code
52
- async function fetchAccessToken(tokenUrl, clientId, clientSecret, redirectUrl, grantType, authCode, sendClientSecretIn = 'header', apiKeyId, authFlowDivEl, scopes = null) {
53
- const respDisplayEl = authFlowDivEl ? authFlowDivEl.querySelector('.oauth-resp-display') : undefined;
54
- const urlFormParams = new URLSearchParams();
55
- const headers = new Headers();
56
- urlFormParams.append('grant_type', grantType);
57
- if (redirectUrl) {
58
- urlFormParams.append('redirect_uri', redirectUrl);
59
- }
60
- if (authCode) {
61
- urlFormParams.append('code', authCode);
62
- }
63
- if (sendClientSecretIn === 'header') {
64
- headers.set('Authorization', `Basic ${btoa(`${clientId}:${clientSecret}`)}`);
65
- } else {
66
- urlFormParams.append('client_id', clientId);
67
- if (clientSecret) {
68
- urlFormParams.append('client_secret', clientSecret);
69
- }
70
- }
71
- if (scopes) {
72
- urlFormParams.append('scope', scopes);
73
- }
74
-
75
- const { codeVerifier } = JSON.parse(localStorage.getItem('openapi-explorer-oauth') || '{}');
76
- localStorage.removeItem('openapi-explorer-oauth');
77
- if (codeVerifier) {
78
- urlFormParams.append('code_verifier', codeVerifier);
79
- }
80
-
81
- try {
82
- const resp = await fetch(tokenUrl, { method: 'POST', headers, body: urlFormParams });
83
- const tokenResp = await resp.json();
84
- if (!resp.ok) {
85
- if (respDisplayEl) {
86
- respDisplayEl.innerHTML = `<span style="color:var(--red)">${tokenResp.error_description || tokenResp.error_description || 'Unable to get access token'}</span>`;
87
- }
88
- return;
89
- }
90
-
91
- if (tokenResp.token_type && tokenResp.access_token) {
92
- updateOAuthKey.call(this, apiKeyId, tokenResp.token_type, tokenResp.access_token);
93
- if (respDisplayEl) {
94
- respDisplayEl.innerHTML = '<span style="color:var(--green)">Access Token Received</span>';
95
- }
96
- }
97
- } catch (err) {
98
- if (respDisplayEl) {
99
- respDisplayEl.innerHTML = '<span style="color:var(--red)">Failed to get access token</span>';
100
- }
101
- }
102
- }
103
-
104
- function getCookieValue(keyId) {
105
- const foundCookie = (document.cookie || '').split(';').find(c => c.split('=')[0] === keyId);
106
- return foundCookie && foundCookie.split('=')[1] || '';
107
- }
108
-
109
- function toObject(urlSearchParams) {
110
- const result = {};
111
-
112
- const entries = urlSearchParams && urlSearchParams.entries() || [];
113
- for (const [key, value] of entries) {
114
- result[key] = value;
115
- }
116
- return result;
117
- }
118
-
119
- // Gets invoked when it receives the Authorization Code from the other window via message-event
120
- export async function checkForAuthToken(redirectToApiLocation) {
121
- const parameters = toObject(new URLSearchParams(window.location.search));
122
- const hashQuery = toObject(new URLSearchParams(window.location.hash.slice(1)));
123
-
124
- Object.assign(parameters, hashQuery);
125
-
126
- const newUrl = new URL(window.location);
127
- newUrl.searchParams.delete('nonce');
128
- newUrl.searchParams.delete('expires_in');
129
- newUrl.searchParams.delete('access_token');
130
- newUrl.searchParams.delete('token_type');
131
- newUrl.searchParams.delete('id_token');
132
- newUrl.searchParams.delete('state');
133
- newUrl.searchParams.delete('code');
134
- newUrl.searchParams.delete('iss');
135
- newUrl.searchParams.delete('scope');
136
- newUrl.searchParams.delete('prompt');
137
- newUrl.searchParams.delete('hd');
138
- newUrl.searchParams.delete('authuser');
139
- newUrl.searchParams.delete('redirect_auth');
140
- if (!parameters.state) {
141
- return;
142
- }
143
- const sanitizedUrlWithHash = newUrl.toString().replace(/#((code|state|access_token|id_token|authuser|expires_in|hd|prompt|scope|token_type)=[^&]+&?)*$/ig, '');
144
- history.replaceState({}, undefined, sanitizedUrlWithHash);
145
-
146
- const { apiKeyId, flowId, url } = JSON.parse(base64url.decode(parameters.state));
147
- if (redirectToApiLocation && url && !parameters.redirect_auth) {
148
- const apiExplorerLocation = new URL(url);
149
- Object.keys(parameters).forEach(key => apiExplorerLocation.searchParams.append(key, parameters[key]));
150
- apiExplorerLocation.searchParams.append('redirect_auth', true);
151
- window.location.replace(apiExplorerLocation.toString());
152
- return;
153
- }
154
- if (parameters.code) {
155
- const securityObj = this.resolvedSpec.securitySchemes.find(v => v.apiKeyId === apiKeyId);
156
- const tokenUrl = securityObj && securityObj.flows[flowId] && new URL(securityObj.flows[flowId].tokenUrl || '', this.selectedServer.computedUrl);
157
- await fetchAccessToken.call(this, tokenUrl, securityObj.clientId, securityObj.clientSecret, securityObj.redirectUri || window.location.href, 'authorization_code', parameters.code, null, apiKeyId);
158
- return;
159
- }
160
-
161
- updateOAuthKey.call(this, apiKeyId, parameters.token_type, parameters.access_token);
162
- }
163
-
164
- async function onInvokeOAuthFlow(apiKeyId, flowType, authUrl, tokenUrl, e) {
165
- const authFlowDivEl = e.target.closest('.oauth-flow');
166
- const clientId = authFlowDivEl.querySelector('.oauth-client-id') ? authFlowDivEl.querySelector('.oauth-client-id').value.trim() : '';
167
- const clientSecret = authFlowDivEl.querySelector('.oauth-client-secret') ? authFlowDivEl.querySelector('.oauth-client-secret').value.trim() : '';
168
- const sendClientSecretIn = authFlowDivEl.querySelector('.oauth-send-client-secret-in') ? authFlowDivEl.querySelector('.oauth-send-client-secret-in').value.trim() : 'header';
169
-
170
- const checkedScopeEls = [...authFlowDivEl.querySelectorAll('input[type="checkbox"]:checked')];
171
- const securityObj = this.resolvedSpec.securitySchemes.find(v => v.apiKeyId === apiKeyId);
172
- let grantType = '';
173
- let responseType = '';
174
-
175
- // clear previous error messages
176
- const errEls = [...authFlowDivEl.parentNode.querySelectorAll('.oauth-resp-display')];
177
- errEls.forEach((v) => { v.innerHTML = ''; });
178
-
179
- if (flowType === 'authorizationCode' || flowType === 'implicit') {
180
- const authUrlObj = new URL(authUrl);
181
- const authCodeParams = new URLSearchParams(authUrlObj.search);
182
- if (flowType === 'authorizationCode') {
183
- const randomBytes = new Uint32Array(3);
184
- (window.crypto || window.msCrypto).getRandomValues(randomBytes);
185
- authCodeParams.set('nonce', randomBytes.toString('hex').split(',').join(''));
186
- grantType = 'authorization_code';
187
- responseType = 'code';
188
- const codeVerifier = randomBytes.toString('hex').split(',').join('');
189
- const hash = await (window.crypto || window.msCrypto).subtle.digest('SHA-256', new TextEncoder().encode(codeVerifier));
190
- const codeChallenge = base64url(hash);
191
-
192
- authCodeParams.set('code_challenge', codeChallenge);
193
- authCodeParams.set('code_challenge_method', 'S256');
194
- localStorage.setItem('openapi-explorer-oauth', JSON.stringify({ codeVerifier }));
195
- } else if (flowType === 'implicit') {
196
- responseType = 'token';
197
- }
198
- const selectedScopes = checkedScopeEls.map((v) => v.value).join(' ');
199
- if (selectedScopes) {
200
- authCodeParams.set('scope', selectedScopes);
201
- }
202
- authCodeParams.set('client_id', clientId);
203
- authCodeParams.set('redirect_uri', securityObj.redirectUri || window.location.href);
204
- authCodeParams.set('response_type', responseType);
205
- authCodeParams.set('state', base64url.encode(JSON.stringify({ apiKeyId, flowId: flowType, url: window.location.href })));
206
-
207
- authUrlObj.search = authCodeParams.toString();
208
- window.location.assign(authUrlObj.toString());
209
- } else if (flowType === 'clientCredentials') {
210
- grantType = 'client_credentials';
211
- const selectedScopes = checkedScopeEls.map((v) => v.value).join(' ');
212
- fetchAccessToken.call(this, tokenUrl, clientId, clientSecret, '', grantType, '', sendClientSecretIn, apiKeyId, authFlowDivEl, selectedScopes);
213
- }
214
- }
215
-
216
- /* eslint-disable indent */
217
-
218
- function oAuthFlowTemplate(flowName, securityObj, authFlow) {
219
- const apiKeyId = securityObj.apiKeyId;
220
- const getFullUrl = url => (url ? new URL(url, this.selectedServer.computedUrl) : undefined);
221
- const authorizationUrl = getFullUrl(authFlow.authorizationUrl, this.selectedServer.computedUrl);
222
- const tokenUrl = getFullUrl(authFlow.tokenUrl, this.selectedServer.computedUrl);
223
- const refreshUrl = getFullUrl(authFlow.refreshUrl, this.selectedServer.computedUrl);
224
- let flowNameDisplay;
225
- if (flowName === 'authorizationCode') {
226
- flowNameDisplay = 'Authorization Code Flow';
227
- } else if (flowName === 'clientCredentials') {
228
- flowNameDisplay = 'Client Credentials Flow';
229
- } else if (flowName === 'implicit') {
230
- flowNameDisplay = 'Implicit Flow';
231
- } else {
232
- flowNameDisplay = flowName;
233
- }
234
- return html`
235
- <div class="oauth-flow" style="padding: 10px 0; margin-bottom:10px;">
236
- <div class="tiny-title upper" style="margin-bottom:5px;">${flowNameDisplay}</div>
237
- ${authorizationUrl
238
- ? html`<div><span style="width:75px; display: inline-block;">Auth URL</span> <span class="mono-font"> ${authorizationUrl} </span></div>`
239
- : ''
240
- }
241
- ${tokenUrl
242
- ? html`<div><span style="width:75px; display: inline-block;">Token URL</span> <span class="mono-font">${tokenUrl}</span></div>`
243
- : ''
244
- }
245
- ${refreshUrl
246
- ? html`<div><span style="width:75px; display: inline-block;">Refresh URL</span> <span class="mono-font">${refreshUrl}</span></div>`
247
- : ''
248
- }
249
- ${flowName === 'authorizationCode' || flowName === 'clientCredentials' || flowName === 'implicit'
250
- ? html`
251
- ${authFlow.scopes
252
- ? html`
253
- <span> Scopes </span>
254
- <div class= "oauth-scopes" part="section-auth-scopes" style = "width:100%; display:flex; flex-direction:column; flex-wrap:wrap; margin:0 0 .125rem 0">
255
- ${Object.entries(authFlow.scopes).map((scopeAndDescr, index) => html`
256
- <div class="m-checkbox" style="display:inline-flex; align-items:center">
257
- <input type="checkbox" checked part="checkbox checkbox-auth-scope" id="${flowName}${index}" value="${scopeAndDescr[0]}">
258
- <label for="${flowName}${index}" style="margin-left:5px">
259
- <span class="mono-font">${scopeAndDescr[0]}</span>
260
- ${scopeAndDescr[0] !== scopeAndDescr[1] ? ` - ${scopeAndDescr[1] || ''}` : ''}
261
- </label>
262
- </div>
263
- `)}
264
- </div>
265
- `
266
- : ''
267
- }
268
- <div style="display:flex;">
269
- <input type="text" part="textbox textbox-auth-client-id" value="${securityObj.clientId || ''}" placeholder="Client ID" spellcheck="false" class="oauth-client-id">
270
- ${flowName === 'clientCredentials'
271
- ? html`
272
- <input type="password" part="textbox textbox-auth-client-secret" value = "" placeholder="Client Secret" spellcheck="false" class="oauth-client-secret" style = "margin:0 5px;">
273
- <select aria-label='oauth client secret location' style="margin-right:5px;" class="oauth-send-client-secret-in">
274
- <option value = 'header' selected> Authorization Header </option>
275
- <option value = 'request-body'> Request Body </option>
276
- </select>`
277
- : html`<div style='width:5px'></div>`
278
- }
279
- ${flowName === 'authorizationCode' || flowName === 'clientCredentials' || flowName === 'implicit'
280
- ? html`
281
- <button class="m-btn thin-border" part="btn btn-outline"
282
- @click="${(e) => { onInvokeOAuthFlow.call(this, apiKeyId, flowName, authorizationUrl, tokenUrl, e); }}"
283
- >GET TOKEN</button>`
284
- : ''
285
- }
286
- </div>
287
- <div class="oauth-resp-display red-text small-font-size"></div>
288
- `
289
- : ''
290
- }
291
- </div>
292
- `;
293
- }
294
-
295
- export default function securitySchemeTemplate() {
296
- const schemes = this.resolvedSpec && this.resolvedSpec.securitySchemes;
297
- if (!schemes) {
298
- return undefined;
299
- }
300
- const providedApiKeys = schemes.filter((v) => (v.finalKeyValue));
301
- return html`
302
- <section id='auth' part="section-auth" class = 'observe-me ${this.renderStyle === 'focused' ? 'section-gap--focused-mode' : 'section-gap'}'>
303
- <slot name="authentication">
304
- <div class="section-padding">
305
- <div class='sub-title regular-font'>AUTHENTICATION</div>
306
- <div class="small-font-size" style="display:flex; align-items: center; min-height:30px">
307
- ${providedApiKeys.length > 0
308
- ? html`
309
- <div class="blue-text"> ${providedApiKeys.length} API key applied </div>
310
- <div style="flex:1"></div>
311
- <button class="m-btn thin-border" part="btn btn-outline" @click=${() => { onClearAllApiKeys.call(this); }}>CLEAR ALL API KEYS</button>`
312
- : html`<div class="red-text">No API key applied</div>`
313
- }
314
- </div>
315
- ${schemes.length > 0
316
- ? html`
317
- <table role="presentation" class='m-table' style="width:100%">
318
- ${schemes.map((v) => html`
319
- <tr>
320
- <td style="max-width:500px; overflow-wrap: break-word;">
321
- <div style="min-height:24px">
322
- <span style="font-weight:bold">${v.typeDisplay}</span>
323
- ${v.finalKeyValue
324
- ? html`
325
- <span class='blue-text'> ${v.finalKeyValue ? 'Key Applied' : ''} </span>
326
- <button class="m-btn thin-border small" part="btn btn-outline" @click=${() => { v.finalKeyValue = ''; this.requestUpdate(); }}>REMOVE</button>
327
- `
328
- : ''
329
- }
330
- </div>
331
- ${v.description
332
- ? html`
333
- <div class="m-markdown">
334
- ${unsafeHTML(marked(v.description || ''))}
335
- </div>`
336
- : ''
337
- }
338
- </td>
339
- <td>
340
- ${v.type && (v.type.toLowerCase() === 'apikey' || v.type.toLowerCase() === 'http' && v.scheme && v.scheme.toLowerCase() === 'bearer')
341
- ? html`
342
- ${v.type.toLowerCase() === 'apikey'
343
- ? html`Send <code>${v.name}</code> in <code>${v.in}</code> with the given value:`
344
- : html`Send <code>Authorization</code> in <code>header</code> containing the word <code>Bearer</code> followed by a space and a Token String.`
345
- }
346
- <div style="display:flex;">
347
- ${v.in === 'cookie'
348
- ? html`
349
- <div style="display: block">
350
- <input type="text" value="${getCookieValue(v.apiKeyId)}" disabled class="api-key-input" placeholder="IygRVGf54B59e0GAkKmigGfuiVlp/uhFfk2ifA+jMMJzau2F1jPldc09gPTfnMw13BFBxqUZIFDm55DPfwkb0A==" spellcheck = "false" style="resize: horizontal; width: 100%">
351
- <br>
352
- <small>
353
- <strong>Cookies</strong>&nbsp;are set and configured by the remote service, therefore it is not possible to configure them from the browser.
354
- </small>
355
- </div>`
356
- : html`
357
- <input type = "text" value = "${v.value}" class="api-key-input" placeholder = "api-token" spellcheck = "false">
358
- <button class="m-btn thin-border" style = "margin-left:5px;"
359
- part = "btn btn-outline"
360
- @click="${(e) => { onApiKeyChange.call(this, v.apiKeyId, e); }}">
361
- ${v.finalKeyValue ? 'UPDATE' : 'SET'}
362
- </button>`
363
- }
364
- </div>`
365
- : ''
366
- }
367
- ${v.type && v.type.toLowerCase() === 'http' && v.scheme && v.scheme.toLowerCase() === 'basic'
368
- ? html`
369
- Send the <code>Authorization</code> header containing the type <code>Basic</code> followed by a space and a base64 encoded string of <code>username:password</code>.
370
- <div style="display:flex;">
371
- <input type="text" value = "${v.user}" placeholder="username" spellcheck="false" class="api-key-user" style="width:100px">
372
- <input type="password" value = "${v.password}" placeholder="password" spellcheck="false" class="api-key-password" style = "width:100px; margin:0 5px;">
373
- <button class="m-btn thin-border"
374
- @click="${(e) => { onApiKeyChange.call(this, v.apiKeyId, e); }}"
375
- part = "btn btn-outline"
376
- >
377
- ${v.finalKeyValue ? 'UPDATE' : 'SET'}
378
- </button>
379
- </div>`
380
- : ''
381
- }
382
- </td>
383
- </tr>
384
- ${v.type.toLowerCase() === 'oauth2'
385
- ? html`
386
- <tr>
387
- <td colspan="2" style="border:none; padding-left:48px">
388
- ${Object.keys(v.flows).map((f) => oAuthFlowTemplate.call(this, f, v, v.flows[f]))}
389
- </td>
390
- </tr>
391
- `
392
- : ''
393
- }
394
- `)}
395
- </table>`
396
- : ''
397
- }
398
- </div>
399
- </slot>
400
- </section>
401
- `;
402
- }
403
-
404
- function getOauthScopeTemplate(scopes) {
405
- if (!scopes || !scopes.length || !Array.isArray(scopes)) {
406
- return '';
407
- }
408
-
409
- return html`
410
- <div>
411
- <b>Required scopes:</b>
412
- <br/>
413
- <div style="margin-left:8px">
414
- ${scopes.map(scope => html`<span>${scope}</span>&nbsp;`)}
415
- </div>
416
- </div>`;
417
- }
418
-
419
- export function pathSecurityTemplate(pathSecurity) {
420
- if (this.resolvedSpec.securitySchemes && pathSecurity) {
421
- const orSecurityKeys1 = [];
422
- pathSecurity.forEach((pSecurity) => {
423
- const andSecurityKeys1 = [];
424
- const andKeyTypes = [];
425
- Object.keys(pSecurity).forEach((pathSecurityKey) => {
426
- const s = this.resolvedSpec.securitySchemes.find((ss) => ss.apiKeyId === pathSecurityKey);
427
- if (s) {
428
- andKeyTypes.push(s.typeDisplay);
429
- andSecurityKeys1.push({ ...s, scopes: pSecurity[pathSecurityKey] });
430
- }
431
- });
432
- orSecurityKeys1.push({
433
- securityTypes: andKeyTypes.length > 1 ? `${andKeyTypes[0]} + ${andKeyTypes.length - 1} more` : andKeyTypes[0],
434
- securityDefs: andSecurityKeys1,
435
- });
436
- });
437
- return html`<div class="security-info-button" data-content-id='auth' @click='${(e) => this.scrollToEventTarget(e, false)}'>
438
- <div style="position:relative; display:flex; min-width:350px; max-width:700px; justify-content: flex-end;">
439
- <svg width="16" height="24" style="cursor: pointer;">
440
- <g>
441
- <path style="fill: var(--fg3)" d="m13.8,8.5l0,-2.6l0,0c0,-3.2 -2.6,-5.8 -5.8,-5.8s-5.8,2.6 -5.8,5.8l0,0l0,2.6l-2.1,0l0,11.2l16,0l0,-11.2l-2.1,0l-0,0l0,0l0,0l-0,0zm-9.8,-2.6c0,0 0,0 0,0c0,-2.2 1.8,-4 4,-4c2.2,0 4,1.8 4,4c0,0 0,0 0,0l0,2.6l-8.03,0l0,-2.6l0,0l0,0z" />
442
- </g>
443
- </svg>
444
- ${orSecurityKeys1.map((orSecurityItem1, i) => html`
445
- ${i !== 0 ? html`<div style="padding:3px 4px;"> OR </div>` : ''}
446
- <div class="tooltip" style="cursor: pointer;">
447
- <div style="padding:2px 4px; white-space:nowrap; text-overflow:ellipsis;max-width:150px; overflow:hidden;">
448
- <span part="anchor anchor-operation-security"> ${orSecurityItem1.securityTypes} </span>
449
- </div>
450
- <div class="tooltip-text" style="position:absolute; color: var(--fg); top:26px; right:0; border:1px solid var(--border-color);padding:2px 4px; display:block;">
451
- ${orSecurityItem1.securityDefs.length > 1 ? html`<div>Requires <b>all</b> of the following </div>` : ''}
452
- <div style="padding-left: 8px">
453
- ${orSecurityItem1.securityDefs.map((andSecurityItem, j) => html`
454
- ${andSecurityItem.type === 'oauth2'
455
- ? html`
456
- <div>
457
- ${orSecurityItem1.securityDefs.length > 1 ? html`<b>${j + 1}.</b> &nbsp;` : html`Requires`}
458
- OAuth token (${andSecurityItem.apiKeyId}) in <b>Authorization header</b>
459
- ${getOauthScopeTemplate(andSecurityItem.scopes)}
460
- </div>`
461
- : andSecurityItem.type === 'http'
462
- ? html`
463
- <div>
464
- ${orSecurityItem1.securityDefs.length > 1 ? html`<b>${j + 1}.</b> &nbsp;` : html`Requires`}
465
- ${andSecurityItem.scheme === 'basic' ? 'Base 64 encoded username:password' : 'Bearer Token'} in <b>Authorization header</b>
466
- ${getOauthScopeTemplate(andSecurityItem.scopes)}
467
- </div>`
468
- : html`
469
- <div>
470
- ${orSecurityItem1.securityDefs.length > 1 ? html`<b>${j + 1}.</b> &nbsp;` : html`Requires`}
471
- Token in <b>${andSecurityItem.name} ${andSecurityItem.in}</b>
472
- ${getOauthScopeTemplate(andSecurityItem.scopes)}
473
- </div>`
474
- }
475
- `)}
476
- </div>
477
- </div>
478
- </div>
479
- `)
480
- }
481
- </div>
482
- `;
483
- }
484
- return '';
485
- }
486
-
487
- /* eslint-enable indent */
@@ -1,106 +0,0 @@
1
- import { html } from 'lit-element';
2
- import { marked } from 'marked';
3
- import { unsafeHTML } from 'lit-html/directives/unsafe-html';
4
-
5
- function onApiServerChange(e, server) {
6
- if (e && e.target.checked) {
7
- this.selectedServer = server;
8
- this.requestUpdate();
9
- }
10
- }
11
-
12
- function onApiServerVarChange(e, serverObj) {
13
- const inputEls = [...e.currentTarget.closest('table').querySelectorAll('input, select')];
14
- let tempUrl = serverObj.url;
15
- inputEls.forEach((v) => {
16
- const regex = new RegExp(`{${v.dataset.var}}`, 'g');
17
- tempUrl = tempUrl.replace(regex, v.value);
18
- });
19
- serverObj.computedUrl = tempUrl;
20
- this.requestUpdate();
21
- }
22
-
23
- /* eslint-disable indent */
24
- function serverVarsTemplate() {
25
- return this.selectedServer && this.selectedServer.variables
26
- ? html`
27
- <div class="table-title"> SERVER VARIABLES</div>
28
- <table role="presentation" class='m-table'>
29
- ${Object.entries(this.selectedServer.variables).map((kv) => html`
30
- <tr>
31
- <td style="vertical-align: middle;" >${kv[0]}</td>
32
- <td>
33
- ${kv[1].enum
34
- ? html`
35
- <select
36
- data-var = "${kv[0]}"
37
- @input = ${(e) => { onApiServerVarChange.call(this, e, this.selectedServer); }}
38
- >
39
- ${Object.entries(kv[1].enum).map((e) => (kv[1].default === e[1]
40
- ? html`
41
- <option
42
- selected
43
- label = ${e[1]}
44
- value = ${e[1]}
45
- />`
46
- : html`
47
- <option
48
- label = ${e[1]}
49
- value = ${e[1]}
50
- />`
51
- ))}
52
- </select>`
53
- : html`
54
- <input
55
- type = "text"
56
- part="textbox textbox-server-var"
57
- spellcheck = "false"
58
- data-var = "${kv[0]}"
59
- value = "${kv[1].default}"
60
- @input = ${(e) => { onApiServerVarChange.call(this, e, this.selectedServer); }}
61
- />`}
62
- </td>
63
- </tr>
64
- ${kv[1].description
65
- ? html`<tr><td colspan="2" style="border:none"><span class="m-markdown-small"> ${unsafeHTML(marked(kv[1].description))} </span></td></tr>`
66
- : ''
67
- }
68
- `)}
69
- </table>
70
- `
71
- : '';
72
- }
73
-
74
- export default function serverTemplate() {
75
- if (!this.resolvedSpec) {
76
- return undefined;
77
- }
78
- return html`
79
- <section id = 'servers' part="section-servers" style="margin-top:24px; margin-bottom:24px;" class='regular-font observe-me section-padding ${this.renderStyle === 'read' ? 'section-gap--read-mode' : (this.renderStyle === 'focused' ? 'section-gap--focused-mode' : 'section-gap')}'>
80
- <div class = 'sub-title'>API SERVER</div>
81
- <div class = 'mono-font' style='margin: 12px 0; font-size:calc(var(--font-size-small) + 1px);'>
82
- ${!this.resolvedSpec.servers || !this.resolvedSpec.servers.length
83
- ? ''
84
- : html`
85
- ${this.resolvedSpec.servers.map((server, i) => html`
86
- <input type = 'radio'
87
- name = 'api_server'
88
- id = 'srvr-opt-${i}'
89
- value = '${server.url}'
90
- @change = ${(e) => { onApiServerChange.call(this, e, server); }}
91
- .checked = '${this.selectedServer.url === server.url}'
92
- style = 'margin:4px 0; cursor: pointer'
93
- />
94
- <label style='cursor: pointer' for='srvr-opt-${i}'>
95
- ${server.url} ${server.description ? html`- <span class='regular-font'>${server.description} </span>` : ''}
96
- </label>
97
- <br/>
98
- `)}
99
- `}
100
- <div class="table-title primary-text" part="label-selected-server"> SELECTED: ${this.selectedServer && this.selectedServer.computedUrl || 'none'}</div>
101
- </div>
102
- <slot name="servers"></slot>
103
- ${serverVarsTemplate.call(this)}
104
- </section>`;
105
- }
106
- /* eslint-enable indent */