openapi-explorer
Version:
OpenAPI Explorer - API viewer with dynamically generated components, documentation, and interaction console
183 lines (179 loc) • 14.4 kB
JavaScript
;
exports.__esModule = true;
exports.default = void 0;
var _lit = require("lit");
var _unsafeHtml = require("lit/directives/unsafe-html.js");
var _schemaUtils = require("../utils/schema-utils.js");
var _commonUtils = require("../utils/common-utils.js");
var _index = require("../languages/index.js");
var _fontStyles = _interopRequireDefault(require("../styles/font-styles.js"));
var _flexStyles = _interopRequireDefault(require("../styles/flex-styles.js"));
var _tableStyles = _interopRequireDefault(require("../styles/table-styles.js"));
var _inputStyles = _interopRequireDefault(require("../styles/input-styles.js"));
var _tabStyles = _interopRequireDefault(require("../styles/tab-styles.js"));
var _borderStyles = _interopRequireDefault(require("../styles/border-styles.js"));
var _schemaStyles = _interopRequireDefault(require("../styles/schema-styles.js"));
var _prismStyles = _interopRequireDefault(require("../styles/prism-styles.js"));
require("./schema-tree.js");
require("./schema-table.js");
require("./syntax-highlighter.js");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
class ApiResponse extends _lit.LitElement {
constructor() {
super();
this.selectedStatus = '';
this.headersForEachRespStatus = {};
this.mimeResponsesForEachStatus = {};
this.activeSchemaTab = 'model';
}
static get properties() {
return {
callback: {
type: String
},
responses: {
type: Object
},
parser: {
type: Object
},
includeNulls: {
type: Boolean,
attribute: 'display-nulls',
converter(value) {
return value === 'true';
}
},
schemaStyle: {
type: String,
attribute: 'schema-style'
},
renderStyle: {
type: String,
attribute: 'render-style'
},
selectedStatus: {
type: String,
attribute: 'selected-status'
},
selectedMimeType: {
type: String,
attribute: 'selected-mime-type'
},
activeSchemaTab: {
type: String,
attribute: 'active-schema-tab'
},
schemaExpandLevel: {
type: Number,
attribute: 'schema-expand-level'
},
schemaHideWriteOnly: {
type: String,
attribute: 'schema-hide-write-only'
}
};
}
static finalizeStyles() {
return [_schemaStyles.default, _fontStyles.default, _flexStyles.default, _tabStyles.default, _tableStyles.default, _inputStyles.default, _borderStyles.default, _prismStyles.default, (0, _lit.css)`.resp-head{vertical-align:middle;padding:16px 0 8px}.resp-head.divider{border-top:1px solid var(--border-color);margin-top:10px}.resp-status{font-weight:700;font-size:calc(var(--font-size-small) + 1px)}.resp-descr{font-size:calc(var(--font-size-small) + 1px)}.top-gap{margin-top:16px}.example-panel{font-size:var(--font-size-small);margin:0}.generic-tree{background:var(--bg2,#333);color:var(--fg,#fff)}.example-panel.generic-tree{margin-top:8px}pre.generic-tree{border:none;padding:8px 10px 10px}.example-panel select{margin-left:8px;padding-top:8px;min-width:100px;max-width:100%}.example-panel .example{padding:0 12px}.focused-mode,.read-mode{padding-top:3rem;margin-top:12px;border-top:1px dashed var(--border-color)}`];
}
render() {
return (0, _lit.html)` <div class="col regular-font response-panel ${this.renderStyle}-mode"> <div class="${this.callback === 'true' ? 'tiny-title' : 'req-res-title'}" role="heading" aria-level="${this.renderStyle === 'focused' ? 3 : 4}"> ${this.callback === 'true' ? (0, _index.getI18nText)('operations.callback-response') : (0, _index.getI18nText)('operations.response')} </div> <div> ${this.responseTemplate()} <div> </div> </div></div>`;
}
resetSelection() {
this.selectedStatus = '';
this.selectedMimeType = '';
}
/* eslint-disable indent */
responseTemplate() {
if (!this.responses) {
return '';
}
for (const statusCode in this.responses) {
if (!this.selectedStatus) {
this.selectedStatus = statusCode;
}
const allMimeResp = {};
for (const mimeResp in this.responses[statusCode] && this.responses[statusCode].content) {
const mimeRespObj = this.responses[statusCode].content[mimeResp];
if (!this.selectedMimeType) {
this.selectedMimeType = mimeResp;
}
// Generate Schema
const schemaTree = (0, _schemaUtils.schemaInObjectNotation)(mimeRespObj.schema, {
includeNulls: this.includeNulls
});
// Generate Example
const respExamples = (0, _schemaUtils.generateExample)(mimeRespObj.examples || '', mimeRespObj.example || '', mimeRespObj.schema, mimeResp, true, false, mimeResp.includes('json') ? 'json' : 'text');
allMimeResp[mimeResp] = {
description: this.responses[statusCode].description,
examples: respExamples,
selectedExample: respExamples[0] && respExamples[0].exampleId || '',
schemaTree
};
}
// Headers for each response status
const tempHeaders = [];
for (const key in this.responses[statusCode] && this.responses[statusCode].headers) {
tempHeaders.push({
name: key,
...this.responses[statusCode].headers[key]
});
}
this.headersForEachRespStatus[statusCode] = tempHeaders;
this.mimeResponsesForEachStatus[statusCode] = allMimeResp;
}
return (0, _lit.html)`<div class="row" style="flex-wrap:wrap" role="group"> ${Object.keys(this.responses).map(respStatus => (0, _lit.html)` ${respStatus === '$$ref' // Swagger-Client parser creates '$$ref' object if JSON references are used to create responses - this should be ignored
? '' : (0, _lit.html)` <button @click="${() => {
this.selectedStatus = respStatus;
if (this.responses[respStatus].content && Object.keys(this.responses[respStatus].content)[0]) {
this.selectedMimeType = Object.keys(this.responses[respStatus].content)[0];
} else {
this.selectedMimeType = undefined;
}
}}" aria-current="${this.selectedStatus === respStatus}" class="m-btn small ${this.selectedStatus === respStatus ? 'primary' : ''}" part="btn--resp ${this.selectedStatus === respStatus ? 'btn-fill--resp' : 'btn-outline--resp'} btn-response-status" style="margin:8px 4px 0 0;text-transform:capitalize"> ${respStatus} </button>`}`)} </div> ${Object.keys(this.responses).map(status => (0, _lit.html)` <div style="display:${status === this.selectedStatus ? 'block' : 'none'}"> <div class="top-gap"> <span class="resp-descr m-markdown">${(0, _unsafeHtml.unsafeHTML)((0, _commonUtils.toMarkdown)(this.responses[status] && this.responses[status].description || ''))}</span> ${this.headersForEachRespStatus[status] && this.headersForEachRespStatus[status].length > 0 ? (0, _lit.html)`${this.responseHeaderListTemplate(this.headersForEachRespStatus[status])}` : ''} </div> ${Object.keys(this.mimeResponsesForEachStatus[status]).length === 0 ? '' : (0, _lit.html)` <div class="tab-panel col"> <div class="tab-buttons row" role="group" @click="${e => {
if (e.target.tagName.toLowerCase() === 'button') {
this.activeSchemaTab = e.target.dataset.tab;
}
}}"> <button class="tab-btn ${this.activeSchemaTab === 'model' ? 'active' : ''}" aria-current="${this.activeSchemaTab === 'model'}" data-tab="model">${(0, _index.getI18nText)('operations.model')}</button> <button class="tab-btn ${this.activeSchemaTab !== 'model' ? 'active' : ''}" aria-current="${this.activeSchemaTab !== 'model'}" data-tab="body">${(0, _index.getI18nText)('operations.example')}</button> <div style="flex:1"></div> ${Object.keys(this.mimeResponsesForEachStatus[status]).length === 1 ? (0, _lit.html)`<span class="small-font-size gray-text" style="align-self:center;margin-top:8px"> ${Object.keys(this.mimeResponsesForEachStatus[status])[0]} </span>` : (0, _lit.html)`${this.mimeTypeDropdownTemplate(Object.keys(this.mimeResponsesForEachStatus[status]))}`} </div> ${this.activeSchemaTab === 'body' ? (0, _lit.html)`<div class="tab-content col" style="flex:1"> ${this.mimeExampleTemplate(this.mimeResponsesForEachStatus[status][this.selectedMimeType])} </div>` : (0, _lit.html)`<div class="tab-content col" style="flex:1"> ${this.mimeSchemaTemplate(this.mimeResponsesForEachStatus[status][this.selectedMimeType])} </div>`} </div> `}</div>`)} `;
}
responseHeaderListTemplate(respHeaders) {
return (0, _lit.html)` <div style="padding:16px 0 8px 0" class="resp-headers small-font-size bold-text">${(0, _index.getI18nText)('operations.response-headers')}</div> <table role="presentation" style="border-collapse:collapse;margin-bottom:16px;border:1px solid var(--border-color);border-radius:var(--border-radius)" class="small-font-size mono-font"> ${respHeaders.map(v => {
var _ref, _typeData$example;
const typeData = (0, _schemaUtils.getTypeInfo)(v, {
enableExampleGeneration: true
});
return (0, _lit.html)` <tr> <td style="padding:8px;vertical-align:baseline;min-width:160px;border-top:1px solid var(--light-border-color);text-overflow:ellipsis"> ${v.name || ''} </td> <td class="${(typeData === null || typeData === void 0 ? void 0 : typeData.cssType) || ''}" style="padding:4px;vertical-align:baseline;min-width:100px;padding:0 5px;border-top:1px solid var(--light-border-color);text-overflow:ellipsis"> ${(typeData === null || typeData === void 0 ? void 0 : typeData.format) || (typeData === null || typeData === void 0 ? void 0 : typeData.type) || ''} </td> <td style="padding:8px;vertical-align:baseline;border-top:1px solid var(--light-border-color);text-overflow:ellipsis"> <div class="m-markdown-small regular-font">${(0, _unsafeHtml.unsafeHTML)((0, _commonUtils.toMarkdown)(v.description || ''))}</div> </td> <td style="padding:8px;vertical-align:baseline;border-top:1px solid var(--light-border-color);text-overflow:ellipsis"> ${(_ref = (_typeData$example = typeData === null || typeData === void 0 ? void 0 : typeData.example) !== null && _typeData$example !== void 0 ? _typeData$example : typeData === null || typeData === void 0 ? void 0 : typeData.default) !== null && _ref !== void 0 ? _ref : ''} </td> </tr> `;
})} </table>`;
}
mimeTypeDropdownTemplate(mimeTypes) {
return (0, _lit.html)` <select aria-label="mime type" @change="${e => {
this.selectedMimeType = e.target.value;
}}" style="margin-bottom:-1px;z-index:1"> ${mimeTypes.map(mimeType => (0, _lit.html)`<option value="${mimeType}" ?selected="${mimeType === this.selectedMimeType}"> ${mimeType} </option>`)} </select>`;
}
onSelectExample(e) {
const exampleContainerEl = e.target.closest('.example-panel');
const exampleEls = [...exampleContainerEl.querySelectorAll('.example')];
exampleEls.forEach(v => {
v.style.display = v.dataset.example === e.target.value ? 'block' : 'none';
});
}
mimeExampleTemplate(mimeRespDetails) {
if (!mimeRespDetails) {
return (0, _lit.html)` <pre style="color:var(--red)" class="example-panel border-top"> No example provided </pre> `;
}
return (0, _lit.html)` ${mimeRespDetails.examples.length === 1 ? (0, _lit.html)` ${mimeRespDetails.examples[0].exampleSummary && mimeRespDetails.examples[0].exampleSummary.length > 80 ? (0, _lit.html)`<div style="padding:4px 0"> ${mimeRespDetails.examples[0].exampleSummary} </div>` : ''} ${mimeRespDetails.examples[0].exampleDescription ? (0, _lit.html)`<div class="m-markdown-small" style="padding:4px 0"> ${(0, _unsafeHtml.unsafeHTML)((0, _commonUtils.toMarkdown)(mimeRespDetails.examples[0].exampleDescription || ''))} </div>` : ''} <syntax-highlighter class="example-panel generic-tree pad-top-8" mime-type="${mimeRespDetails.examples[0].exampleType}" .content="${mimeRespDetails.examples[0].exampleValue}">` : (0, _lit.html)` <span class="example-panel generic-tree ${this.renderStyle === 'read' ? 'border pad-8-16' : 'border-top pad-top-8'}"> <select aria-label="response body example" @change="${e => this.onSelectExample(e)}"> ${mimeRespDetails.examples.map(v => (0, _lit.html)`<option value="${v.exampleId}" ?selected="${v.exampleId === mimeRespDetails.selectedExample}"> ${!v.exampleSummary || v.exampleSummary.length > 80 ? v.exampleId : v.exampleSummary} </option>`)} </select> ${mimeRespDetails.examples.map(v => (0, _lit.html)` <div class="example" data-example="${v.exampleId}" style="display:${v.exampleId === mimeRespDetails.selectedExample ? 'block' : 'none'}"> ${v.exampleSummary && v.exampleSummary.length > 80 ? (0, _lit.html)`<div style="padding:4px 0"> ${v.exampleSummary} </div>` : ''} ${v.exampleDescription && v.exampleDescription !== v.exampleSummary ? (0, _lit.html)`<div class="m-markdown-small" style="padding:4px 0"> ${(0, _unsafeHtml.unsafeHTML)((0, _commonUtils.toMarkdown)(v.exampleDescription || ''))} </div>` : ''} <syntax-highlighter mime-type="${v.exampleType}" .content="${v.exampleValue}"> </div> `)} </span> `} `;
}
mimeSchemaTemplate(mimeRespDetails) {
if (!mimeRespDetails) {
return (0, _lit.html)` <pre style="color:var(--red)" class="${this.renderStyle === 'read' ? 'border pad-8-16' : 'border-top'}"> Schema not found</pre> `;
}
return (0, _lit.html)` ${this.schemaStyle === 'table' ? (0, _lit.html)` <schema-table render-style="${this.renderStyle}" .data="${mimeRespDetails.schemaTree}" class="example-panel ${this.renderStyle === 'read' ? 'border pad-8-16' : 'border-top pad-top-8'}" schema-expand-level="${this.schemaExpandLevel}" schema-hide-read-only="false" schema-hide-write-only="${this.schemaHideWriteOnly}" exportparts="schema-key, schema-type, schema-description, schema-table-header"> </schema-table> ` : (0, _lit.html)` <schema-tree render-style="${this.renderStyle}" .data="${mimeRespDetails.schemaTree}" class="example-panel ${this.renderStyle === 'read' ? 'border pad-8-16' : 'pad-top-8'}" schema-expand-level="${this.schemaExpandLevel}" schema-hide-read-only="false" schema-hide-write-only="${this.schemaHideWriteOnly}" exportparts="schema-key, schema-type, schema-description"> </schema-tree>`}`;
}
/* eslint-enable indent */
}
// Register the element with the browser
exports.default = ApiResponse;
if (!customElements.get('openapi-explorer')) {
customElements.define('api-response', ApiResponse);
}