openapi-explorer 2.2.725 → 2.2.730
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.
@@ -162,13 +162,17 @@ export default class ApiRequest extends LitElement {
|
|
162
162
|
return keyed(id, html` <div id="api-request-${id}" class="api-request col regular-font request-panel ${this.renderStyle === 'focused' || this.callback === 'true' ? 'focused-mode' : 'view-mode'}"> <div class="${this.callback === 'true' ? 'tiny-title' : 'req-res-title'}"> ${this.callback === 'true' ? 'CALLBACK REQUEST' : getI18nText('operations.request')} </div> <div> ${this.inputParametersTemplate('path')} ${this.inputParametersTemplate('query')} ${this.inputParametersTemplate('header')} ${this.inputParametersTemplate('cookie')} ${this.requestBodyTemplate()} ${this.allowTry === 'false' ? '' : html`${this.apiCallTemplate()}`} </div> </div> `);
|
163
163
|
}
|
164
164
|
updated(changedProperties) {
|
165
|
+
// When the operation is changed, reset the display view properties
|
166
|
+
if (changedProperties.get('elementId')) {
|
167
|
+
this.activeResponseTab = 'curl';
|
168
|
+
}
|
165
169
|
// In focused mode after rendering the request component, update the text-areas(which contains examples) using the original values from hidden textareas.
|
166
170
|
// This is done coz, user may update the dom by editing the textarea's and once the DOM is updated externally change detection wont happen, therefore update the values manually
|
167
171
|
if (this.renderStyle !== 'focused') {
|
168
172
|
return;
|
169
173
|
}
|
170
174
|
|
171
|
-
//
|
175
|
+
// don't update example as only tabs is switched
|
172
176
|
if (changedProperties.size === 1 && changedProperties.has('activeSchemaTab')) {
|
173
177
|
return;
|
174
178
|
}
|
@@ -195,7 +199,7 @@ export default class ApiRequest extends LitElement {
|
|
195
199
|
}[paramLocation];
|
196
200
|
const tableRows = [];
|
197
201
|
for (const param of filteredParams) {
|
198
|
-
var
|
202
|
+
var _param$style, _param$explode;
|
199
203
|
if (!param.schema) {
|
200
204
|
continue;
|
201
205
|
}
|
@@ -207,33 +211,57 @@ export default class ApiRequest extends LitElement {
|
|
207
211
|
continue;
|
208
212
|
}
|
209
213
|
const defaultVal = Array.isArray(paramSchema.default) ? paramSchema.default : `${paramSchema.default}`;
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
214
|
+
// Set the default style: https://spec.openapis.org/oas/v3.1.0.html#fixed-fields-9
|
215
|
+
const paramStyle = (_param$style = param.style) !== null && _param$style !== void 0 ? _param$style : {
|
216
|
+
query: 'form',
|
217
|
+
path: 'simple',
|
218
|
+
header: 'simple',
|
219
|
+
cookie: 'form'
|
220
|
+
}[paramLocation];
|
221
|
+
const paramExplode = (_param$explode = param.explode) !== null && _param$explode !== void 0 ? _param$explode : param.style === 'form';
|
222
|
+
const rowGenerator = ({
|
223
|
+
name: paramName,
|
224
|
+
description: paramDescription,
|
225
|
+
required: paramRequired
|
226
|
+
}, generatedParamSchema) => {
|
227
|
+
var _this$storedParamValu, _generatedParamSchema;
|
228
|
+
const displayAllowedValuesHints = (generatedParamSchema.type === 'object' || generatedParamSchema.type === 'array') && generatedParamSchema.allowedValues;
|
229
|
+
return html` <tr> <td colspan="1" style="width:160px;min-width:50px;vertical-align:top"> <div class="param-name ${generatedParamSchema.deprecated ? 'deprecated' : ''}" style="margin-top:1rem"> ${paramName}${!generatedParamSchema.deprecated && paramRequired ? html`<span style="color:var(--red)">*</span>` : ''} </div> <div class="param-type" style="margin-bottom:1rem"> ${generatedParamSchema.type === 'array' ? `${generatedParamSchema.arrayType}` : `${generatedParamSchema.format ? generatedParamSchema.format : generatedParamSchema.type}`}${!generatedParamSchema.deprecated && paramRequired ? html`<span style="opacity:0">*</span>` : ''} </div> </td> <td colspan="2" style="min-width:160px;vertical-align:top"> ${this.allowTry === 'true' ? generatedParamSchema.type === 'array' && html` <div style="margin-top:1rem;margin-bottom:1rem"> <tag-input class="request-param" autocomplete="on" id="request-param-${paramName}" style="width:100%" data-ptype="${paramLocation}" data-pname="${paramName}" data-default="${Array.isArray(defaultVal) ? defaultVal.join('~|~') : defaultVal}" data-param-serialize-style="${paramStyle}" data-param-serialize-explode="${paramExplode}" data-array="true" placeholder="add-multiple ↩" @change="${e => {
|
230
|
+
this.storedParamValues[paramName] = e.detail.value;
|
231
|
+
this.computeCurlSyntax();
|
232
|
+
}}" .value="${(_this$storedParamValu = this.storedParamValues[paramName]) !== null && _this$storedParamValu !== void 0 ? _this$storedParamValu : this.fillRequestWithDefault === 'true' && Array.isArray(defaultVal) ? defaultVal : defaultVal.split(',')}"></tag-input> </div>` || generatedParamSchema.type === 'object' && html` <textarea autocomplete="on" id="request-param-${paramName}" @input="${() => {
|
233
|
+
this.computeCurlSyntax();
|
234
|
+
}}" class="textarea small request-param" part="textarea small textarea-param" rows="3" data-ptype="${paramLocation}" data-pname="${paramName}" data-default="${defaultVal}" data-param-serialize-style="${paramStyle}" data-param-serialize-explode="${paramExplode}" spellcheck="false" placeholder="${generatedParamSchema.example || defaultVal || ''}" style="width:100%;margin-top:1rem;margin-bottom:1rem" .value="${this.fillRequestWithDefault === 'true' ? defaultVal : ''}"></textarea>` || generatedParamSchema.allowedValues && html` <select aria-label="mime type" style="width:100%;margin-top:1rem;margin-bottom:1rem" data-ptype="${paramLocation}" data-pname="${paramName}" .value="${this.fillRequestWithDefault === 'true' ? defaultVal : ''}" @change="${e => {
|
235
|
+
this.storedParamValues[paramName] = e;
|
236
|
+
this.computeCurlSyntax();
|
237
|
+
}}"> ${generatedParamSchema.allowedValues.map(allowedValue => html` <option value="${allowedValue}" ?selected="${allowedValue === this.storedParamValues[paramName]}"> ${allowedValue === null ? '-' : allowedValue} </option>`)} </select>` || html` <input type="${generatedParamSchema.format === 'password' ? 'password' : 'text'}" spellcheck="false" style="width:100%;margin-top:1rem;margin-bottom:1rem" autocomplete="on" id="request-param-${paramName}" @input="${() => {
|
238
|
+
this.computeCurlSyntax();
|
239
|
+
}}" placeholder="${generatedParamSchema.example || defaultVal || ''}" class="request-param" part="textbox textbox-param" data-ptype="${paramLocation}" data-pname="${paramName}" data-default="${Array.isArray(defaultVal) ? defaultVal.join('~|~') : defaultVal}" data-array="false" @keyup="${this.requestParamFunction}" .value="${this.fillRequestWithDefault === 'true' ? defaultVal : ''}">` : ''} ${this.exampleListTemplate.call(this, param, generatedParamSchema.type)} </td> ${this.renderStyle === 'focused' ? html` <td colspan="2" style="vertical-align:top"> ${paramDescription ? html` <div class="param-description" style="margin-top:1rem"> ${unsafeHTML(toMarkdown(paramDescription))} </div>` : ''} ${generatedParamSchema.constraints.length || displayAllowedValuesHints || generatedParamSchema.pattern ? html` <div class="param-constraint" style="margin-top:1rem"> ${generatedParamSchema.constraints.length ? html`<span style="font-weight:700">Constraints: </span>${generatedParamSchema.constraints.join(', ')}<br>` : ''} ${generatedParamSchema.pattern ? html` <div class="tooltip tooltip-replace" style="cursor:pointer;max-width:100%;display:flex"> <div style="white-space:nowrap;font-weight:700;margin-right:2px">Pattern: </div> <div style="white-space:nowrap;text-overflow:ellipsis;max-width:100%;overflow:hidden">${generatedParamSchema.pattern}</div> <br> <div class="tooltip-text" style="position:absolute;display:block">${generatedParamSchema.pattern}</div> </div> ` : ''} ${(_generatedParamSchema = generatedParamSchema.allowedValues) === null || _generatedParamSchema === void 0 ? void 0 : _generatedParamSchema.map((v, i) => html` ${i > 0 ? '|' : html`<span style="font-weight:700">Allowed: </span>`} ${html` <a part="anchor anchor-param-constraint" class="${this.allowTry === 'true' ? '' : 'inactive-link'}" data-type="${generatedParamSchema.type === 'array' ? 'array' : 'string'}" data-enum="${v === null || v === void 0 ? void 0 : v.trim()}" @click="${e => {
|
240
|
+
const inputEl = e.target.closest('table').querySelector(`[data-pname="${paramName}"]`);
|
241
|
+
if (inputEl) {
|
242
|
+
inputEl.value = e.target.dataset.type === 'array' ? [e.target.dataset.enum] : e.target.dataset.enum;
|
243
|
+
}
|
244
|
+
}}"> ${v === null ? '-' : v} </a>`}`)} </div>` : ''} </td> ` : ''} </tr>`;
|
245
|
+
};
|
246
|
+
let newRows = [];
|
247
|
+
if (paramStyle === 'form' && paramExplode) {
|
248
|
+
newRows = Object.keys(param.schema.properties).map(explodedParamKey => {
|
249
|
+
var _param$schema, _param$schema$require;
|
250
|
+
const explodedParam = param.schema.properties[explodedParamKey];
|
251
|
+
const explodedParamSchema = getTypeInfo(explodedParam, {
|
252
|
+
includeNulls: this.includeNulls,
|
253
|
+
enableExampleGeneration: true
|
254
|
+
});
|
255
|
+
return rowGenerator({
|
256
|
+
name: explodedParamKey,
|
257
|
+
description: explodedParam.description,
|
258
|
+
required: (_param$schema = param.schema) === null || _param$schema === void 0 ? void 0 : (_param$schema$require = _param$schema.required) === null || _param$schema$require === void 0 ? void 0 : _param$schema$require.includes(explodedParamKey)
|
259
|
+
}, explodedParamSchema);
|
260
|
+
});
|
261
|
+
} else {
|
262
|
+
newRows = rowGenerator(param, paramSchema);
|
219
263
|
}
|
220
|
-
|
221
|
-
tableRows.push(html` <tr> <td colspan="1" style="width:160px;min-width:50px;vertical-align:top"> <div class="param-name ${paramSchema.deprecated ? 'deprecated' : ''}" style="margin-top:1rem"> ${param.name}${!paramSchema.deprecated && param.required ? html`<span style="color:var(--red)">*</span>` : ''} </div> <div class="param-type" style="margin-bottom:1rem"> ${paramSchema.type === 'array' ? `${paramSchema.arrayType}` : `${paramSchema.format ? paramSchema.format : paramSchema.type}`}${!paramSchema.deprecated && param.required ? html`<span style="opacity:0">*</span>` : ''} </div> </td> <td colspan="2" style="min-width:160px;vertical-align:top"> ${this.allowTry === 'true' ? paramSchema.type === 'array' && html` <div style="margin-top:1rem;margin-bottom:1rem"> <tag-input class="request-param" autocomplete="on" id="request-param-${param.name}" style="width:100%" data-ptype="${paramLocation}" data-pname="${param.name}" data-default="${Array.isArray(defaultVal) ? defaultVal.join('~|~') : defaultVal}" data-param-serialize-style="${paramStyle}" data-param-serialize-explode="${paramExplode}" data-array="true" placeholder="add-multiple ↩" @change="${e => {
|
222
|
-
this.storedParamValues[param.name] = e.detail.value;
|
223
|
-
this.computeCurlSyntax();
|
224
|
-
}}" .value="${(_this$storedParamValu = this.storedParamValues[param.name]) !== null && _this$storedParamValu !== void 0 ? _this$storedParamValu : this.fillRequestWithDefault === 'true' && Array.isArray(defaultVal) ? defaultVal : defaultVal.split(',')}"></tag-input> </div>` || paramSchema.type === 'object' && html` <textarea autocomplete="on" id="request-param-${param.name}" @input="${() => {
|
225
|
-
this.computeCurlSyntax();
|
226
|
-
}}" class="textarea small request-param" part="textarea small textarea-param" rows="3" data-ptype="${paramLocation}" data-pname="${param.name}" data-default="${defaultVal}" data-param-serialize-style="${paramStyle}" data-param-serialize-explode="${paramExplode}" spellcheck="false" placeholder="${paramSchema.example || defaultVal || ''}" style="width:100%;margin-top:1rem;margin-bottom:1rem" .value="${this.fillRequestWithDefault === 'true' ? defaultVal : ''}"></textarea>` || paramSchema.allowedValues && html` <select aria-label="mime type" style="width:100%;margin-top:1rem;margin-bottom:1rem" data-ptype="${paramLocation}" data-pname="${param.name}" .value="${this.fillRequestWithDefault === 'true' ? defaultVal : ''}" @change="${e => {
|
227
|
-
this.storedParamValues[param.name] = e;
|
228
|
-
this.computeCurlSyntax();
|
229
|
-
}}"> ${paramSchema.allowedValues.map(allowedValue => html` <option value="${allowedValue}" ?selected="${allowedValue === this.storedParamValues[param.name]}"> ${allowedValue === null ? '-' : allowedValue} </option>`)} </select>` || html` <input type="${paramSchema.format === 'password' ? 'password' : 'text'}" spellcheck="false" style="width:100%;margin-top:1rem;margin-bottom:1rem" autocomplete="on" id="request-param-${param.name}" @input="${() => {
|
230
|
-
this.computeCurlSyntax();
|
231
|
-
}}" placeholder="${paramSchema.example || defaultVal || ''}" class="request-param" part="textbox textbox-param" data-ptype="${paramLocation}" data-pname="${param.name}" data-default="${Array.isArray(defaultVal) ? defaultVal.join('~|~') : defaultVal}" data-array="false" @keyup="${this.requestParamFunction}" .value="${this.fillRequestWithDefault === 'true' ? defaultVal : ''}">` : ''} ${this.exampleListTemplate.call(this, param, paramSchema.type)} </td> ${this.renderStyle === 'focused' ? html` <td colspan="2" style="vertical-align:top"> ${param.description ? html` <div class="param-description" style="margin-top:1rem"> ${unsafeHTML(toMarkdown(param.description))} </div>` : ''} ${paramSchema.constraints.length || displayAllowedValuesHints || paramSchema.pattern ? html` <div class="param-constraint" style="margin-top:1rem"> ${paramSchema.constraints.length ? html`<span style="font-weight:700">Constraints: </span>${paramSchema.constraints.join(', ')}<br>` : ''} ${paramSchema.pattern ? html` <div class="tooltip tooltip-replace" style="cursor:pointer;max-width:100%;display:flex"> <div style="white-space:nowrap;font-weight:700;margin-right:2px">Pattern: </div> <div style="white-space:nowrap;text-overflow:ellipsis;max-width:100%;overflow:hidden">${paramSchema.pattern}</div> <br> <div class="tooltip-text" style="position:absolute;display:block">${paramSchema.pattern}</div> </div> ` : ''} ${(_paramSchema$allowedV = paramSchema.allowedValues) === null || _paramSchema$allowedV === void 0 ? void 0 : _paramSchema$allowedV.map((v, i) => html` ${i > 0 ? '|' : html`<span style="font-weight:700">Allowed: </span>`} ${html` <a part="anchor anchor-param-constraint" class="${this.allowTry === 'true' ? '' : 'inactive-link'}" data-type="${paramSchema.type === 'array' ? 'array' : 'string'}" data-enum="${v === null || v === void 0 ? void 0 : v.trim()}" @click="${e => {
|
232
|
-
const inputEl = e.target.closest('table').querySelector(`[data-pname="${param.name}"]`);
|
233
|
-
if (inputEl) {
|
234
|
-
inputEl.value = e.target.dataset.type === 'array' ? [e.target.dataset.enum] : e.target.dataset.enum;
|
235
|
-
}
|
236
|
-
}}"> ${v === null ? '-' : v} </a>`}`)} </div>` : ''} </td> ` : ''} </tr>`);
|
264
|
+
tableRows.push(newRows);
|
237
265
|
}
|
238
266
|
return html` <div class="table-title top-gap">${title}${paramLocation === 'path' ? html`<span style="color:var(--red)">*</span>` : ''}</div> <div style="display:block;overflow-x:auto;max-width:100%"> <table role="presentation" class="m-table" style="width:100%;word-break:break-word"> ${tableRows} </table> </div>`;
|
239
267
|
}
|
@@ -427,7 +455,7 @@ export default class ApiRequest extends LitElement {
|
|
427
455
|
return;
|
428
456
|
}
|
429
457
|
this.activeResponseTab = e.target.dataset.tab;
|
430
|
-
}}"> <br> <div style="width:100%"> <button class="tab-btn ${!hasResponse || this.activeResponseTab === 'curl' ? 'active' : ''}" data-tab="curl">
|
458
|
+
}}"> <br> <div style="width:100%"> <button class="tab-btn ${!hasResponse || this.activeResponseTab === 'curl' ? 'active' : ''}" data-tab="curl">REQUEST</button> ${!hasResponse ? '' : html` <button class="tab-btn ${this.activeResponseTab === 'response' ? 'active' : ''}" data-tab="response">${getI18nText('operations.response')}</button> <button class="tab-btn ${this.activeResponseTab === 'headers' ? 'active' : ''}" data-tab="headers">${getI18nText('operations.response-headers')}</button>`} </div> </div> ${this.responseIsBlob ? html` <div class="tab-content col" style="flex:1;display:${this.activeResponseTab === 'response' ? 'flex' : 'none'}"> ${this.responseBlobType === 'image' ? html`<img style="max-height:var(--resp-area-height,300px);object-fit:contain" class="mar-top-8" src="${this.responseBlobUrl}">` : ''} <div style="display:flex;justify-content:center"> <div> <button class="m-btn thin-border mar-top-8" style="width:135px" @click="${this.downloadResponseBlob}" part="btn btn-outline">DOWNLOAD</button> ${this.responseBlobType === 'view' || this.responseBlobType === 'image' ? html`<button class="m-btn thin-border mar-top-8" style="width:135px" @click="${this.viewResponseBlob}" part="btn btn-outline">VIEW (NEW TAB)</button>` : ''} </div> </div> </div>` : html` <div class="tab-content col m-markdown" style="flex:1;display:${this.activeResponseTab === 'response' ? 'flex' : 'none'}"> <syntax-highlighter style="min-height:60px" mime-type="${this.responseContentType}" .content="${this.responseText}"> </div>`} <div class="tab-content col m-markdown" style="flex:1;display:${this.activeResponseTab === 'headers' ? 'flex' : 'none'}"> <syntax-highlighter style="min-height:60px" language="http" .content="${this.responseHeaders}"> </div> <div class="tab-content m-markdown col" style="flex:1;display:${this.activeResponseTab === 'curl' ? 'flex' : 'none'}"> <syntax-highlighter style="min-height:60px" language="shell" .content="${curlSyntax.trim()}"> </div> </div>`;
|
431
459
|
}
|
432
460
|
apiCallTemplate() {
|
433
461
|
return html` <div style="display:flex;align-items:flex-end;margin:16px 0;font-size:var(--font-size-small)"> ${this.parameters.length > 0 || this.request_body ? html` <button class="m-btn thin-border" part="btn btn-outline" style="margin-right:5px" @click="${this.onClearRequestData}"> ${getI18nText('operations.clear')} </button>` : ''} <button class="m-btn primary btn-execute thin-border" part="btn btn-fill btn-try" @click="${this.onTryClick}">${getI18nText('operations.execute')}</button> </div> ${this.apiResponseTabTemplate()} `;
|
@@ -455,11 +483,20 @@ export default class ApiRequest extends LitElement {
|
|
455
483
|
this.dispatchEvent(new CustomEvent('event', event));
|
456
484
|
this.computeCurlSyntax();
|
457
485
|
}
|
486
|
+
validateAllRequestParameters() {
|
487
|
+
const requestPanelEl = this.closest('.request-panel');
|
488
|
+
const pathParamEls = [...requestPanelEl.querySelectorAll("[data-ptype='path']")];
|
489
|
+
const missingPathParameterValue = pathParamEls.find(el => !el.value);
|
490
|
+
if (missingPathParameterValue) {
|
491
|
+
const error = Error(`All path parameters are required and a valid value was not found for the parameter: '${missingPathParameterValue.dataset.pname}'.`);
|
492
|
+
error.code = 'MissingPathParameter';
|
493
|
+
throw error;
|
494
|
+
}
|
495
|
+
}
|
458
496
|
recomputeFetchOptions() {
|
459
497
|
const requestPanelEl = this.closest('.request-panel');
|
460
498
|
const pathParamEls = [...requestPanelEl.querySelectorAll("[data-ptype='path']")];
|
461
499
|
const queryParamEls = [...requestPanelEl.querySelectorAll("[data-ptype='query']")];
|
462
|
-
const queryParamObjTypeEls = [...requestPanelEl.querySelectorAll("[data-ptype='query-object']")];
|
463
500
|
const headerParamEls = [...requestPanelEl.querySelectorAll("[data-ptype='header']")];
|
464
501
|
const requestBodyContainerEl = requestPanelEl.querySelector('.request-body-container');
|
465
502
|
let pathUrl = `${this.serverUrl.replace(/\/$/, '')}${this.path.replaceAll(' ', '')}`;
|
@@ -470,12 +507,6 @@ export default class ApiRequest extends LitElement {
|
|
470
507
|
pathParameterMap[el.dataset.pname] = el.value;
|
471
508
|
pathUrl = pathUrl.replace(`{${el.dataset.pname}}`, encodeURIComponent(el.value) || '-');
|
472
509
|
});
|
473
|
-
const missingPathParameterValue = pathParamEls.find(el => !el.value);
|
474
|
-
if (missingPathParameterValue) {
|
475
|
-
const error = Error(`All path parameters are required and a valid value was not found for the parameter: '${missingPathParameterValue.dataset.pname}'.`);
|
476
|
-
error.code = 'MissingPathParameter';
|
477
|
-
throw error;
|
478
|
-
}
|
479
510
|
|
480
511
|
// Handle relative serverUrls
|
481
512
|
if (!pathUrl.startsWith('http')) {
|
@@ -507,7 +538,7 @@ export default class ApiRequest extends LitElement {
|
|
507
538
|
} else if (paramSerializeStyle === 'pipeDelimited') {
|
508
539
|
fetchUrl.searchParams.append(el.dataset.pname, values.join('|').replace(/^\||\|$/g, ''));
|
509
540
|
} else {
|
510
|
-
if (paramSerializeExplode === 'true') {
|
541
|
+
if (paramSerializeExplode === 'true' || paramSerializeExplode === true) {
|
511
542
|
// eslint-disable-line no-lonely-if
|
512
543
|
values.forEach(v => {
|
513
544
|
fetchUrl.searchParams.append(el.dataset.pname, v);
|
@@ -520,40 +551,6 @@ export default class ApiRequest extends LitElement {
|
|
520
551
|
}
|
521
552
|
});
|
522
553
|
|
523
|
-
// Query Params (Dynamic - create from JSON)
|
524
|
-
queryParamObjTypeEls.map(el => {
|
525
|
-
try {
|
526
|
-
let queryParamObj = {};
|
527
|
-
const paramSerializeStyle = el.dataset.paramSerializeStyle;
|
528
|
-
const paramSerializeExplode = el.dataset.paramSerializeExplode;
|
529
|
-
queryParamObj = Object.assign(queryParamObj, JSON.parse(el.value.replace(/\s+/g, ' ')));
|
530
|
-
for (const key in queryParamObj) {
|
531
|
-
if (typeof queryParamObj[key] === 'object') {
|
532
|
-
if (Array.isArray(queryParamObj[key])) {
|
533
|
-
if (paramSerializeStyle === 'spaceDelimited') {
|
534
|
-
fetchUrl.searchParams.append(key, queryParamObj[key].join(' '));
|
535
|
-
} else if (paramSerializeStyle === 'pipeDelimited') {
|
536
|
-
fetchUrl.searchParams.append(key, queryParamObj[key].join('|'));
|
537
|
-
} else {
|
538
|
-
if (paramSerializeExplode === 'true') {
|
539
|
-
// eslint-disable-line no-lonely-if
|
540
|
-
queryParamObj[key].forEach(v => {
|
541
|
-
fetchUrl.searchParams.append(key, v);
|
542
|
-
});
|
543
|
-
} else {
|
544
|
-
fetchUrl.searchParams.append(key, queryParamObj[key]);
|
545
|
-
}
|
546
|
-
}
|
547
|
-
}
|
548
|
-
} else {
|
549
|
-
fetchUrl.searchParams.append(key, queryParamObj[key]);
|
550
|
-
}
|
551
|
-
}
|
552
|
-
} catch (err) {
|
553
|
-
console.log('OpenAPI Explorer: unable to parse %s into object', el.value); // eslint-disable-line no-console
|
554
|
-
}
|
555
|
-
});
|
556
|
-
|
557
554
|
// Add Authentication api keys if provided
|
558
555
|
this.api_keys.filter(v => v.finalKeyValue).forEach(v => {
|
559
556
|
if (v.in === 'query') {
|
@@ -702,7 +699,7 @@ export default class ApiRequest extends LitElement {
|
|
702
699
|
} = this.recomputeFetchOptions();
|
703
700
|
const curl = `curl -X ${this.method.toUpperCase()} "${fetchUrl.toString()}"`;
|
704
701
|
const headers = headerOverride !== null && headerOverride !== void 0 ? headerOverride : fetchOptions.headers;
|
705
|
-
const curlHeaders = [...headers.entries()].reduce((acc, [key, value]) => `${acc} \\\n -H "${key}: ${value}"`, '');
|
702
|
+
const curlHeaders = [...headers.entries()].reduce((acc, [key, value]) => `${acc} \\\n -H "${key}: ${value.replace(/"/g, '\\"')}"`, '');
|
706
703
|
this.curlSyntax = `${curl}${curlHeaders}${curlParts.data}${curlParts.form}`;
|
707
704
|
} catch (error) {
|
708
705
|
/* There was an explicit issue and likely it was because the fetch options threw. */
|
@@ -734,6 +731,16 @@ export default class ApiRequest extends LitElement {
|
|
734
731
|
this.activeResponseTab = 'response';
|
735
732
|
return;
|
736
733
|
}
|
734
|
+
try {
|
735
|
+
this.validateAllRequestParameters();
|
736
|
+
} catch (error) {
|
737
|
+
this.responseMessage = error.message;
|
738
|
+
this.responseStatus = 'error';
|
739
|
+
this.responseUrl = '';
|
740
|
+
this.responseHeaders = '';
|
741
|
+
this.responseText = '';
|
742
|
+
return;
|
743
|
+
}
|
737
744
|
this.responseIsBlob = false;
|
738
745
|
this.respContentDisposition = '';
|
739
746
|
if (this.responseBlobUrl) {
|
@@ -167,13 +167,17 @@ class ApiRequest extends _lit.LitElement {
|
|
167
167
|
return (0, _keyed.keyed)(id, (0, _lit.html)` <div id="api-request-${id}" class="api-request col regular-font request-panel ${this.renderStyle === 'focused' || this.callback === 'true' ? 'focused-mode' : 'view-mode'}"> <div class="${this.callback === 'true' ? 'tiny-title' : 'req-res-title'}"> ${this.callback === 'true' ? 'CALLBACK REQUEST' : (0, _index.getI18nText)('operations.request')} </div> <div> ${this.inputParametersTemplate('path')} ${this.inputParametersTemplate('query')} ${this.inputParametersTemplate('header')} ${this.inputParametersTemplate('cookie')} ${this.requestBodyTemplate()} ${this.allowTry === 'false' ? '' : (0, _lit.html)`${this.apiCallTemplate()}`} </div> </div> `);
|
168
168
|
}
|
169
169
|
updated(changedProperties) {
|
170
|
+
// When the operation is changed, reset the display view properties
|
171
|
+
if (changedProperties.get('elementId')) {
|
172
|
+
this.activeResponseTab = 'curl';
|
173
|
+
}
|
170
174
|
// In focused mode after rendering the request component, update the text-areas(which contains examples) using the original values from hidden textareas.
|
171
175
|
// This is done coz, user may update the dom by editing the textarea's and once the DOM is updated externally change detection wont happen, therefore update the values manually
|
172
176
|
if (this.renderStyle !== 'focused') {
|
173
177
|
return;
|
174
178
|
}
|
175
179
|
|
176
|
-
//
|
180
|
+
// don't update example as only tabs is switched
|
177
181
|
if (changedProperties.size === 1 && changedProperties.has('activeSchemaTab')) {
|
178
182
|
return;
|
179
183
|
}
|
@@ -200,7 +204,7 @@ class ApiRequest extends _lit.LitElement {
|
|
200
204
|
}[paramLocation];
|
201
205
|
const tableRows = [];
|
202
206
|
for (const param of filteredParams) {
|
203
|
-
var
|
207
|
+
var _param$style, _param$explode;
|
204
208
|
if (!param.schema) {
|
205
209
|
continue;
|
206
210
|
}
|
@@ -212,33 +216,57 @@ class ApiRequest extends _lit.LitElement {
|
|
212
216
|
continue;
|
213
217
|
}
|
214
218
|
const defaultVal = Array.isArray(paramSchema.default) ? paramSchema.default : `${paramSchema.default}`;
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
219
|
+
// Set the default style: https://spec.openapis.org/oas/v3.1.0.html#fixed-fields-9
|
220
|
+
const paramStyle = (_param$style = param.style) !== null && _param$style !== void 0 ? _param$style : {
|
221
|
+
query: 'form',
|
222
|
+
path: 'simple',
|
223
|
+
header: 'simple',
|
224
|
+
cookie: 'form'
|
225
|
+
}[paramLocation];
|
226
|
+
const paramExplode = (_param$explode = param.explode) !== null && _param$explode !== void 0 ? _param$explode : param.style === 'form';
|
227
|
+
const rowGenerator = ({
|
228
|
+
name: paramName,
|
229
|
+
description: paramDescription,
|
230
|
+
required: paramRequired
|
231
|
+
}, generatedParamSchema) => {
|
232
|
+
var _this$storedParamValu, _generatedParamSchema;
|
233
|
+
const displayAllowedValuesHints = (generatedParamSchema.type === 'object' || generatedParamSchema.type === 'array') && generatedParamSchema.allowedValues;
|
234
|
+
return (0, _lit.html)` <tr> <td colspan="1" style="width:160px;min-width:50px;vertical-align:top"> <div class="param-name ${generatedParamSchema.deprecated ? 'deprecated' : ''}" style="margin-top:1rem"> ${paramName}${!generatedParamSchema.deprecated && paramRequired ? (0, _lit.html)`<span style="color:var(--red)">*</span>` : ''} </div> <div class="param-type" style="margin-bottom:1rem"> ${generatedParamSchema.type === 'array' ? `${generatedParamSchema.arrayType}` : `${generatedParamSchema.format ? generatedParamSchema.format : generatedParamSchema.type}`}${!generatedParamSchema.deprecated && paramRequired ? (0, _lit.html)`<span style="opacity:0">*</span>` : ''} </div> </td> <td colspan="2" style="min-width:160px;vertical-align:top"> ${this.allowTry === 'true' ? generatedParamSchema.type === 'array' && (0, _lit.html)` <div style="margin-top:1rem;margin-bottom:1rem"> <tag-input class="request-param" autocomplete="on" id="request-param-${paramName}" style="width:100%" data-ptype="${paramLocation}" data-pname="${paramName}" data-default="${Array.isArray(defaultVal) ? defaultVal.join('~|~') : defaultVal}" data-param-serialize-style="${paramStyle}" data-param-serialize-explode="${paramExplode}" data-array="true" placeholder="add-multiple ↩" @change="${e => {
|
235
|
+
this.storedParamValues[paramName] = e.detail.value;
|
236
|
+
this.computeCurlSyntax();
|
237
|
+
}}" .value="${(_this$storedParamValu = this.storedParamValues[paramName]) !== null && _this$storedParamValu !== void 0 ? _this$storedParamValu : this.fillRequestWithDefault === 'true' && Array.isArray(defaultVal) ? defaultVal : defaultVal.split(',')}"></tag-input> </div>` || generatedParamSchema.type === 'object' && (0, _lit.html)` <textarea autocomplete="on" id="request-param-${paramName}" @input="${() => {
|
238
|
+
this.computeCurlSyntax();
|
239
|
+
}}" class="textarea small request-param" part="textarea small textarea-param" rows="3" data-ptype="${paramLocation}" data-pname="${paramName}" data-default="${defaultVal}" data-param-serialize-style="${paramStyle}" data-param-serialize-explode="${paramExplode}" spellcheck="false" placeholder="${generatedParamSchema.example || defaultVal || ''}" style="width:100%;margin-top:1rem;margin-bottom:1rem" .value="${this.fillRequestWithDefault === 'true' ? defaultVal : ''}"></textarea>` || generatedParamSchema.allowedValues && (0, _lit.html)` <select aria-label="mime type" style="width:100%;margin-top:1rem;margin-bottom:1rem" data-ptype="${paramLocation}" data-pname="${paramName}" .value="${this.fillRequestWithDefault === 'true' ? defaultVal : ''}" @change="${e => {
|
240
|
+
this.storedParamValues[paramName] = e;
|
241
|
+
this.computeCurlSyntax();
|
242
|
+
}}"> ${generatedParamSchema.allowedValues.map(allowedValue => (0, _lit.html)` <option value="${allowedValue}" ?selected="${allowedValue === this.storedParamValues[paramName]}"> ${allowedValue === null ? '-' : allowedValue} </option>`)} </select>` || (0, _lit.html)` <input type="${generatedParamSchema.format === 'password' ? 'password' : 'text'}" spellcheck="false" style="width:100%;margin-top:1rem;margin-bottom:1rem" autocomplete="on" id="request-param-${paramName}" @input="${() => {
|
243
|
+
this.computeCurlSyntax();
|
244
|
+
}}" placeholder="${generatedParamSchema.example || defaultVal || ''}" class="request-param" part="textbox textbox-param" data-ptype="${paramLocation}" data-pname="${paramName}" data-default="${Array.isArray(defaultVal) ? defaultVal.join('~|~') : defaultVal}" data-array="false" @keyup="${this.requestParamFunction}" .value="${this.fillRequestWithDefault === 'true' ? defaultVal : ''}">` : ''} ${this.exampleListTemplate.call(this, param, generatedParamSchema.type)} </td> ${this.renderStyle === 'focused' ? (0, _lit.html)` <td colspan="2" style="vertical-align:top"> ${paramDescription ? (0, _lit.html)` <div class="param-description" style="margin-top:1rem"> ${(0, _unsafeHtml.unsafeHTML)((0, _commonUtils.toMarkdown)(paramDescription))} </div>` : ''} ${generatedParamSchema.constraints.length || displayAllowedValuesHints || generatedParamSchema.pattern ? (0, _lit.html)` <div class="param-constraint" style="margin-top:1rem"> ${generatedParamSchema.constraints.length ? (0, _lit.html)`<span style="font-weight:700">Constraints: </span>${generatedParamSchema.constraints.join(', ')}<br>` : ''} ${generatedParamSchema.pattern ? (0, _lit.html)` <div class="tooltip tooltip-replace" style="cursor:pointer;max-width:100%;display:flex"> <div style="white-space:nowrap;font-weight:700;margin-right:2px">Pattern: </div> <div style="white-space:nowrap;text-overflow:ellipsis;max-width:100%;overflow:hidden">${generatedParamSchema.pattern}</div> <br> <div class="tooltip-text" style="position:absolute;display:block">${generatedParamSchema.pattern}</div> </div> ` : ''} ${(_generatedParamSchema = generatedParamSchema.allowedValues) === null || _generatedParamSchema === void 0 ? void 0 : _generatedParamSchema.map((v, i) => (0, _lit.html)` ${i > 0 ? '|' : (0, _lit.html)`<span style="font-weight:700">Allowed: </span>`} ${(0, _lit.html)` <a part="anchor anchor-param-constraint" class="${this.allowTry === 'true' ? '' : 'inactive-link'}" data-type="${generatedParamSchema.type === 'array' ? 'array' : 'string'}" data-enum="${v === null || v === void 0 ? void 0 : v.trim()}" @click="${e => {
|
245
|
+
const inputEl = e.target.closest('table').querySelector(`[data-pname="${paramName}"]`);
|
246
|
+
if (inputEl) {
|
247
|
+
inputEl.value = e.target.dataset.type === 'array' ? [e.target.dataset.enum] : e.target.dataset.enum;
|
248
|
+
}
|
249
|
+
}}"> ${v === null ? '-' : v} </a>`}`)} </div>` : ''} </td> ` : ''} </tr>`;
|
250
|
+
};
|
251
|
+
let newRows = [];
|
252
|
+
if (paramStyle === 'form' && paramExplode) {
|
253
|
+
newRows = Object.keys(param.schema.properties).map(explodedParamKey => {
|
254
|
+
var _param$schema, _param$schema$require;
|
255
|
+
const explodedParam = param.schema.properties[explodedParamKey];
|
256
|
+
const explodedParamSchema = (0, _schemaUtils.getTypeInfo)(explodedParam, {
|
257
|
+
includeNulls: this.includeNulls,
|
258
|
+
enableExampleGeneration: true
|
259
|
+
});
|
260
|
+
return rowGenerator({
|
261
|
+
name: explodedParamKey,
|
262
|
+
description: explodedParam.description,
|
263
|
+
required: (_param$schema = param.schema) === null || _param$schema === void 0 ? void 0 : (_param$schema$require = _param$schema.required) === null || _param$schema$require === void 0 ? void 0 : _param$schema$require.includes(explodedParamKey)
|
264
|
+
}, explodedParamSchema);
|
265
|
+
});
|
266
|
+
} else {
|
267
|
+
newRows = rowGenerator(param, paramSchema);
|
224
268
|
}
|
225
|
-
|
226
|
-
tableRows.push((0, _lit.html)` <tr> <td colspan="1" style="width:160px;min-width:50px;vertical-align:top"> <div class="param-name ${paramSchema.deprecated ? 'deprecated' : ''}" style="margin-top:1rem"> ${param.name}${!paramSchema.deprecated && param.required ? (0, _lit.html)`<span style="color:var(--red)">*</span>` : ''} </div> <div class="param-type" style="margin-bottom:1rem"> ${paramSchema.type === 'array' ? `${paramSchema.arrayType}` : `${paramSchema.format ? paramSchema.format : paramSchema.type}`}${!paramSchema.deprecated && param.required ? (0, _lit.html)`<span style="opacity:0">*</span>` : ''} </div> </td> <td colspan="2" style="min-width:160px;vertical-align:top"> ${this.allowTry === 'true' ? paramSchema.type === 'array' && (0, _lit.html)` <div style="margin-top:1rem;margin-bottom:1rem"> <tag-input class="request-param" autocomplete="on" id="request-param-${param.name}" style="width:100%" data-ptype="${paramLocation}" data-pname="${param.name}" data-default="${Array.isArray(defaultVal) ? defaultVal.join('~|~') : defaultVal}" data-param-serialize-style="${paramStyle}" data-param-serialize-explode="${paramExplode}" data-array="true" placeholder="add-multiple ↩" @change="${e => {
|
227
|
-
this.storedParamValues[param.name] = e.detail.value;
|
228
|
-
this.computeCurlSyntax();
|
229
|
-
}}" .value="${(_this$storedParamValu = this.storedParamValues[param.name]) !== null && _this$storedParamValu !== void 0 ? _this$storedParamValu : this.fillRequestWithDefault === 'true' && Array.isArray(defaultVal) ? defaultVal : defaultVal.split(',')}"></tag-input> </div>` || paramSchema.type === 'object' && (0, _lit.html)` <textarea autocomplete="on" id="request-param-${param.name}" @input="${() => {
|
230
|
-
this.computeCurlSyntax();
|
231
|
-
}}" class="textarea small request-param" part="textarea small textarea-param" rows="3" data-ptype="${paramLocation}" data-pname="${param.name}" data-default="${defaultVal}" data-param-serialize-style="${paramStyle}" data-param-serialize-explode="${paramExplode}" spellcheck="false" placeholder="${paramSchema.example || defaultVal || ''}" style="width:100%;margin-top:1rem;margin-bottom:1rem" .value="${this.fillRequestWithDefault === 'true' ? defaultVal : ''}"></textarea>` || paramSchema.allowedValues && (0, _lit.html)` <select aria-label="mime type" style="width:100%;margin-top:1rem;margin-bottom:1rem" data-ptype="${paramLocation}" data-pname="${param.name}" .value="${this.fillRequestWithDefault === 'true' ? defaultVal : ''}" @change="${e => {
|
232
|
-
this.storedParamValues[param.name] = e;
|
233
|
-
this.computeCurlSyntax();
|
234
|
-
}}"> ${paramSchema.allowedValues.map(allowedValue => (0, _lit.html)` <option value="${allowedValue}" ?selected="${allowedValue === this.storedParamValues[param.name]}"> ${allowedValue === null ? '-' : allowedValue} </option>`)} </select>` || (0, _lit.html)` <input type="${paramSchema.format === 'password' ? 'password' : 'text'}" spellcheck="false" style="width:100%;margin-top:1rem;margin-bottom:1rem" autocomplete="on" id="request-param-${param.name}" @input="${() => {
|
235
|
-
this.computeCurlSyntax();
|
236
|
-
}}" placeholder="${paramSchema.example || defaultVal || ''}" class="request-param" part="textbox textbox-param" data-ptype="${paramLocation}" data-pname="${param.name}" data-default="${Array.isArray(defaultVal) ? defaultVal.join('~|~') : defaultVal}" data-array="false" @keyup="${this.requestParamFunction}" .value="${this.fillRequestWithDefault === 'true' ? defaultVal : ''}">` : ''} ${this.exampleListTemplate.call(this, param, paramSchema.type)} </td> ${this.renderStyle === 'focused' ? (0, _lit.html)` <td colspan="2" style="vertical-align:top"> ${param.description ? (0, _lit.html)` <div class="param-description" style="margin-top:1rem"> ${(0, _unsafeHtml.unsafeHTML)((0, _commonUtils.toMarkdown)(param.description))} </div>` : ''} ${paramSchema.constraints.length || displayAllowedValuesHints || paramSchema.pattern ? (0, _lit.html)` <div class="param-constraint" style="margin-top:1rem"> ${paramSchema.constraints.length ? (0, _lit.html)`<span style="font-weight:700">Constraints: </span>${paramSchema.constraints.join(', ')}<br>` : ''} ${paramSchema.pattern ? (0, _lit.html)` <div class="tooltip tooltip-replace" style="cursor:pointer;max-width:100%;display:flex"> <div style="white-space:nowrap;font-weight:700;margin-right:2px">Pattern: </div> <div style="white-space:nowrap;text-overflow:ellipsis;max-width:100%;overflow:hidden">${paramSchema.pattern}</div> <br> <div class="tooltip-text" style="position:absolute;display:block">${paramSchema.pattern}</div> </div> ` : ''} ${(_paramSchema$allowedV = paramSchema.allowedValues) === null || _paramSchema$allowedV === void 0 ? void 0 : _paramSchema$allowedV.map((v, i) => (0, _lit.html)` ${i > 0 ? '|' : (0, _lit.html)`<span style="font-weight:700">Allowed: </span>`} ${(0, _lit.html)` <a part="anchor anchor-param-constraint" class="${this.allowTry === 'true' ? '' : 'inactive-link'}" data-type="${paramSchema.type === 'array' ? 'array' : 'string'}" data-enum="${v === null || v === void 0 ? void 0 : v.trim()}" @click="${e => {
|
237
|
-
const inputEl = e.target.closest('table').querySelector(`[data-pname="${param.name}"]`);
|
238
|
-
if (inputEl) {
|
239
|
-
inputEl.value = e.target.dataset.type === 'array' ? [e.target.dataset.enum] : e.target.dataset.enum;
|
240
|
-
}
|
241
|
-
}}"> ${v === null ? '-' : v} </a>`}`)} </div>` : ''} </td> ` : ''} </tr>`);
|
269
|
+
tableRows.push(newRows);
|
242
270
|
}
|
243
271
|
return (0, _lit.html)` <div class="table-title top-gap">${title}${paramLocation === 'path' ? (0, _lit.html)`<span style="color:var(--red)">*</span>` : ''}</div> <div style="display:block;overflow-x:auto;max-width:100%"> <table role="presentation" class="m-table" style="width:100%;word-break:break-word"> ${tableRows} </table> </div>`;
|
244
272
|
}
|
@@ -432,7 +460,7 @@ class ApiRequest extends _lit.LitElement {
|
|
432
460
|
return;
|
433
461
|
}
|
434
462
|
this.activeResponseTab = e.target.dataset.tab;
|
435
|
-
}}"> <br> <div style="width:100%"> <button class="tab-btn ${!hasResponse || this.activeResponseTab === 'curl' ? 'active' : ''}" data-tab="curl">
|
463
|
+
}}"> <br> <div style="width:100%"> <button class="tab-btn ${!hasResponse || this.activeResponseTab === 'curl' ? 'active' : ''}" data-tab="curl">REQUEST</button> ${!hasResponse ? '' : (0, _lit.html)` <button class="tab-btn ${this.activeResponseTab === 'response' ? 'active' : ''}" data-tab="response">${(0, _index.getI18nText)('operations.response')}</button> <button class="tab-btn ${this.activeResponseTab === 'headers' ? 'active' : ''}" data-tab="headers">${(0, _index.getI18nText)('operations.response-headers')}</button>`} </div> </div> ${this.responseIsBlob ? (0, _lit.html)` <div class="tab-content col" style="flex:1;display:${this.activeResponseTab === 'response' ? 'flex' : 'none'}"> ${this.responseBlobType === 'image' ? (0, _lit.html)`<img style="max-height:var(--resp-area-height,300px);object-fit:contain" class="mar-top-8" src="${this.responseBlobUrl}">` : ''} <div style="display:flex;justify-content:center"> <div> <button class="m-btn thin-border mar-top-8" style="width:135px" @click="${this.downloadResponseBlob}" part="btn btn-outline">DOWNLOAD</button> ${this.responseBlobType === 'view' || this.responseBlobType === 'image' ? (0, _lit.html)`<button class="m-btn thin-border mar-top-8" style="width:135px" @click="${this.viewResponseBlob}" part="btn btn-outline">VIEW (NEW TAB)</button>` : ''} </div> </div> </div>` : (0, _lit.html)` <div class="tab-content col m-markdown" style="flex:1;display:${this.activeResponseTab === 'response' ? 'flex' : 'none'}"> <syntax-highlighter style="min-height:60px" mime-type="${this.responseContentType}" .content="${this.responseText}"> </div>`} <div class="tab-content col m-markdown" style="flex:1;display:${this.activeResponseTab === 'headers' ? 'flex' : 'none'}"> <syntax-highlighter style="min-height:60px" language="http" .content="${this.responseHeaders}"> </div> <div class="tab-content m-markdown col" style="flex:1;display:${this.activeResponseTab === 'curl' ? 'flex' : 'none'}"> <syntax-highlighter style="min-height:60px" language="shell" .content="${curlSyntax.trim()}"> </div> </div>`;
|
436
464
|
}
|
437
465
|
apiCallTemplate() {
|
438
466
|
return (0, _lit.html)` <div style="display:flex;align-items:flex-end;margin:16px 0;font-size:var(--font-size-small)"> ${this.parameters.length > 0 || this.request_body ? (0, _lit.html)` <button class="m-btn thin-border" part="btn btn-outline" style="margin-right:5px" @click="${this.onClearRequestData}"> ${(0, _index.getI18nText)('operations.clear')} </button>` : ''} <button class="m-btn primary btn-execute thin-border" part="btn btn-fill btn-try" @click="${this.onTryClick}">${(0, _index.getI18nText)('operations.execute')}</button> </div> ${this.apiResponseTabTemplate()} `;
|
@@ -460,11 +488,20 @@ class ApiRequest extends _lit.LitElement {
|
|
460
488
|
this.dispatchEvent(new CustomEvent('event', event));
|
461
489
|
this.computeCurlSyntax();
|
462
490
|
}
|
491
|
+
validateAllRequestParameters() {
|
492
|
+
const requestPanelEl = this.closest('.request-panel');
|
493
|
+
const pathParamEls = [...requestPanelEl.querySelectorAll("[data-ptype='path']")];
|
494
|
+
const missingPathParameterValue = pathParamEls.find(el => !el.value);
|
495
|
+
if (missingPathParameterValue) {
|
496
|
+
const error = Error(`All path parameters are required and a valid value was not found for the parameter: '${missingPathParameterValue.dataset.pname}'.`);
|
497
|
+
error.code = 'MissingPathParameter';
|
498
|
+
throw error;
|
499
|
+
}
|
500
|
+
}
|
463
501
|
recomputeFetchOptions() {
|
464
502
|
const requestPanelEl = this.closest('.request-panel');
|
465
503
|
const pathParamEls = [...requestPanelEl.querySelectorAll("[data-ptype='path']")];
|
466
504
|
const queryParamEls = [...requestPanelEl.querySelectorAll("[data-ptype='query']")];
|
467
|
-
const queryParamObjTypeEls = [...requestPanelEl.querySelectorAll("[data-ptype='query-object']")];
|
468
505
|
const headerParamEls = [...requestPanelEl.querySelectorAll("[data-ptype='header']")];
|
469
506
|
const requestBodyContainerEl = requestPanelEl.querySelector('.request-body-container');
|
470
507
|
let pathUrl = `${this.serverUrl.replace(/\/$/, '')}${this.path.replaceAll(' ', '')}`;
|
@@ -475,12 +512,6 @@ class ApiRequest extends _lit.LitElement {
|
|
475
512
|
pathParameterMap[el.dataset.pname] = el.value;
|
476
513
|
pathUrl = pathUrl.replace(`{${el.dataset.pname}}`, encodeURIComponent(el.value) || '-');
|
477
514
|
});
|
478
|
-
const missingPathParameterValue = pathParamEls.find(el => !el.value);
|
479
|
-
if (missingPathParameterValue) {
|
480
|
-
const error = Error(`All path parameters are required and a valid value was not found for the parameter: '${missingPathParameterValue.dataset.pname}'.`);
|
481
|
-
error.code = 'MissingPathParameter';
|
482
|
-
throw error;
|
483
|
-
}
|
484
515
|
|
485
516
|
// Handle relative serverUrls
|
486
517
|
if (!pathUrl.startsWith('http')) {
|
@@ -512,7 +543,7 @@ class ApiRequest extends _lit.LitElement {
|
|
512
543
|
} else if (paramSerializeStyle === 'pipeDelimited') {
|
513
544
|
fetchUrl.searchParams.append(el.dataset.pname, values.join('|').replace(/^\||\|$/g, ''));
|
514
545
|
} else {
|
515
|
-
if (paramSerializeExplode === 'true') {
|
546
|
+
if (paramSerializeExplode === 'true' || paramSerializeExplode === true) {
|
516
547
|
// eslint-disable-line no-lonely-if
|
517
548
|
values.forEach(v => {
|
518
549
|
fetchUrl.searchParams.append(el.dataset.pname, v);
|
@@ -525,40 +556,6 @@ class ApiRequest extends _lit.LitElement {
|
|
525
556
|
}
|
526
557
|
});
|
527
558
|
|
528
|
-
// Query Params (Dynamic - create from JSON)
|
529
|
-
queryParamObjTypeEls.map(el => {
|
530
|
-
try {
|
531
|
-
let queryParamObj = {};
|
532
|
-
const paramSerializeStyle = el.dataset.paramSerializeStyle;
|
533
|
-
const paramSerializeExplode = el.dataset.paramSerializeExplode;
|
534
|
-
queryParamObj = Object.assign(queryParamObj, JSON.parse(el.value.replace(/\s+/g, ' ')));
|
535
|
-
for (const key in queryParamObj) {
|
536
|
-
if (typeof queryParamObj[key] === 'object') {
|
537
|
-
if (Array.isArray(queryParamObj[key])) {
|
538
|
-
if (paramSerializeStyle === 'spaceDelimited') {
|
539
|
-
fetchUrl.searchParams.append(key, queryParamObj[key].join(' '));
|
540
|
-
} else if (paramSerializeStyle === 'pipeDelimited') {
|
541
|
-
fetchUrl.searchParams.append(key, queryParamObj[key].join('|'));
|
542
|
-
} else {
|
543
|
-
if (paramSerializeExplode === 'true') {
|
544
|
-
// eslint-disable-line no-lonely-if
|
545
|
-
queryParamObj[key].forEach(v => {
|
546
|
-
fetchUrl.searchParams.append(key, v);
|
547
|
-
});
|
548
|
-
} else {
|
549
|
-
fetchUrl.searchParams.append(key, queryParamObj[key]);
|
550
|
-
}
|
551
|
-
}
|
552
|
-
}
|
553
|
-
} else {
|
554
|
-
fetchUrl.searchParams.append(key, queryParamObj[key]);
|
555
|
-
}
|
556
|
-
}
|
557
|
-
} catch (err) {
|
558
|
-
console.log('OpenAPI Explorer: unable to parse %s into object', el.value); // eslint-disable-line no-console
|
559
|
-
}
|
560
|
-
});
|
561
|
-
|
562
559
|
// Add Authentication api keys if provided
|
563
560
|
this.api_keys.filter(v => v.finalKeyValue).forEach(v => {
|
564
561
|
if (v.in === 'query') {
|
@@ -707,7 +704,7 @@ class ApiRequest extends _lit.LitElement {
|
|
707
704
|
} = this.recomputeFetchOptions();
|
708
705
|
const curl = `curl -X ${this.method.toUpperCase()} "${fetchUrl.toString()}"`;
|
709
706
|
const headers = headerOverride !== null && headerOverride !== void 0 ? headerOverride : fetchOptions.headers;
|
710
|
-
const curlHeaders = [...headers.entries()].reduce((acc, [key, value]) => `${acc} \\\n -H "${key}: ${value}"`, '');
|
707
|
+
const curlHeaders = [...headers.entries()].reduce((acc, [key, value]) => `${acc} \\\n -H "${key}: ${value.replace(/"/g, '\\"')}"`, '');
|
711
708
|
this.curlSyntax = `${curl}${curlHeaders}${curlParts.data}${curlParts.form}`;
|
712
709
|
} catch (error) {
|
713
710
|
/* There was an explicit issue and likely it was because the fetch options threw. */
|
@@ -739,6 +736,16 @@ class ApiRequest extends _lit.LitElement {
|
|
739
736
|
this.activeResponseTab = 'response';
|
740
737
|
return;
|
741
738
|
}
|
739
|
+
try {
|
740
|
+
this.validateAllRequestParameters();
|
741
|
+
} catch (error) {
|
742
|
+
this.responseMessage = error.message;
|
743
|
+
this.responseStatus = 'error';
|
744
|
+
this.responseUrl = '';
|
745
|
+
this.responseHeaders = '';
|
746
|
+
this.responseText = '';
|
747
|
+
return;
|
748
|
+
}
|
742
749
|
this.responseIsBlob = false;
|
743
750
|
this.respContentDisposition = '';
|
744
751
|
if (this.responseBlobUrl) {
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "openapi-explorer",
|
3
|
-
"version": "2.2.
|
3
|
+
"version": "2.2.730",
|
4
4
|
"description": "OpenAPI Explorer - API viewer with dynamically generated components, documentation, and interaction console",
|
5
5
|
"author": "Authress Developers <developers@authress.io>",
|
6
6
|
"type": "module",
|