- ${nameEditor ? this[renameInputTemplate](id, label, 'schema') : label}
+ ${nameEditor ? this[renameInputTemplate](id, 'schema', label) : label}
`;
}
/**
- * @return {TemplateResult|string} The template for the security section.
+ * @return The template for the security section.
*/
- [securitiesTemplate]() {
+ [securitiesTemplate](): TemplateResult | string {
const items = this[getFilteredSecurity]();
if (!items.length) {
return '';
@@ -2179,7 +2201,7 @@ export default class ApiNavigationElement extends EventsTargetMixin(LitElement)
const { securityOpened } = this;
const classes = {
security: true,
- opened: securityOpened,
+ opened: !!securityOpened,
};
const toggleState = securityOpened ? 'Expanded' : 'Collapsed';
return html`
@@ -2217,17 +2239,16 @@ export default class ApiNavigationElement extends EventsTargetMixin(LitElement)
}
/**
- * @param {SecurityItem} item
- * @return {TemplateResult} The template for the security list item.
+ * @return The template for the security list item.
*/
- [securityTemplate](item) {
+ [securityTemplate](item: SecurityItem): TemplateResult {
const { id, displayName, name, selected, secondarySelected, type } = item;
const label = displayName || name || 'Unnamed security';
const classes = {
'list-item': true,
security: true,
- selected,
- secondarySelected,
+ selected: !!selected,
+ secondarySelected: !!secondarySelected,
}
return html`
): string;
-
-
-/**
- * Computes condition value to render path label.
- *
- * @param allowPaths Component configuration property.
- * @param renderPath Endpoint property
- * @returns True if both arguments are truly.
- */
-export declare function computeRenderPath(allowPaths: boolean, renderPath: boolean): boolean;
-
-/**
- * `api-navigation`
- * A navigation for an API spec using AMF model.
- *
- * This element is to replace deprecated `raml-path-selector`.
- * It is lightweight and much less complex in comparison.
- *
- * The element works with [AMF](https://github.com/mulesoft/amf)
- * json/ld model. When the model is set it computes list of documentation
- * nodes, types, endpoints, methods and security schemas.
- * As a result user can select any of the items in the UI and the application
- * is informed about user choice via custom event.
- *
- * The selection is a selected API shape `@id`. The application is responsible
- * for computing the model selected by the user.
- *
- * Note, this element does not contain polyfills for Array platform features.
- * Use `arc-polyfills` to add support for IE and Safari 9.
- *
- * ## Passive navigation
- *
- * Passive navigation means that a navigation event occurred but it wasn't
- * invoked by intentional user interaction. For example
- * `api-endpoint-documentation` component renders list of documentations for
- * HTTP methods. While scrolling through the list navigation context
- * changes (user reads documentation of a method) but the navigation never
- * was caused by user intentional interaction.
- * This event, annotated with `passive: true` property in the detail object
- * prohibits other element from taking a navigation action but some
- * may reflect the change in the UI.
- *
- * @fires apinavigate
- */
-export default class ApiNavigationElement extends AmfHelperMixin(LitElement) {
- [queryValue]: string;
- [queryDebouncer]: boolean;
- [hasPassiveSelection]: boolean;
- [selectedItemValue]: HTMLElement;
- [domainIdValue]: string;
- [domainTypeValue]: string;
- [operationsOpened]: boolean;
- [shiftTabPressed]: boolean;
- [rearrangeEndpointsValue]: boolean;
- [renderFullPathsValue]: boolean;
- [focusedItemPrivate]: HTMLElement;
- [focusedItemValue]: HTMLElement;
- [itemsValue]: Element[];
- /**
- * A model `@id` of selected documentation part.
- * Special case is for `summary` view. It's not part of an API
- * but most applications has some kins of summary view for the
- * API.
- * @attribute
- */
- domainId: string;
-
- /**
- * Type of the selected item.
- * One of `documentation`, `type`, `security`, `endpoint`, `method`
- * or `summary`.
- *
- * This property is set after `domainId` property.
- * @attribute
- */
- domainType: SelectionType;
-
- /**
- * If set it renders `API summary` menu option.
- * It will allow to set `domainId` and `domainType` to `summary`
- * when this option is set.
- * @attribute
- */
- summary: boolean;
-
- /**
- * A label for the `summary` section.
- * @default "Summary"
- * @attribute
- */
- summaryLabel: string;
-
- /**
- * Computed list of documentation items in the API.
- */
- [docsValue]: DocumentationItem[];
-
- /**
- * Determines and changes state of documentation panel.
- * @attribute
- */
- docsOpened: boolean;
-
- /**
- * Computed list of "type" items in the API.
- */
- [typesValue]: TypeItem[];
-
- /**
- * Determines and changes state of types panel.
- * @attribute
- */
- typesOpened: boolean;
-
- /**
- * Computed list of Security schemes items in the API.
- */
- [securityValue]: SecurityItem[];
-
- /**
- * Determines and changes state of security panel.
- * @attribute
- */
- securityOpened: boolean;
-
- /**
- * Computed list of endpoint items in the API.
- */
- [endpointsValue]: EndpointItem[];
-
- /**
- * Determines and changes state of endpoints panel.
- * @attribute
- */
- endpointsOpened: boolean;
-
- /**
- * If true, the element will not produce a ripple effect when interacted with via the pointer.
- * @attribute
- */
- noink: boolean;
-
- /**
- * Filters list elements by this value when set.
- * Clear the value to reset the search.
- *
- * This is not currently exposed in element's UI due
- * to complexity of search and performance.
- * @attribute
- */
- query: string;
-
- /**
- * Size of endpoint indentation for nested resources.
- * In pixels.
- *
- * The attribute name for this property is `indent-size`. Note, that this
- * will change to web consistent name `indentSize` in the future.
- * @attribute
- */
- indentSize: number;
-
- /**
- * Flag set when passed AMF model is a RAML fragment.
- */
- [isFragmentValue]: boolean;
-
- /**
- * When set it renders full path below endpoint name if the endpoint has
- * a name (different than the path).
- * This is not always recommended to use this option as some complex APIs
- * may render this component difficult to understand.
- * @attribute
- */
- allowPaths: boolean;
-
- /**
- * If this value is set, then the navigation component will sort the list
- * of endpoints based on the `path` value of the endpoint, keeping the order
- * of which endpoint was first in the list, relative to each other
- * @attribute
- */
- rearrangeEndpoints: boolean;
-
- /**
- * Enables Anypoint platform styles.
- * @attribute
- */
- anypoint: boolean;
-
- /**
- * Determines and changes state of endpoints.
- * @attribute
- */
- operationsOpened: boolean;
-
- /**
- * No overview as a separated element. Overview can be seen by clicking the endpoint label.
- * @attribute
- */
- noOverview: boolean;
-
- /**
- * When set, avoids truncating and indentation of endpoint paths.
- * Instead, the full path for each endpoint will be rendered.
- * @attribute
- */
- renderFullPaths: boolean;
-
- /**
- * true when `[docsValue]` property is set with values
- */
- get hasDocs(): boolean;
-
- /**
- * true when `[typesValue]` property is set with values
- */
- get hasTypes(): boolean;
-
- /**
- * true when `[securityValue]` property is set with values
- */
- get hasSecurity(): boolean;
-
- /**
- * true when `[endpointsValue]` property is set with values
- */
- get hasEndpoints(): boolean;
- /**
- * True when summary should be rendered.
- * Summary should be rendered only when `summary` is set and
- * current model is not a RAML fragment.
- */
- get summaryRendered(): boolean;
-
- /**
- * The currently selected item.
- */
- get selectedItem(): HTMLElement;
- /**
- * The currently focused item.
- */
- get focusedItem(): HTMLElement;
-
- /**
- * Ensures aria role attribute is in place.
- * Attaches element's listeners.
- */
- connectedCallback(): void;
- disconnectedCallback(): void;
-
- /**
- * Collects the information about the API and creates data model
- * for the navigation element
- *
- * @returns Data model for the API navigation
- */
- [collectData](model: object): TargetModel;
-
- /**
- * Collects the data from the security fragment
- *
- * @param model Security fragment model
- */
- [collectSecurityData](model: object): TargetModel|undefined;
-
- /**
- * Collects the data from the documentation fragment
- *
- * @param model Documentation fragment model
- */
- [collectDocumentationData](model: object): TargetModel|undefined;
-
- /**
- * Collects the data from the type fragment
- *
- * @param model Type fragment model
- */
- [collectTypeData](model: object): TargetModel|undefined;
-
- /**
- * Traverses the `http://raml.org/vocabularies/document#declares`
- * node to find types and security schemes.
- *
- * @param target Target object where to put data.
- */
- [traverseDeclarations](model: object, target: TargetModel): void;
-
- /**
- * Traverses the `http://raml.org/vocabularies/document#references`
- *
- * @param model AMF model
- * @param target Target object where to put data.
- */
- [traverseReferences](model: object, target: TargetModel): void;
-
- /**
- * Traverses the `http://raml.org/vocabularies/document#encodes`
- * node to find documentation and endpoints.
- *
- * @param target Target object where to put data.
- */
- [traverseEncodes](model: object, target: TargetModel): void;
-
- /**
- * Sort endpoints alphabetically based on path
- */
- [rearrangeEndpoints](endpoints: EndPoint[]): EndPoint[];
-
- /**
- * Appends declaration of navigation data model to the target if
- * it matches documentation or security types.
- */
- [appendModelItem](item: object, target: TargetModel): void;
-
- /**
- * Appends "type" item to the results.
- *
- * @param item Type item declaration
- */
- [appendTypeItem](item: object, target: TargetModel): void;
-
- /**
- * Appends "security" item to the results.
- *
- * @param item Type item declaration
- */
- [appendSecurityItem](item: object, target: TargetModel): void;
-
- /**
- * Appends "documentation" item to the results.
- *
- * @param item Type item declaration
- */
- [appendDocumentationItem](item: object, target: TargetModel): void;
-
- /**
- * Appends "endpoint" item to the results.
- * This also iterates over methods to extract method data.
- *
- * @param item Endpoint item declaration
- */
- [appendEndpointItem](item: object, target: TargetModel): void;
-
- /**
- * Creates the view model for an operation.
- *
- * @param item Operation AMF model
- * @returns Method view model
- */
- [createOperationModel](item: object): MethodItem;
-
- /**
- * Click handler for section name item.
- * Toggles the view.
- */
- [toggleSectionHandler](e: MouseEvent): void;
- [toggleSection](node: HTMLElement): void;
-
- /**
- * Selects new item in the menu.
- */
- [selectItem](node: HTMLElement): void;
-
- /**
- * Toggles selection state of a node that has `data-api-id` set to
- * `id`.
- *
- * @param id Selected node id.
- * @returns Type of selected node.
- */
- [addSelection](id: string): string|undefined;
-
- /**
- * Removes any current selection that may exist.
- */
- [clearSelection](): void;
-
- /**
- * Toggles endpoint operations list.
- *
- * @param id ID of the endpoint.
- */
- toggleOperations(id: string): void;
-
- /**
- * Updates the state of selected element when `domainId` changes.
- *
- * @param current New selection
- */
- [selectedChanged](current: string): void;
-
- /**
- * When `query` property change it runs the filter function
- * in a debouncer set for ~50 ms.
- */
- [queryChanged](): void;
-
- /**
- * Calls `render()` function on each data repeater that have filterable
- * items.
- * It set's `__effectiveQuery` property on the element that is beyond
- * Polymer's data binding system so it skips 2 function calls each time
- * it is read. In a repeater filter function that can be a lot.
- *
- * Also the `__effectiveQuery` is transformed to perform text search.
- */
- [flushQuery](): void;
-
- /**
- * Dispatches the navigation event on selection change.
- *
- * @param selected Selected id
- * @param selectedType Type of AMF shape
- */
- [selectionChanged](selected: string, selectedType: string): void;
-
- /**
- * Navigation item click handler.
- * It used to be common function for all clicks inside the element
- * but in tests not all events were handled.
- */
- [itemClickHandler](e: MouseEvent): void;
-
- /**
- * Handler for the navigation event. Updates the selection
- * if dispatched from other element.
- */
- [navigationHandler](e: CustomEvent): void;
- [handlePassiveNavigation](detail: object): void;
- [cleanPassiveSelection](): void;
- [selectMethodPassive](id: string): void;
-
- /**
- * Endpoint label click handler.
- * Toggles endpoint's methods list.
- */
- [toggleEndpoint](e: MouseEvent): void;
-
- /**
- * Computes `style` attribute value for endpoint item.
- * It sets padding-left property to indent resources.
- * See https://github.com/mulesoft/api-console/issues/571.
- *
- * @param factor Computed indent factor for the resource
- * @param size The size of indentation in pixels.
- * @returns Style attribute value for the item.
- */
- [computeEndpointPadding](factor: Number, size: Number): String;
- [computeMethodPadding](factor: Number, size: Number): string;
-
- /**
- * Computes operation list item left padding from CSS variables.
- */
- [computeOperationPaddingLeft](): Number;
-
- /**
- * Computes endpoint list item left padding from CSS variables.
- */
- [computeEndpointPaddingLeft](): Number;
-
- /**
- * Returns filtered list of items to render in the menu list.
- * When `query` is set it tests `label` property of each item if it contains
- * the query. Otherwise it returns all items.
- *
- * @param prop Name of the source property keeping array values to render.
- */
- [getFilteredType](prop: NavigationItem[]): NavigationItem[]|undefined;
-
- /**
- * Returns a list of endpoints to render.
- * When `query` is set it returns filtered list of endpoints for given query.
- * Otherwise it returns all endpoints.
- *
- * @returns Filtered list of endpoints
- */
- [getFilteredEndpoints](): EndpointItem[]|undefined;
-
- /**
- * Closes all `iron-collapse` elements
- */
- [closeCollapses](): void;
-
- /**
- * A handler for the focus event on this element.
- */
- [focusHandler](e: FocusEvent): void;
-
- /**
- * Focuses on the previous item in the navigation.
- */
- focusPrevious(): void;
-
- /**
- * Focuses on the next item in the navigation.
- */
- focusNext(): void;
-
- /**
- * Resets all tabindex attributes to the appropriate value based on the
- * current selection state. The appropriate value is `0` (focusable) for
- * the default selected item, and `-1` (not keyboard focusable) for all
- * other items. Also sets the correct initial values for aria-selected
- * attribute, true for default selected item and false for others.
- */
- [resetTabindices](): void;
-
- /**
- * Lists all HTML elements that are currently rendered in the view.
- * @returns Currently rendered items.
- */
- [listActiveItems](): Element[];
-
- /**
- * @param selector The prefix for the query selector
- * @returns Nodes returned from query function.
- */
- [listSectionActiveNodes](selector: string): Element[];
-
- /**
- * Handler for the keydown event.
- */
- [keydownHandler](e: KeyboardEvent): void;
-
- /**
- * Handler that is called when the up key is pressed.
- *
- * @param e A key combination event.
- */
- [onUpKey](e: KeyboardEvent): void;
-
- /**
- * Handler that is called when the down key is pressed.
- *
- * @param e A key combination event.
- */
- [onDownKey](e: KeyboardEvent): void;
-
- /**
- * Handler that is called when the esc key is pressed.
- */
- [onEscKey](): void;
-
- /**
- * A handler for the space bar key down.
- */
- [onSpace](e: KeyboardEvent): void;
-
- /**
- * Handler that is called when a shift+tab keypress is detected by the menu.
- */
- [onShiftTabDown](): void;
-
- /**
- * Renders a template for endpoints and methods list.
- */
- [endpointsTemplate](): TemplateResult|string;
- [endpointTemplate](item: EndpointItem): TemplateResult;
- [methodTemplate](endpointItem: EndpointItem, methodItem: MethodItem): TemplateResult;
-
- /**
- * Renders a template for documentation list.
- */
- [documentationTemplate](): TemplateResult|string;
-
- /**
- * @returns Template for an docs item
- */
- [documentationItemTemplate](item: DocumentationItem): TemplateResult;
-
- /**
- * Renders a template for types list.
- */
- [typesTemplate](): TemplateResult|string;
-
- /**
- * Renders a template for security schemes list.
- */
- [securityTemplate](): TemplateResult|string;
- render(): TemplateResult;
-}
diff --git a/src/elements/ApiNavigationLegacyElement.js b/src/elements/ApiNavigationLegacyElement.js
deleted file mode 100644
index 0219a73..0000000
--- a/src/elements/ApiNavigationLegacyElement.js
+++ /dev/null
@@ -1,2224 +0,0 @@
-/* eslint-disable lit-a11y/click-events-have-key-events */
-import { LitElement, html } from 'lit-element';
-import '@anypoint-web-components/awc/anypoint-icon-button.js';
-import '@anypoint-web-components/awc/anypoint-collapse.js';
-import { keyboardArrowDown, openInNew, } from '@advanced-rest-client/icons/ArcIcons.js';
-import { HttpStyles } from '@advanced-rest-client/base/api.js';
-import { AmfHelperMixin } from '../helpers/AmfHelperMixin.js';
-import navStyles from './styles/Navigation.js';
-import { EventTypes } from '../events/EventTypes.js'
-import { NavigationEvents } from '../events/NavigationEvents.js';
-
-/* eslint-disable no-plusplus */
-/* eslint-disable no-continue */
-/* eslint-disable max-len */
-/* eslint-disable no-param-reassign */
-/* eslint-disable class-methods-use-this */
-/* eslint-disable prefer-destructuring */
-/* eslint-disable consistent-return */
-
-/** @typedef {import('@anypoint-web-components/awc').AnypointCollapseElement} AnypointCollapseElement */
-/** @typedef {import('lit-element').TemplateResult} TemplateResult */
-/** @typedef {import('./ApiNavigationLegacyElement').MethodItem} MethodItem */
-/** @typedef {import('./ApiNavigationLegacyElement').EndpointItem} EndpointItem */
-/** @typedef {import('./ApiNavigationLegacyElement').SecurityItem} SecurityItem */
-/** @typedef {import('./ApiNavigationLegacyElement').TypeItem} TypeItem */
-/** @typedef {import('./ApiNavigationLegacyElement').DocumentationItem} DocumentationItem */
-/** @typedef {import('./ApiNavigationLegacyElement').TargetModel} TargetModel */
-/** @typedef {import('./ApiNavigationLegacyElement').NavigationItem} NavigationItem */
-/** @typedef {import('../types').SelectionType} SelectionType */
-/** @typedef {import('../helpers/amf').EndPoint} EndPoint */
-/** @typedef {import('../helpers/amf').AmfDocument} AmfDocument */
-/** @typedef {import('../events/NavigationEvents').ApiNavigationEvent} ApiNavigationEvent */
-/** @typedef {import('../events/NavigationEvents').ApiNavigationEventDetail} ApiNavigationEventDetail */
-
-export const openedOperationsValue = Symbol('openedOperationsValue');
-export const collectData = Symbol('collectData');
-export const queryValue = Symbol('queryValue');
-export const queryDebouncer = Symbol('queryDebouncer');
-export const hasPassiveSelection = Symbol('hasPassiveSelection');
-export const getFilteredType = Symbol('getFilteredType');
-export const docsValue = Symbol('docsValue');
-export const typesValue = Symbol('typesValue');
-export const securityValue = Symbol('securityValue');
-export const endpointsValue = Symbol('endpointsValue');
-export const endpointsTemplate = Symbol('endpointsTemplate');
-export const documentationTemplate = Symbol('documentationTemplate');
-export const typesTemplate = Symbol('typesTemplate');
-export const securityTemplate = Symbol('securityTemplate');
-export const overviewTemplate = Symbol('overviewTemplate');
-export const endpointPathTemplate = Symbol('endpointPathTemplate');
-export const endpointTemplate = Symbol('endpointTemplate');
-export const methodTemplate = Symbol('methodTemplate');
-export const documentationItemTemplate = Symbol('documentationItemTemplate');
-export const isFragmentValue = Symbol('isFragmentValue');
-export const selectedItemValue = Symbol('selectedItemValue');
-export const updatedOpenedOperations = Symbol('updatedOpenedOperations');
-export const domainIdValue = Symbol('domainIdValue');
-export const domainTypeValue = Symbol('domainTypeValue');
-export const selectedChanged = Symbol('selectedChanged');
-export const selectionChanged = Symbol('selectionChanged');
-export const operationsOpened = Symbol('operationsOpened');
-export const addOpenedOperations = Symbol('addOpenedOperations');
-export const shiftTabPressed = Symbol('shiftTabPressed');
-export const focusedItemPrivate = Symbol('focusedItemPrivate');
-export const focusedItemValue = Symbol('focusedItemValue');
-export const summaryTemplate = Symbol('summaryTemplate');
-export const itemClickHandler = Symbol('itemClickHandler');
-export const queryChanged = Symbol('queryChanged');
-export const flushQuery = Symbol('flushQuery');
-export const queryValue2 = Symbol('queryValue2');
-export const noOverviewValue = Symbol('noOverviewValue');
-export const rearrangeEndpointsValue = Symbol('rearrangeEndpointsValue');
-export const renderFullPathsValue = Symbol('renderFullPathsValue');
-export const itemsValue = Symbol('itemsValue');
-export const resetTabindices = Symbol('resetTabindices');
-export const navigationHandler = Symbol('navigationHandler');
-export const focusHandler = Symbol('focusHandler');
-export const keydownHandler = Symbol('keydownHandler');
-export const collectSecurityData = Symbol('collectSecurityData');
-export const collectDocumentationData = Symbol('collectDocumentationData');
-export const collectTypeData = Symbol('collectTypeData');
-export const traverseDeclarations = Symbol('traverseDeclarations');
-export const traverseReferences = Symbol('traverseReferences');
-export const traverseEncodes = Symbol('traverseEncodes');
-export const rearrangeEndpoints = Symbol('rearrangeEndpoints');
-export const closeCollapses = Symbol('closeCollapses');
-export const appendSecurityItem = Symbol('appendSecurityItem');
-export const appendTypeItem = Symbol('appendTypeItem');
-export const validUrl = Symbol('validUrl');
-export const appendDocumentationItem = Symbol('appendDocumentationItem');
-export const appendEndpointItem = Symbol('appendEndpointItem');
-export const appendModelItem = Symbol('appendModelItem');
-export const createOperationModel = Symbol('createOperationModel');
-export const toggleSectionHandler = Symbol('toggleSectionHandler');
-export const toggleSection = Symbol('toggleSection');
-export const selectItem = Symbol('selectItem');
-export const addSelection = Symbol('addSelection');
-export const clearSelection = Symbol('clearSelection');
-export const cleanPassiveSelection = Symbol('cleanPassiveSelection');
-export const handlePassiveNavigation = Symbol('handlePassiveNavigation');
-export const selectMethodPassive = Symbol('selectMethodPassive');
-export const toggleEndpoint = Symbol('toggleEndpoint');
-export const toggleEndpointDocumentation = Symbol('toggleEndpointDocumentation');
-export const toggleEndpointButton = Symbol('toggleEndpointButton');
-export const computeEndpointPadding = Symbol('computeEndpointPadding');
-export const computeEndpointPaddingLeft = Symbol('computeEndpointPaddingLeft');
-export const computeMethodPadding = Symbol('computeMethodPadding');
-export const computeOperationPaddingLeft = Symbol('computeOperationPaddingLeft');
-export const getFilteredEndpoints = Symbol('getFilteredEndpoints');
-export const listActiveItems = Symbol('listActiveItems');
-export const listSectionActiveNodes = Symbol('listSectionActiveNodes');
-export const onUpKey = Symbol('onUpKey');
-export const onDownKey = Symbol('onDownKey');
-export const onEscKey = Symbol('onEscKey');
-export const onSpace = Symbol('onSpace');
-export const onShiftTabDown = Symbol('onShiftTabDown');
-
-/**
- * Maps authorization scheme name to a label
- * @param {string} name
- * @return {string}
- */
-function mapAuthName(name) {
- switch (name) {
- case 'http':
- return 'HTTP';
- case 'openIdConnect':
- return 'OpenID Connect';
- default:
- return name;
- }
-}
-
-/**
- * Discretely updates tabindex values among menu items as the focused item
- * changes.
- *
- * @param {HTMLElement} focusedItem The element that is currently focused.
- * @param {HTMLElement=} old The last element that was considered focused, if
- * applicable.
- */
-function focusedItemChanged(focusedItem, old) {
- if (old) {
- old.setAttribute('tabindex', '-1');
- }
- if (focusedItem && !focusedItem.hasAttribute('disabled')) {
- focusedItem.setAttribute('tabindex', '0');
- focusedItem.focus();
- }
-}
-
-/**
- * Computes label for an endpoint when name is missing and the endpoint
- * is indented, hence name should be truncated.
- * @param {string} currentPath Endpoint's path
- * @param {string[]} parts Path parts
- * @param {number} indent Endpoint indentation
- * @param {string[]} basePaths List of base paths already used.
- * @return {string} Name of the path to render.
- */
-export function computePathName(currentPath, parts, indent, basePaths) {
- let path = '';
- const latestBasePath = basePaths[basePaths.length - 1];
- for (let i = 0, len = parts.length - 1; i < len; i++) {
- path += `/${parts[i]}`;
- if (!latestBasePath || latestBasePath.indexOf(`${path}/`) !== -1) {
- indent--;
- }
- if (indent === 0) {
- break;
- }
- }
- return currentPath.replace(path, '');
-}
-
-/**
- * Computes condition value to render path label.
- * @param {boolean} allowPaths Component configuration property.
- * @param {boolean} renderPath Endpoint property
- * @return {boolean} True if both arguments are truly.
- */
-export function computeRenderPath(allowPaths, renderPath) {
- return !!(allowPaths && renderPath);
-}
-
-/**
- * `api-navigation`
- * A navigation for an API spec using AMF model.
- *
- * This element is to replace deprecated `raml-path-selector`.
- * It is lightweight and much less complex in comparison.
- *
- * The element works with [AMF](https://github.com/mulesoft/amf)
- * json/ld model. When the model is set it computes list of documentation
- * nodes, types, endpoints, methods and security schemas.
- * As a result user can select any of the items in the UI and the application
- * is informed about user choice via custom event.
- *
- * The selection is a selected API shape `@id`. The application is responsible
- * for computing the model selected by the user.
- *
- * Note, this element does not contain polyfills for Array platform features.
- * Use `arc-polyfills` to add support for IE and Safari 9.
- *
- * ## Passive navigation
- *
- * Passive navigation means that a navigation event occurred but it wasn't
- * invoked by intentional user interaction. For example
- * `api-endpoint-documentation` component renders list of documentations for
- * HTTP methods. While scrolling through the list navigation context
- * changes (user reads documentation of a method) but the navigation never
- * was caused by user intentional interaction.
- * This event, annotated with `passive: true` property in the detail object
- * prohibits other element from taking a navigation action but some
- * may reflect the change in the UI.
- */
-export default class ApiNavigationElement extends AmfHelperMixin(LitElement) {
- static get properties() {
- return {
- /**
- * A model `@id` of selected documentation part.
- * Special case is for `summary` view. It's not part of an API
- * but most applications has some kins of summary view for the
- * API.
- */
- domainId: { type: String, reflect: true },
- /**
- * Type of the domain item.
- * One of `documentation`, `schema`, `security`, `resource`, `operation`
- * or `summary`.
- *
- * This property is set after `domainId` property.
- */
- domainType: { type: String, reflect: true },
- /**
- * If set it renders `API summary` menu option.
- * It will allow to set `domainId` and `domainType` to `summary`
- * when this option is set.
- */
- summary: { type: Boolean, reflect: true },
- /**
- * A label for the `summary` section.
- */
- summaryLabel: { type: String, reflect: true },
- /**
- * Determines and changes state of documentation panel.
- */
- docsOpened: { type: Boolean, reflect: true },
-
- /**
- * Determines and changes state of types panel.
- */
- typesOpened: { type: Boolean, reflect: true },
- /**
- * Determines and changes state of security panel.
- */
- securityOpened: { type: Boolean, reflect: true },
- /**
- * Determines and changes state of endpoints panel.
- */
- endpointsOpened: { type: Boolean, reflect: true },
- /**
- * If true, the element will not produce a ripple effect when interacted with via the pointer.
- */
- noink: { type: Boolean, reflect: true },
- /**
- * Filters list elements by this value when set.
- * Clear the value to reset the search.
- *
- * This is not currently exposed in element's UI due
- * to complexity of search and performance.
- */
- query: { type: String, reflect: true },
- /**
- * Size of endpoint indentation for nested resources.
- * In pixels.
- *
- * The attribute name for this property is `indent-size`. Note, that this
- * will change to web consistent name `indentSize` in the future.
- */
- indentSize: { type: Number, reflect: true },
- /**
- * When set it renders full path below endpoint name if the endpoint has
- * a name (different than the path).
- * This is not always recommended to use this option as some complex APIs
- * may render this component difficult to understand.
- */
- allowPaths: { type: Boolean },
- /**
- * If this value is set, then the navigation component will sort the list
- * of endpoints alphabetically based on the `path` value of the endpoint
- */
- rearrangeEndpoints: { type: Boolean },
- /**
- * Enables Anypoint platform styles.
- */
- anypoint: { type: Boolean },
- /**
- * Determines and changes state of endpoints.
- */
- operationsOpened: { type: Boolean, reflect: true },
- /**
- * No overview as a separated node.
- * Overview can be seen by clicking the endpoint label.
- */
- noOverview: { type: Boolean },
- /**
- * When set, avoids truncating and indentation of endpoint paths.
- * Instead, the full path for each endpoint will be rendered.
- */
- renderFullPaths: { type: Boolean },
- };
- }
-
- get styles() {
- return [navStyles, HttpStyles.default];
- }
-
- /** @returns {string} */
- get domainId() {
- return this[domainIdValue];
- }
-
- /** @param {string} value */
- set domainId(value) {
- const old = this[domainIdValue];
- /* istanbul ignore if */
- if (old === value) {
- return;
- }
- this[domainIdValue] = value;
- this.requestUpdate('domainId', old);
- this[selectedChanged](value);
- this[selectionChanged](value, this.domainType);
- }
-
- /** @returns {SelectionType} */
- get domainType() {
- return this[domainTypeValue];
- }
-
- /** @param {SelectionType} value */
- set domainType(value) {
- const old = this[domainTypeValue];
- /* istanbul ignore if */
- if (old === value) {
- return;
- }
- this[domainTypeValue] = value;
- this.requestUpdate('domainType', old);
- this[selectionChanged](this.domainId, value);
- }
-
- /** @param {boolean} value */
- set operationsOpened(value) {
- const old = this[operationsOpened];
- /* istanbul ignore if */
- if (old === value) {
- return;
- }
- this[operationsOpened] = value;
-
- if (value === undefined) {
- return;
- }
-
- this[updatedOpenedOperations] = !value;
- if (!value) {
- this[openedOperationsValue] = /** @type string[] */ ([]);
- } else {
- this[addOpenedOperations](this[endpointsValue]);
- }
- }
-
- /** @returns {boolean} */
- get operationsOpened() {
- return this[operationsOpened];
- }
-
- /**
- * @return {boolean} true when `[docsValue]` property is set with values
- */
- get hasDocs() {
- const items = this[docsValue];
- return Array.isArray(items) && !!items.length;
- }
-
- /**
- * @return {boolean} true when `[typesValue]` property is set with values
- */
- get hasTypes() {
- const items = this[typesValue];
- return Array.isArray(items) && !!items.length;
- }
-
- /**
- * @return {boolean} true when `[securityValue]` property is set with values
- */
- get hasSecurity() {
- const items = this[securityValue];
- return Array.isArray(items) && !!items.length;
- }
-
- /**
- * @return {boolean} true when `[endpointsValue]` property is set with values
- */
- get hasEndpoints() {
- const items = this[endpointsValue];
- return Array.isArray(items) && !!items.length;
- }
-
- /**
- * @return {boolean} True when summary should be rendered.
- * Summary should be rendered only when `summary` is set and
- * current model is not a RAML fragment.
- */
- get summaryRendered() {
- const { summary } = this;
- return !!(summary && !this[isFragmentValue]);
- }
-
- get query() {
- return this[queryValue2];
- }
-
- set query(value) {
- const old = this[queryValue2];
- /* istanbul ignore if */
- if (old === value) {
- return;
- }
- this[queryValue2] = value;
- this.requestUpdate('query', old);
- this[queryChanged]();
- }
-
- /**
- * @return {HTMLElement=} A reference to currently selected node.
- */
- get selectedItem() {
- return this[selectedItemValue];
- }
-
- /**
- * @return {HTMLElement=} The currently focused item.
- */
- get focusedItem() {
- return this[focusedItemPrivate];
- }
-
- get [focusedItemPrivate]() {
- return this[focusedItemValue];
- }
-
- set [focusedItemPrivate](value) {
- const old = this[focusedItemValue];
- /* istanbul ignore if */
- if (old === value) {
- return;
- }
- this[focusedItemValue] = value;
- focusedItemChanged(value, old);
- }
-
- /** @returns {boolean} */
- get noOverview() {
- return this[noOverviewValue];
- }
-
- /** @param {boolean} value */
- set noOverview(value) {
- const old = this[noOverviewValue];
- if (old === value) {
- return;
- }
- this[noOverviewValue] = value;
- this.requestUpdate('noOverview', old);
- this[itemsValue] = null;
- }
-
- /** @param {boolean} value */
- set rearrangeEndpoints(value) {
- const old = this[rearrangeEndpointsValue];
- if (old === value) {
- return;
- }
- this[rearrangeEndpointsValue] = value;
- this.requestUpdate('rearrangeEndpoints', old);
- this.__amfChanged(this.amf);
- }
-
- /** @returns {boolean} */
- get rearrangeEndpoints() {
- return this[rearrangeEndpointsValue];
- }
-
- /** @param {boolean} value */
- set renderFullPaths(value) {
- const old = this[renderFullPathsValue];
- if (old === value) {
- return;
- }
- this[renderFullPathsValue] = value;
- this.requestUpdate('renderFullPaths', old);
- this.__amfChanged(this.amf);
- }
-
- /** @returns {boolean} */
- get renderFullPaths() {
- return this[renderFullPathsValue];
- }
-
- constructor() {
- super();
-
- this.summaryLabel = 'Summary';
- /**
- * Flag set when passed AMF model is a RAML fragment.
- * @type boolean
- */
- this[isFragmentValue] = false;
- this.summary = false;
- this.noink = false;
- this.allowPaths = false;
- this.anypoint = false;
- this.rearrangeEndpoints = false;
- this.indentSize = 8;
- /**
- * @type HTMLElement
- */
- this[selectedItemValue] = null;
- /**
- * List of opened operation ids
- * @type {string[]}
- */
- this[openedOperationsValue] = [];
- this[updatedOpenedOperations] = true;
- this.noOverview = false;
- this.renderFullPaths = false;
- /** @type {string} */
- this[queryValue] = undefined;
- /**
- * Computed list of documentation items in the API.
- * @type {DocumentationItem[]}
- */
- this[docsValue] = undefined;
- /**
- * Computed list of "type" items in the API.
- * @type {TypeItem[]}
- */
- this[typesValue] = undefined;
- /**
- * Computed list of Security schemes items in the API.
- * @type {SecurityItem[]}
- */
- this[securityValue] = undefined;
- /**
- * Computed list of endpoint items in the API.
- * @type {EndpointItem[]}
- */
- this[endpointsValue] = undefined;
- /** @type {Element[]} */
- this[itemsValue] = undefined;
-
- this[navigationHandler] = this[navigationHandler].bind(this);
- this[focusHandler] = this[focusHandler].bind(this);
- this[keydownHandler] = this[keydownHandler].bind(this);
- }
-
- /**
- * Ensures aria role attribute is in place.
- * Attaches element's listeners.
- */
- connectedCallback() {
- super.connectedCallback();
- // @ts-ignore
- if (window.ShadyCSS) {
- // @ts-ignore
- window.ShadyCSS.styleElement(this);
- }
- // Pawel: This role requires children to be present in the DOM, but in this case none is rendered
- // in the light DOM but rather in the shadow DOM. Therefore the element cannot have this role.
- // if (!this.getAttribute('role')) {
- // this.setAttribute('role', 'menubar');
- // }
- if (!this.getAttribute('aria-label')) {
- this.setAttribute('aria-label', 'API structure');
- }
- if (!this.getAttribute('tabindex')) {
- this.setAttribute('tabindex', '0');
- }
- window.addEventListener(EventTypes.Navigation.apiNavigate, this[navigationHandler]);
- this.addEventListener('focus', this[focusHandler]);
- this.addEventListener('keydown', this[keydownHandler]);
-
- this[resetTabindices]();
- }
-
- disconnectedCallback() {
- super.disconnectedCallback();
- window.removeEventListener(EventTypes.Navigation.apiNavigate, this[navigationHandler]);
- this.removeEventListener('focus', this[focusHandler]);
- this.removeEventListener('keydown', this[keydownHandler]);
- this[itemsValue] = null;
- }
-
- /**
- * @param {EndpointItem[]} endpoints
- */
- [addOpenedOperations](endpoints) {
- if (!this[updatedOpenedOperations] && endpoints) {
- this[openedOperationsValue] = endpoints.map(e => e.id);
- this[updatedOpenedOperations] = true;
- }
- }
-
- /**
- * Overrides `AmfHelperMixin.__amfChanged()`
- * @param {AmfDocument} api AMF model
- * @override
- */
- __amfChanged(api) {
- if (!api) {
- return;
- }
- let model = api;
- if (Array.isArray(model)) {
- [model] = model;
- }
- let data = {};
- let isFragment = true;
- this[itemsValue] = null;
-
- const { vocabularies } = this.ns.aml;
- const moduleKey = this._getAmfKey(vocabularies.document.Module);
- if (this._hasType(model, vocabularies.document.Document)) {
- isFragment = false;
- model = this._ensureAmfModel(model);
- data = this[collectData](model);
- } else if (this._hasType(model, vocabularies.security.SecuritySchemeFragment) ) {
- data = this[collectSecurityData](model);
- this.securityOpened = true;
- } else if (this._hasType(model, vocabularies.apiContract.UserDocumentationFragment)) {
- data = this[collectDocumentationData](model);
- this.docsOpened = true;
- } else if (this._hasType(model, vocabularies.shapes.DataTypeFragment)) {
- data = this[collectTypeData](model);
- this.typesOpened = true;
- } else if (model['@type'] && moduleKey === model['@type'][0]) {
- data = this[collectData](model);
- }
- if (this[isFragmentValue] !== isFragment) {
- this[isFragmentValue] = isFragment;
- }
- this[docsValue] = data.documentation;
- this[typesValue] = data.types;
- this[securityValue] = data.securitySchemes;
- this[endpointsValue] = data.endpoints;
- this.requestUpdate();
- this[closeCollapses]();
- setTimeout(() => {
- this[selectedChanged](this.domainId);
- this[resetTabindices]();
- this[addOpenedOperations](data.endpoints)
- });
- }
-
- /**
- * Collects the information about the API and creates data model
- * for the navigation element
- *
- * @param {AmfDocument} model
- * @return {TargetModel} Data model for the API navigation
- */
- [collectData](model) {
- const result = {
- documentation: [],
- types: [],
- securitySchemes: [],
- endpoints: [],
- };
- if (!model) {
- return result;
- }
- result._typeIds = [];
- result._basePaths = [];
- this[traverseDeclarations](model, result);
- this[traverseReferences](model, result);
- this[traverseEncodes](model, result);
- delete result._typeIds;
- delete result._basePaths;
- return result;
- }
-
- /**
- * Collects the data from the security fragment
- * @param {AmfDocument} model Security fragment model
- * @return {TargetModel|undefined}
- */
- [collectSecurityData](model) {
- const result = {
- securitySchemes: [],
- };
- const encodes = this._computeEncodes(model);
- if (!encodes) {
- return undefined;
- }
- this[appendSecurityItem](encodes, result);
- return result;
- }
-
- /**
- * Collects the data from the documentation fragment
- * @param {AmfDocument} model Documentation fragment model
- * @return {TargetModel|undefined}
- */
- [collectDocumentationData](model) {
- const result = {
- documentation: [],
- };
- const encodes = this._computeEncodes(model);
- if (!encodes) {
- return undefined;
- }
- this[appendDocumentationItem](encodes, result);
- return result;
- }
-
- /**
- * Collects the data from the type fragment
- * @param {AmfDocument} model Type fragment model
- * @return {TargetModel|undefined}
- */
- [collectTypeData](model) {
- const result = {
- types: [],
- _typeIds: [],
- };
- const encodes = this._computeEncodes(model);
- if (!encodes) {
- return undefined;
- }
- this[appendTypeItem](encodes, result);
- delete result._typeIds;
- return result;
- }
-
- /**
- * Traverses the `http://raml.org/vocabularies/document#declares`
- * node to find types and security schemes.
- *
- * @param {object} model AMF model
- * @param {TargetModel} target Target object where to put data.
- */
- [traverseDeclarations](model, target) {
- const declares = this._computeDeclares(model);
- if (!declares) {
- return;
- }
- declares.forEach(item => this[appendModelItem](item, target));
- }
-
- /**
- * Traverses the `http://raml.org/vocabularies/document#references`
- *
- * @param {object} model AMF model
- * @param {TargetModel} target Target object where to put data.
- */
- [traverseReferences](model, target) {
- const refs = this._computeReferences(model);
- if (!refs) {
- return;
- }
- refs.forEach((item) => {
- if (!this._hasType(item, this.ns.aml.vocabularies.document.Module)) {
- return;
- }
- this[traverseDeclarations](item, target);
- });
- }
-
- /**
- * Traverses the `http://raml.org/vocabularies/document#encodes`
- * node to find documentation and endpoints.
- *
- * @param {object} model AMF model
- * @param {TargetModel} target Target object where to put data.
- */
- [traverseEncodes](model, target) {
- const data = this._computeApi(model);
- if (!data) {
- return;
- }
- const eKey = this._getAmfKey(this.ns.aml.vocabularies.apiContract.endpoint);
- let endpoint = /** @type EndPoint[] */ (this._ensureArray(data[eKey]));
- if (this.rearrangeEndpoints) {
- endpoint = this[rearrangeEndpoints](endpoint);
- }
- if (endpoint) {
- endpoint.forEach(item => this[appendModelItem](item, target));
- }
- const dKey = this._getAmfKey(this.ns.aml.vocabularies.core.documentation);
- const documentation = this._ensureArray(data[dKey]);
- if (documentation) {
- documentation.forEach(item => this[appendModelItem](item, target));
- }
- }
-
- /**
- * Sort endpoints alphabetically based on path
- * @param {EndPoint[]} endpoints
- * @return {EndPoint[]}
- */
- [rearrangeEndpoints](endpoints) {
- if (!endpoints) {
- return null;
- }
- const pathKey = this._getAmfKey(this.ns.aml.vocabularies.apiContract.path);
- return [...endpoints].sort((a,b) => {
- const pathA = this._getValue(a, pathKey);
- const pathB = this._getValue(b, pathKey);
-
- if (pathA < pathB){
- return -1;
- }
-
- if (pathA > pathB){
- return 1;
- }
-
- return 0;
- });
- }
-
- /**
- * Appends declaration of navigation data model to the target if
- * it matches documentation or security types.
- *
- * @param {Object} item AMF model item to check for data.
- * @param {TargetModel} target The target to which append values.
- */
- [appendModelItem](item, target) {
- if (this._hasType(item, this.ns.w3.shacl.Shape)) {
- this[appendTypeItem](item, target);
- } else if (
- this._hasType(item, this.ns.aml.vocabularies.security.SecurityScheme)
- ) {
- this[appendSecurityItem](item, target);
- } else if (
- this._hasType(item, this.ns.aml.vocabularies.core.CreativeWork)
- ) {
- this[appendDocumentationItem](item, target);
- } else if (
- this._hasType(item, this.ns.aml.vocabularies.apiContract.EndPoint)
- ) {
- this[appendEndpointItem](item, target);
- }
- }
-
- /**
- * Appends "type" item to the results.
- *
- * @param {Object} item Type item declaration
- * @param {TargetModel} target
- */
- [appendTypeItem](item, target) {
- const w3name = /** @type string */ (this._getValue(item, this.ns.w3.shacl.name));
- if (w3name && w3name.indexOf('amf_inline_type') === 0) {
- // https://www.mulesoft.org/jira/browse/APIMF-972
- return;
- }
- let name = /** @type string */ (this._getValue(item, this.ns.aml.vocabularies.core.name));
- if (!name && w3name) {
- name = w3name;
- } else if (!name) {
- return;
- }
- const id = item['@id'];
- if (!id) {
- return;
- }
- const rfIdKey = this._getAmfKey(this.ns.aml.vocabularies.document.referenceId);
- const compareId = item['@id'];
- const refNode = this._ensureArray(item[rfIdKey]);
- const refId = refNode ? refNode[0]['@id'] : undefined;
- const idIndex = target._typeIds.indexOf(compareId);
- const refIndex = refId ? target._typeIds.indexOf(refId) : -1;
- if (idIndex === -1 && refIndex === -1) {
- target._typeIds[target._typeIds.length] = id;
- if (refId) {
- target._typeIds[target._typeIds.length] = refId;
- }
- target.types.push({
- label: name,
- id,
- });
- }
- }
-
- /**
- * Appends "security" item to the results.
- *
- * @param {Object} item Type item declaration
- * @param {TargetModel} target
- */
- [appendSecurityItem](item, target) {
- const voc = this.ns.aml.vocabularies;
- let name = this._getValue(item, voc.core.displayName);
- const secType = /** @type string */ (this._getValue(item, voc.security.type));
- if (!secType) {
- // this is a case when the security scheme is referenced from a library.
- // This creates an entry in the graph model but there is no actual definition of the
- // security.
- // The definition will be discovered when scanning references.
- return;
- }
- if (!name) {
- name = this._getValue(item, voc.security.name);
- }
- if (!name) {
- name = this._getValue(item, voc.core.name);
- }
- name = `${name || ''} - ${mapAuthName(secType)}`
- const id = item['@id'];
- target.securitySchemes.push({
- label: String(name),
- id,
- });
- }
-
- /**
- * @param {string} url
- * @returns {string}
- */
- [validUrl](url) {
- return url.startsWith('http://') || url.startsWith('https://')
- ? url
- : 'about:blank';
- }
-
- /**
- * Appends "documentation" item to the results.
- *
- * @param {Object} item Type item declaration
- * @param {TargetModel} target
- */
- [appendDocumentationItem](item, target) {
- const { core } = this.ns.aml.vocabularies;
- const id = item['@id'];
- const urlNode = item[this._getAmfKey(core.url)];
- const title = this._getValue(item, core.title);
- const description = this._getValue(item, core.description);
- const label = title ? String(title) : String(description);
- let isExternal = false;
- let url = urlNode ? (urlNode[0] || urlNode)['@id'] : undefined;
- if (url) {
- url = this[validUrl](url);
- isExternal = true;
- }
- const result = {
- id,
- label,
- isExternal,
- url,
- };
- target.documentation.push(result);
- }
-
- /**
- * Appends "endpoint" item to the results.
- * This also iterates over methods to extract method data.
- *
- * @param {any} item Endpoint item declaration
- * @param {TargetModel} target
- */
- [appendEndpointItem](item, target) {
- const result = {};
- const { vocabularies } = this.ns.aml;
- let name = this._getValue(item, vocabularies.core.name);
- const path = /** @type string */ (this._getValue(item, vocabularies.apiContract.path));
- result.path = path;
-
- let tmpPath = path;
- if (tmpPath[0] === '/') {
- tmpPath = tmpPath.substr(1);
- }
- const parts = tmpPath.split('/');
- let indent = 0;
- target._basePaths[target._basePaths.length] = path;
- if (parts.length > 1 && !this.renderFullPaths) {
- const lowerParts = parts.slice(0, parts.length - 1);
- if (lowerParts.length) {
- for (let i = lowerParts.length - 1; i >= 0; i--) {
- const currentPath = `/${lowerParts.slice(0, i + 1).join('/')}`;
- const previousBasePathItem =
- target._basePaths[target._basePaths.length - 2];
- if (
- previousBasePathItem &&
- (previousBasePathItem === currentPath ||
- previousBasePathItem.startsWith(`${currentPath}/`))
- ) {
- indent++;
- }
- }
- }
- }
- if (!name) {
- result.renderPath = false;
- if (indent > 0) {
- try {
- name = computePathName(path, parts, indent, target._basePaths);
- } catch (_) {
- name = path;
- }
- } else {
- name = path;
- }
- } else {
- result.renderPath = true;
- }
- const id = item['@id'];
- const key = this._getAmfKey(vocabularies.apiContract.supportedOperation);
- const operations = this._ensureArray(item[key]) || [];
- const methods = operations.map(op => this[createOperationModel](op));
- result.label = String(name);
- result.id = id;
- result.indent = indent;
- result.methods = methods;
- target.endpoints.push(result);
- }
-
- /**
- * Creates the view model for an optation.
- *
- * @param {any} item Operation AMF model
- * @return {MethodItem} Method view model
- */
- [createOperationModel](item) {
- const label = /** @type string */ (this._getValue(item, this.ns.aml.vocabularies.core.name));
- const methodKey = this.ns.aml.vocabularies.apiContract.method;
- const id = item['@id'];
- const method = /** @type string */ (this._getValue(item, methodKey));
- return {
- label,
- id,
- method,
- };
- }
-
- /**
- * Click handler for section name item.
- * Toggles the view.
- *
- * @param {MouseEvent} e
- */
- [toggleSectionHandler](e) {
- // @ts-ignore: this is for polyfills
- const path = e.composedPath();
- /** @type HTMLElement */
- let node;
- const test = true;
- while (test) {
- node = /** @type HTMLElement */ (path.shift());
- if (!node) {
- return;
- }
- if (node.dataset && node.dataset.section) {
- break;
- }
- }
- this[toggleSection](node);
- }
-
- /**
- * @param {HTMLElement} node
- */
- [toggleSection](node) {
- const { section } = node.dataset;
- const openedKey = `${section}Opened`;
- this[openedKey] = !this[openedKey];
- }
-
- /**
- * Selects new item in the menu.
- *
- * @param {HTMLElement} node
- */
- [selectItem](node) {
- const id = node.dataset.apiId;
- const { shape } = node.dataset;
- this.domainType = undefined; // cancels event firing
- this.domainId = id;
- this.domainType = /** @type SelectionType */ (shape); // now fire event
- this[selectedItemValue] = node;
- this[focusedItemPrivate] = node;
- }
-
- /**
- * Toggles selection state of a node that has `data-api-id` set to
- * `id`.
- *
- * @param {string} id Selected node id.
- * @return {string|undefined} Type of selected node.
- */
- [addSelection](id) {
- if (!this.shadowRoot) {
- return undefined;
- }
- let node = /** @type HTMLElement */ (this.shadowRoot.querySelector(`[data-api-id="${id}"]`));
- if (!node) {
- return undefined;
- }
- if (node.localName === 'anypoint-collapse') {
- node = this.shadowRoot.querySelector(`.operation[data-api-id="${id}"]`);
- } else if (node.className === 'endpoint-name-overview' && this.noOverview) {
- node = this.shadowRoot.querySelector(`.endpoint[data-endpoint-id="${id}"]`);
- }
- if (!node) {
- return undefined;
- }
- node.classList.add('selected');
- if (node.part && node.part.add) {
- node.part.add('api-navigation-list-item-selected');
- }
- let collapse;
- switch (node.dataset.shape) {
- case 'operation':
- collapse = /** @type AnypointCollapseElement */ (node.parentElement);
- this.endpointsOpened = true;
- break;
- case 'endpoint':
- collapse = /** @type AnypointCollapseElement */ (node.parentElement);
- break;
- case 'type':
- case 'documentation':
- case 'security':
- collapse = /** @type AnypointCollapseElement */ (node.parentElement
- .parentElement);
- break;
- default:
- collapse = undefined;
- }
- if (node.dataset.shape === 'operation' || node.dataset.shape === 'endpoint') {
- if (!this[openedOperationsValue].includes(id)) {
- this.toggleOperations(id)
- }
- if (collapse && !this[openedOperationsValue].includes(collapse.dataset.apiId)) {
- this.toggleOperations(collapse.dataset.apiId);
- }
- } else if (collapse && !collapse.opened) {
- collapse.opened = true;
- }
- return node.dataset.shape;
- }
-
- /**
- * Removes any current selection that may exist.
- */
- [clearSelection]() {
- if (!this.shadowRoot) {
- return;
- }
- const nodes = this.shadowRoot.querySelectorAll('.selected');
- for (let i = 0, len = nodes.length; i < len; i++) {
- const node = nodes[i];
- node.classList.remove('selected');
- // @ts-ignore
- if (node.part && node.part.remove) {
- // @ts-ignore
- node.part.remove('api-navigation-list-item-selected');
- }
- }
- }
-
- /**
- * Toggles endpoint operations list.
- *
- * @param {string} id ID of the endpoint.
- */
- toggleOperations(id) {
- const operationIndex = this[openedOperationsValue].indexOf(id);
- if (operationIndex !== -1) {
- this[openedOperationsValue].splice(operationIndex, 1)
- } else {
- this[openedOperationsValue].push(id)
- }
- this.requestUpdate();
- }
-
- /**
- * Updates the state of selected element when `selected` changes.
- *
- * @param {string} current New selection
- */
- [selectedChanged](current) {
- this[clearSelection]();
- this[cleanPassiveSelection]();
- if (current) {
- this[addSelection](current);
- }
- }
-
- /**
- * When `query` property change it runs the filter function
- * in a debouncer set for ~50 ms.
- */
- [queryChanged]() {
- if (this[queryDebouncer]) {
- return;
- }
- this[queryDebouncer] = true;
- setTimeout(() => {
- this[flushQuery]();
- this[queryDebouncer] = false;
- });
- }
-
- /**
- * Calls `render()` function on each data repeater that have filterable
- * items.
- * It set's `[queryValue]` property on the element that is beyond
- * Polymer's data binding system so it skips 2 function calls each time
- * it is read. In a repeater filter function that can be a lot.
- *
- * Also the `[queryValue]` is transformed to perform text search.
- */
- [flushQuery]() {
- let q = this.query;
- if (q) {
- q = q.toLowerCase();
- }
- this[queryValue] = q;
- this.requestUpdate();
- }
-
- /**
- * Dispatches the navigation event when selection change.
- *
- * @param {string} domainId Selected id
- * @param {SelectionType} domainType Type of AMF shape
- */
- [selectionChanged](domainId, domainType) {
- if (!domainType || this.__cancelNavigationEvent) {
- return;
- }
- let endpointId;
- if (domainType === 'operation' && domainId) {
- const node = /** @type HTMLElement */ (this.shadowRoot.querySelector(`.operation[data-api-id="${domainId}"]`));
- if (node) {
- endpointId = node.dataset.parentId;
- }
- }
- NavigationEvents.apiNavigate(this, domainId, domainType, endpointId);
- }
-
- /**
- * Navigation item click handler.
- * It used to be common function for all clicks inside the element
- * but in tests not all events were handled.
- *
- * @param {MouseEvent} e
- */
- [itemClickHandler](e) {
- const eTarget = /** @type HTMLElement */ (e.target);
- let target;
- if (e.currentTarget) {
- target = /** @type HTMLElement */ (e.currentTarget);
- } else if (eTarget.classList.contains('method-label')) {
- target = /** @type HTMLElement */ (eTarget.parentNode);
- } else {
- target = eTarget;
- }
- this[selectItem](target);
- }
-
- /**
- * Handler for the navigation event. Updates the selection if dispatched from other element.
- * @param {ApiNavigationEvent} e
- */
- [navigationHandler](e) {
- const path = e.composedPath();
- if (path[0] === this) {
- return;
- }
- this[cleanPassiveSelection]();
- if (e.detail.passive === true) {
- this[handlePassiveNavigation](e.detail);
- return;
- }
- if (this.domainId !== e.detail.domainId) {
- this.__cancelNavigationEvent = true;
- this.domainId = e.detail.domainId;
- this.domainType = e.detail.domainType;
- this.__cancelNavigationEvent = false;
- this.requestUpdate();
- }
- }
-
- /**
- * @param {ApiNavigationEventDetail} detail
- */
- [handlePassiveNavigation](detail) {
- if (detail.domainType === 'operation') {
- this[selectMethodPassive](detail.domainId);
- }
- }
-
- [cleanPassiveSelection]() {
- // Very simple optimization to not query local DOM if we are sure
- // that there's no selection.
- if (!this[hasPassiveSelection]) {
- return;
- }
- const nodes = this.shadowRoot.querySelectorAll('.passive-selected');
- for (let i = 0, len = nodes.length; i < len; i++) {
- nodes[i].classList.remove('passive-selected');
- }
- this[hasPassiveSelection] = false;
- }
-
- /**
- * @param {string} id
- */
- [selectMethodPassive](id) {
- const selector = `[data-api-id="${id}"]`;
- const node = this.shadowRoot.querySelector(selector);
- if (!node) {
- return;
- }
- node.classList.add('passive-selected');
- this[hasPassiveSelection] = true;
- const collapse = /** @type AnypointCollapseElement */ (node.parentElement);
- if (!collapse.opened) {
- collapse.opened = true;
- }
- }
-
- /**
- * Endpoint label click handler.
- * Toggles endpoint's methods list.
- *
- * @param {MouseEvent} e
- */
- [toggleEndpoint](e) {
- // @ts-ignore
- const path = (e.composedPath && e.composedPath()) || e.path;
- const test = true;
- while (test) {
- const node = path.shift();
- if (!node) {
- return;
- }
- if (node.nodeType !== 1) {
- continue;
- }
- if (!node.dataset.endpointId) {
- continue;
- }
- this.toggleOperations(node.dataset.endpointId);
- break;
- }
- }
-
- /**
- * @param {MouseEvent} e
- */
- [toggleEndpointDocumentation](e) {
- if (!this.noOverview) {
- return this[toggleEndpoint](e)
- }
- }
-
- /**
- * @param {MouseEvent} e
- */
- [toggleEndpointButton](e) {
- if (this.noOverview) {
- return this[toggleEndpoint](e)
- }
- }
-
- /**
- * Computes `style` attribute value for endpoint item.
- * It sets padding-left property to indent resources.
- * See https://github.com/mulesoft/api-console/issues/571.
- *
- * @param {number} factor Computed indent factor for the resource
- * @param {number} size The size of indentation in pixels.
- * @returns {string} Style attribute value for the item.
- */
- [computeEndpointPadding](factor, size) {
- const padding = this[computeEndpointPaddingLeft]();
- if (factor < 1) {
- return `padding-left: ${padding}px`;
- }
- const result = factor * size + padding;
- return `padding-left: ${result}px`;
- }
-
- /**
- * @param {number} factor
- * @param {number} size
- * @returns {string}
- */
- [computeMethodPadding](factor, size) {
- const padding = this[computeOperationPaddingLeft]();
- if (factor < 1) {
- return `padding-left: ${padding}px`;
- }
- const result = factor * size + padding;
- return `padding-left: ${result}px`;
- }
-
- /**
- * Computes operation list item left padding from CSS variables.
- * @return {number}
- */
- [computeOperationPaddingLeft]() {
- let paddingLeft;
- const prop = '--api-navigation-operation-item-padding-left';
- const defaultPadding = 24;
- // @ts-ignore
- if (window.ShadyCSS) {
- // @ts-ignore
- paddingLeft = window.ShadyCSS.getComputedStyleValue(this, prop);
- } else {
- paddingLeft = getComputedStyle(this).getPropertyValue(prop);
- }
- if (!paddingLeft) {
- return defaultPadding;
- }
- paddingLeft = paddingLeft.replace('px', '').trim();
- const result = Number(paddingLeft);
- if (Number.isNaN(result)) {
- return defaultPadding;
- }
- return result;
- }
-
- /**
- * Computes endpoint list item left padding from CSS variables.
- * @return {Number}
- */
- [computeEndpointPaddingLeft]() {
- let padding;
- const prop = '--api-navigation-list-item-padding';
- const defaultPadding = 16;
- // @ts-ignore
- if (window.ShadyCSS) {
- // @ts-ignore
- padding = window.ShadyCSS.getComputedStyleValue(this, prop);
- } else {
- padding = getComputedStyle(this).getPropertyValue(prop);
- }
- if (!padding) {
- return defaultPadding;
- }
- const parts = padding.split(' ');
- let paddingLeftValue;
- switch (parts.length) {
- case 1:
- paddingLeftValue = parts[0];
- break;
- case 2:
- paddingLeftValue = parts[1];
- break;
- case 3:
- paddingLeftValue = parts[1];
- break;
- case 4:
- paddingLeftValue = parts[3];
- break;
- default:
- return defaultPadding;
- }
- if (!paddingLeftValue) {
- return defaultPadding;
- }
- paddingLeftValue = paddingLeftValue.replace('px', '').trim();
- const result = Number(paddingLeftValue);
- if (Number.isNaN(result)) {
- return defaultPadding;
- }
- return result;
- }
-
- /**
- * Returns filtered list of items to render in the menu list.
- * When `query` is set it tests `label` property of each item if it contains
- * the query. Otherwise it returns all items.
- * @param {NavigationItem[]} items Name of the source property keeping array values to render.
- * @returns {Array
|undefined}
- */
- [getFilteredType](items) {
- if (!Array.isArray(items) || !items.length) {
- return undefined;
- }
- const q = this[queryValue];
- if (!q) {
- return items;
- }
- return items.filter(item => {
- if (typeof item.label !== 'string') {
- return false;
- }
- return item.label.toLowerCase().indexOf(q) !== -1;
- });
- }
-
- /**
- * Returns a list of endpoints to render.
- * When `query` is set it returns filtered list of endpoints for given query.
- * Otherwise it returns all endpoints.
- * @returns {EndpointItem[]|undefined} Filtered list of endpoints
- */
- [getFilteredEndpoints]() {
- const value = this[endpointsValue];
- if (!value || !value.length) {
- return undefined;
- }
- const q = this[queryValue];
- if (!q) {
- return value;
- }
-
- const result = [];
- for (let i = 0, len = value.length; i < len; i++) {
- const endpoint = value[i];
- // If the endpoint's path or label matches the query include whole item
- if (
- (endpoint.path || '').toLowerCase().indexOf(q) !== -1 ||
- (endpoint.label || '').toLowerCase().indexOf(q) !== -1
- ) {
- result[result.length] = endpoint;
- continue;
- }
- // otherwise check all methods and only include matched methods. If none match
- // then do not include endpoint.
- const eMethods = endpoint.methods;
- if (!eMethods || !eMethods.length) {
- continue;
- }
- const methods = [];
- for (let j = 0, mLen = eMethods.length; j < mLen; j++) {
- const method = eMethods[j];
- if (
- (method.label || '').toLowerCase().indexOf(q) !== -1 ||
- method.method.indexOf(q) !== -1
- ) {
- methods[methods.length] = method;
- }
- }
- if (methods.length) {
- const copy = { ...endpoint };
- copy.methods = methods;
- result[result.length] = copy;
- }
- }
- return result;
- }
-
- /**
- * Closes all `anypoint-collapse` elements
- */
- [closeCollapses]() {
- if (this[openedOperationsValue].length > 0) {
- this[openedOperationsValue] = /** @type string[] */ ([]);
- this.requestUpdate();
- }
- }
-
- /**
- * A handler for the focus event on this element.
- * @param {FocusEvent} e
- */
- [focusHandler](e) {
- if (this[shiftTabPressed]) {
- // do not focus the menu itself
- return;
- }
- // @ts-ignore
- const path = (e.composedPath && e.composedPath()) || e.path;
- const rootTarget = path[0];
- if (
- rootTarget !== this &&
- typeof rootTarget.tabIndex !== 'undefined' &&
- !this.contains(rootTarget)
- ) {
- return;
- }
- this[focusedItemPrivate] = null;
- if (this.selectedItem) {
- this.selectedItem.focus();
- this[focusedItemPrivate] = this.selectedItem;
- } else {
- this.focusNext();
- }
- }
-
- /**
- * Focuses on the previous item in the navigation.
- */
- focusPrevious() {
- const items = this[listActiveItems]();
- const { length } = items;
- const curFocusIndex = items.indexOf(this[focusedItemPrivate]);
- for (let i = 1; i < length + 1; i++) {
- const item = items[(curFocusIndex - i + length) % length];
- if (!item.hasAttribute('disabled')) {
- const owner = (item.getRootNode && item.getRootNode()) || document;
- this[focusedItemPrivate] = item;
- // Focus might not have worked, if the element was hidden or not
- // focusable. In that case, try again.
- // @ts-ignore
- if (owner.activeElement === item) {
- return;
- }
- }
- }
- }
-
- /**
- * Focuses on the next item in the navigation.
- */
- focusNext() {
- const items = this[listActiveItems]();
- const { length } = items;
- const curFocusIndex = items.indexOf(this[focusedItemPrivate]);
- for (let i = 1; i < length + 1; i++) {
- const item = items[(curFocusIndex + i) % length];
- if (!item.hasAttribute('disabled')) {
- const owner = (item.getRootNode && item.getRootNode()) || document;
- this[focusedItemPrivate] = item;
- // Focus might not have worked, if the element was hidden or not
- // focusable. In that case, try again.
- // @ts-ignore
- if (owner.activeElement === item) {
- return;
- }
- }
- }
- }
-
- /**
- * Resets all tabindex attributes to the appropriate value based on the
- * current selection state. The appropriate value is `0` (focusable) for
- * the default selected item, and `-1` (not keyboard focusable) for all
- * other items. Also sets the correct initial values for aria-selected
- * attribute, true for default selected item and false for others.
- */
- [resetTabindices]() {
- const { selectedItem } = this;
- const items = this[listActiveItems]();
- items.forEach(item => {
- item.setAttribute('tabindex', item === selectedItem ? '0' : '-1');
- });
- }
-
- /**
- * Lists all HTML elements that are currently rendered in the view.
- * @return {Element[]} Currently rendered items.
- */
- [listActiveItems]() {
- if (this[itemsValue]) {
- return this[itemsValue];
- }
- let result = [];
- if (this.summary) {
- const node = this.shadowRoot.querySelector('.list-item.summary');
- if (node) {
- result[result.length] = node;
- }
- }
- if (this.hasEndpoints) {
- const node = this.shadowRoot.querySelector('.endpoints .section-title');
- if (node) {
- result[result.length] = node;
- }
- let nodes;
- if (this.noOverview) {
- nodes = this.shadowRoot.querySelectorAll(
- '.endpoints .list-item.endpoint .path-details,.endpoint-toggle-button'
- );
- } else {
- nodes = this.shadowRoot.querySelectorAll(
- '.endpoints .list-item.endpoint'
- );
- }
- for (let i = 0; i < nodes.length; i++) {
- const item = nodes[i];
- result[result.length] = item;
- const collapse = this.noOverview ? item.parentElement.nextElementSibling : item.nextElementSibling;
- if (collapse.localName !== 'anypoint-collapse') {
- continue;
- }
- if (!item.classList.contains('path-details')) {
- const children = collapse.querySelectorAll('.list-item.operation');
- if (children.length) {
- result = result.concat(Array.from(children));
- }
- }
- }
- }
- if (this.hasDocs) {
- const children = this[listSectionActiveNodes]('.documentation');
- result = result.concat(Array.from(children));
- }
- if (this.hasTypes) {
- const children = this[listSectionActiveNodes]('.types');
- result = result.concat(Array.from(children));
- }
- if (this.hasSecurity) {
- const children = this[listSectionActiveNodes]('.security');
- result = result.concat(Array.from(children));
- }
- this[itemsValue] = result.length ? result : undefined;
- return result;
- }
-
- /**
- * @param {string} selector The prefix for the query selector
- * @return {Element[]} Nodes returned from query function.
- */
- [listSectionActiveNodes](selector) {
- let result = [];
- const node = this.shadowRoot.querySelector(`${selector} .section-title`);
- if (node) {
- result[result.length] = node;
- const collapse = node.nextElementSibling;
- if (collapse) {
- const children = collapse.querySelectorAll('.list-item');
- if (children.length) {
- result = result.concat(Array.from(children));
- }
- }
- }
- return result;
- }
-
- /**
- * Handler for the keydown event.
- * @param {KeyboardEvent} e
- */
- [keydownHandler](e) {
- if (e.key === 'ArrowDown') {
- this[onDownKey](e);
- } else if (e.key === 'ArrowUp') {
- this[onUpKey](e);
- } else if (e.key === 'Tab' && e.shiftKey) {
- this[onShiftTabDown]();
- } else if (e.key === 'Escape') {
- this[onEscKey]();
- } else if (e.key === ' ' || e.code === 'Space') {
- this[onSpace](e);
- } else if (e.key === 'Enter' || e.key === 'NumpadEnter') {
- this[onSpace](e);
- }
- e.stopPropagation();
- }
-
- /**
- * Handler that is called when the up key is pressed.
- *
- * @param {KeyboardEvent} e A key combination event.
- */
- [onUpKey](e) {
- this.focusPrevious();
- e.preventDefault();
- }
-
- /**
- * Handler that is called when the down key is pressed.
- *
- * @param {KeyboardEvent} e A key combination event.
- */
- [onDownKey](e) {
- e.preventDefault();
- e.stopPropagation();
- this.focusNext();
- }
-
- /**
- * Handler that is called when the esc key is pressed.
- */
- [onEscKey]() {
- const { focusedItem } = this;
- if (focusedItem) {
- focusedItem.blur();
- }
- }
-
- /**
- * A handler for the space bar key down.
- * @param {KeyboardEvent} e
- */
- [onSpace](e) {
- e.preventDefault();
- e.stopPropagation();
- // @ts-ignore
- const path = (e.composedPath && e.composedPath()) || e.path;
- const target = /** @type HTMLElement */ (path && path[0]);
- if (!target) {
- return;
- }
- const { classList } = target;
- if (classList.contains('section-title')) {
- this[toggleSection](target);
- } else if (
- classList.contains('list-item') &&
- classList.contains('endpoint')
- ) {
- this.toggleOperations(target.dataset.endpointId);
- } else if (classList.contains('list-item')) {
- this[selectItem](target);
- }
- }
-
- /**
- * Handler that is called when a shift+tab keypress is detected by the menu.
- */
- [onShiftTabDown]() {
- const oldTabIndex = this.getAttribute('tabindex');
- this[shiftTabPressed] = true;
- this[focusedItemPrivate] = null;
- this.setAttribute('tabindex', '-1');
- setTimeout(() => {
- this.setAttribute('tabindex', oldTabIndex);
- this[shiftTabPressed] = false;
- }, 1);
- }
-
- render() {
- const { styles } = this;
- return html`
-
-
- ${this[summaryTemplate]()}
- ${this[endpointsTemplate]()}
- ${this[documentationTemplate]()}
- ${this[typesTemplate]()}
- ${this[securityTemplate]()}
-
`;
- }
-
- /**
- * @return {TemplateResult|string} The template for the summary entry.
- */
- [summaryTemplate]() {
- if (!this.summaryRendered) {
- return '';
- }
- return html`
-
-
- ${this.summaryLabel}
-
-
- `;
- }
-
- /**
- * Renders a template for endpoints and methods list.
- * @return {TemplateResult|string}
- */
- [endpointsTemplate]() {
- if (!this.hasEndpoints) {
- return '';
- }
- const items = this[getFilteredEndpoints]();
- if (!items || !items.length) {
- return '';
- }
-
- const sectionLabel = this._isWebAPI(this.amf) ? 'Endpoints' : 'Channels';
- const lowercaseSectionLabel = sectionLabel.toLowerCase();
-
- return html`
-
-
${sectionLabel}
-
- ${keyboardArrowDown}
-
-
-
-
- ${items.map(item => this[endpointTemplate](item))}
-
-
- `;
- }
-
- /**
- * @param {EndpointItem} item
- * @return {TemplateResult|string} Template for an endpoint overview.
- */
- [overviewTemplate](item) {
- if (this.noOverview) {
- return '';
- }
- const style = /** @type string */ (this[computeMethodPadding](item.indent, this.indentSize));
- return html`
-
- Overview
-
`
- }
-
- /**
- * @param {EndpointItem} item
- * @return {TemplateResult} Template for an endpoint path.
- */
- [endpointPathTemplate](item) {
- const { noOverview } = this;
- return html`
- ${noOverview ?
- html`
${item.label}
`
- : html`
${item.label}
`}
- ${computeRenderPath(this.allowPaths, item.renderPath)
- ? html`
${item.path}
`
- : undefined}
-
`;
- }
-
- /**
- * @param {EndpointItem} item
- * @return {TemplateResult} Template for an endpoint item.
- */
- [endpointTemplate](item) {
- const isEndpointOpened = this[openedOperationsValue].includes(item.id);
- return html`
-
- ${this[endpointPathTemplate](item)}
-
- ${keyboardArrowDown}
-
-
-
- ${this[overviewTemplate](item)}
- ${item.methods.map(methodItem =>
- this[methodTemplate](item, methodItem)
- )}
- `;
- }
-
- /**
- * @param {EndpointItem} endpointItem
- * @param {MethodItem} operation
- * @return {TemplateResult}
- */
- [methodTemplate](endpointItem, operation) {
- const style = /** @type string */ (this[computeMethodPadding](endpointItem.indent, this.indentSize));
- return html`
- ${operation.method}
- ${operation.label}
-
`;
- }
-
- /**
- * Renders a template for documentation list.
- * @return {TemplateResult|string}
- */
- [documentationTemplate]() {
- if (!this.hasDocs) {
- return '';
- }
- const items = /** @type DocumentationItem[] */ (this[getFilteredType](this[docsValue]));
- if (!items || !items.length) {
- return '';
- }
-
- return html`
-
-
-
Documentation
-
- ${keyboardArrowDown}
-
-
-
-
- ${items.map(item => this[documentationItemTemplate](item))}
-
-
-
- `;
- }
-
- /**
- * @param {DocumentationItem} item
- * @return {TemplateResult} Template for an docs item
- */
- [documentationItemTemplate](item) {
- if (item.isExternal) {
- return html`
- ${item.label}
- ${openInNew}
- `;
- }
- return html`
- ${item.label}
-
`;
- }
-
- /**
- * Renders a template for types list.
- * @return {TemplateResult|string}
- */
- [typesTemplate]() {
- if (!this.hasTypes) {
- return '';
- }
- const items = this[getFilteredType](this[typesValue]);
- if (!items || !items.length) {
- return '';
- }
-
- return html`
-
-
-
Types
-
- ${keyboardArrowDown}
-
-
-
-
- ${items.map(
- item =>
- html`
- ${item.label}
-
`
- )}
-
-
-
- `;
- }
-
- /**
- * @return {TemplateResult|string} template for security schemes list.
- */
- [securityTemplate]() {
- if (!this.hasSecurity) {
- return '';
- }
- const items = this[getFilteredType](this[securityValue]);
- if (!items || !items.length) {
- return '';
- }
-
- return html`
-
-
Security
-
- ${keyboardArrowDown}
-
-
-
-
- ${items.map(
- item => html`
- ${item.label}
-
`
- )}
-
-
- `;
- }
-}
diff --git a/src/elements/ApiOperationDocumentElement.d.ts b/src/elements/ApiOperationDocumentElement.d.ts
deleted file mode 100644
index 62766cc..0000000
--- a/src/elements/ApiOperationDocumentElement.d.ts
+++ /dev/null
@@ -1,341 +0,0 @@
-import { TemplateResult } from 'lit-element';
-import { ApiDocumentationBase } from './ApiDocumentationBase.js';
-import { ApiEndPoint, ApiServer, ApiOperation, ApiResponse, ApiCallback, ApiSecurityRequirement } from '../helpers/api';
-
-export const queryEndpoint: unique symbol;
-export const queryOperation: unique symbol;
-export const queryServers: unique symbol;
-export const queryResponses: unique symbol;
-export const operationValue: unique symbol;
-export const endpointValue: unique symbol;
-export const serversValue: unique symbol;
-export const serverIdValue: unique symbol;
-export const urlValue: unique symbol;
-export const queryProtocols: unique symbol;
-export const protocolsValue: unique symbol;
-export const queryVersion: unique symbol;
-export const versionValue: unique symbol;
-export const responsesValue: unique symbol;
-export const computeUrlValue: unique symbol;
-export const computeParametersValue: unique symbol;
-export const snippetsParametersValue: unique symbol;
-export const computeSnippetsPayload: unique symbol;
-export const computeSnippetsHeaders: unique symbol;
-export const snippetsPayloadValue: unique symbol;
-export const snippetsHeadersValue: unique symbol;
-export const baseUriValue: unique symbol;
-export const preselectResponse: unique symbol;
-export const preselectSecurity: unique symbol;
-export const requestMimeChangeHandler: unique symbol;
-export const titleTemplate: unique symbol;
-export const traitsTemplate: unique symbol;
-export const summaryTemplate: unique symbol;
-export const urlTemplate: unique symbol;
-export const requestTemplate: unique symbol;
-export const responseTemplate: unique symbol;
-export const responseTabsTemplate: unique symbol;
-export const responseContentTemplate: unique symbol;
-export const statusCodeHandler: unique symbol;
-export const securitySectionTemplate: unique symbol;
-export const securityTemplate: unique symbol;
-export const deprecatedTemplate: unique symbol;
-export const metaDataTemplate: unique symbol;
-export const tryItTemplate: unique symbol;
-export const tryItHandler: unique symbol;
-export const callbacksTemplate: unique symbol;
-export const callbackTemplate: unique symbol;
-export const snippetsTemplate: unique symbol;
-export const securitySelectorTemplate: unique symbol;
-export const securitySelectionHandler: unique symbol;
-export const securityTabTemplate: unique symbol;
-
-/**
- * A web component that renders the documentation page for an API operation built from
- * the AMF graph model.
- *
- * @fires tryit
- */
-export default class ApiOperationDocumentElement extends ApiDocumentationBase {
- /**
- * @returns The computed list of servers.
- */
- get servers(): ApiServer[]|undefined;
- [serversValue]: ApiServer[]|undefined;
-
- /**
- * @returns The current server in use.
- */
- get server(): ApiServer|undefined;
-
- get operation(): ApiOperation;
- set operation(value: ApiOperation);
- [operationValue]: ApiOperation;
-
- get endpoint(): ApiEndPoint;
- set endpoint(value: ApiEndPoint);
- [endpointValue]: ApiEndPoint;
-
- /**
- * @returns The computed URI for the endpoint.
- */
- get endpointUri(): string|undefined;
-
- get snippetsUri(): string;
-
- /**
- * @returns The computed list of responses for this operation.
- */
- get responses(): ApiResponse[]|undefined;
- [responsesValue]: ApiResponse[]|undefined;
-
- /**
- * A property to set to override AMF's model base URI information.
- * When this property is set, the `endpointUri` property is recalculated.
- * @attribute
- */
- baseUri: string;
- [baseUriValue]: string;
- /**
- * The id of the currently selected server to use to construct the URL.
- * If not set a first server in the API servers array is used.
- * @attribute
- */
- serverId: String;
- /**
- * The domain id of the currently selected security to render.
- * This is only used when a multiple security schemes are applied to the operation.
- * @attribute
- */
- securityId: String;
- /**
- * When set it opens the response section
- * @attribute
- */
- responsesOpened: boolean;
- /**
- * When set it opens the security section
- * @attribute
- */
- securityOpened: boolean;
- /**
- * When set it opens the code snippets section
- * @attribute
- */
- snippetsOpened: boolean;
- /**
- * The selected status code in the responses section.
- * @attribute
- */
- selectedStatus: string;
- /**
- * Whether the callbacks section is opened.
- * @attribute
- */
- callbacksOpened: string;
- /**
- * When set it renders the "try it" button that dispatches the `tryit` event.
- * @attribute
- */
- tryItButton: boolean;
- /**
- * When set it renders the view optimised for asynchronous API operation.
- * @attribute
- */
- asyncApi: boolean;
- /**
- * When set it renders code examples section is the documentation
- * @attribute
- */
- renderCodeSnippets: boolean;
- /**
- * When set it renders security documentation when applicable
- * @attribute
- */
- renderSecurity: boolean;
- /**
- * The currently rendered request panel mime type.
- * @attribute
- */
- requestMimeType: string;
-
- [urlValue]: string;
- [snippetsPayloadValue]: string;
- [snippetsHeadersValue]: string;
- /**
- * The API's protocols.
- */
- get protocols(): string[]|undefined;
- [protocolsValue]: string[]|undefined;
-
- /**
- * The API's version.
- */
- get version(): string|undefined;
- [versionValue]: string|undefined;
- /**
- * Optional. The parent endpoint id. When set it uses this value to query for the endpoint
- * instead of querying for a parent through the operation id.
- * Also, when `endpoint` is set and the `endpointId` match then it ignores querying for
- * the endpoint.
- * @attribute
- */
- endpointId: string;
-
- constructor();
- processGraph(): Promise;
- /**
- * Queries the store for the operation data.
- */
- [queryOperation](): Promise;
-
- /**
- * Queries for the API operation's endpoint data.
- */
- [queryEndpoint](): Promise;
-
- /**
- * Queries for the current servers value.
- */
- [queryServers](): Promise;
-
- /**
- * Queries the API store for the API protocols list.
- */
- [queryProtocols](): Promise;
-
- /**
- * Queries the API store for the API version value.
- */
- [queryVersion](): Promise;
-
- /**
- * Queries for the responses data of the current operation.
- */
- [queryResponses](): Promise;
-
- /**
- * Updates the `selectedStatus` if not selected or the current selection doesn't
- * exists in the current list of responses.
- */
- [preselectResponse](): void;
-
- /**
- * Updates the `securityId` if not selected or the current selection doesn't
- * exists in the current list of security.
- */
- [preselectSecurity](): void;
-
- /**
- * Computes the URL value for the current serves, selected server, and endpoint's path.
- */
- [computeUrlValue](): void;
-
- /**
- * Computes query parameters for the code snippets.
- */
- [computeParametersValue](): void;
-
- /**
- * Computes payload value for the code snippets.
- */
- [computeSnippetsPayload](): void;
-
- /**
- * Computes headers value for the code snippets.
- */
- [computeSnippetsHeaders](): void;
-
- /**
- * A handler for the status code tab selection.
- */
- [statusCodeHandler](e: Event): void;
-
- /**
- * A handler for the status code tab selection.
- */
- [securitySelectionHandler](e: Event): void;
-
- /**
- * A handler for the try it button click.
- * It dispatches the `tryit` custom event.
- */
- [tryItHandler](): void;
-
- /**
- * A handler for the request panel mime type change.
- */
- [requestMimeChangeHandler](e: Event): void;
-
- render(): TemplateResult;
-
- /**
- * @returns The template for the Operation title.
- */
- [titleTemplate](): TemplateResult|string;
-
- /**
- * @returns The template for the Operation traits.
- */
- [traitsTemplate](): TemplateResult|string;
-
- /**
- * @returns The template for the operation summary filed.
- */
- [summaryTemplate](): TemplateResult|string;
-
- /**
- * @returns {TemplateResult[]|string} The template for the Operation meta information.
- */
- [metaDataTemplate](): TemplateResult|string;
-
- /**
- * @returns The template for the deprecated message.
- */
- [deprecatedTemplate](): TemplateResult|string;
-
- /**
- * @returns The template for the operation's URL.
- */
- [urlTemplate](): TemplateResult|string;
-
- /**
- * @returns The template for the operation's request documentation element.
- */
- [requestTemplate](): TemplateResult|string;
-
- [callbacksTemplate](): TemplateResult|string;
-
- /**
- * @returns The template for the operation's request documentation element.
- */
- [callbackTemplate](callback: ApiCallback): TemplateResult|string;
-
- [responseTemplate](): TemplateResult|string;
- /**
- * @param responses The responses to render.
- * @returns The template for the responses selector.
- */
- [responseTabsTemplate](responses: ApiResponse[]): TemplateResult|string;
-
- /**
- * @param responses The responses to render.
- * @returns The template for the currently selected response.
- */
- [responseContentTemplate](responses: ApiResponse[]): TemplateResult|string;
-
- /**
- * @returns The template for the security list section.
- */
- [securitySectionTemplate](): TemplateResult|string;
- [securityTemplate](security: ApiSecurityRequirement): TemplateResult|string;
- [securitySelectorTemplate](): TemplateResult|string;
- [securityTabTemplate](security: ApiSecurityRequirement): TemplateResult|string;
- /**
- * @returns The template for the "try it" button.
- */
- [tryItTemplate](): TemplateResult|string;
- /**
- * @returns The template for the code snippets.
- */
- [snippetsTemplate](): TemplateResult|string;
-}
diff --git a/src/elements/ApiOperationDocumentElement.js b/src/elements/ApiOperationDocumentElement.ts
similarity index 65%
rename from src/elements/ApiOperationDocumentElement.js
rename to src/elements/ApiOperationDocumentElement.ts
index 9df5993..2a3941d 100644
--- a/src/elements/ApiOperationDocumentElement.js
+++ b/src/elements/ApiOperationDocumentElement.ts
@@ -1,21 +1,21 @@
/* eslint-disable class-methods-use-this */
-import { html } from 'lit-element';
-import { classMap } from 'lit-html/directives/class-map.js';
+import { html, TemplateResult, CSSResult } from 'lit';
+import { property } from 'lit/decorators.js';
+import { AmfShapes, ApiDefinitions, ApiSchemaGenerator, ApiSchemaValues, AmfNamespace } from '@api-client/core/build/browser.js';
+import { classMap } from 'lit/directives/class-map.js';
import { MarkdownStyles } from '@advanced-rest-client/highlight';
+import { AnypointTabsElement } from '@anypoint-web-components/awc';
import '@advanced-rest-client/highlight/arc-marked.js';
-import '@anypoint-web-components/awc/anypoint-tab.js';
-import '@anypoint-web-components/awc/anypoint-tabs.js';
+import '@anypoint-web-components/awc/dist/define/anypoint-tab.js';
+import '@anypoint-web-components/awc/dist/define/anypoint-tabs.js';
import '@advanced-rest-client/icons/arc-icon.js';
import '@advanced-rest-client/http-code-snippets/http-code-snippets.js';
import { HttpStyles } from '@advanced-rest-client/base/api.js';
-import { ApiSchemaGenerator } from '../schema/ApiSchemaGenerator.js';
-import { ApiSchemaValues } from '../schema/ApiSchemaValues.js';
-import { ns } from "../helpers/Namespace.js";
import { QueryParameterProcessor } from '../lib/QueryParameterProcessor.js';
import elementStyles from './styles/ApiOperation.js';
import commonStyles from './styles/Common.js';
-import {
- ApiDocumentationBase,
+import {
+ ApiDocumentationBase,
paramsSectionTemplate,
descriptionTemplate,
customDomainPropertiesTemplate,
@@ -29,20 +29,7 @@ import schemaStyles from './styles/SchemaCommon.js';
import '../../define/api-request-document.js';
import '../../define/api-response-document.js';
import '../../define/api-security-requirement-document.js';
-
-/** @typedef {import('lit-element').TemplateResult} TemplateResult */
-/** @typedef {import('../helpers/api').ApiEndPoint} ApiEndPoint */
-/** @typedef {import('../helpers/api').ApiServer} ApiServer */
-/** @typedef {import('../helpers/api').ApiOperation} ApiOperation */
-/** @typedef {import('../helpers/amf').EndPoint} EndPoint */
-/** @typedef {import('../helpers/api').ApiResponse} ApiResponse */
-/** @typedef {import('../helpers/api').ApiCallback} ApiCallback */
-/** @typedef {import('../helpers/api').ApiAnyShape} ApiAnyShape */
-/** @typedef {import('../helpers/api').ApiParameter} ApiParameter */
-/** @typedef {import('../helpers/api').ApiScalarShape} ApiScalarShape */
-/** @typedef {import('../helpers/api').ApiSecurityRequirement} ApiSecurityRequirement */
-/** @typedef {import('@anypoint-web-components/awc').AnypointTabsElement} AnypointTabs */
-/** @typedef {import('./ApiRequestDocumentElement').default} ApiRequestDocumentElement */
+import ApiRequestDocumentElement from './ApiRequestDocumentElement.js';
export const queryEndpoint = Symbol('queryEndpoint');
export const queryOperation = Symbol('queryOperation');
@@ -98,21 +85,45 @@ export const securityTabTemplate = Symbol('securityTabTemplate');
* @fires tryit
*/
export default class ApiOperationDocumentElement extends ApiDocumentationBase {
- get styles() {
+ static get styles(): CSSResult[] {
return [elementStyles, commonStyles, HttpStyles.default, MarkdownStyles, schemaStyles];
}
+ [endpointValue]?: ApiDefinitions.IApiEndPoint;
+
+ [operationValue]?: ApiDefinitions.IApiOperation;
+
+ [serversValue]?: ApiDefinitions.IApiServer[];
+
+ [responsesValue]?: ApiDefinitions.IApiResponse[];
+
+ [serverIdValue]?: string;
+
+ [baseUriValue]?: string;
+
+ [urlValue]?: string;
+
+ [versionValue]?: string;
+
+ [protocolsValue]?: string[];
+
+ [snippetsPayloadValue]?: string;
+
+ [snippetsHeadersValue]?: string;
+
+ [snippetsParametersValue]?: string;
+
/**
- * @returns {string}
+ * The id of the currently selected server to use to construct the URL.
+ * If not set a first server in the API servers array is used.
+ * @attribute
*/
- get serverId() {
+ @property({ type: String, reflect: true })
+ get serverId(): string | undefined {
return this[serverIdValue];
}
- /**
- * @param {string} value
- */
- set serverId(value) {
+ set serverId(value: string | undefined) {
const old = this[serverIdValue];
if (old === value) {
return;
@@ -124,16 +135,16 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
}
/**
- * @returns {ApiServer[]|undefined} The computed list of servers.
+ * The computed list of servers.
*/
- get servers() {
+ get servers(): ApiDefinitions.IApiServer[] | undefined {
return this[serversValue];
}
/**
- * @returns {ApiServer|undefined} The current server in use.
+ * The current server in use.
*/
- get server() {
+ get server(): ApiDefinitions.IApiServer | undefined {
const servers = this[serversValue];
const serverId = this[serverIdValue];
let server;
@@ -147,16 +158,10 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
return server;
}
- /**
- * @returns {ApiOperation|undefined}
- */
- get operation() {
+ get operation(): ApiDefinitions.IApiOperation | undefined {
return this[operationValue];
}
- /**
- * @param {ApiOperation} value
- */
set operation(value) {
const old = this[operationValue];
if (old === value) {
@@ -166,16 +171,10 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
this.processGraph();
}
- /**
- * @returns {ApiEndPoint|undefined}
- */
- get endpoint() {
+ get endpoint(): ApiDefinitions.IApiEndPoint | undefined {
return this[endpointValue];
}
- /**
- * @param {ApiEndPoint} value
- */
set endpoint(value) {
const old = this[endpointValue];
if (old === value) {
@@ -188,15 +187,15 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
}
/**
- * @returns {string|undefined}
+ * A property to set to override AMF's model base URI information.
+ * When this property is set, the `endpointUri` property is recalculated.
+ * @attribute
*/
- get baseUri() {
+ @property({ type: String })
+ get baseUri(): string | undefined {
return this[baseUriValue];
}
- /**
- * @param {string} value
- */
set baseUri(value) {
const old = this[baseUriValue];
if (old === value) {
@@ -209,165 +208,126 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
}
/**
- * @returns {string|undefined} The computed URI for the endpoint.
+ * The computed URI for the endpoint.
*/
- get endpointUri() {
+ get endpointUri(): string | undefined {
return this[urlValue];
}
- /**
- * @returns {string}
- */
- get snippetsUri() {
+ get snippetsUri(): string {
const base = this[urlValue] || '';
const query = this[snippetsParametersValue] || '';
return `${base}${query}`
}
/**
- * @returns {ApiResponse[]|undefined} The computed list of responses for this operation.
+ * The computed list of responses for this operation.
*/
- get responses() {
+ get responses(): ApiDefinitions.IApiResponse[] | undefined {
return this[responsesValue];
}
/**
- * @returns {string[]|undefined} The API's protocols.
+ * The API's protocols.
*/
- get protocols() {
+ get protocols(): string[] | undefined {
return this[protocolsValue];
}
- /**
- * @returns {string|undefined} The API's version.
- */
- get version() {
+
+ get version(): string | undefined {
return this[versionValue];
}
- static get properties() {
- return {
- /**
- * A property to set to override AMF's model base URI information.
- * When this property is set, the `endpointUri` property is recalculated.
- */
- baseUri: { type: String },
- /**
- * The id of the currently selected server to use to construct the URL.
- * If not set a first server in the API servers array is used.
- */
- serverId: { type: String, reflect: true },
- /**
- * The domain id of the currently selected security to render.
- * This is only used when a multiple security schemes are applied to the operation.
- */
- securityId: { type: String, reflect: true },
- /**
- * When set it opens the response section
- */
- responsesOpened: { type: Boolean, reflect: true },
- /**
- * When set it opens the security section
- */
- securityOpened: { type: Boolean, reflect: true },
- /**
- * When set it opens the code snippets section
- */
- snippetsOpened: { type: Boolean, reflect: true },
- /**
- * The selected status code in the responses section.
- */
- selectedStatus: { type: String },
- /**
- * Whether the callbacks section is opened.
- */
- callbacksOpened: { type: String },
- /**
- * When set it renders the "try it" button that dispatches the `tryit` event.
- */
- tryItButton: { type: Boolean, reflect: true },
- /**
- * When set it renders the view optimised for asynchronous API operation.
- */
- asyncApi: { type: Boolean, reflect: true },
- /**
- * When set it renders code examples section is the documentation
- */
- renderCodeSnippets: { type: Boolean },
- /**
- * When set it renders security documentation when applicable
- */
- renderSecurity: { type: Boolean },
- /**
- * The currently rendered request panel mime type.
- */
- requestMimeType: { type: String },
- /**
- * Optional. The parent endpoint id. When set it uses this value to query for the endpoint
- * instead of querying for a parent through the operation id.
- * Also, when `endpoint` is set and the `endpointId` match then it ignores querying for
- * the endpoint.
- */
- endpointId: { type: String },
- };
- }
+ /**
+ * The domain id of the currently selected security to render.
+ * This is only used when a multiple security schemes are applied to the operation.
+ * @attribute
+ */
+ @property({ type: String, reflect: true })
+ securityId?: string;
- constructor() {
- super();
- /**
- * @type {ApiOperation}
- */
- this[operationValue] = undefined;
- /**
- * @type {ApiServer[]}
- */
- this[serversValue] = undefined;
- /**
- * @type {ApiEndPoint}
- */
- this[endpointValue] = undefined;
- /**
- * @type {string}
- */
- this[urlValue] = undefined;
- /**
- * @type {ApiResponse[]}
- */
- this[responsesValue] = undefined;
- /** @type {string} */
- this.selectedStatus = undefined;
- /** @type {boolean} */
- this.responsesOpened = undefined;
- /** @type {boolean} */
- this.callbacksOpened = undefined;
- /** @type {boolean} */
- this.securityOpened = undefined;
- /** @type {boolean} */
- this.snippetsOpened = undefined;
- /** @type {boolean} */
- this.tryItButton = undefined;
- /** @type {boolean} */
- this.asyncApi = undefined;
- /** @type {boolean} */
- this.renderCodeSnippets = undefined;
- /** @type {boolean} */
- this.renderSecurity = undefined;
- /** @type {string} */
- this.requestMimeType = undefined;
- /** @type {string} */
- this[snippetsPayloadValue] = undefined;
- /** @type {string} */
- this[snippetsHeadersValue] = undefined;
- /** @type {string} */
- this.securityId = undefined;
- /** @type {string} */
- this.endpointId = undefined;
- }
+ /**
+ * When set it opens the response section
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true })
+ responsesOpened?: boolean;
+
+ /**
+ * When set it opens the security section
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true })
+ securityOpened?: boolean;
+
+ /**
+ * When set it opens the code snippets section
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true })
+ snippetsOpened?: boolean;
+
+ /**
+ * The selected status code in the responses section.
+ * @attribute
+ */
+ @property({ type: String })
+ selectedStatus?: string;
+
+ /**
+ * Whether the callbacks section is opened.
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true })
+ callbacksOpened?: boolean;
+
+ /**
+ * When set it renders the "try it" button that dispatches the `tryit` event.
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true })
+ tryItButton?: boolean;
+
+ /**
+ * When set it renders the view optimised for asynchronous API operation.
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true })
+ asyncApi?: boolean;
/**
- * @returns {Promise}
+ * When set it renders code examples section is the documentation
+ * @attribute
*/
- async processGraph() {
+ @property({ type: Boolean, reflect: true })
+ renderCodeSnippets?: boolean;
+
+ /**
+ * When set it renders security documentation when applicable
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true })
+ renderSecurity?: boolean;
+
+ /**
+ * The currently rendered request panel mime type.
+ * @attribute
+ */
+ @property({ type: String })
+ requestMimeType?: string;
+
+ /**
+ * Optional. The parent endpoint id. When set it uses this value to query for the endpoint
+ * instead of querying for a parent through the operation id.
+ * Also, when `endpoint` is set and the `endpointId` match then it ignores querying for
+ * the endpoint.
+ * @attribute
+ */
+ @property({ type: String })
+ endpointId?: string;
+
+ async processGraph(): Promise {
await this[queryEndpoint]();
await this[queryOperation]();
await this[queryServers]();
@@ -379,15 +339,15 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
this[computeParametersValue]();
this[computeSnippetsPayload]();
this[computeSnippetsHeaders]();
- await this.requestUpdate();
+ this.requestUpdate();
+ await this.updateComplete;
this.dispatchEvent(new Event('graphload'));
}
/**
* Queries the store for the operation data, when needed.
- * @returns {Promise}
*/
- async [queryOperation]() {
+ async [queryOperation](): Promise {
const { domainId } = this;
if (!domainId) {
// this[operationValue] = undefined;
@@ -402,16 +362,16 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
const info = await Events.Operation.get(this, domainId, endpointId);
this[operationValue] = info;
} catch (e) {
- Events.Telemetry.exception(this, e.message, false);
- Events.Reporting.error(this, e, `Unable to query for API operation data: ${e.message}`, this.localName);
+ const ex = e as Error;
+ Events.Telemetry.exception(this, ex.message, false);
+ Events.Reporting.error(this, ex, `Unable to query for API operation data: ${ex.message}`, this.localName);
}
}
/**
* Queries the store for the endpoint data.
- * @returns {Promise}
*/
- async [queryEndpoint]() {
+ async [queryEndpoint](): Promise {
const { domainId, endpointId } = this;
if (!domainId) {
// this[endpointValue] = undefined;
@@ -426,15 +386,16 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
const info = await (endpointId ? Events.Endpoint.get(this, endpointId) : Events.Operation.getParent(this, domainId));
this[endpointValue] = info;
} catch (e) {
- Events.Telemetry.exception(this, e.message, false);
- Events.Reporting.error(this, e, `Unable to query for API endpoint data: ${e.message}`, this.localName);
+ const ex = e as Error;
+ Events.Telemetry.exception(this, ex.message, false);
+ Events.Reporting.error(this, ex, `Unable to query for API endpoint data: ${ex.message}`, this.localName);
}
}
/**
* Queries for the current servers value.
*/
- async [queryServers]() {
+ async [queryServers](): Promise {
const { domainId } = this;
const endpointId = this[endpointValue] && this[endpointValue].id;
try {
@@ -444,50 +405,53 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
});
this[serversValue] = info;
} catch (e) {
+ const ex = e as Error;
this[serversValue] = undefined;
- Events.Telemetry.exception(this, e.message, false);
- Events.Reporting.error(this, e, `Unable to query for API servers: ${e.message}`, this.localName);
+ Events.Telemetry.exception(this, ex.message, false);
+ Events.Reporting.error(this, ex, `Unable to query for API servers: ${ex.message}`, this.localName);
}
}
/**
* Queries the API store for the API protocols list.
*/
- async [queryProtocols]() {
+ async [queryProtocols](): Promise {
this[protocolsValue] = undefined;
try {
const info = await Events.Api.protocols(this);
this[protocolsValue] = info;
} catch (e) {
- Events.Telemetry.exception(this, e.message, false);
- Events.Reporting.error(this, e, `Unable to query for API protocols list: ${e.message}`, this.localName);
+ const ex = e as Error;
+ Events.Telemetry.exception(this, ex.message, false);
+ Events.Reporting.error(this, ex, `Unable to query for API protocols list: ${ex.message}`, this.localName);
}
}
/**
* Queries the API store for the API version value.
*/
- async [queryVersion]() {
+ async [queryVersion](): Promise {
this[versionValue] = undefined;
try {
const info = await Events.Api.version(this);
this[versionValue] = info;
} catch (e) {
- Events.Telemetry.exception(this, e.message, false);
- Events.Reporting.error(this, e, `Unable to query for API version value: ${e.message}`, this.localName);
+ const ex = e as Error;
+ Events.Telemetry.exception(this, ex.message, false);
+ Events.Reporting.error(this, ex, `Unable to query for API version value: ${ex.message}`, this.localName);
}
}
/**
* Queries for the responses data of the current operation.
*/
- async [queryResponses]() {
+ async [queryResponses](): Promise {
this[responsesValue] = undefined;
const { operation } = this;
if (!operation) {
return;
}
- const { responses=[] } = operation;
+ const { responses = [] } = operation;
if (!responses.length) {
return;
}
@@ -498,7 +462,7 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
* Updates the `selectedStatus` if not selected or the current selection doesn't
* exists in the current list of responses.
*/
- [preselectResponse]() {
+ [preselectResponse](): void {
const responses = this[responsesValue];
if (!Array.isArray(responses) || !responses.length) {
return;
@@ -525,7 +489,7 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
* Updates the `securityId` if not selected or the current selection doesn't
* exists in the current list of security.
*/
- [preselectSecurity]() {
+ [preselectSecurity](): void {
const { operation, renderSecurity, securityId } = this;
if (!renderSecurity || !operation || !Array.isArray(operation.security) || !operation.security.length) {
return;
@@ -544,7 +508,7 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
/**
* Computes the URL value for the current serves, selected server, and endpoint's path.
*/
- [computeUrlValue]() {
+ [computeUrlValue](): void {
if (this.asyncApi) {
return;
}
@@ -557,7 +521,7 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
/**
* Computes query parameters for the code snippets.
*/
- [computeParametersValue]() {
+ [computeParametersValue](): void {
this[snippetsParametersValue] = undefined;
const { operation } = this;
if (!operation) {
@@ -568,13 +532,12 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
return;
}
const { queryParameters, queryString } = request;
- /** @type ApiParameter[] */
- let params;
+ let params: ApiDefinitions.IApiParameter[] | undefined;
if (Array.isArray(queryParameters) && queryParameters.length) {
params = queryParameters;
} else if (queryString) {
const factory = new QueryParameterProcessor();
- const items = factory.collectOperationParameters(request.queryString, 'query');
+ const items = factory.collectOperationParameters(request.queryString as AmfShapes.IShapeUnion, 'query');
if (Array.isArray(items) && items.length) {
params = items.map(i => i.parameter);
}
@@ -582,24 +545,27 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
if (!params || !params.length) {
return;
}
- const qp = /** @type {Record} */ ({});
+ const qp: Record = {}
params.forEach((param) => {
const { required, schema, paramName, name } = param;
if (!required) {
return;
}
const parameterName = paramName || name;
- const anySchema = /** @type ApiAnyShape */ (schema);
- const { defaultValueStr, examples=[] } = anySchema;
+ if (!parameterName) {
+ return;
+ }
+ const anySchema = schema as AmfShapes.IApiAnyShape;
+ const { defaultValueStr, examples = [] } = anySchema;
if (defaultValueStr) {
qp[parameterName] = defaultValueStr;
} else if (examples.length) {
const exp = examples.find(e => e.value);
- if (exp) {
+ if (exp && exp.value) {
qp[parameterName] = exp.value;
}
} else {
- const value = ApiSchemaValues.generateDefaultValue(/** @type ApiScalarShape */ (schema));
+ const value = ApiSchemaValues.generateDefaultValue(schema as AmfShapes.IApiScalarShape);
if (value || value === false || value === 0 || value === null) {
qp[parameterName] = value;
}
@@ -617,7 +583,7 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
/**
* Computes payload value for the code snippets.
*/
- [computeSnippetsPayload]() {
+ [computeSnippetsPayload](): void {
this[snippetsPayloadValue] = undefined
if (this.asyncApi) {
return;
@@ -630,7 +596,7 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
if (!request) {
return;
}
- const { payloads=[] } = request;
+ const { payloads = [] } = request;
if (!payloads.length) {
return;
}
@@ -638,9 +604,9 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
if (!payload) {
return;
}
- const { examples=[], schema } = payload;
+ const { examples = [], schema } = payload;
let examplesCopy = [...examples];
- const anySchema = /** @type ApiAnyShape */ (schema);
+ const anySchema = schema as AmfShapes.IApiAnyShape;
if (Array.isArray(anySchema.examples) && anySchema.examples.length) {
examplesCopy = examplesCopy.concat(anySchema.examples);
}
@@ -653,20 +619,20 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
}
}
if (!payloadValue) {
- payloadValue = ApiSchemaGenerator.asExample(schema, requestMimeType, {
+ payloadValue = ApiSchemaGenerator.asExample(schema as AmfShapes.IShapeUnion, requestMimeType, {
renderExamples: true,
renderOptional: true,
});
}
if (payloadValue && payloadValue.renderValue) {
- this[snippetsPayloadValue] = payloadValue.renderValue;
+ this[snippetsPayloadValue] = payloadValue.renderValue as string;
}
}
/**
* Computes headers value for the code snippets.
*/
- [computeSnippetsHeaders]() {
+ [computeSnippetsHeaders](): void {
this[snippetsHeadersValue] = undefined;
if (this.asyncApi) {
return;
@@ -679,15 +645,15 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
if (!request) {
return;
}
- const { headers=[] } = request;
+ const { headers = [] } = request;
const parts = [];
let hasMime = false;
headers.forEach((param) => {
const { paramName, name, schema } = param;
- if (!schema || !schema.types.includes(ns.aml.vocabularies.shapes.ScalarShape)) {
+ if (!schema || !schema.types.includes(AmfNamespace.aml.vocabularies.shapes.ScalarShape)) {
return;
}
- const typedScalar = /** @type ApiScalarShape */ (schema);
+ const typedScalar = schema as AmfShapes.IApiScalarShape;
let value = ApiSchemaValues.readInputValue(param, typedScalar, { fromExamples: true });
if (Array.isArray(value)) {
value = value.join(',');
@@ -709,19 +675,17 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
/**
* A handler for the status code tab selection.
- * @param {Event} e
*/
- [statusCodeHandler](e) {
- const tabs = /** @type AnypointTabs */ (e.target);
+ [statusCodeHandler](e: Event): void {
+ const tabs = e.target as AnypointTabsElement;
this.selectedStatus = String(tabs.selected);
}
/**
* A handler for the status code tab selection.
- * @param {Event} e
*/
- [securitySelectionHandler](e) {
- const tabs = /** @type AnypointTabs */ (e.target);
+ [securitySelectionHandler](e: Event): void {
+ const tabs = e.target as AnypointTabsElement;
this.securityId = String(tabs.selected);
}
@@ -729,7 +693,7 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
* A handler for the try it button click.
* It dispatches the `tryit` custom event.
*/
- [tryItHandler]() {
+ [tryItHandler](): void {
const { operation, asyncApi } = this;
if (!operation || asyncApi) {
return;
@@ -751,43 +715,41 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
/**
* A handler for the request panel mime type change.
- * @param {Event} e
*/
- [requestMimeChangeHandler](e) {
- const panel = /** @type ApiRequestDocumentElement */ (e.target);
+ [requestMimeChangeHandler](e: Event): void {
+ const panel = e.target as ApiRequestDocumentElement;
this.requestMimeType = panel.mimeType;
this[computeSnippetsPayload]();
this[computeSnippetsHeaders]();
this.requestUpdate();
}
- render() {
- if (!this[operationValue]) {
+ render(): TemplateResult {
+ const op = this[operationValue];
+ if (!op) {
return html``;
}
return html`
-
- ${this[titleTemplate]()}
- ${this[summaryTemplate]()}
- ${this[urlTemplate]()}
- ${this[traitsTemplate]()}
- ${this[deprecatedTemplate]()}
- ${this[descriptionTemplate](this[operationValue].description)}
- ${this[metaDataTemplate]()}
- ${this[customDomainPropertiesTemplate](this[operationValue].customDomainProperties)}
+ ${this[titleTemplate](op)}
+ ${this[summaryTemplate](op)}
+ ${this[urlTemplate](op)}
+ ${this[traitsTemplate](op)}
+ ${this[deprecatedTemplate](op)}
+ ${this[descriptionTemplate](op.description)}
+ ${this[metaDataTemplate](op)}
+ ${this[customDomainPropertiesTemplate](op.customDomainProperties)}
${this[requestTemplate]()}
- ${this[callbacksTemplate]()}
- ${this[snippetsTemplate]()}
+ ${this[callbacksTemplate](op)}
+ ${this[snippetsTemplate](op)}
${this[responseTemplate]()}
- ${this[securitySectionTemplate]()}
+ ${this[securitySectionTemplate](op)}
`;
}
/**
- * @returns {TemplateResult} The template for the Operation title.
+ * @returns The template for the Operation title.
*/
- [titleTemplate]() {
- const operation = this[operationValue];
+ [titleTemplate](operation: ApiDefinitions.IApiOperation): TemplateResult {
const { name, method, deprecated } = operation;
const label = name || method;
const labelClasses = {
@@ -808,10 +770,9 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
}
/**
- * @returns {TemplateResult|string} The template for the Operation traits.
+ * @returns The template for the Operation traits.
*/
- [traitsTemplate]() {
- const operation = /** @type ApiOperation */ (this[operationValue]);
+ [traitsTemplate](operation: ApiDefinitions.IApiOperation): TemplateResult | string {
const { extends: traits } = operation;
if (!traits || !traits.length) {
return '';
@@ -824,10 +785,9 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
}
/**
- * @returns {TemplateResult|string} The template for the operation summary filed.
+ * @returns The template for the operation summary filed.
*/
- [summaryTemplate]() {
- const operation = this[operationValue];
+ [summaryTemplate](operation: ApiDefinitions.IApiOperation): TemplateResult | string {
const { summary } = operation;
if (!summary) {
return '';
@@ -838,11 +798,10 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
}
/**
- * @returns {TemplateResult[]|string} The template for the Operation meta information.
+ * @returns The template for the Operation meta information.
*/
- [metaDataTemplate]() {
- const operation = this[operationValue];
- const { operationId, } = operation;
+ [metaDataTemplate](operation: ApiDefinitions.IApiOperation): TemplateResult[] | string {
+ const { operationId } = operation;
const result = [];
if (operationId) {
result.push(tablePropertyTemplate('Operation ID', operationId, 'operation-id'));
@@ -854,10 +813,9 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
}
/**
- * @returns {TemplateResult|string} The template for the deprecated message.
+ * @returns The template for the deprecated message.
*/
- [deprecatedTemplate]() {
- const operation = this[operationValue];
+ [deprecatedTemplate](operation: ApiDefinitions.IApiOperation): TemplateResult | string {
const { deprecated } = operation;
if (!deprecated) {
return '';
@@ -873,14 +831,13 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
}
/**
- * @returns {TemplateResult|string} The template for the operation's URL.
+ * @returns The template for the operation's URL.
*/
- [urlTemplate]() {
+ [urlTemplate](operation: ApiDefinitions.IApiOperation): TemplateResult | string {
if (this.asyncApi) {
return '';
}
const url = this[urlValue];
- const operation = this[operationValue];
const { method } = operation;
return html`
@@ -891,9 +848,9 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
}
/**
- * @returns {TemplateResult|string} The template for the operation's request documentation element.
+ * @returns The template for the operation's request documentation element.
*/
- [requestTemplate]() {
+ [requestTemplate](): TemplateResult | string {
const { operation } = this;
if (!operation) {
return '';
@@ -914,8 +871,7 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
`;
}
- [callbacksTemplate]() {
- const { operation } = this;
+ [callbacksTemplate](operation: ApiDefinitions.IApiOperation): TemplateResult | string {
const { callbacks } = operation;
if (!Array.isArray(callbacks) || !callbacks.length) {
return '';
@@ -925,15 +881,14 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
}
/**
- * @param {ApiCallback} callback
- * @returns {TemplateResult} The template for the operation's request documentation element.
+ * @returns The template for the operation's request documentation element.
*/
- [callbackTemplate](callback) {
+ [callbackTemplate](callback: ApiDefinitions.IApiCallback): TemplateResult {
const { name, endpoint } = callback;
if (!endpoint) {
return html``;
}
- const { operations=[] } = endpoint;
+ const { operations = [] } = endpoint;
const [operation] = operations;
if (!operation) {
return html``;
@@ -944,7 +899,7 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
!!item.statusCode);
if (!filtered.length) {
@@ -985,7 +940,7 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
@selected="${this[statusCodeHandler]}"
?anypoint="${anypoint}"
>
- ${filtered.map((item) => html`${item.statusCode}`)}
+ ${filtered.map((item) => html`${item.statusCode}`)}
@@ -993,10 +948,10 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
}
/**
- * @param {ApiResponse[]} responses The responses to render.
- * @returns {TemplateResult} The template for the currently selected response.
+ * @param responses The responses to render.
+ * @returns The template for the currently selected response.
*/
- [responseContentTemplate](responses) {
+ [responseContentTemplate](responses: ApiDefinitions.IApiResponse[]): TemplateResult {
const { selectedStatus } = this;
const response = responses.find((item) => item.statusCode === selectedStatus);
if (!response) {
@@ -1015,10 +970,10 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
}
/**
- * @returns {TemplateResult|string} The template for the security list section.
+ * @returns The template for the security list section.
*/
- [securitySectionTemplate]() {
- const { operation, renderSecurity, securityId } = this;
+ [securitySectionTemplate](operation: ApiDefinitions.IApiOperation): TemplateResult | string {
+ const { renderSecurity, securityId } = this;
if (!renderSecurity || !operation || !Array.isArray(operation.security) || !operation.security.length) {
return '';
}
@@ -1027,7 +982,7 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
if (security.length === 1) {
content.push(this[securityTemplate](security[0]));
} else if (securityId) {
- content.push(this[securitySelectorTemplate]());
+ content.push(this[securitySelectorTemplate](operation));
const item = security.find(i => i.id === securityId);
if (item) {
content.push(this[securityTemplate](item));
@@ -1037,11 +992,7 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
return this[paramsSectionTemplate]('Security', 'securityOpened', content);
}
- /**
- * @param {ApiSecurityRequirement} security
- * @returns {TemplateResult}
- */
- [securityTemplate](security) {
+ [securityTemplate](security: ApiDefinitions.IApiSecurityRequirement): TemplateResult {
return html``
}
- /**
- * @returns {TemplateResult}
- */
- [securitySelectorTemplate]() {
- const { operation, securityId, anypoint } = this;
+
+ [securitySelectorTemplate](operation: ApiDefinitions.IApiOperation): TemplateResult {
+ const { securityId, anypoint } = this;
const { security } = operation;
return html`
@@ -1071,12 +1020,9 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
`;
}
- /**
- * @param {ApiSecurityRequirement} security
- * @returns {TemplateResult}
- */
- [securityTabTemplate](security) {
- const { name, schemes=[], id } = security;
+
+ [securityTabTemplate](security: ApiDefinitions.IApiSecurityRequirement): TemplateResult {
+ const { name, schemes = [], id } = security;
let label = 'unknown';
if (name) {
label = name;
@@ -1086,13 +1032,13 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
label = parts.join('/');
}
}
- return html`
${label}`;
+ return html`
${label}`;
}
/**
- * @returns {TemplateResult|string} The template for the "try it" button.
+ * @returns The template for the "try it" button.
*/
- [tryItTemplate]() {
+ [tryItTemplate](): TemplateResult | string {
if (!this.tryItButton) {
return '';
}
@@ -1107,21 +1053,20 @@ export default class ApiOperationDocumentElement extends ApiDocumentationBase {
}
/**
- * @returns {TemplateResult|string} The template for the code snippets.
+ * @returns The template for the code snippets.
*/
- [snippetsTemplate]() {
+ [snippetsTemplate](operation: ApiDefinitions.IApiOperation): TemplateResult | string {
if (!this.renderCodeSnippets || this.asyncApi) {
return '';
}
- const { operation } = this;
const content = html`
`;
return this[paramsSectionTemplate]('Code snippets', 'snippetsOpened', content);
diff --git a/src/elements/ApiParameterDocumentElement.d.ts b/src/elements/ApiParameterDocumentElement.d.ts
deleted file mode 100644
index 66bda21..0000000
--- a/src/elements/ApiParameterDocumentElement.d.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { TemplateResult } from 'lit-element';
-import { ApiDocumentationBase, descriptionTemplate } from './ApiDocumentationBase.js';
-import { ApiParameter, ApiShapeUnion } from '../helpers/api';
-
-export const queryParameter: unique symbol;
-export const querySchema: unique symbol;
-export const parameterValue: unique symbol;
-export const schemaValue: unique symbol;
-export const computeParamType: unique symbol;
-export const typeLabelValue: unique symbol;
-
-/**
- * A web component that renders the documentation for a single request / response parameter.
- */
-export default class ApiParameterDocumentElement extends ApiDocumentationBase {
- get parameter(): ApiParameter
- set parameter(value: ApiParameter);
- [parameterValue]: ApiParameter
- [schemaValue]: ApiShapeUnion;
- [typeLabelValue]: string;
-
- constructor();
-
- /**
- * Prepares the values to be rendered.
- */
- processGraph(): Promise
;
-
- /**
- * Reads the schema from the parameter.
- */
- [querySchema](): Promise;
-
- /**
- * Computes the schema type label value to render in the type view.
- */
- [computeParamType](): void;
-
- render(): TemplateResult;
- /**
- * @return The template for the parameter description.
- */
- [descriptionTemplate](): TemplateResult|string;
-}
diff --git a/src/elements/ApiParameterDocumentElement.js b/src/elements/ApiParameterDocumentElement.ts
similarity index 72%
rename from src/elements/ApiParameterDocumentElement.js
rename to src/elements/ApiParameterDocumentElement.ts
index 42fa2f9..1404c30 100644
--- a/src/elements/ApiParameterDocumentElement.js
+++ b/src/elements/ApiParameterDocumentElement.ts
@@ -1,5 +1,6 @@
/* eslint-disable class-methods-use-this */
-import { html } from 'lit-element';
+import { html, TemplateResult, CSSResult } from 'lit';
+import { AmfShapes, ApiDefinitions } from '@api-client/core/build/browser.js';
import { MarkdownStyles } from '@advanced-rest-client/highlight';
import '@advanced-rest-client/highlight/arc-marked.js';
import commonStyles from './styles/Common.js';
@@ -9,13 +10,6 @@ import { readPropertyTypeLabel } from '../lib/Utils.js';
import { paramNameTemplate, typeValueTemplate, detailsTemplate, pillTemplate } from './SchemaCommonTemplates.js';
import { ApiDocumentationBase, descriptionTemplate } from './ApiDocumentationBase.js';
-/** @typedef {import('lit-element').TemplateResult} TemplateResult */
-/** @typedef {import('../helpers/api').ApiParameter} ApiParameter */
-/** @typedef {import('../helpers/api').ApiShapeUnion} ApiShapeUnion */
-/** @typedef {import('../helpers/api').ApiScalarShape} ApiScalarShape */
-/** @typedef {import('../helpers/api').ApiArrayShape} ApiArrayShape */
-/** @typedef {import('../helpers/api').ApiScalarNode} ApiScalarNode */
-
export const queryParameter = Symbol('queryParameter');
export const querySchema = Symbol('querySchema');
export const parameterValue = Symbol('parameterValue');
@@ -27,20 +21,20 @@ export const typeLabelValue = Symbol('typeLabelValue');
* A web component that renders the documentation for a single request / response parameter.
*/
export default class ApiParameterDocumentElement extends ApiDocumentationBase {
- get styles() {
+ static get styles(): CSSResult[] {
return [MarkdownStyles, commonStyles, schemaStyles, elementStyles];
}
- /**
- * @returns {ApiParameter}
- */
- get parameter() {
+ [parameterValue]?: ApiDefinitions.IApiParameter;
+
+ [schemaValue]?: AmfShapes.IShapeUnion;
+
+ [typeLabelValue]?: string;
+
+ get parameter(): ApiDefinitions.IApiParameter | undefined {
return this[parameterValue];
}
- /**
- * @param {ApiParameter} value
- */
set parameter(value) {
const old = this[parameterValue];
if (old === value) {
@@ -50,33 +44,24 @@ export default class ApiParameterDocumentElement extends ApiDocumentationBase {
this.processGraph();
}
- constructor() {
- super();
- /** @type {ApiParameter} */
- this[parameterValue] = undefined;
- /** @type {ApiShapeUnion} */
- this[schemaValue] = undefined;
- /** @type {string} */
- this[typeLabelValue] = undefined;
- }
-
/**
* Prepares the values to be rendered.
*/
- async processGraph() {
+ async processGraph(): Promise {
const { parameter } = this;
if (!parameter) {
return;
}
await this[querySchema]();
this[computeParamType]();
- await this.requestUpdate();
+ this.requestUpdate();
+ await this.updateComplete;
}
/**
* Reads the schema from the parameter.
*/
- async [querySchema]() {
+ async [querySchema](): Promise {
this[schemaValue] = undefined;
const param = this[parameterValue];
if (!param || !param.schema) {
@@ -88,13 +73,17 @@ export default class ApiParameterDocumentElement extends ApiDocumentationBase {
/**
* Computes the schema type label value to render in the type view.
*/
- [computeParamType]() {
+ [computeParamType](): void {
const schema = this[schemaValue];
+ if (!schema) {
+ this[typeLabelValue] = undefined;
+ return;
+ }
const label = readPropertyTypeLabel(schema);
this[typeLabelValue] = label;
}
- render() {
+ render(): TemplateResult {
const param = this[parameterValue];
if (!param) {
return html``;
@@ -103,7 +92,6 @@ export default class ApiParameterDocumentElement extends ApiDocumentationBase {
const type = this[typeLabelValue];
const schema = this[schemaValue];
return html`
-
${paramNameTemplate(name, required)}
@@ -122,14 +110,17 @@ export default class ApiParameterDocumentElement extends ApiDocumentationBase {
}
/**
- * @return {TemplateResult|string} The template for the parameter description.
+ * @returns The template for the parameter description.
*/
- [descriptionTemplate]() {
+ [descriptionTemplate](): TemplateResult | string {
const schema = this[schemaValue];
if (schema && schema.description) {
return super[descriptionTemplate](schema.description);
}
const param = this[parameterValue];
- return super[descriptionTemplate](param.description);
+ if (param && param.description) {
+ return super[descriptionTemplate](param.description);
+ }
+ return '';
}
}
diff --git a/src/elements/ApiParametrizedSecuritySchemeElement.d.ts b/src/elements/ApiParametrizedSecuritySchemeElement.d.ts
deleted file mode 100644
index acee2db..0000000
--- a/src/elements/ApiParametrizedSecuritySchemeElement.d.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { TemplateResult } from "lit-element";
-import ApiSecurityDocumentElement, { settingsTemplate } from "./ApiSecurityDocumentElement.js";
-import { ApiSecuritySettingsUnion } from '../helpers/api';
-
-export const settingsIdValue: unique symbol;
-export const querySettings: unique symbol;
-export const settingsValue: unique symbol;
-export const mergeSettings: unique symbol;
-
-export default class ApiParametrizedSecuritySchemeElement extends ApiSecurityDocumentElement {
- get settings(): ApiSecuritySettingsUnion|undefined
- set settings(value: ApiSecuritySettingsUnion|undefined);
- [settingsValue]: ApiSecuritySettingsUnion|undefined;
-
- constructor();
-
- /**
- * @returns The template for the security settings, when required.
- */
- [settingsTemplate](): TemplateResult|string;
-
- /**
- * @param applied The settings applied to the current object
- * @param scheme The settings defined in the scheme
- * @returns The merged settings to render.
- */
- [mergeSettings](applied: ApiSecuritySettingsUnion, scheme: ApiSecuritySettingsUnion): ApiSecuritySettingsUnion;
-}
diff --git a/src/elements/ApiParametrizedSecuritySchemeElement.js b/src/elements/ApiParametrizedSecuritySchemeElement.ts
similarity index 50%
rename from src/elements/ApiParametrizedSecuritySchemeElement.js
rename to src/elements/ApiParametrizedSecuritySchemeElement.ts
index bcab899..2470a0c 100644
--- a/src/elements/ApiParametrizedSecuritySchemeElement.js
+++ b/src/elements/ApiParametrizedSecuritySchemeElement.ts
@@ -1,39 +1,30 @@
/* eslint-disable class-methods-use-this */
-import { ns } from '../helpers/Namespace.js';
+import { TemplateResult, CSSResult } from 'lit';
+import { ApiDefinitions, AmfNamespace } from '@api-client/core/build/browser.js';
import ApiSecurityDocumentElement, {
settingsTemplate,
- securityValue,
apiKeySettingsTemplate,
openIdConnectSettingsTemplate,
oAuth2SettingsTemplate,
} from "./ApiSecurityDocumentElement.js";
import elementStyles from './styles/ParametrizedSecurityElement.js';
-/** @typedef {import('lit-element').TemplateResult} TemplateResult */
-/** @typedef {import('../helpers/api').ApiSecuritySettingsUnion} ApiSecuritySettingsUnion */
-/** @typedef {import('../helpers/api').ApiSecurityOAuth2Settings} ApiSecurityOAuth2Settings */
-
export const settingsIdValue = Symbol('settingsIdValue');
export const querySettings = Symbol('querySettings');
export const settingsValue = Symbol('settingsValue');
export const mergeSettings = Symbol('mergeSettings');
export default class ApiParametrizedSecuritySchemeElement extends ApiSecurityDocumentElement {
- get styles() {
- // @ts-ignore
+ static get styles(): CSSResult[] {
return [...super.styles, elementStyles];
}
- /**
- * @returns {ApiSecuritySettingsUnion|undefined}
- */
- get settings() {
+ [settingsValue]: ApiDefinitions.IApiSecuritySettingsUnion | undefined;
+
+ get settings(): ApiDefinitions.IApiSecuritySettingsUnion | undefined {
return this[settingsValue];
}
- /**
- * @returns {ApiSecuritySettingsUnion|undefined}
- */
set settings(value) {
const old = this[settingsValue];
if (old === value) {
@@ -43,21 +34,14 @@ export default class ApiParametrizedSecuritySchemeElement extends ApiSecurityDoc
this.requestUpdate();
}
- constructor() {
- super();
- /** @type {ApiSecuritySettingsUnion} */
- this[settingsValue] = undefined;
- }
-
/**
- * @returns {TemplateResult|string} The template for the security settings, when required.
+ * @returns The template for the security settings, when required.
*/
- [settingsTemplate]() {
+ [settingsTemplate](scheme: ApiDefinitions.IApiSecurityScheme): TemplateResult | string {
const appliedSettings = this[settingsValue];
if (!appliedSettings) {
- return super[settingsTemplate]();
+ return super[settingsTemplate](scheme);
}
- const scheme = this[securityValue];
const { settings } = scheme;
if (!settings) {
return '';
@@ -65,30 +49,31 @@ export default class ApiParametrizedSecuritySchemeElement extends ApiSecurityDoc
const { types } = settings;
const mergedSettings = this[mergeSettings](appliedSettings, settings);
- if (types.includes(ns.aml.vocabularies.security.ApiKeySettings)) {
+ if (types.includes(AmfNamespace.aml.vocabularies.security.ApiKeySettings)) {
return this[apiKeySettingsTemplate](mergedSettings);
}
- if (types.includes(ns.aml.vocabularies.security.OpenIdConnectSettings)) {
+ if (types.includes(AmfNamespace.aml.vocabularies.security.OpenIdConnectSettings)) {
return this[openIdConnectSettingsTemplate](mergedSettings);
}
- if (types.includes(ns.aml.vocabularies.security.OAuth2Settings)) {
- return this[oAuth2SettingsTemplate](/** @type ApiSecurityOAuth2Settings */ (mergedSettings));
+ if (types.includes(AmfNamespace.aml.vocabularies.security.OAuth2Settings)) {
+ return this[oAuth2SettingsTemplate](mergedSettings as ApiDefinitions.IApiSecurityOAuth2Settings);
}
return '';
}
/**
- * @param {ApiSecuritySettingsUnion} applied The settings applied to the current object
- * @param {ApiSecuritySettingsUnion} scheme The settings defined in the scheme
- * @returns {ApiSecuritySettingsUnion} The merged settings to render.
+ * @param applied The settings applied to the current object
+ * @param scheme The settings defined in the scheme
+ * @returns The merged settings to render.
*/
- [mergeSettings](applied, scheme) {
- const result = { ...scheme };
+ [mergeSettings](applied: ApiDefinitions.IApiSecuritySettingsUnion, scheme: ApiDefinitions.IApiSecuritySettingsUnion): ApiDefinitions.IApiSecuritySettingsUnion {
+ const result = { ...scheme } as ApiDefinitions.IApiSecuritySettingsUnion;
Object.keys(applied).forEach((key) => {
if (['id', 'types', 'additionalProperties'].includes(key)) {
return;
}
- result[key] = applied[key];
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ result[key as keyof ApiDefinitions.IApiSecuritySettingsUnion] = (applied as any)[key];
});
return result;
}
diff --git a/src/elements/ApiPayloadDocumentElement.d.ts b/src/elements/ApiPayloadDocumentElement.d.ts
deleted file mode 100644
index 41d6cae..0000000
--- a/src/elements/ApiPayloadDocumentElement.d.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import { TemplateResult } from 'lit-element';
-import { ApiDocumentationBase } from './ApiDocumentationBase.js';
-import { ApiPayload } from '../helpers/api';
-
-export const queryPayload: unique symbol;
-export const queryExamples: unique symbol;
-export const payloadValue: unique symbol;
-export const processPayload: unique symbol;
-export const mediaTypeTemplate: unique symbol;
-export const nameTemplate: unique symbol;
-export const schemaTemplate: unique symbol;
-
-export default class ApiPayloadDocumentElement extends ApiDocumentationBase {
- get payload(): ApiPayload;
- set payload(value: ApiPayload);
- [payloadValue]: ApiPayload;
-
- constructor();
-
- /**
- * Queries the graph store for the API Payload data.
- */
- processGraph(): Promise
;
-
- [processPayload](): Promise;
-
- render(): TemplateResult;
-
- /**
- * @return The template for the payload mime type.
- */
- [mediaTypeTemplate](): TemplateResult|string;
-
- /**
- * @return The template for the payload name
- */
- [nameTemplate](): TemplateResult|string;
-
- /**
- * @return The template for the payload's schema
- */
- [schemaTemplate](): TemplateResult|string;
-}
diff --git a/src/elements/ApiPayloadDocumentElement.js b/src/elements/ApiPayloadDocumentElement.ts
similarity index 72%
rename from src/elements/ApiPayloadDocumentElement.js
rename to src/elements/ApiPayloadDocumentElement.ts
index 1cba7af..4369070 100644
--- a/src/elements/ApiPayloadDocumentElement.js
+++ b/src/elements/ApiPayloadDocumentElement.ts
@@ -1,5 +1,7 @@
/* eslint-disable class-methods-use-this */
-import { html } from 'lit-element';
+import { html, TemplateResult, CSSResult } from 'lit';
+import { property } from 'lit/decorators.js';
+import { ApiDefinitions } from '@api-client/core/build/browser.js';
import commonStyles from './styles/Common.js';
import elementStyles from './styles/ApiPayload.js';
import {
@@ -26,20 +28,17 @@ export const nameTemplate = Symbol('nameTemplate');
export const schemaTemplate = Symbol('schemaTemplate');
export default class ApiPayloadDocumentElement extends ApiDocumentationBase {
- get styles() {
+ static get styles(): CSSResult[] {
return [commonStyles, elementStyles];
}
- /**
- * @returns {ApiPayload}
- */
- get payload() {
+ [payloadValue]: ApiDefinitions.IApiPayload | undefined
+
+ @property({ type: Object })
+ get payload(): ApiDefinitions.IApiPayload | undefined {
return this[payloadValue];
}
- /**
- * @param {ApiPayload} value
- */
set payload(value) {
const old = this[payloadValue];
if (old === value) {
@@ -49,29 +48,21 @@ export default class ApiPayloadDocumentElement extends ApiDocumentationBase {
this.processGraph();
}
- constructor() {
- super();
- /**
- * @type {ApiPayload}
- */
- this[payloadValue] = undefined;
- }
-
/**
* Queries the graph store for the API Payload data.
- * @returns {Promise}
*/
- async processGraph() {
+ async processGraph(): Promise {
await this[queryPayload]();
await this[processPayload]();
- await this.requestUpdate();
+ this.requestUpdate();
+ await this.updateComplete;
}
/**
* Queries the store for the payload data, when needed.
* @returns {Promise}
*/
- async [queryPayload]() {
+ async [queryPayload](): Promise {
const { domainId } = this;
if (!domainId) {
// this[requestValue] = undefined;
@@ -86,12 +77,13 @@ export default class ApiPayloadDocumentElement extends ApiDocumentationBase {
this[payloadValue] = info;
} catch (e) {
this[payloadValue] = undefined;
- Events.Telemetry.exception(this, e.message, false);
- Events.Reporting.error(this, e, `Unable to query for API payload data: ${e.message}`, this.localName);
+ const ex = e as Error;
+ Events.Telemetry.exception(this, ex.message, false);
+ Events.Reporting.error(this, ex, `Unable to query for API payload data: ${ex.message}`, this.localName);
}
}
- async [processPayload]() {
+ async [processPayload](): Promise {
this[examplesValue] = undefined;
const { payload } = this;
if (!payload) {
@@ -104,25 +96,23 @@ export default class ApiPayloadDocumentElement extends ApiDocumentationBase {
}
}
- render() {
+ render(): TemplateResult {
const { payload } = this;
if (!payload) {
return html``;
}
return html`
-
- ${this[nameTemplate]()}
- ${this[mediaTypeTemplate]()}
+ ${this[nameTemplate](payload)}
+ ${this[mediaTypeTemplate](payload)}
${this[examplesTemplate]()}
- ${this[schemaTemplate]()}
+ ${this[schemaTemplate](payload)}
`;
}
/**
- * @return {TemplateResult|string} The template for the payload mime type.
+ * @returns The template for the payload mime type.
*/
- [mediaTypeTemplate]() {
- const { payload } = this;
+ [mediaTypeTemplate](payload: ApiDefinitions.IApiPayload): TemplateResult | string {
const { mediaType } = payload;
if (!mediaType) {
return '';
@@ -136,10 +126,9 @@ export default class ApiPayloadDocumentElement extends ApiDocumentationBase {
}
/**
- * @return {TemplateResult|string} The template for the payload name
+ * @returns The template for the payload name
*/
- [nameTemplate]() {
- const { payload } = this;
+ [nameTemplate](payload: ApiDefinitions.IApiPayload): TemplateResult | string {
const { name } = payload;
if (!name) {
return '';
@@ -150,10 +139,9 @@ export default class ApiPayloadDocumentElement extends ApiDocumentationBase {
}
/**
- * @return {TemplateResult} The template for the payload's schema
+ * @returns The template for the payload's schema
*/
- [schemaTemplate]() {
- const { payload } = this;
+ [schemaTemplate](payload: ApiDefinitions.IApiPayload): TemplateResult {
const { schema, mediaType } = payload;
if (!schema) {
return html`Schema is not defined for this payload.
`;
diff --git a/src/elements/ApiRequestDocumentElement.d.ts b/src/elements/ApiRequestDocumentElement.d.ts
deleted file mode 100644
index 0b76348..0000000
--- a/src/elements/ApiRequestDocumentElement.d.ts
+++ /dev/null
@@ -1,138 +0,0 @@
-import { TemplateResult } from 'lit-element';
-import { ApiDocumentationBase } from './ApiDocumentationBase.js';
-import { ApiRequest, ApiPayload, ApiServer, ApiEndPoint, ApiParameter } from '../helpers/api';
-import { OperationParameter } from '../types';
-
-export const queryRequest: unique symbol;
-export const requestValue: unique symbol;
-export const queryPayloads: unique symbol;
-export const payloadsValue: unique symbol;
-export const payloadValue: unique symbol;
-export const notifyMime: unique symbol;
-export const preselectMime: unique symbol;
-export const queryParamsTemplate: unique symbol;
-export const headersTemplate: unique symbol;
-export const cookiesTemplate: unique symbol;
-export const payloadTemplate: unique symbol;
-export const payloadSelectorTemplate: unique symbol;
-export const mediaTypeSelectHandler: unique symbol;
-export const processQueryParameters: unique symbol;
-export const queryParametersValue: unique symbol;
-
-/**
- * A web component that renders the documentation page for an API request object.
- *
- * @fires mimechange
- */
-export default class ApiRequestDocumentElement extends ApiDocumentationBase {
- /**
- * @returns {boolean} true when has cookie parameters definition
- */
- get hasCookieParameters(): boolean;
-
- /**
- * @returns {boolean} true when has headers parameters definition
- */
- get hasHeaders(): boolean;
-
- /**
- * @returns {boolean} true when has query parameters definition
- */
- get hasQueryParameters(): boolean;
-
- /**
- * @returns The combined list of path parameters in the server, endpoint, and the request.
- */
- get uriParameters(): ApiParameter[];
-
- /**
- * @returns {boolean} true when has query string definition
- */
- get hasQueryString(): boolean;
- get [payloadValue](): ApiPayload|undefined;
- [payloadsValue]: ApiPayload|undefined;
- get request(): ApiRequest;
- set request(value: ApiRequest);
- [requestValue]: ApiRequest;
-
- /**
- * When set it opens the parameters section
- * @attribute
- */
- parametersOpened: boolean;
- /**
- * When set it opens the headers section
- * @attribute
- */
- headersOpened: boolean;
- /**
- * When set it opens the cookies section
- * @attribute
- */
- cookiesOpened: boolean;
- /**
- * When set it opens the payload section
- * @attribute
- */
- payloadOpened: boolean;
- /**
- * The currently selected media type for the payloads.
- * @attribute
- */
- mimeType: string;
- /**
- * The current server in use.
- * It adds path parameters defined for the server.
- */
- server: ApiServer;
- /**
- * The parent endpoint of this request.
- * It adds path parameters defined for the endpoint.
- */
- endpoint: ApiEndPoint;
- [queryParametersValue]: OperationParameter[];
- constructor();
- processGraph(): Promise;
- [queryPayloads](): Promise;
- /**
- * Creates a parameter
- */
- [processQueryParameters](): Promise;
- /**
- * Pre-selects when needed the mime type for the current payload.
- */
- [preselectMime](): void;
- [mediaTypeSelectHandler](e: Event): void;
-
- /**
- * Dispatches the `mimechange` event.
- */
- [notifyMime](): void;
-
- render(): TemplateResult;
-
- /**
- * @return The template for the query parameters
- */
- [queryParamsTemplate](): TemplateResult|string;
-
- /**
- * @return The template for the headers
- */
- [headersTemplate](): TemplateResult|string;
-
- /**
- * @return The template for the cookies list section
- */
- [cookiesTemplate](): TemplateResult|string;
-
- /**
- * @return The template for the payload section
- */
- [payloadTemplate](): TemplateResult|string;
-
- /**
- * @return The template for the payload media type selector.
- */
- [payloadSelectorTemplate](): TemplateResult|string;
-}
diff --git a/src/elements/ApiRequestDocumentElement.js b/src/elements/ApiRequestDocumentElement.ts
similarity index 59%
rename from src/elements/ApiRequestDocumentElement.js
rename to src/elements/ApiRequestDocumentElement.ts
index 76c4f94..7ff5214 100644
--- a/src/elements/ApiRequestDocumentElement.js
+++ b/src/elements/ApiRequestDocumentElement.ts
@@ -1,29 +1,22 @@
/* eslint-disable class-methods-use-this */
-import { html } from 'lit-element';
-import '@anypoint-web-components/awc/anypoint-radio-button.js';
-import '@anypoint-web-components/awc/anypoint-radio-group.js';
+import { html, TemplateResult, CSSResult } from 'lit';
+import { property } from 'lit/decorators.js';
+import { AmfShapes, ApiDefinitions } from '@api-client/core/build/browser.js';
+import { AnypointRadioGroupElement } from '@anypoint-web-components/awc';
+import '@anypoint-web-components/awc/dist/define/anypoint-radio-button.js';
+import '@anypoint-web-components/awc/dist/define/anypoint-radio-group.js';
import commonStyles from './styles/Common.js';
import elementStyles from './styles/ApiRequest.js';
-import {
- ApiDocumentationBase,
- paramsSectionTemplate,
+import {
+ ApiDocumentationBase,
+ paramsSectionTemplate,
schemaItemTemplate,
} from './ApiDocumentationBase.js';
import { QueryParameterProcessor } from '../lib/QueryParameterProcessor.js';
import { Events } from '../events/Events.js';
import '../../define/api-payload-document.js';
import '../../define/api-parameter-document.js';
-
-/** @typedef {import('lit-element').TemplateResult} TemplateResult */
-/** @typedef {import('../helpers/api').ApiRequest} ApiRequest */
-/** @typedef {import('../helpers/api').ApiPayload} ApiPayload */
-/** @typedef {import('../helpers/api').ApiNodeShape} ApiNodeShape */
-/** @typedef {import('../helpers/api').ApiArrayShape} ApiArrayShape */
-/** @typedef {import('../helpers/api').ApiServer} ApiServer */
-/** @typedef {import('../helpers/api').ApiEndPoint} ApiEndPoint */
-/** @typedef {import('../helpers/api').ApiParameter} ApiParameter */
-/** @typedef {import('@anypoint-web-components/awc').AnypointRadioGroupElement} AnypointRadioGroupElement */
-/** @typedef {import('../types').OperationParameter} OperationParameter */
+import { OperationParameter } from '../types.js';
export const queryRequest = Symbol('queryRequest');
export const requestValue = Symbol('requestValue');
@@ -45,14 +38,18 @@ export const queryParametersValue = Symbol('queryParametersValue');
* A web component that renders the documentation page for an API request object.
*/
export default class ApiRequestDocumentElement extends ApiDocumentationBase {
- get styles() {
+ static get styles(): CSSResult[] {
return [commonStyles, elementStyles];
}
+ [requestValue]?: ApiDefinitions.IApiRequest;
+
+ [payloadsValue]?: ApiDefinitions.IApiPayload[];
+
/**
- * @returns {boolean} true when has cookie parameters definition
+ * @returns true when has cookie parameters definition
*/
- get hasCookieParameters() {
+ get hasCookieParameters(): boolean {
const request = this[requestValue];
if (!request) {
return false;
@@ -61,9 +58,9 @@ export default class ApiRequestDocumentElement extends ApiDocumentationBase {
}
/**
- * @returns {boolean} true when has headers parameters definition
+ * @returns true when has headers parameters definition
*/
- get hasHeaders() {
+ get hasHeaders(): boolean {
const request = this[requestValue];
if (!request) {
return false;
@@ -72,9 +69,9 @@ export default class ApiRequestDocumentElement extends ApiDocumentationBase {
}
/**
- * @returns {boolean} true when has query parameters definition
+ * @returns true when has query parameters definition
*/
- get hasQueryParameters() {
+ get hasQueryParameters(): boolean {
const request = this[requestValue];
if (!request) {
return false;
@@ -83,12 +80,12 @@ export default class ApiRequestDocumentElement extends ApiDocumentationBase {
}
/**
- * @returns {ApiParameter[]} The combined list of path parameters in the server, endpoint, and the request.
+ * @returns The combined list of path parameters in the server, endpoint, and the request.
*/
- get uriParameters() {
- const request = /** @type ApiRequest */ (this[requestValue]);
+ get uriParameters(): ApiDefinitions.IApiParameter[] {
+ const request = this[requestValue];
const { server, endpoint } = this;
- let result = /** @type ApiParameter[] */ ([]);
+ let result: ApiDefinitions.IApiParameter[] = [];
if (server && Array.isArray(server.variables) && server.variables.length) {
result = result.concat(server.variables);
}
@@ -102,20 +99,17 @@ export default class ApiRequestDocumentElement extends ApiDocumentationBase {
}
/**
- * @returns {boolean} true when has query string definition
+ * @returns true when has query string definition
*/
- get hasQueryString() {
- const request = /** @type ApiRequest */ (this[requestValue]);
+ get hasQueryString(): boolean {
+ const request = this[requestValue];
if (!request) {
return false;
}
return !!request.queryString;
}
- /**
- * @returns {ApiPayload|undefined}
- */
- get [payloadValue]() {
+ get [payloadValue](): ApiDefinitions.IApiPayload | undefined {
const { mimeType } = this;
const payloads = this[payloadsValue];
if (!Array.isArray(payloads) || !payloads.length) {
@@ -127,17 +121,11 @@ export default class ApiRequestDocumentElement extends ApiDocumentationBase {
return payloads.find((item) => item.mediaType === mimeType);
}
- /**
- * @returns {ApiRequest}
- */
- get request() {
+ get request(): ApiDefinitions.IApiRequest | undefined {
return this[requestValue];
}
- /**
- * @param {ApiRequest} value
- */
- set request(value) {
+ set request(value: ApiDefinitions.IApiRequest | undefined) {
const old = this[requestValue];
if (old === value) {
return;
@@ -146,86 +134,64 @@ export default class ApiRequestDocumentElement extends ApiDocumentationBase {
this.processGraph();
}
- static get properties() {
- return {
- /**
- * When set it opens the parameters section
- */
- parametersOpened: { type: Boolean, reflect: true },
- /**
- * When set it opens the headers section
- */
- headersOpened: { type: Boolean, reflect: true },
- /**
- * When set it opens the cookies section
- */
- cookiesOpened: { type: Boolean, reflect: true },
- /**
- * When set it opens the payload section
- */
- payloadOpened: { type: Boolean, reflect: true },
- /**
- * The currently selected media type for the payloads.
- */
- mimeType: { type: String, reflect: true },
- /**
- * The current server in use.
- * It adds path parameters defined for the server.
- */
- server: { type: Object },
- /**
- * The parent endpoint of this request.
- * It adds path parameters defined for the endpoint.
- */
- endpoint: { type: Object },
- };
- }
+ /**
+ * When set it opens the parameters section
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true }) parametersOpened?: boolean;
- constructor() {
- super();
- /**
- * @type {ApiRequest}
- */
- this[requestValue] = undefined;
- /**
- * @type {ApiPayload[]}
- */
- this[payloadsValue] = undefined;
- /** @type {string} */
- this.mimeType = undefined;
- /** @type {boolean} */
- this.headersOpened = undefined;
- /** @type {boolean} */
- this.payloadOpened = undefined;
- /** @type {boolean} */
- this.cookiesOpened = undefined;
- /** @type {boolean} */
- this.parametersOpened = undefined;
- /** @type {ApiServer} */
- this.server = undefined;
- /** @type {ApiEndPoint} */
- this.endpoint = undefined;
- /** @type {OperationParameter[]} */
- this[queryParametersValue] = undefined;
- }
+ /**
+ * When set it opens the headers section
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true }) headersOpened?: boolean;
- /**
- * @returns {Promise}
+ /**
+ * When set it opens the cookies section
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true }) cookiesOpened?: boolean;
+
+ /**
+ * When set it opens the payload section
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true }) payloadOpened?: boolean;
+
+ /**
+ * The currently selected media type for the payloads.
+ * @attribute
*/
- async processGraph() {
+ @property({ type: String, reflect: true }) mimeType?: string;
+
+ /**
+ * The current server in use.
+ * It adds path parameters defined for the server.
+ */
+ @property({ type: Object }) server?: ApiDefinitions.IApiServer;
+
+ /**
+ * The parent endpoint of this request.
+ * It adds path parameters defined for the endpoint.
+ */
+ @property({ type: Object }) endpoint?: ApiDefinitions.IApiEndPoint;
+
+ [queryParametersValue]?: OperationParameter[];
+
+ async processGraph(): Promise {
this.mimeType = undefined;
await this[queryRequest]();
await this[queryPayloads]();
await this[processQueryParameters]();
this[preselectMime]();
- await this.requestUpdate();
+ this.requestUpdate();
+ await this.updateComplete;
}
/**
* Queries the store for the request data, when needed.
- * @returns {Promise}
*/
- async [queryRequest]() {
+ async [queryRequest](): Promise {
const { domainId } = this;
if (!domainId) {
// this[requestValue] = undefined;
@@ -240,12 +206,13 @@ export default class ApiRequestDocumentElement extends ApiDocumentationBase {
this[requestValue] = info;
} catch (e) {
this[requestValue] = undefined;
- Events.Telemetry.exception(this, e.message, false);
- Events.Reporting.error(this, e, `Unable to query for API request data: ${e.message}`, this.localName);
+ const ex = e as Error;
+ Events.Telemetry.exception(this, ex.message, false);
+ Events.Reporting.error(this, ex, `Unable to query for API request data: ${ex.message}`, this.localName);
}
}
- async [queryPayloads]() {
+ async [queryPayloads](): Promise {
const { request } = this;
if (!request || !request.payloads.length) {
this[payloadsValue] = undefined;
@@ -257,31 +224,31 @@ export default class ApiRequestDocumentElement extends ApiDocumentationBase {
/**
* Creates a parameter
*/
- async [processQueryParameters]() {
+ async [processQueryParameters](): Promise {
this[queryParametersValue] = undefined;
const { request } = this;
if (!request) {
return;
}
- const nodeShape = /** @type ApiNodeShape */ (request.queryString);
+ const nodeShape = (request.queryString as AmfShapes.IApiNodeShape);
if (!nodeShape) {
return;
}
const factory = new QueryParameterProcessor();
- const params = factory.collectOperationParameters(request.queryString, 'query');
+ const params = factory.collectOperationParameters(request.queryString as AmfShapes.IShapeUnion, 'query');
this[queryParametersValue] = params;
}
/**
* Pre-selects when needed the mime type for the current payload.
*/
- [preselectMime]() {
+ [preselectMime](): void {
const { mimeType } = this;
const payloads = this[payloadsValue];
if (!Array.isArray(payloads) || !payloads.length) {
return;
}
- const mime = /** @type string[] */ ([]);
+ const mime: string[] = [];
let hasCurrent = false;
payloads.forEach((item) => {
if (item.mediaType) {
@@ -303,11 +270,8 @@ export default class ApiRequestDocumentElement extends ApiDocumentationBase {
this[notifyMime]();
}
- /**
- * @param {Event} e
- */
- [mediaTypeSelectHandler](e) {
- const group = /** @type AnypointRadioGroupElement */ (e.target);
+ [mediaTypeSelectHandler](e: Event): void {
+ const group = e.target as AnypointRadioGroupElement;
const { selectedItem } = group;
if (!selectedItem) {
return;
@@ -320,17 +284,16 @@ export default class ApiRequestDocumentElement extends ApiDocumentationBase {
/**
* Dispatches the `mimechange` event.
*/
- [notifyMime]() {
+ [notifyMime](): void {
this.dispatchEvent(new Event('mimechange'));
}
- render() {
+ render(): TemplateResult {
const { request, server, endpoint } = this;
if (!request && !server && !endpoint) {
return html``;
}
return html`
-
${this[queryParamsTemplate]()}
${this[headersTemplate]()}
${this[cookiesTemplate]()}
@@ -339,55 +302,55 @@ export default class ApiRequestDocumentElement extends ApiDocumentationBase {
}
/**
- * @return {TemplateResult|string} The template for the query parameters
+ * @return The template for the query parameters
*/
- [queryParamsTemplate]() {
+ [queryParamsTemplate](): TemplateResult | string {
const { uriParameters, hasQueryParameters } = this;
if (!hasQueryParameters && !uriParameters.length) {
return '';
}
const { request } = this;
- let queryParameters = [];
+ let queryParameters: ApiDefinitions.IApiParameter[] = [];
if (request && Array.isArray(request.queryParameters)) {
queryParameters = request.queryParameters;
}
if (!queryParameters.length && this[queryParametersValue] && this[queryParametersValue].length) {
queryParameters = this[queryParametersValue].map(i => i.parameter);
}
- const content = [];
+ const content: (TemplateResult | string)[] = [];
uriParameters.forEach(param => content.push(this[schemaItemTemplate](param, 'uri')));
queryParameters.forEach(param => content.push(this[schemaItemTemplate](param, 'query')));
return this[paramsSectionTemplate]('Parameters', 'parametersOpened', content);
}
/**
- * @return {TemplateResult|string} The template for the headers
+ * @return The template for the headers
*/
- [headersTemplate]() {
+ [headersTemplate](): TemplateResult | string {
if (!this.hasHeaders) {
return '';
}
const { request } = this;
- const content = request.headers.map((param) => this[schemaItemTemplate](param, 'header'));
+ const content = (request as ApiDefinitions.IApiRequest).headers.map((param) => this[schemaItemTemplate](param, 'header'));
return this[paramsSectionTemplate]('Headers', 'headersOpened', content);
}
/**
- * @return {TemplateResult|string} The template for the cookies list section
+ * @return The template for the cookies list section
*/
- [cookiesTemplate]() {
+ [cookiesTemplate](): TemplateResult | string {
if (!this.hasCookieParameters) {
return '';
}
const { request } = this;
- const content = request.cookieParameters.map((param) => this[schemaItemTemplate](param, 'cookie'));
+ const content = (request as ApiDefinitions.IApiRequest).cookieParameters.map((param) => this[schemaItemTemplate](param, 'cookie'));
return this[paramsSectionTemplate]('Cookies', 'cookiesOpened', content);
}
/**
- * @return {TemplateResult|string} The template for the payload section
+ * @return The template for the payload section
*/
- [payloadTemplate]() {
+ [payloadTemplate](): TemplateResult | string {
const payload = this[payloadValue];
if (!payload) {
return '';
@@ -400,14 +363,14 @@ export default class ApiRequestDocumentElement extends ApiDocumentationBase {
}
/**
- * @return {TemplateResult|string} The template for the payload media type selector.
+ * @return The template for the payload media type selector.
*/
- [payloadSelectorTemplate]() {
+ [payloadSelectorTemplate](): TemplateResult | string {
const payloads = this[payloadsValue];
if (!Array.isArray(payloads) || payloads.length < 2) {
return '';
}
- const mime = /** @type string[] */ ([]);
+ const mime: string[] = [];
payloads.forEach((item) => {
if (item.mediaType) {
mime.push(item.mediaType);
@@ -425,8 +388,8 @@ export default class ApiRequestDocumentElement extends ApiDocumentationBase {
attrForSelected="data-value"
.selected="${mimeType}"
>
- ${mime.map((item) =>
- html`${item}`)}
+ ${mime.map((item) =>
+ html`${item}`)}
`;
diff --git a/src/elements/ApiRequestEditorElement.d.ts b/src/elements/ApiRequestEditorElement.d.ts
deleted file mode 100644
index 45bc6ec..0000000
--- a/src/elements/ApiRequestEditorElement.d.ts
+++ /dev/null
@@ -1,673 +0,0 @@
-/**
-@license
-Copyright 2021 The Advanced REST client authors
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-http://www.apache.org/licenses/LICENSE-2.0
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
-*/
-import { TemplateResult, LitElement } from 'lit-element';
-import { EventsTargetMixin } from '@anypoint-web-components/awc';
-import { Oauth2Credentials } from '@advanced-rest-client/base';
-import { ApiEndPoint, ApiOperation, ApiPayload, ApiParameter, ApiServer } from '../helpers/api';
-import { AmfParameterMixin } from '../lib/AmfParameterMixin';
-import { SecuritySelectorListItem, ApiConsoleRequest, OperationParameter, ServerType } from '../types';
-
-export const EventCategory: string;
-
-export const domainIdValue: unique symbol;
-export const operationValue: unique symbol;
-export const endpointValue: unique symbol;
-export const loadingRequestValue: unique symbol;
-export const requestIdValue: unique symbol;
-export const baseUriValue: unique symbol;
-export const urlInvalidValue: unique symbol;
-export const serverLocalValue: unique symbol;
-export const processOperation: unique symbol;
-export const processEndpoint: unique symbol;
-export const processSecurity: unique symbol;
-export const processPayload: unique symbol;
-export const appendToParams: unique symbol;
-export const securityList: unique symbol;
-export const updateServer: unique symbol;
-export const updateServerParameters: unique symbol;
-export const updateEndpointParameters: unique symbol;
-export const computeUrlValue: unique symbol;
-export const getOrderedPathParams: unique symbol;
-export const validateUrl: unique symbol;
-export const readUrlValidity: unique symbol;
-export const authSelectorHandler: unique symbol;
-export const mediaTypeSelectHandler: unique symbol;
-export const modelBodyEditorChangeHandler: unique symbol;
-export const rawBodyChangeHandler: unique symbol;
-export const serverCountHandler: unique symbol;
-export const serverHandler: unique symbol;
-export const populateAnnotatedFieldsHandler: unique symbol;
-export const authRedirectChangedHandler: unique symbol;
-export const responseHandler: unique symbol;
-export const sendHandler: unique symbol;
-export const abortHandler: unique symbol;
-export const optionalToggleHandler: unique symbol;
-export const addCustomHandler: unique symbol;
-export const authorizationTemplate: unique symbol;
-export const authorizationSelectorTemplate: unique symbol;
-export const authorizationSelectorItemTemplate: unique symbol;
-export const mediaTypeSelectorTemplate: unique symbol;
-export const bodyTemplate: unique symbol;
-export const formDataEditorTemplate: unique symbol;
-export const multipartEditorTemplate: unique symbol;
-export const rawEditorTemplate: unique symbol;
-export const headersTemplate: unique symbol;
-export const parametersTemplate: unique symbol;
-export const serverSelectorTemplate: unique symbol;
-export const toggleOptionalTemplate: unique symbol;
-export const urlLabelTemplate: unique symbol;
-export const formActionsTemplate: unique symbol;
-export const abortButtonTemplate: unique symbol;
-export const sendButtonTemplate: unique symbol;
-export const addCustomButtonTemplate: unique symbol;
-export const urlEditorTemplate: unique symbol;
-export const urlEditorChangeHandler: unique symbol;
-export const computeUrlRegexp: unique symbol;
-export const urlSearchRegexpValue: unique symbol;
-export const applyUriValues: unique symbol;
-export const applyQueryParamsValues: unique symbol;
-export const orderPathParameters: unique symbol;
-export const queryOperation: unique symbol;
-export const queryEndpoint: unique symbol;
-export const queryServers: unique symbol;
-export const queryProtocols: unique symbol;
-export const protocolsValue: unique symbol;
-export const serversValue: unique symbol;
-export const queryVersion: unique symbol;
-export const versionValue: unique symbol;
-export const graphChangeHandler: unique symbol;
-export const debounceValue: unique symbol;
-export const processDebounce: unique symbol;
-
-/**
- * @fires apirequest
- * @fires apiabort
- */
-export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTargetMixin(LitElement)) {
- /**
- * The currently selected media type for the payloads.
- * @attribute
- */
- mimeType: string;
- /**
- * The domain id (AMF's id) of an API operation.
- * @attribute
- */
- domainId: string;
- [domainIdValue]: string;
- /**
- * When set it renders a label with the computed URL.
- * @attribute
- */
- urlLabel: boolean;
- /**
- * When set it renders the URL input above the URL parameters.
- * @attribute
- */
- urlEditor: boolean;
- /**
- * A base URI for the API. To be set if RAML spec is missing `baseUri`
- * declaration and this produces invalid URL input. This information
- * is passed to the URL editor that prefixes the URL with `baseUri` value
- * if passed URL is a relative URL.
- * @attribute
- */
- baseUri: string;
- [baseUriValue]: string;
- /**
- * If set it computes `hasOptional` property and shows checkbox in the
- * form to show / hide optional properties.
- * @attribute
- */
- allowHideOptional: boolean;
- /**
- * When set, renders "add custom" item button.
- * If the element is to be used without AMF model this should always
- * be enabled. Otherwise users won't be able to add a parameter.
- * @attribute
- */
- allowCustom: boolean;
- /**
- * Enables Anypoint platform styles.
- * @attribute
- */
- anypoint: boolean;
- /**
- * Enables Material Design outlined style
- * @attribute
- */
- outlined: boolean;
- /**
- * OAuth2 redirect URI.
- * This value **must** be set in order for OAuth 1/2 to work properly.
- * @attribute
- */
- redirectUri: string;
- /**
- * Final request URL including settings like `baseUri`, AMF
- * model settings and user provided parameters.
- * @attribute
- */
- url: string;
- /**
- * Holds the value of the currently selected server
- * Data type: URI
- * @attribute
- */
- serverValue: string;
- /**
- * Holds the type of the currently selected server
- * Values: `server` | `uri` | `custom`
- * @attribute
- */
- serverType: ServerType;
- /**
- * Optional property to set
- * If true, the server selector is not rendered
- * @attribute
- */
- noServerSelector: boolean;
- /**
- * Optional property to set
- * If true, the server selector custom base URI option is rendered
- * @attribute
- */
- allowCustomBaseUri: boolean;
- /**
- * List of credentials source
- */
- credentialsSource: Oauth2Credentials[];
- /**
- * The index of the selected security definition to apply.
- * @attribute
- */
- selectedSecurity: number;
- /**
- * When set it applies the authorization values to the request dispatched
- * with the API request event.
- * If possible, it applies the authorization values to query parameter or headers
- * depending on the configuration.
- *
- * When the values arr applied to the request the authorization config is kept in the
- * request object, but its `enabled` state is always `false`, meaning other potential
- * processors should ignore this values.
- *
- * If this property is not set then the application hosting this component should
- * process the authorization data and apply them to the request.
- * @attribute
- */
- applyAuthorization: boolean;
- /**
- * By default the element stores user input in a map that is associated with the specific
- * instance of this element. This way the element can be used multiple times in the same document.
- * However, this way parameter values generated by the generators or entered by the user won't
- * get populated in different operations.
- *
- * By setting this value the element prefers a global cache for values. Once the user enter
- * a value it is registered in the global cache and restored when the same parameter is used again.
- *
- * Do not use this option when the element is embedded multiple times in the page. It will result
- * in generating request data from the cache and not what's in the form inputs and these may not be in sync.
- *
- * These values are stored in memory only. Listen to the `change` event to learn that something changed.
- * @attribute
- */
- globalCache: boolean;
-
- /**
- * @returns The HTTP method name.
- */
- get httpMethod(): string;
-
- /**
- * True when the request is being loaded.
- */
- get loadingRequest(): boolean;
- [loadingRequestValue]: boolean;
-
- /**
- * The current request id.
- */
- get requestId(): string;
- [requestIdValue]: string;
-
- /**
- * Currently used server definition.
- */
- get server(): ApiServer;
-
- /**
- * This is the final computed value for the baseUri to propagate downwards
- * If baseUri is defined, return baseUri
- * Else, return the selectedServerValue if serverType is not `server`
- */
- get effectiveBaseUri(): string;
-
- /**
- * True when there are not enough servers to render the selector
- */
- get serverSelectorHidden(): boolean;
-
- /**
- * The security requirement for the operation or undefined.
- */
- get security(): SecuritySelectorListItem[]|undefined;
-
- /**
- * The currently rendered payload, if any.
- */
- get payload(): ApiPayload|undefined;
-
- /**
- * The list of all possible payloads for this operation.
- */
- get payloads(): ApiPayload[]|undefined;
-
- /**
- * API defined base URI (current server + the endpoint)
- */
- get apiBaseUri(): string|undefined;
-
- /**
- * @returns True when the URL input is invalid.
- */
- get urlInvalid(): boolean;
- /**
- * The API's protocols.
- */
- get protocols(): string[]|undefined;
- /**
- * The API's version.
- */
- get version(): string|undefined
- [protocolsValue]: string[]|undefined;
- [versionValue]: string|undefined;
- /**
- * Set when the selection change, this is a JS object created form the
- * supportedOperation definition of the AMF graph.
- */
- [operationValue]: ApiOperation;
- [endpointValue]: ApiEndPoint;
- /**
- * The list of security list items to render.
- * An operation may have multiple security definition in an or/and fashion.
- * This allows to render the selector to pick the current security.
- */
- [securityList]: SecuritySelectorListItem[];
- /**
- * The list of parameter groups that are opened when `allowHideOptional` is set.
- */
- openedOptional: string[];
-
- serversCount?: number;
- /**
- * The list of computed servers for this AMF configuration.
- */
- get servers(): ApiServer[];
- /**
- * Optional. The parent endpoint id. When set it uses this value to query for the endpoint
- * instead of querying for a parent through the operation id.
- * Also, when `endpoint` is set and the `endpointId` match then it ignores querying for
- * the endpoint.
- * @attribute
- */
- endpointId: string;
- endpoint: ApiEndPoint|undefined;
- /**
- * The timeout after which the `queryGraph()` function is called
- * in the debouncer.
- */
- queryDebouncerTimeout: number;
- [serversValue]: ApiServer[];
- [serverLocalValue]: ApiServer;
- constructor();
-
- // for the AmfParameterMixin
- notifyChange(): void;
- _attachListeners(node: EventTarget): void;
- _detachListeners(node: EventTarget): void;
-
- /**
- * Handler for the event dispatched by the store when the graph model change.
- */
- [graphChangeHandler](): void;
-
- /**
- * Calls the `queryGraph()` function in a debouncer.
- */
- [processDebounce](): void;
- /**
- * Reads the URL data from the ApiUrlDataModel library and sets local variables.
- */
- readUrlData(): void;
-
- /**
- * A function to be overwritten by child classes to execute an action when a parameter has changed.
- */
- paramChanged(key: string): void;
-
- /**
- * Computes the URL value for the current serves, selected server, and endpoint's path.
- */
- [computeUrlValue](): void;
-
- /**
- * Checks if the current server has variables and update the parameters array
- */
- [updateServerParameters](): void;
-
- /**
- * Checks if the current endpoint has variables and requests them when needed.
- */
- [updateEndpointParameters](): void;
-
- reset(): void;
-
- /**
- * Processes the selection of the domain id for an operation.
- */
- processGraph(): Promise;
-
- /**
- * Queries the store for the operation data, when needed.
- * @returns {Promise}
- */
- [queryOperation](): Promise;
-
- /**
- * Queries the store for the endpoint data.
- * @returns {Promise}
- */
- [queryEndpoint](): Promise;
-
- /**
- * Queries for the current servers value.
- */
- [queryServers](): Promise;
-
- /**
- * Queries the API store for the API protocols list.
- */
- [queryProtocols](): Promise;
-
- /**
- * Queries the API store for the API version value.
- */
- [queryVersion](): Promise;
-
- /**
- * Searches for the current operation endpoint and sets variables from the endpoint definition.
- */
- [processEndpoint](): void;
-
- /**
- * Collects operations input parameters into a single object.
- */
- [processOperation](): void;
-
- /**
- * Processes security information for the UI.
- */
- [processSecurity](): void;
-
- /**
- * Appends a list of parameters to the list of rendered parameters
- */
- [appendToParams](list: ApiParameter[], source: string): void;
-
- /**
- * A handler for the change event dispatched by the `raw` editor.
- */
- [rawBodyChangeHandler](e: Event): void;
-
- /**
- * A handler for the change event dispatched by the
- * `urlEncode` editor.
- * Updated the local value, model, and notifies the change.
- */
- [modelBodyEditorChangeHandler](e: Event): void;
- [authSelectorHandler](e: Event): void;
-
- /**
- * Handles send button click.
- * Depending on authorization validity it either sends the
- * request or forces authorization and sends the request.
- */
- [sendHandler](): void;
-
- /**
- * To be called when the user want to execute the request but
- * authorization is invalid (missing values).
- * This function brings the auth panel to front and displays error toast
- *
- * TODO: There is a case when the user didn't requested OAuth2 token
- * but provided all the data. This function should check for this
- * condition and call authorization function automatically.
- */
- authAndExecute(): Promise;
-
- /**
- * Executes the request by dispatching `api-request` custom event.
- * The event must be handled by hosting application to ensure transport.
- * Use `advanced-rest-client/xhr-simple-request` component to add logic
- * that uses XHR as a transport.
- *
- * Hosting application also must reset state of `loadingRequest` property
- * once the response is ready. It also can dispatch `api-response`
- * custom event handled by this element to reset state. This is also
- * handled by `xhr-simple-request` component.
- */
- execute(): void;
-
- /**
- * Sends the `abort-api-request` custom event to cancel the request.
- * Calling this method before sending request may have unexpected
- * behavior because `requestId` is only set with `execute()` method.
- */
- abort(): void;
-
- /**
- * Event handler for abort click.
- */
- [abortHandler](): void;
-
- /**
- * Serializes the state of the request editor into the `ApiConsoleRequest` object.
- *
- * @return {ApiConsoleRequest}
- */
- serialize(): ApiConsoleRequest;
-
- /**
- * Handler for the `api-response` custom event.
- * Clears the loading state.
- */
- [responseHandler](e: CustomEvent): void;
-
- /**
- * Handler for the `oauth2-redirect-uri-changed` custom event. Changes
- * the `redirectUri` property.
- */
- [authRedirectChangedHandler](e: CustomEvent): void;
-
- /**
- * Handle event for populating annotated fields in the editor.
- */
- [populateAnnotatedFieldsHandler](e: CustomEvent): void;
-
- /**
- * Computes a current server value for selection made in the server selector.
- */
- [updateServer](): void;
-
- /**
- * Handler for the change dispatched from the server selector.
- */
- [serverCountHandler](e: CustomEvent): void;
-
- /**
- * Handler for the change dispatched from the server selector.
- */
- [serverHandler](e: CustomEvent): void;
-
- /**
- * Computes a regexp for the base URI defined in the server to process URL input change
- * and set the `[urlSearchRegexpValue]` value.
- * This should be computed only when a server and en endpoint change.
- */
- [computeUrlRegexp](): void;
- [mediaTypeSelectHandler](e: Event): void;
-
- /**
- * Toggles optional parameter groups.
- */
- [optionalToggleHandler](e: Event): void;
-
- /**
- * When enabled it adds a new custom parameter to the request section defined in the source button.
- */
- [addCustomHandler](e: Event): void;
-
- /**
- * Updates path/query model from user input.
- *
- * @param e The change event
- */
- [urlEditorChangeHandler](e: Event): void;
-
- /**
- * Sets the value of `[urlInvalidValue]` and therefore `urlInvalid` properties.
- */
- [validateUrl](): void;
-
- /**
- * Validates the current URL value.
- * @returns True when the current URL is a valid URL.
- */
- [readUrlValidity](): boolean;
-
- /**
- * Reads the ordered list of path parameters from the server and the endpoint.
- */
- [getOrderedPathParams](): OperationParameter[];
-
- /**
- * Applies values from the `values` array to the uri parameters which names are in the `names` array.
- * Both lists are ordered list of parameters.
- *
- * @param values Values for the parameters
- * @param params List of path parameters.
- * @returns True when any parameter was changed.
- */
- [applyUriValues](values: string[], params: OperationParameter[]): boolean;
-
- /**
- * Applies query parameters values to the render list.
- *
- * @returns True when any parameter was changed.
- */
- [applyQueryParamsValues](map: Record): boolean;
-
- render(): TemplateResult;
-
- /**
- * @return {} Template for the request URL label.
- */
- [urlLabelTemplate](): TemplateResult|string;
-
- /**
- * @returns {TemplateResult} The template for the security drop down selector.
- */
- [authorizationSelectorTemplate](security: SecuritySelectorListItem[], selected: number): TemplateResult;
-
- /**
- * @returns {TemplateResult} The template for the security drop down selector list item.
- */
- [authorizationSelectorItemTemplate](info: SecuritySelectorListItem): TemplateResult;
-
- [formActionsTemplate](): TemplateResult;
-
- /**
- * Creates a template for the "abort" button.
- *
- * @return {TemplateResult}
- */
- [abortButtonTemplate](): TemplateResult;
-
- /**
- * Creates a template for the "send" or "auth and send" button.
- *
- * @return {TemplateResult}
- */
- [sendButtonTemplate](): TemplateResult;
-
- /**
- * @return {TemplateResult} A template for the server selector
- */
- [serverSelectorTemplate](): TemplateResult;
-
- [parametersTemplate](): TemplateResult;
-
- [headersTemplate](): TemplateResult|string;
-
- /**
- * @param {string} type
- * @returns {TemplateResult} The template for the add custom parameter button
- */
- [addCustomButtonTemplate](type): TemplateResult;
-
- /**
- * @return {TemplateResult|string} The template for the payload's mime type selector.
- */
- [mediaTypeSelectorTemplate](): TemplateResult|string;
-
- /**
- * @returns {TemplateResult|string} The template for the body editor.
- */
- [bodyTemplate](): TemplateResult|string;
-
- /**
- * @param {any} info
- * @param {string} id
- * @returns {TemplateResult} The template for the editor that specializes in the URL encoded form data
- */
- [formDataEditorTemplate](info, id): TemplateResult;
-
- /**
- * @param {any} info
- * @param {string} id
- * @returns {TemplateResult} The template for the editor that specializes in the multipart form data
- */
- [multipartEditorTemplate](info, id): TemplateResult;
-
- /**
- * @param {any} info
- * @param {string} id
- * @param {string} mimeType
- * @returns {TemplateResult} The template for the editor that specializes in any text data
- */
- [rawEditorTemplate](info, id, mimeType): TemplateResult;
-
- /**
- * @param {string} target The name of the target parameter group.
- * @param {OperationParameter[]} params The list of parameters. When all are required or empty it won't render then button.
- * @returns {TemplateResult|string} Template for the switch button to toggle visibility of the optional items.
- */
- [toggleOptionalTemplate](target, params): TemplateResult|string;
-
- /**
- * @returns {TemplateResult|string} A template for the URL editor.
- */
- [urlEditorTemplate](): TemplateResult|string;
-}
diff --git a/src/elements/ApiRequestEditorElement.js b/src/elements/ApiRequestEditorElement.ts
similarity index 67%
rename from src/elements/ApiRequestEditorElement.js
rename to src/elements/ApiRequestEditorElement.ts
index b166994..216f48b 100644
--- a/src/elements/ApiRequestEditorElement.js
+++ b/src/elements/ApiRequestEditorElement.ts
@@ -14,27 +14,28 @@ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations under
the License.
*/
-import { html, LitElement } from 'lit-element';
-import { classMap } from 'lit-html/directives/class-map.js';
-import { EventsTargetMixin } from '@anypoint-web-components/awc';
+import { html, LitElement, CSSResult, TemplateResult } from 'lit';
+import { property } from 'lit/decorators.js';
+import { classMap } from 'lit/directives/class-map.js';
+import { uuidV4, Headers, ApiDefinitions, AmfShapes } from '@api-client/core/build/browser.js';
+import { AnypointInputElement, AnypointListboxElement, AnypointRadioGroupElement, EventsTargetMixin } from '@anypoint-web-components/awc';
import { RequestEventTypes } from '@advanced-rest-client/events';
-import { v4 } from '@advanced-rest-client/uuid';
-import { HeadersParser, ifProperty } from '@advanced-rest-client/base';
-import '@anypoint-web-components/awc/anypoint-dropdown-menu.js';
-import '@anypoint-web-components/awc/anypoint-listbox.js';
-import '@anypoint-web-components/awc/anypoint-item.js';
-import '@anypoint-web-components/awc/anypoint-item-body.js';
-import '@anypoint-web-components/awc/anypoint-radio-button.js';
-import '@anypoint-web-components/awc/anypoint-radio-group.js';
-import '@anypoint-web-components/awc/anypoint-icon-button.js';
-import '@anypoint-web-components/awc/anypoint-switch.js';
+import { BodyFormdataEditorElement, BodyRawEditorElement, ifProperty, Oauth2Credentials } from '@advanced-rest-client/base';
+import '@anypoint-web-components/awc/dist/define/anypoint-dropdown-menu.js';
+import '@anypoint-web-components/awc/dist/define/anypoint-listbox.js';
+import '@anypoint-web-components/awc/dist/define/anypoint-item.js';
+import '@anypoint-web-components/awc/dist/define/anypoint-item-body.js';
+import '@anypoint-web-components/awc/dist/define/anypoint-radio-button.js';
+import '@anypoint-web-components/awc/dist/define/anypoint-radio-group.js';
+import '@anypoint-web-components/awc/dist/define/anypoint-icon-button.js';
+import '@anypoint-web-components/awc/dist/define/anypoint-switch.js';
import '@advanced-rest-client/base/define/body-formdata-editor.js';
import '@advanced-rest-client/base/define/body-multipart-editor.js';
import '@advanced-rest-client/base/define/body-raw-editor.js';
import '@advanced-rest-client/icons/arc-icon.js';
import elementStyles from './styles/Editor.styles.js';
import { ensureContentType, generateHeaders } from "../lib/Utils.js";
-import { cachePayloadValue, getPayloadValue, readCachePayloadValue } from "../lib/PayloadUtils.js";
+import { cachePayloadValue, getPayloadValue, PayloadInfo, readCachePayloadValue } from "../lib/PayloadUtils.js";
import { applyUrlParameters, applyUrlVariables, computeEndpointUri, applyQueryParamStringToObject } from '../lib/UrlUtils.js';
import { SecurityProcessor } from '../lib/SecurityProcessor.js';
import { AmfParameterMixin } from '../lib/AmfParameterMixin.js';
@@ -44,28 +45,7 @@ import { Events } from '../events/Events.js';
import { EventTypes } from '../events/EventTypes.js';
import '../../define/api-authorization-editor.js';
import '../../define/api-server-selector.js';
-
-/** @typedef {import('lit-element').TemplateResult} TemplateResult */
-/** @typedef {import('@advanced-rest-client/events').ApiTypes.ApiType} ApiType */
-/** @typedef {import('@advanced-rest-client/base').Oauth2Credentials} Oauth2Credentials */
-/** @typedef {import('@advanced-rest-client/base').BodyRawEditorElement} BodyRawEditorElement */
-/** @typedef {import('@advanced-rest-client/base').BodyFormdataEditorElement} BodyFormdataEditorElement */
-/** @typedef {import('../helpers/api').ApiEndPoint} ApiEndPoint */
-/** @typedef {import('../helpers/api').ApiOperation} ApiOperation */
-/** @typedef {import('../helpers/api').ApiPayload} ApiPayload */
-/** @typedef {import('../helpers/api').ApiParameter} ApiParameter */
-/** @typedef {import('../helpers/api').ApiServer} ApiServer */
-/** @typedef {import('../helpers/amf').Operation} Operation */
-/** @typedef {import('../helpers/api').ApiScalarShape} ApiScalarShape */
-/** @typedef {import('../helpers/api').ApiScalarNode} ApiScalarNode */
-/** @typedef {import('@anypoint-web-components/awc').AnypointListboxElement} AnypointListbox */
-/** @typedef {import('@anypoint-web-components/awc').AnypointRadioGroupElement} AnypointRadioGroupElement */
-/** @typedef {import('@anypoint-web-components/awc').AnypointInputElement} AnypointInput */
-/** @typedef {import('../elements/ApiAuthorizationEditorElement').default} ApiAuthorizationEditorElement */
-/** @typedef {import('../types').ApiConsoleRequest} ApiConsoleRequest */
-/** @typedef {import('../types').PopulationInfo} PopulationInfo */
-/** @typedef {import('../types').SecuritySelectorListItem} SecuritySelectorListItem */
-/** @typedef {import('../types').OperationParameter} OperationParameter */
+import { AbortRequestEventDetail, ApiConsoleRequest, OperationParameter, PopulationInfo, SecuritySelectorListItem } from '../types.js';
export const EventCategory = 'API Request editor';
@@ -142,144 +122,164 @@ export const processDebounce = Symbol('processDebounce');
export const authorizationChangeHandler = Symbol('authorizationChangeHandler');
export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTargetMixin(LitElement)) {
- get styles() {
+ static get styles(): CSSResult[] {
return [
elementStyles,
];
}
- static get properties() {
- return {
- /**
- * The currently selected media type for the payloads.
- */
- mimeType: { type: String, reflect: true, },
- /**
- * The domain id (AMF's id) of an API operation.
- */
- domainId: { type: String },
- /**
- * When set it renders a label with the computed URL.
- */
- urlLabel: { type: Boolean },
- /**
- * When set it renders the URL input above the URL parameters.
- */
- urlEditor: { type: Boolean },
- /**
- * A base URI for the API. To be set if RAML spec is missing `baseUri`
- * declaration and this produces invalid URL input. This information
- * is passed to the URL editor that prefixes the URL with `baseUri` value
- * if passed URL is a relative URL.
- */
- baseUri: { type: String },
- /**
- * If set it computes `hasOptional` property and shows checkbox in the
- * form to show / hide optional properties.
- */
- allowHideOptional: { type: Boolean },
- /**
- * When set, renders "add custom" item button.
- * If the element is to be used without AMF model this should always
- * be enabled. Otherwise users won't be able to add a parameter.
- */
- allowCustom: { type: Boolean },
- /**
- * Enables Anypoint platform styles.
- */
- anypoint: { type: Boolean, reflect: true },
- /**
- * Enables Material Design outlined style
- */
- outlined: { type: Boolean },
- /**
- * OAuth2 redirect URI.
- * This value **must** be set in order for OAuth 1/2 to work properly.
- */
- redirectUri: { type: String },
- /**
- * Final request URL including settings like `baseUri`, AMF
- * model settings and user provided parameters.
- */
- url: { type: String },
- /**
- * Holds the value of the currently selected server
- * Data type: URI
- */
- serverValue: { type: String },
- /**
- * Holds the type of the currently selected server
- * Values: `server` | `uri` | `custom`
- */
- serverType: { type: String },
- /**
- * Optional property to set
- * If true, the server selector is not rendered
- */
- noServerSelector: { type: Boolean },
- /**
- * Optional property to set
- * If true, the server selector custom base URI option is rendered
- */
- allowCustomBaseUri: { type: Boolean },
- /**
- * List of credentials source
- */
- credentialsSource: { type: Array },
- /**
- * The index of the selected security definition to apply.
- */
- selectedSecurity: { type: Number },
- /**
- * When set it applies the authorization values to the request dispatched
- * with the API request event.
- * If possible, it applies the authorization values to query parameter or headers
- * depending on the configuration.
- *
- * When the values arr applied to the request the authorization config is kept in the
- * request object, but its `enabled` state is always `false`, meaning other potential
- * processors should ignore this values.
- *
- * If this property is not set then the application hosting this component should
- * process the authorization data and apply them to the request.
- */
- applyAuthorization: { type: Boolean },
- /**
- * By default the element stores user input in a map that is associated with the specific
- * instance of this element. This way the element can be used multiple times in the same document.
- * However, this way parameter values generated by the generators or entered by the user won't
- * get populated in different operations.
- *
- * By setting this value the element prefers a global cache for values. Once the user enter
- * a value it is registered in the global cache and restored when the same parameter is used again.
- *
- * Do not use this option when the element is embedded multiple times in the page. It will result
- * in generating request data from the cache and not what's in the form inputs and these may not be in sync.
- *
- * These values are stored in memory only. Listen to the `change` event to learn that something changed.
- */
- globalCache: { type: Boolean, reflect: true },
- /**
- * Optional. The parent endpoint id. When set it uses this value to query for the endpoint
- * instead of querying for a parent through the operation id.
- * Also, when `endpoint` is set and the `endpointId` match then it ignores querying for
- * the endpoint.
- */
- endpointId: { type: String },
- };
- }
+ /**
+ * The currently selected media type for the payloads.
+ * @attribute
+ */
+ @property({ type: String, reflect: true, }) mimeType?: string;
/**
- * @returns {string} The domain id (AMF id) of the rendered operation.
+ * When set it renders a label with the computed URL.
+ * @attribute
*/
- get domainId() {
- return this[domainIdValue];
- }
+ @property({ type: Boolean, reflect: true }) urlLabel?: boolean;
+
+ /**
+ * When set it renders the URL input above the URL parameters.
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true }) urlEditor?: boolean;
+
+ /**
+ * If set it computes `hasOptional` property and shows checkbox in the
+ * form to show / hide optional properties.
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true }) allowHideOptional?: boolean;
+
+ /**
+ * When set, renders "add custom" item button.
+ * If the element is to be used without AMF model this should always
+ * be enabled. Otherwise users won't be able to add a parameter.
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true }) allowCustom?: boolean;
+
+ /**
+ * Enables Anypoint platform styles.
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true }) anypoint?: boolean;
/**
- * @param {string} value The domain id (AMF id) of the rendered operation.
+ * Enables Material Design outlined style
+ * @attribute
*/
- set domainId(value) {
+ @property({ type: Boolean, reflect: true }) outlined?: boolean;
+
+ /**
+ * OAuth2 redirect URI.
+ * This value **must** be set in order for OAuth 1/2 to work properly.
+ * @attribute
+ */
+ @property({ type: String }) redirectUri?: string;
+
+ /**
+ * Final request URL including settings like `baseUri`, AMF
+ * model settings and user provided parameters.
+ * @attribute
+ */
+ @property({ type: String }) url?: string;
+
+ /**
+ * Holds the value of the currently selected server
+ * Data type: URI
+ * @attribute
+ */
+ @property({ type: String }) serverValue?: string;
+
+ /**
+ * Holds the type of the currently selected server
+ * Values: `server` | `uri` | `custom`
+ * @attribute
+ */
+ @property({ type: String }) serverType?: string;
+
+ /**
+ * Optional property to set
+ * If true, the server selector is not rendered
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true }) noServerSelector?: boolean;
+
+ /**
+ * Optional property to set
+ * If true, the server selector custom base URI option is rendered
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true }) allowCustomBaseUri?: boolean;
+
+ /**
+ * List of credentials source
+ */
+ @property({ type: Array }) credentialsSource?: Oauth2Credentials[];
+
+ /**
+ * The index of the selected security definition to apply.
+ * @attribute
+ */
+ @property({ type: Number }) selectedSecurity: number;
+
+ /**
+ * When set it applies the authorization values to the request dispatched
+ * with the API request event.
+ * If possible, it applies the authorization values to query parameter or headers
+ * depending on the configuration.
+ *
+ * When the values arr applied to the request the authorization config is kept in the
+ * request object, but its `enabled` state is always `false`, meaning other potential
+ * processors should ignore this values.
+ *
+ * If this property is not set then the application hosting this component should
+ * process the authorization data and apply them to the request.
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true }) applyAuthorization?: boolean;
+
+ /**
+ * By default the element stores user input in a map that is associated with the specific
+ * instance of this element. This way the element can be used multiple times in the same document.
+ * However, this way parameter values generated by the generators or entered by the user won't
+ * get populated in different operations.
+ *
+ * By setting this value the element prefers a global cache for values. Once the user enter
+ * a value it is registered in the global cache and restored when the same parameter is used again.
+ *
+ * Do not use this option when the element is embedded multiple times in the page. It will result
+ * in generating request data from the cache and not what's in the form inputs and these may not be in sync.
+ *
+ * These values are stored in memory only. Listen to the `change` event to learn that something changed.
+ * @attribute
+ */
+ @property({ type: Boolean, reflect: true }) globalCache: boolean;
+
+ /**
+ * Optional. The parent endpoint id. When set it uses this value to query for the endpoint
+ * instead of querying for a parent through the operation id.
+ * Also, when `endpoint` is set and the `endpointId` match then it ignores querying for
+ * the endpoint.
+ * @attribute
+ */
+ @property({ type: String }) endpointId?: string;
+
+ [domainIdValue]: string | undefined;
+
+ /**
+ * The domain id (AMF id) of the rendered operation.
+ * @attribute
+ */
+ @property({ type: String, reflect: true })
+ get domainId(): string | undefined {
+ return this[domainIdValue];
+ }
+
+ set domainId(value: string | undefined) {
const old = this[domainIdValue];
/* istanbul ignore if */
if (old === value) {
@@ -290,17 +290,14 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
this[processDebounce]();
}
- /**
- * @returns {ApiEndPoint|undefined}
- */
- get endpoint() {
+ [endpointValue]: ApiDefinitions.IApiEndPoint | undefined;
+
+
+ get endpoint(): ApiDefinitions.IApiEndPoint | undefined {
return this[endpointValue];
}
- /**
- * @param {ApiEndPoint} value
- */
- set endpoint(value) {
+ set endpoint(value: ApiDefinitions.IApiEndPoint | undefined) {
const old = this[endpointValue];
if (old === value) {
return;
@@ -312,9 +309,9 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
}
/**
- * @returns {string} The HTTP method name.
+ * The HTTP method name.
*/
- get httpMethod() {
+ get httpMethod(): string | undefined {
const op = this[operationValue];
if (!op) {
return undefined;
@@ -322,31 +319,38 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
return op.method;
}
+ [loadingRequestValue]: boolean | undefined;
+
/**
- * @returns {boolean}
+ * A flag set when the request is being made.
*/
- get loadingRequest() {
+ get loadingRequest(): boolean | undefined {
return this[loadingRequestValue];
}
+ [requestIdValue]: string | undefined;
+
/**
- * @returns {string}
+ * Generated request ID when the request is sent. This value is reported in send and abort events
*/
- get requestId() {
+ get requestId(): string | undefined {
return this[requestIdValue];
}
+ [baseUriValue]: string | undefined;
+
/**
- * @returns {string}
+ * A base URI for the API. To be set if RAML spec is missing `baseUri`
+ * declaration and this produces invalid URL input. This information
+ * is passed to the URL editor that prefixes the URL with `baseUri` value
+ * if passed URL is a relative URL.
+ * @attribute
*/
- get baseUri() {
+ @property({ type: String }) get baseUri(): string | undefined {
return this[baseUriValue];
}
- /**
- * @param {string} value
- */
- set baseUri(value) {
+ set baseUri(value: string | undefined) {
const old = this[baseUriValue];
if (old === value) {
return;
@@ -356,17 +360,18 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
this.requestUpdate('baseUri', old);
}
+ [serversValue]: ApiDefinitions.IApiServer[] | undefined;
+
/**
- * @returns {ApiServer[]|undefined} The computed list of servers.
+ * The computed list of servers.
*/
- get servers() {
+ get servers(): ApiDefinitions.IApiServer[] | undefined {
return this[serversValue];
}
- /**
- * @returns {ApiServer}
- */
- get server() {
+ [serverLocalValue]: ApiDefinitions.IApiServer | undefined;
+
+ get server(): ApiDefinitions.IApiServer | undefined {
return this[serverLocalValue];
}
@@ -374,30 +379,36 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
* This is the final computed value for the baseUri to propagate downwards
* If baseUri is defined, return baseUri
* Else, return the selectedServerValue if serverType is not `server`
- * @returns {string}
*/
- get effectiveBaseUri() {
+ get effectiveBaseUri(): string {
if (this.baseUri) {
return this.baseUri;
}
if (this.serverType !== 'server') {
- return this.serverValue;
+ return this.serverValue as string;
}
return '';
}
/**
- * @return {boolean} True when there are not enough servers to render the selector
+ * @return True when there are not enough servers to render the selector
*/
- get serverSelectorHidden() {
- const { serversCount = 0, noServerSelector, allowCustomBaseUri } = this;
+ get serverSelectorHidden(): boolean {
+ const { serversCount = 0, noServerSelector = false, allowCustomBaseUri } = this;
return noServerSelector || (!allowCustomBaseUri && serversCount < 2);
}
+ /**
+ * The list of security list items to render.
+ * An operation may have multiple security definition in an or/and fashion.
+ * This allows to render the selector to pick the current security.
+ */
+ [securityList]: SecuritySelectorListItem[] | undefined;
+
/**
- * @returns {SecuritySelectorListItem[]|undefined} The security requirement for the operation or undefined.
+ * The security requirement for the operation or undefined.
*/
- get security() {
+ get security(): SecuritySelectorListItem[] | undefined {
const items = this[securityList];
if (Array.isArray(items) && items.length) {
return items;
@@ -406,16 +417,15 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
}
/**
- * @returns {ApiPayload|undefined} The currently rendered payload, if any.
+ * The currently rendered payload, if any.
*/
- get payload() {
+ get payload(): ApiDefinitions.IApiPayload | undefined {
const { payloads } = this;
if (!payloads) {
return undefined;
}
const { mimeType } = this;
- /** @type ApiPayload */
- let payload;
+ let payload: ApiDefinitions.IApiPayload | undefined;
if (mimeType) {
payload = payloads.find(i => i.mediaType === mimeType);
}
@@ -426,9 +436,9 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
}
/**
- * @returns {ApiPayload[]|undefined} The list of all possible payloads for this operation.
+ * The list of all possible payloads for this operation.
*/
- get payloads() {
+ get payloads(): ApiDefinitions.IApiPayload[] | undefined {
const operation = this[operationValue];
if (!operation) {
return undefined;
@@ -447,41 +457,66 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* @returns {string|undefined} API defined base URI (current server + the endpoint)
*/
- get apiBaseUri() {
- const endpoint = /** @type ApiEndPoint */ (this[endpointValue]);
- const server = /** @type ApiServer */ (this[serverLocalValue]);
+ get apiBaseUri(): string | undefined {
+ const endpoint = this[endpointValue];
+ const server = this[serverLocalValue];
if (!server || !endpoint) {
return undefined;
}
- const { path='' } = endpoint;
- let { url='' } = server;
+ const { path = '' } = endpoint;
+ let { url = '' } = server;
if (url.endsWith('/')) {
url = url.substr(0, url.length - 1);
}
return `${url}${path}`;
}
+ [urlInvalidValue]?: boolean;
+
/**
- * @returns {boolean} True when the URL input is invalid.
+ * True when the URL input is invalid.
*/
- get urlInvalid() {
+ get urlInvalid(): boolean | undefined {
return this[urlInvalidValue];
}
+ [protocolsValue]: string[] | undefined;
+
/**
- * @returns {string[]|undefined} The API's protocols.
+ * The API's protocols.
*/
- get protocols() {
+ get protocols(): string[] | undefined {
return this[protocolsValue];
}
+ [versionValue]: string | undefined;
+
/**
- * @returns {string|undefined} The API's version.
+ * The API's version.
*/
- get version() {
+ get version(): string | undefined {
return this[versionValue];
}
+ queryDebouncerTimeout: number;
+
+ /**
+ * Set when the selection change, this is a JS object created form the
+ * supportedOperation definition of the AMF graph.
+ */
+ [operationValue]?: ApiDefinitions.IApiOperation;
+
+ /**
+ * The list of parameter groups that are opened when `allowHideOptional` is set.
+ */
+ openedOptional: string[];
+
+ [debounceValue]: any;
+
+ [urlSearchRegexpValue]: RegExp | undefined;
+
+ serversCount?: number;
+
/**
* @constructor
*/
@@ -496,90 +531,27 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
this[authRedirectChangedHandler] = this[authRedirectChangedHandler].bind(this);
this[populateAnnotatedFieldsHandler] = this[populateAnnotatedFieldsHandler].bind(this);
this[internalSendHandler] = this[internalSendHandler].bind(this);
- /** @type boolean */
- this.urlLabel = undefined;
- /** @type boolean */
- this.urlEditor = undefined;
- /** @type boolean */
- this.outlined = undefined;
- /** @type boolean */
- this.anypoint = undefined;
- /** @type boolean */
- this.noServerSelector = undefined;
- /** @type boolean */
- this.allowCustom = undefined;
- /** @type boolean */
- this.allowHideOptional = undefined;
- /** @type boolean */
- this.allowCustomBaseUri = undefined;
- /** @type Oauth2Credentials[] */
- this.credentialsSource = undefined;
this.selectedSecurity = 0;
-
- /** @type string */
- this.url = undefined;
- /** @type string */
- this.baseUri = undefined;
- /**
- * Set when the selection change, this is a JS object created form the
- * supportedOperation definition of the AMF graph.
- * @type {ApiOperation}
- */
- this[operationValue] = undefined;
- /** @type ApiEndPoint */
- this[endpointValue] = undefined;
- /**
- * The list of security list items to render.
- * An operation may have multiple security definition in an or/and fashion.
- * This allows to render the selector to pick the current security.
- * @type {SecuritySelectorListItem[]}
- */
- this[securityList] = undefined;
- /** @type ApiServer[] */
- this[serversValue] = undefined;
- /** @type ApiServer */
- this[serverLocalValue] = undefined;
- /** @type boolean */
- this.applyAuthorization = undefined;
- /** @type boolean */
- this.globalCache = undefined;
- /** @type string */
- this.mimeType = undefined;
+ this.openedOptional = [];
+ this.globalCache = false;
+
// for the AmfParameterMixin
this.target = this;
- /**
- * Flag set when the request is being made.
- * @type {boolean}
- */
- this[loadingRequestValue] = undefined;
- /**
- * Generated request ID when the request is sent. This value is reported
- * in send and abort events
- * @type {string}
- */
- this[requestIdValue] = undefined;
- /**
- * The list of parameter groups that are opened when `allowHideOptional` is set.
- * @type {string[]}
- */
- this.openedOptional = [];
- /** @type {string} */
- this.endpointId = undefined;
InputCache.registerLocal(this);
this[graphChangeHandler] = this[graphChangeHandler].bind(this);
}
// for the AmfParameterMixin
- notifyChange() {
+ notifyChange(): void {
this.dispatchEvent(new Event('change'));
}
- connectedCallback() {
+ connectedCallback(): void {
super.connectedCallback();
this[processDebounce]();
}
- disconnectedCallback() {
+ disconnectedCallback(): void {
super.disconnectedCallback();
if (this[debounceValue]) {
clearTimeout(this[debounceValue]);
@@ -587,32 +559,26 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
}
}
- /**
- * @param {EventTarget} node
- */
- _attachListeners(node) {
+ _attachListeners(node: EventTarget): void {
node.addEventListener(EventTypes.Store.graphChange, this[graphChangeHandler]);
- node.addEventListener(EventTypes.Request.apiResponse, this[responseHandler]);
- node.addEventListener(EventTypes.Request.apiResponseLegacy, this[responseHandler]);
- node.addEventListener(EventTypes.Request.redirectUriChange, this[authRedirectChangedHandler]);
- node.addEventListener(EventTypes.Request.redirectUriChangeLegacy, this[authRedirectChangedHandler]);
- node.addEventListener(EventTypes.Request.populateAnnotatedFields, this[populateAnnotatedFieldsHandler]);
- node.addEventListener(EventTypes.Request.populateAnnotatedFieldsLegacy, this[populateAnnotatedFieldsHandler]);
+ node.addEventListener(EventTypes.Request.apiResponse, this[responseHandler] as EventListener);
+ node.addEventListener(EventTypes.Request.apiResponseLegacy, this[responseHandler] as EventListener);
+ node.addEventListener(EventTypes.Request.redirectUriChange, this[authRedirectChangedHandler] as EventListener);
+ node.addEventListener(EventTypes.Request.redirectUriChangeLegacy, this[authRedirectChangedHandler] as EventListener);
+ node.addEventListener(EventTypes.Request.populateAnnotatedFields, this[populateAnnotatedFieldsHandler] as EventListener);
+ node.addEventListener(EventTypes.Request.populateAnnotatedFieldsLegacy, this[populateAnnotatedFieldsHandler] as EventListener);
this.addEventListener(RequestEventTypes.send, this[internalSendHandler]);
super._attachListeners(node);
}
- /**
- * @param {EventTarget} node
- */
- _detachListeners(node) {
+ _detachListeners(node: EventTarget): void {
node.removeEventListener(EventTypes.Store.graphChange, this[graphChangeHandler]);
- node.removeEventListener(EventTypes.Request.apiResponse, this[responseHandler]);
- node.removeEventListener(EventTypes.Request.apiResponseLegacy, this[responseHandler]);
- node.removeEventListener(EventTypes.Request.redirectUriChange, this[authRedirectChangedHandler]);
- node.removeEventListener(EventTypes.Request.redirectUriChangeLegacy, this[authRedirectChangedHandler]);
- node.removeEventListener(EventTypes.Request.populateAnnotatedFields, this[populateAnnotatedFieldsHandler]);
- node.removeEventListener(EventTypes.Request.populateAnnotatedFieldsLegacy, this[populateAnnotatedFieldsHandler]);
+ node.removeEventListener(EventTypes.Request.apiResponse, this[responseHandler] as EventListener);
+ node.removeEventListener(EventTypes.Request.apiResponseLegacy, this[responseHandler] as EventListener);
+ node.removeEventListener(EventTypes.Request.redirectUriChange, this[authRedirectChangedHandler] as EventListener);
+ node.removeEventListener(EventTypes.Request.redirectUriChangeLegacy, this[authRedirectChangedHandler] as EventListener);
+ node.removeEventListener(EventTypes.Request.populateAnnotatedFields, this[populateAnnotatedFieldsHandler] as EventListener);
+ node.removeEventListener(EventTypes.Request.populateAnnotatedFieldsLegacy, this[populateAnnotatedFieldsHandler] as EventListener);
this.removeEventListener(RequestEventTypes.send, this[internalSendHandler]);
super._detachListeners(node);
}
@@ -620,14 +586,14 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Handler for the event dispatched by the store when the graph model change.
*/
- [graphChangeHandler]() {
+ [graphChangeHandler](): void {
this[processDebounce]()
}
/**
* Calls the `queryGraph()` function in a debouncer.
*/
- [processDebounce]() {
+ [processDebounce](): void {
if (this[debounceValue]) {
clearTimeout(this[debounceValue]);
}
@@ -640,7 +606,7 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Reads the URL data from the ApiUrlDataModel library and sets local variables.
*/
- readUrlData() {
+ readUrlData(): void {
this[updateServerParameters]();
this[orderPathParameters]()
this[computeUrlValue]();
@@ -649,7 +615,7 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* It makes sure that the path parameters are rendered in order (server, endpoint) and in order of occurrence in the URL.
*/
- [orderPathParameters]() {
+ [orderPathParameters](): void {
const params = this[getOrderedPathParams]();
if (!params || !params.length) {
return;
@@ -660,14 +626,13 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* A function to be overwritten by child classes to execute an action when a parameter has changed.
- * @param {string} key
*/
- paramChanged(key) {
+ paramChanged(key: string): void {
this[computeUrlValue]();
this[validateUrl]();
const param = this.parametersValue.find(p => p.paramId === key);
if (param && param.binding === 'header' && (param.parameter.name || '').toLocaleLowerCase() === 'content-type') {
- const value = InputCache.get(this, param.paramId, this.globalCache);
+ const value = InputCache.get(this, param.paramId, this.globalCache) as string;
this.mimeType = value;
}
}
@@ -675,13 +640,13 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Computes the URL value for the current serves, selected server, and endpoint's path.
*/
- [computeUrlValue]() {
+ [computeUrlValue](): void {
const { effectiveBaseUri, server, protocols, version } = this;
const endpoint = this[endpointValue];
const result = computeEndpointUri({
- baseUri: effectiveBaseUri,
- server,
- endpoint,
+ baseUri: effectiveBaseUri,
+ server,
+ endpoint,
protocols,
version,
forceHttpProtocol: true,
@@ -696,23 +661,23 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Checks if the current server has variables and update the parameters array
*/
- [updateServerParameters]() {
+ [updateServerParameters](): void {
const { server } = this;
const source = 'server';
// clears previously set request parameters related to server configuration.
this.parametersValue = this.parametersValue.filter(item => item.source !== source);
- if (!server || ['custom', 'uri'].includes(this.serverType)) {
+ if (!server || ['custom', 'uri'].includes(this.serverType || '')) {
// we don't need to compute server variables for a custom URLs.
return;
}
if (Array.isArray(server.variables) && server.variables.length) {
server.variables.forEach((param) => {
- const item = /** @type OperationParameter */ ({
- binding: param.binding,
+ const item: OperationParameter = {
+ binding: param.binding || '',
paramId: param.id,
parameter: param,
source,
- });
+ };
if (param.schema) {
item.schema = param.schema;
item.schemaId = param.schema.id;
@@ -725,7 +690,7 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Checks if the current endpoint has variables and requests them when needed.
*/
- [updateEndpointParameters]() {
+ [updateEndpointParameters](): void {
const source = 'endpoint';
// clears previously set request parameters related to server configuration.
this.parametersValue = this.parametersValue.filter(item => item.source !== source);
@@ -736,12 +701,12 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
}
if (Array.isArray(endpoint.parameters) && endpoint.parameters.length) {
endpoint.parameters.forEach((param) => {
- const item = /** @type OperationParameter */ ({
- binding: param.binding,
+ const item: OperationParameter = {
+ binding: param.binding || '',
paramId: param.id,
parameter: param,
source,
- });
+ };
if (param.schema) {
item.schema = param.schema;
item.schemaId = param.schema.id;
@@ -751,16 +716,16 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
}
}
- reset() {
+ reset(): void {
this[securityList] = undefined;
this.mimeType = undefined;
- this.parametersValue = /** @type {OperationParameter[]} */ ([]);
+ this.parametersValue = [];
}
/**
* Processes the selection of the domain id for an operation.
*/
- async processGraph() {
+ async processGraph(): Promise {
await this[queryEndpoint]();
await this[queryOperation]();
await this[queryServers]();
@@ -776,9 +741,8 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Queries the store for the operation data, when needed.
- * @returns {Promise}
*/
- async [queryOperation]() {
+ async [queryOperation](): Promise {
const { domainId } = this;
if (!domainId || domainId === 'undefined') {
// this[operationValue] = undefined;
@@ -793,8 +757,9 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
const info = await Events.Operation.get(this, domainId, endpointId);
this[operationValue] = info;
} catch (e) {
- Events.Telemetry.exception(this, e.message, false);
- Events.Reporting.error(this, e, `Unable to query for API operation data: ${e.message}`, this.localName);
+ const ex = e as Error;
+ Events.Telemetry.exception(this, ex.message, false);
+ Events.Reporting.error(this, ex, `Unable to query for API operation data: ${ex.message}`, this.localName);
}
}
@@ -802,7 +767,7 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
* Queries the store for the endpoint data.
* @returns {Promise}
*/
- async [queryEndpoint]() {
+ async [queryEndpoint](): Promise {
const { domainId, endpointId } = this;
if (!domainId || domainId === 'undefined') {
// this[endpointValue] = undefined;
@@ -817,15 +782,16 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
const info = await (endpointId ? Events.Endpoint.get(this, endpointId) : Events.Operation.getParent(this, domainId));
this[endpointValue] = info;
} catch (e) {
- Events.Telemetry.exception(this, e.message, false);
- Events.Reporting.error(this, e, `Unable to query for API endpoint data: ${e.message}`, this.localName);
+ const ex = e as Error;
+ Events.Telemetry.exception(this, ex.message, false);
+ Events.Reporting.error(this, ex, `Unable to query for API endpoint data: ${ex.message}`, this.localName);
}
}
/**
* Queries for the current servers value.
*/
- async [queryServers]() {
+ async [queryServers](): Promise {
const { domainId } = this;
const endpointId = this[endpointValue] && this[endpointValue].id;
try {
@@ -835,44 +801,47 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
});
this[serversValue] = info || undefined;
} catch (e) {
+ const ex = e as Error;
this[serversValue] = undefined;
- Events.Telemetry.exception(this, e.message, false);
- Events.Reporting.error(this, e, `Unable to query for API servers: ${e.message}`, this.localName);
+ Events.Telemetry.exception(this, ex.message, false);
+ Events.Reporting.error(this, ex, `Unable to query for API servers: ${ex.message}`, this.localName);
}
}
/**
* Queries the API store for the API protocols list.
*/
- async [queryProtocols]() {
+ async [queryProtocols](): Promise {
this[protocolsValue] = undefined;
try {
const info = await Events.Api.protocols(this);
this[protocolsValue] = info;
} catch (e) {
- Events.Telemetry.exception(this, e.message, false);
- Events.Reporting.error(this, e, `Unable to query for API protocols list: ${e.message}`, this.localName);
+ const ex = e as Error;
+ Events.Telemetry.exception(this, ex.message, false);
+ Events.Reporting.error(this, ex, `Unable to query for API protocols list: ${ex.message}`, this.localName);
}
}
/**
* Queries the API store for the API version value.
*/
- async [queryVersion]() {
+ async [queryVersion](): Promise {
this[versionValue] = undefined;
try {
const info = await Events.Api.version(this);
this[versionValue] = info;
} catch (e) {
- Events.Telemetry.exception(this, e.message, false);
- Events.Reporting.error(this, e, `Unable to query for API version value: ${e.message}`, this.localName);
+ const ex = e as Error;
+ Events.Telemetry.exception(this, ex.message, false);
+ Events.Reporting.error(this, ex, `Unable to query for API version value: ${ex.message}`, this.localName);
}
}
/**
* Searches for the current operation endpoint and sets variables from the endpoint definition.
*/
- [processEndpoint]() {
+ [processEndpoint](): void {
this[updateEndpointParameters]();
this[computeUrlRegexp]();
}
@@ -880,7 +849,7 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Collects operations input parameters into a single object.
*/
- [processOperation]() {
+ [processOperation](): void {
const source = 'request';
const operation = this[operationValue];
// clears previously set request parameters (query, path, headers)
@@ -892,7 +861,7 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
if (!request) {
return;
}
- const uri = [];
+ const uri: ApiDefinitions.IApiParameter[] = [];
if (Array.isArray(request.uriParameters)) {
// OAS has this weird thing where you can define URI parameters on the endpoint and the operation.
// this eliminates the duplicates and merges the schemas
@@ -918,7 +887,7 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Processes security information for the UI.
*/
- [processSecurity]() {
+ [processSecurity](): void {
const operation = this[operationValue];
if (!operation) {
return;
@@ -931,7 +900,7 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Makes sure the correct mime type is selected for the current selection.
*/
- [processPayload]() {
+ [processPayload](): void {
const operation = this[operationValue];
if (!operation) {
return;
@@ -940,7 +909,7 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
if (!request) {
return;
}
- const { payloads=[] } = request;
+ const { payloads = [] } = request;
if (!payloads.length) {
return;
}
@@ -962,17 +931,15 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Appends a list of parameters to the list of rendered parameters
- * @param {ApiParameter[]} list
- * @param {string} source
*/
- [appendToParams](list, source) {
+ [appendToParams](list: ApiDefinitions.IApiParameter[], source: string): void {
const params = this.parametersValue;
if (Array.isArray(list)) {
list.forEach((param) => {
params.push({
paramId: param.id,
parameter: param,
- binding: param.binding,
+ binding: param.binding || '',
source,
schema: param.schema,
schemaId: param.schema && param.schema.id ? param.schema.id : undefined,
@@ -983,10 +950,9 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* A handler for the change event dispatched by the `raw` editor.
- * @param {Event} e
*/
- [rawBodyChangeHandler](e) {
- const editor = /** @type BodyRawEditorElement */ (e.target);
+ [rawBodyChangeHandler](e: Event): void {
+ const editor = e.target as BodyRawEditorElement;
const { value, dataset } = editor;
const { payloadId } = dataset;
if (!payloadId) {
@@ -999,10 +965,9 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
* A handler for the change event dispatched by the
* `urlEncode` editor.
* Updated the local value, model, and notifies the change.
- * @param {Event} e
*/
- [modelBodyEditorChangeHandler](e) {
- const editor = /** @type BodyFormdataEditorElement */ (e.target);
+ [modelBodyEditorChangeHandler](e: Event): void {
+ const editor = e.target as BodyFormdataEditorElement;
const { value, model, dataset } = editor;
const { payloadId } = dataset;
if (!payloadId) {
@@ -1011,11 +976,8 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
cachePayloadValue(payloadId, value, model);
}
- /**
- * @param {Event} e
- */
- [authSelectorHandler](e) {
- const list = /** @type AnypointListbox */ (e.target);
+ [authSelectorHandler](e: Event): void {
+ const list = e.target as AnypointListboxElement;
const { selected } = list;
this.selectedSecurity = Number(selected);
this.requestUpdate();
@@ -1026,7 +988,7 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
* Depending on authorization validity it either sends the
* request or forces authorization and sends the request.
*/
- [sendHandler]() {
+ [sendHandler](): void {
this.execute();
}
@@ -1039,14 +1001,20 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
* but provided all the data. This function should check for this
* condition and call authorization function automatically.
*/
- async authAndExecute() {
- const panel = this.shadowRoot.querySelector('api-authorization-editor');
- if (panel) {
- await panel.authorize();
- const valid = panel.validate();
- if (valid) {
- this.execute();
- }
+ async authAndExecute(): Promise {
+ const { shadowRoot } = this;
+ if (!shadowRoot) {
+ throw new Error(`Invalid state. The element is not initialized.`);
+ }
+
+ const panel = shadowRoot.querySelector('api-authorization-editor');
+ if (!panel) {
+ throw new Error(`Invalid state. The authorization editor element was removed from the DOM.`);
+ }
+ await panel.authorize();
+ const valid = panel.validate();
+ if (valid) {
+ this.execute();
}
}
@@ -1061,9 +1029,9 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
* custom event handled by this element to reset state. This is also
* handled by `xhr-simple-request` component.
*/
- execute() {
+ execute(): void {
const request = this.serialize();
- const uuid = v4();
+ const uuid = uuidV4();
this[requestIdValue] = uuid;
request.id = uuid;
this[loadingRequestValue] = true;
@@ -1082,10 +1050,14 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
* Calling this method before sending request may have unexpected
* behavior because `requestId` is only set with `execute()` method.
*/
- abort() {
- const detail = {
- url: this.url,
- id: this.requestId,
+ abort(): void {
+ const { url, requestId } = this;
+ if (!url || !requestId) {
+ return;
+ }
+ const detail: AbortRequestEventDetail = {
+ url,
+ id: requestId,
};
Events.Request.abortApiRequest(this, detail);
Events.Request.abortApiRequestLegacy(this, detail);
@@ -1102,22 +1074,20 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Event handler for abort click.
*/
- [abortHandler]() {
+ [abortHandler](): void {
this.abort();
}
/**
* Serializes the state of the request editor into the `ApiConsoleRequest` object.
- *
- * @return {ApiConsoleRequest}
*/
- serialize() {
+ serialize(): ApiConsoleRequest {
const op = this[operationValue];
if (!op) {
throw new Error(`No API operation defined on the editor`);
}
const method = (op.method || 'get').toUpperCase();
- const params = [];
+ const params: ApiDefinitions.IApiParameter[] = [];
this.parametersValue.forEach((item) => {
const { parameter, enabled } = item;
if (enabled === false) {
@@ -1127,23 +1097,22 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
});
const report = AmfInputParser.reportRequestInputs(params, InputCache.getStore(this, this.globalCache), this.nilValues);
const serverUrl = computeEndpointUri({
- baseUri: this.effectiveBaseUri,
- server: this.server,
- endpoint: this[endpointValue],
+ baseUri: this.effectiveBaseUri,
+ server: this.server,
+ endpoint: this[endpointValue],
protocols: this.protocols,
forceHttpProtocol: true,
});
let url = applyUrlVariables(serverUrl, report.path, true);
url = applyUrlParameters(url, report.query, true);
const headers = generateHeaders(report.header);
- const request = /** @type ApiConsoleRequest */ ({
+ const request: ApiConsoleRequest = {
method,
url,
headers,
- });
+ };
if (!['GET', 'HEAD'].includes(method)) {
- /** @type any */
- let body;
+ let body: any;
const { payload } = this;
if (payload) {
const info = readCachePayloadValue(payload.id);
@@ -1152,15 +1121,17 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
}
}
if (body instanceof FormData) {
- request.headers = /** @type string */ (HeadersParser.replace(request.headers, 'content-type', null));
+ const parser = new Headers(request.headers);
+ parser.delete('content-type');
+ request.headers = parser.toString();
} else if (payload) {
- request.headers = ensureContentType(request.headers, payload.mediaType);
+ request.headers = ensureContentType(request.headers || '', payload.mediaType);
}
if (typeof body !== 'undefined') {
request.payload = body;
}
}
- const authElement = this.shadowRoot.querySelector('api-authorization-editor');
+ const authElement = this.shadowRoot?.querySelector('api-authorization-editor');
if (authElement) {
const auth = authElement.serialize();
request.authorization = auth;
@@ -1174,10 +1145,8 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Handler for the `api-response` custom event.
* Clears the loading state.
- *
- * @param {CustomEvent} e
*/
- [responseHandler](e) {
+ [responseHandler](e: CustomEvent): void {
if (!e.detail || (e.detail.id !== this.requestId)) {
return;
}
@@ -1188,25 +1157,23 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Handler for the `oauth2-redirect-uri-changed` custom event. Changes
* the `redirectUri` property.
- * @param {CustomEvent} e
*/
- [authRedirectChangedHandler](e) {
+ [authRedirectChangedHandler](e: CustomEvent): void {
this.redirectUri = e.detail.value;
}
/**
* Handle event for populating annotated fields in the editor.
- * @param {CustomEvent} e
*/
- [populateAnnotatedFieldsHandler](e) {
- const populationInfoArray = /** @type PopulationInfo[] */ (e.detail.values);
- const { parametersValue=[] } = this;
+ [populateAnnotatedFieldsHandler](e: CustomEvent): void {
+ const populationInfoArray: PopulationInfo[] = e.detail.values;
+ const { parametersValue = [] } = this;
const allAnnotated = parametersValue.filter(param => Array.isArray(param.parameter.customDomainProperties) && !!param.parameter.customDomainProperties.length);
let update = false;
populationInfoArray.forEach(({ annotationName, annotationValue, fieldValue }) => {
allAnnotated.forEach((item) => {
const { parameter, paramId } = item;
- const hasAnnotation = (parameter.customDomainProperties || []).some((property) => property.name === annotationName && /** @type ApiScalarNode */ (property.extension).value === annotationValue);
+ const hasAnnotation = (parameter.customDomainProperties || []).some((prop) => prop.name === annotationName && (prop.extension as AmfShapes.IApiScalarNode).value === annotationValue);
if (!hasAnnotation) {
return;
}
@@ -1223,10 +1190,10 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Computes a current server value for selection made in the server selector.
*/
- [updateServer]() {
- const { serverValue, serverType, servers=[] } = this;
+ [updateServer](): void {
+ const { serverValue, serverType, servers = [] } = this;
if (serverType !== 'server') {
- this[serverLocalValue] = /** @type ApiServer */ (undefined);
+ this[serverLocalValue] = undefined;
} else {
this[serverLocalValue] = servers.find(server => server.url === serverValue);
}
@@ -1236,10 +1203,9 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Handler for the change dispatched from the server selector.
- * @param {CustomEvent} e
*/
- [serverCountHandler](e) {
- const { value } = e.detail;
+ [serverCountHandler](e: CustomEvent): void {
+ const { value=0 } = e.detail;
this.serversCount = value;
this[updateServer]();
this.requestUpdate();
@@ -1247,9 +1213,8 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Handler for the change dispatched from the server selector.
- * @param {CustomEvent} e
*/
- [serverHandler](e) {
+ [serverHandler](e: CustomEvent): void {
const { value, type } = e.detail;
this.serverType = type;
this.serverValue = value;
@@ -1262,12 +1227,12 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
* and set the `[urlSearchRegexpValue]` value.
* This should be computed only when a server and en endpoint change.
*/
- [computeUrlRegexp]() {
+ [computeUrlRegexp](): void {
const { effectiveBaseUri } = this;
let value;
if (effectiveBaseUri) {
value = computeEndpointUri({
- baseUri: effectiveBaseUri,
+ baseUri: effectiveBaseUri,
endpoint: this[endpointValue],
forceHttpProtocol: true,
});
@@ -1285,11 +1250,8 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
}
}
- /**
- * @param {Event} e
- */
- [mediaTypeSelectHandler](e) {
- const select = /** @type AnypointRadioGroupElement */ (e.target);
+ [mediaTypeSelectHandler](e: Event): void {
+ const select = e.target as AnypointRadioGroupElement;
const { selected } = select;
const mime = String(selected);
this.mimeType = mime;
@@ -1301,10 +1263,9 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Toggles optional parameter groups.
- * @param {Event} e
*/
- async [optionalToggleHandler](e) {
- const node = /** @type HTMLElement */ (e.target);
+ async [optionalToggleHandler](e: Event): Promise {
+ const node = e.target as HTMLElement;
const { target } = node.dataset;
if (!target) {
return;
@@ -1318,23 +1279,23 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
} else {
this.openedOptional.push(target);
}
- await this.requestUpdate();
+ this.requestUpdate();
+ await this.updateComplete;
this.dispatchEvent(new Event('resize', { bubbles: true, composed: true }));
}
/**
* When enabled it adds a new custom parameter to the request section defined in the source button.
- * @param {Event} e
*/
- [addCustomHandler](e) {
- const button = /** @type HTMLElement */ (e.currentTarget);
+ [addCustomHandler](e: Event): void {
+ const button = e.currentTarget as HTMLElement;
const { type } = button.dataset;
- if (!['query', 'header'].includes(type)) {
+ if (!['query', 'header'].includes(type as string)) {
return;
}
- const id = v4();
- const param = /** @type OperationParameter */ ({
- binding: type,
+ const id = uuidV4();
+ const param: OperationParameter = {
+ binding: type || '',
source: 'custom',
paramId: id,
parameter: {
@@ -1342,8 +1303,12 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
required: true,
binding: type,
name: '',
+ examples: [],
+ payloads: [],
+ customDomainProperties: [],
+ types: [],
},
- });
+ };
this.parametersValue.push(param);
this.requestUpdate();
}
@@ -1351,10 +1316,10 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Updates path/query model from user input.
*
- * @param {Event} e The change event
+ * @param e The change event
*/
- [urlEditorChangeHandler](e) {
- const { value } = /** @type {HTMLInputElement} */ (e.target);
+ [urlEditorChangeHandler](e: Event): void {
+ const { value } = e.target as HTMLInputElement;
let matches;
const uriRegexp = this[urlSearchRegexpValue];
// parameters must be in order from server to the endpoint
@@ -1369,7 +1334,7 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
}
const matchesNew = value.match(/[^&?]*?=[^&?]*/g);
if (matchesNew) {
- const params = /** @type Record */ ({});
+ const params: Record = {};
matchesNew.forEach((item) => applyQueryParamStringToObject(item, params));
const qpChanged = this[applyQueryParamsValues](params);
if (!changed) {
@@ -1385,16 +1350,16 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Sets the value of `[urlInvalidValue]` and therefore `urlInvalid` properties.
*/
- [validateUrl]() {
+ [validateUrl](): void {
this[urlInvalidValue] = !this[readUrlValidity]();
this.requestUpdate();
}
/**
* Validates the current URL value.
- * @returns {boolean} True when the current URL is a valid URL.
+ * @returns True when the current URL is a valid URL.
*/
- [readUrlValidity]() {
+ [readUrlValidity](): boolean {
const { url } = this;
if (!url) {
return false;
@@ -1405,24 +1370,27 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
if (url.indexOf('{') !== -1 && url.indexOf('}') !== -1) {
return false;
}
- const inputElement = /** @type AnypointInput */ (this.shadowRoot.querySelector('.url-input'));
+ const { shadowRoot } = this;
+ if (!shadowRoot) {
+ return true;
+ }
+ const inputElement = shadowRoot.querySelector('.url-input') as AnypointInputElement;
if (inputElement) {
- return inputElement.validate();
+ return inputElement.checkValidity();
}
return true;
}
/**
* Reads the ordered list of path parameters from the server and the endpoint.
- * @returns {OperationParameter[]}
*/
- [getOrderedPathParams]() {
- const result = /** @type OperationParameter[] */ [];
+ [getOrderedPathParams](): OperationParameter[] {
+ const result: OperationParameter[] = [];
const { effectiveBaseUri } = this;
let url;
if (effectiveBaseUri) {
url = computeEndpointUri({
- baseUri: effectiveBaseUri,
+ baseUri: effectiveBaseUri,
endpoint: this[endpointValue],
forceHttpProtocol: true,
});
@@ -1451,11 +1419,11 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
* Applies values from the `values` array to the uri parameters which names are in the `names` array.
* Both lists are ordered list of parameters.
*
- * @param {string[]} values Values for the parameters
- * @param {OperationParameter[]} params List of path parameters.
- * @returns {boolean} True when any parameter was changed.
+ * @param values Values for the parameters
+ * @param params List of path parameters.
+ * @returns True when any parameter was changed.
*/
- [applyUriValues](values, params) {
+ [applyUriValues](values: string[], params: OperationParameter[]): boolean {
let changed = false;
for (let i = 0, len = params.length; i < len; i++) {
const value = values[i];
@@ -1475,10 +1443,9 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Applies query parameters values to the render list.
*
- * @param {Record} map
- * @returns {boolean} True when any parameter was changed.
+ * @returns True when any parameter was changed.
*/
- [applyQueryParamsValues](map) {
+ [applyQueryParamsValues](map: Record): boolean {
if (!map) {
return false;
}
@@ -1501,10 +1468,7 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
return changed;
}
- /**
- * @param {Event} e
- */
- [internalSendHandler](e) {
+ [internalSendHandler](e: Event): void {
e.stopPropagation();
this.execute();
}
@@ -1512,13 +1476,12 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* A handler for the change event on the authorization panel.
*/
- [authorizationChangeHandler]() {
+ [authorizationChangeHandler](): void {
this.notifyChange();
}
- render() {
- const { styles } = this;
- return html`
+ render(): TemplateResult {
+ return html`
${this[serverSelectorTemplate]()}
${this[urlLabelTemplate]()}
@@ -1533,9 +1496,9 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
}
/**
- * @return {TemplateResult|string} Template for the request URL label.
+ * @return Template for the request URL label.
*/
- [urlLabelTemplate]() {
+ [urlLabelTemplate](): TemplateResult | string {
const { urlLabel, url } = this;
if (!urlLabel) {
return '';
@@ -1543,7 +1506,7 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
return html`
${url}
`;
}
- [authorizationTemplate]() {
+ [authorizationTemplate](): TemplateResult | string {
const { security } = this;
if (!security) {
return '';
@@ -1567,11 +1530,9 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
}
/**
- * @param {SecuritySelectorListItem[]} security
- * @param {number} selected
- * @returns {TemplateResult} The template for the security drop down selector.
+ * @returns The template for the security drop down selector.
*/
- [authorizationSelectorTemplate](security, selected) {
+ [authorizationSelectorTemplate](security: SecuritySelectorListItem[], selected: number): TemplateResult {
const { anypoint } = this;
return html`
@@ -1625,10 +1585,8 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
/**
* Creates a template for the "abort" button.
- *
- * @return {TemplateResult}
*/
- [abortButtonTemplate]() {
+ [abortButtonTemplate](): TemplateResult {
const { anypoint } = this;
return html`
{
@@ -1708,14 +1662,14 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
path.push(item);
}
});
- const { allowCustom, openedOptional=[] } = this;
+ const { allowCustom, openedOptional = [] } = this;
if (!allowCustom && !qp.length && !path.length) {
return '';
}
const pathOptions = Object.freeze({ required: true });
const queryClasses = {
'query-params': true,
- 'hide-optional': this.allowHideOptional && !openedOptional.includes('query'),
+ 'hide-optional': !!this.allowHideOptional && !openedOptional.includes('query'),
};
return html`
@@ -1733,8 +1687,8 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
`;
}
- [headersTemplate]() {
- const headers = /** @type OperationParameter[] */ ([]);
+ [headersTemplate](): TemplateResult | string {
+ const headers: OperationParameter[] = [];
// NOTE, the "* Required field" has been added after the a11y audit of API Console.
let hasRequired = false;
this.parametersValue.forEach((item) => {
@@ -1745,13 +1699,13 @@ export default class ApiRequestEditorElement extends AmfParameterMixin(EventsTar
}
}
});
- const { allowCustom, openedOptional=[] } = this;
+ const { allowCustom, openedOptional = [] } = this;
if (!allowCustom && !headers.length) {
return '';
}
const classes = {
'header-params': true,
- 'hide-optional': this.allowHideOptional && !openedOptional.includes('header'),
+ 'hide-optional': !!this.allowHideOptional && !openedOptional.includes('header'),
};
return html`