Jelajahi Sumber

Add types to the ad-hoc plugins

JC Brand 1 tahun lalu
induk
melakukan
7aca70f02d

+ 15 - 25
src/headless/plugins/adhoc/api.js

@@ -1,3 +1,7 @@
+/**
+ * @typedef {import('./utils').AdHocCommand} AdHocCommand
+ * @typedef {import('./utils').AdHocCommandFields} AdHocCommandFields
+ */
 import log from '../../log.js';
 import _converse from '../../shared/_converse.js';
 import api from '../../shared/api/index.js';
@@ -19,7 +23,7 @@ export default {
     adhoc: {
         /**
          * @method api.adhoc.getCommands
-         * @param { String } to_jid
+         * @param {string} to_jid
          */
         async getCommands (to_jid) {
             try {
@@ -37,34 +41,20 @@ export default {
 
         /**
          * @method api.adhoc.fetchCommandForm
+         * @param {string} jid
+         * @param {string} node
+         * @returns {Promise<AdHocCommandFields>}
          */
-        async fetchCommandForm (command) {
-            const node = command.node;
-            const jid = command.jid;
+        async fetchCommandForm (jid, node) {
             const stanza = $iq({
-                'type': 'set',
-                'to': jid
+                type: 'set',
+                to: jid
             }).c('command', {
-                'xmlns': Strophe.NS.ADHOC,
-                'node': node,
-                'action': 'execute'
+                xmlns: Strophe.NS.ADHOC,
+                action: 'execute',
+                node,
             });
-            try {
-                return getCommandFields(await api.sendIQ(stanza), jid);
-
-            } catch (e) {
-                if (e === null) {
-                    log.error(`Error: timeout while trying to execute command for ${jid}`);
-                } else {
-                    log.error(`Error while trying to execute command for ${jid}`);
-                    log.error(e);
-                }
-                const { __ } = _converse;
-                return {
-                    instructions: __('An error occurred while trying to fetch the command form'),
-                    fields: []
-                }
-            }
+            return getCommandFields(await api.sendIQ(stanza), jid);
         },
 
         /**

+ 21 - 0
src/headless/plugins/adhoc/utils.js

@@ -1,19 +1,40 @@
+/**
+ * @typedef {import('lit').TemplateResult} TemplateResult
+ */
 import sizzle from 'sizzle';
 import converse from '../../shared/api/public.js';
 
 const { Strophe, u } = converse.env;
 
+/**
+ * @typedef {Object} AdHocCommand
+ * @property {string} action
+ * @property {string} node
+ * @property {string} sessionid
+ * @property {string} status
+ */
+
 /**
  * @param {Element} stanza
+ * @returns {AdHocCommand[]}
  */
 export function parseForCommands (stanza) {
     const items = sizzle(`query[xmlns="${Strophe.NS.DISCO_ITEMS}"][node="${Strophe.NS.ADHOC}"] item`, stanza);
     return items.map(u.getAttributes);
 }
 
+/**
+ * @typedef {Object} AdHocCommandFields
+ * @property {string} sessionid
+ * @property {string} [instructions]
+ * @property {TemplateResult[]} [fields]
+ * @property {string[]} [actions]
+ */
+
 /**
  * @param {Element} iq
  * @param {string} [jid]
+ * @returns {AdHocCommandFields}
  */
 export function getCommandFields (iq, jid) {
     const cmd_el = sizzle(`command[xmlns="${Strophe.NS.ADHOC}"]`, iq).pop();

+ 12 - 15
src/headless/types/plugins/adhoc/api.d.ts

@@ -2,21 +2,16 @@ declare namespace _default {
     namespace adhoc {
         /**
          * @method api.adhoc.getCommands
-         * @param { String } to_jid
+         * @param {string} to_jid
          */
-        function getCommands(to_jid: string): Promise<any>;
+        function getCommands(to_jid: string): Promise<import("./utils.js").AdHocCommand[]>;
         /**
          * @method api.adhoc.fetchCommandForm
+         * @param {string} jid
+         * @param {string} node
+         * @returns {Promise<AdHocCommandFields>}
          */
-        function fetchCommandForm(command: any): Promise<{
-            sessionid: any;
-            instructions: any;
-            fields: any;
-            actions: any[];
-        } | {
-            instructions: any;
-            fields: any[];
-        }>;
+        function fetchCommandForm(jid: string, node: string): Promise<import("./utils.js").AdHocCommandFields>;
         /**
          * @method api.adhoc.runCommand
          * @param { String } jid
@@ -29,13 +24,15 @@ declare namespace _default {
             [k: string]: string;
         }[]): Promise<{
             note: any;
-            sessionid?: any;
-            instructions?: any;
-            fields?: any;
-            actions?: any[];
+            sessionid?: string;
+            instructions?: string;
+            fields?: import("./utils.js").TemplateResult[];
+            actions?: string[];
             status: any;
         }>;
     }
 }
 export default _default;
+export type AdHocCommand = import('./utils').AdHocCommand;
+export type AdHocCommandFields = import('./utils').AdHocCommandFields;
 //# sourceMappingURL=api.d.ts.map

+ 30 - 6
src/headless/types/plugins/adhoc/utils.d.ts

@@ -1,15 +1,39 @@
+/**
+ * @typedef {Object} AdHocCommand
+ * @property {string} action
+ * @property {string} node
+ * @property {string} sessionid
+ * @property {string} status
+ */
 /**
  * @param {Element} stanza
+ * @returns {AdHocCommand[]}
+ */
+export function parseForCommands(stanza: Element): AdHocCommand[];
+/**
+ * @typedef {Object} AdHocCommandFields
+ * @property {string} sessionid
+ * @property {string} [instructions]
+ * @property {TemplateResult[]} [fields]
+ * @property {string[]} [actions]
  */
-export function parseForCommands(stanza: Element): any;
 /**
  * @param {Element} iq
  * @param {string} [jid]
+ * @returns {AdHocCommandFields}
  */
-export function getCommandFields(iq: Element, jid?: string): {
-    sessionid: any;
-    instructions: any;
-    fields: any;
-    actions: any[];
+export function getCommandFields(iq: Element, jid?: string): AdHocCommandFields;
+export type AdHocCommand = {
+    action: string;
+    node: string;
+    sessionid: string;
+    status: string;
+};
+export type AdHocCommandFields = {
+    sessionid: string;
+    instructions?: string;
+    fields?: TemplateResult[];
+    actions?: string[];
 };
+export type TemplateResult = import('lit').TemplateResult;
 //# sourceMappingURL=utils.d.ts.map

+ 35 - 8
src/plugins/adhoc-views/adhoc-commands.js

@@ -1,3 +1,7 @@
+/**
+ * @typedef {import('@converse/headless/types/plugins/adhoc/utils').AdHocCommand} AdHocCommand
+ * @typedef {import('@converse/headless/types/plugins/adhoc/utils').AdHocCommandFields} AdHocCommandFields
+ */
 import 'shared/autocomplete/index.js';
 import tplAdhoc from './templates/ad-hoc.js';
 import { CustomElement } from 'shared/components/element.js';
@@ -7,6 +11,17 @@ import { getNameAndValue } from 'utils/html.js';
 
 const { Strophe, sizzle } = converse.env;
 
+/**
+ * @typedef {Object} UIProps
+ * @property {string} instructions
+ * @property {string} jid
+ * @property {string} [alert]
+ * @property {'danger'|'primary'} [alert_type]
+ * @property {'cancel'|'complete'|'execute'|'next'|'prev'} name
+ *
+ * @typedef {AdHocCommand & AdHocCommandFields & UIProps} AdHocCommandUIProps
+ */
+
 
 export default class AdHocCommands extends CustomElement {
     static get properties () {
@@ -25,7 +40,7 @@ export default class AdHocCommands extends CustomElement {
         this.view = 'choose-service';
         this.fetching = false;
         this.showform = '';
-        this.commands = [];
+        this.commands = /** @type {AdHocCommandUIProps[]} */([]);
     }
 
     render () {
@@ -61,13 +76,13 @@ export default class AdHocCommands extends CustomElement {
 
         if (supported) {
             try {
-                this.commands = await api.adhoc.getCommands(jid);
+                this.commands = /** @type {AdHocCommandUIProps[]} */(await api.adhoc.getCommands(jid));
                 this.view = 'list-commands';
             } catch (e) {
                 log.error(e);
                 this.alert_type = 'danger';
                 this.alert = __('Sorry, an error occurred while looking for commands on that entity.');
-                this.commands = [];
+                this.commands = /** @type {AdHocCommandUIProps[]} */([]);
                 log.error(e);
                 return;
             }
@@ -81,15 +96,27 @@ export default class AdHocCommands extends CustomElement {
         ev.preventDefault();
         const node = ev.target.getAttribute('data-command-node');
         const cmd = this.commands.filter(c => c.node === node)[0];
+        const { jid } = cmd;
+
         if (this.showform === node) {
             this.showform = '';
             this.requestUpdate();
         } else {
-            const form = await api.adhoc.fetchCommandForm(cmd);
-            cmd.sessionid = form.sessionid;
-            cmd.instructions = form.instructions;
-            cmd.fields = form.fields;
-            cmd.actions = form.actions;
+            try {
+                const form = await api.adhoc.fetchCommandForm(jid, node);
+                cmd.sessionid = form.sessionid;
+                cmd.instructions = form.instructions;
+                cmd.fields = form.fields;
+                cmd.actions = form.actions;
+            } catch (e) {
+                if (e === null) {
+                    log.error(`Error: timeout while trying to execute command for ${jid}`);
+                } else {
+                    log.error(`Error while trying to execute command for ${jid}`);
+                    log.error(e);
+                }
+                cmd.instructions = __('An error occurred while trying to fetch the command form');
+            }
             this.showform = node;
         }
     }

+ 41 - 26
src/plugins/adhoc-views/templates/ad-hoc-command-form.js

@@ -1,43 +1,58 @@
+/**
+ * @typedef {import('../adhoc-commands').default} AdHocCommands
+ * @typedef {import('../adhoc-commands').AdHocCommandUIProps} AdHocCommandUIProps
+ */
+import { html } from 'lit';
 import { __ } from 'i18n';
-import { html } from "lit";
-
 
 const action_map = {
     execute: __('Execute'),
     prev: __('Previous'),
     next: __('Next'),
     complete: __('Complete'),
-}
+};
 
+/**
+ * @param {AdHocCommands} el
+ * @param {AdHocCommandUIProps} command
+ */
 export default (el, command) => {
     const i18n_cancel = __('Cancel');
 
     return html`
-        <span> <!-- Don't remove this <span>,
-                    this is a workaround for a lit bug where a <form> cannot be removed
-                    if it contains an <input> with name "remove" -->
+        <span>
+            <!-- Don't remove this <span>,
+                 this is a workaround for a lit bug where a <form> cannot be removed
+                 if it contains an <input> with name "remove" -->
             <form>
-            ${ command.alert ? html`<div class="alert alert-${command.alert_type}" role="alert">${command.alert}</div>` : '' }
-            <fieldset class="form-group">
-                <input type="hidden" name="command_node" value="${command.node}"/>
-                <input type="hidden" name="command_jid" value="${command.jid}"/>
+                ${command.alert
+                    ? html`<div class="alert alert-${command.alert_type}" role="alert">${command.alert}</div>`
+                    : ''}
+                <fieldset class="form-group">
+                    <input type="hidden" name="command_node" value="${command.node}" />
+                    <input type="hidden" name="command_jid" value="${command.jid}" />
 
-                <p class="form-instructions">${command.instructions}</p>
-                ${ command.fields }
-            </fieldset>
-            <fieldset>
-                ${ command.actions.map((action) =>
-                    html`<input data-action="${action}"
-                        @click=${(ev) => el.executeAction(ev)}
+                    <p class="form-instructions">${command.instructions}</p>
+                    ${command.fields ?? []}
+                </fieldset>
+                <fieldset>
+                    ${command.actions?.map(
+                        (action) =>
+                            html`<input
+                                data-action="${action}"
+                                @click=${(ev) => el.executeAction(ev)}
+                                type="button"
+                                class="btn btn-primary"
+                                value="${action_map[action]}"
+                            />`
+                    )}<input
                         type="button"
-                        class="btn btn-primary"
-                        value="${action_map[action]}">`)
-                 }<input type="button"
-                       class="btn btn-secondary button-cancel"
-                       value="${i18n_cancel}"
-                       @click=${(ev) => el.cancel(ev)}>
-            </fieldset>
-        </form>
+                        class="btn btn-secondary button-cancel"
+                        value="${i18n_cancel}"
+                        @click=${(ev) => el.cancel(ev)}
+                    />
+                </fieldset>
+            </form>
         </span>
     `;
-}
+};

+ 9 - 0
src/plugins/adhoc-views/templates/ad-hoc-command.js

@@ -1,6 +1,15 @@
+/**
+ * @typedef {import('@converse/headless/types/plugins/adhoc/utils').AdHocCommand} AdHocCommand
+ * @typedef {import('../adhoc-commands').default} AdHocCommands
+ * @typedef {import('../adhoc-commands').AdHocCommandUIProps} AdHocCommandUIProps
+ */
 import { html } from "lit";
 import tplCommandForm from './ad-hoc-command-form.js';
 
+/**
+ * @param {AdHocCommands} el
+ * @param {AdHocCommandUIProps} command
+ */
 export default (el, command) => html`
     <li class="room-item list-group-item">
         <div class="available-chatroom d-flex flex-row">

+ 27 - 17
src/plugins/adhoc-views/templates/ad-hoc.js

@@ -1,21 +1,27 @@
+/**
+ * @typedef {import('../adhoc-commands').default} AdHocCommands
+ */
 import tplCommand from './ad-hoc-command.js';
 import tplSpinner from 'templates/spinner.js';
 import { __ } from 'i18n';
 import { getAutoCompleteList } from 'plugins/muc-views/utils.js';
-import { html } from "lit";
-
+import { html } from 'lit';
 
+/**
+ * @param {AdHocCommands} el
+ */
 export default (el) => {
     const i18n_choose_service = __('On which entity do you want to run commands?');
     const i18n_choose_service_instructions = __(
-        'Certain XMPP services and entities allow privileged users to execute ad-hoc commands on them.');
+        'Certain XMPP services and entities allow privileged users to execute ad-hoc commands on them.'
+    );
     const i18n_commands_found = __('Commands found');
     const i18n_fetch_commands = __('List available commands');
     const i18n_jid_placeholder = __('XMPP Address');
     const i18n_no_commands_found = __('No commands found');
     return html`
-        ${ el.alert ? html`<div class="alert alert-${el.alert_type}" role="alert">${el.alert}</div>` : '' }
-        ${ el.note ? html`<p class="form-help">${el.note}</p>` : '' }
+        ${el.alert ? html`<div class="alert alert-${el.alert_type}" role="alert">${el.alert}</div>` : ''}
+        ${el.note ? html`<p class="form-help">${el.note}</p>` : ''}
 
         <form class="converse-form" @submit=${el.fetchCommands}>
             <fieldset class="form-group">
@@ -26,22 +32,26 @@ export default (el) => {
                         .getAutoCompleteList="${getAutoCompleteList}"
                         required
                         placeholder="${i18n_jid_placeholder}"
-                        name="jid">
+                        name="jid"
+                    >
                     </converse-autocomplete>
                 </label>
             </fieldset>
             <fieldset class="form-group">
-                ${ el.fetching ? tplSpinner() : html`<input type="submit" class="btn btn-primary" value="${i18n_fetch_commands}">` }
+                ${el.fetching
+                    ? tplSpinner()
+                    : html`<input type="submit" class="btn btn-primary" value="${i18n_fetch_commands}" />`}
             </fieldset>
-            ${ el.view === 'list-commands' ? html`
-            <fieldset class="form-group">
-                <ul class="list-group">
-                    <li class="list-group-item active">${ el.commands.length ? i18n_commands_found : i18n_no_commands_found }:</li>
-                    ${ el.commands.map(cmd => tplCommand(el, cmd)) }
-                </ul>
-            </fieldset>`
-            : '' }
-
+            ${el.view === 'list-commands'
+                ? html` <fieldset class="form-group">
+                      <ul class="list-group">
+                          <li class="list-group-item active">
+                              ${el.commands.length ? i18n_commands_found : i18n_no_commands_found}:
+                          </li>
+                          ${el.commands.map((cmd) => tplCommand(el, cmd))}
+                      </ul>
+                  </fieldset>`
+                : ''}
         </form>
     `;
-}
+};

+ 21 - 1
src/types/plugins/adhoc-views/adhoc-commands.d.ts

@@ -1,3 +1,13 @@
+/**
+ * @typedef {Object} UIProps
+ * @property {string} instructions
+ * @property {string} jid
+ * @property {string} [alert]
+ * @property {'danger'|'primary'} [alert_type]
+ * @property {'cancel'|'complete'|'execute'|'next'|'prev'} name
+ *
+ * @typedef {AdHocCommand & AdHocCommandFields & UIProps} AdHocCommandUIProps
+ */
 export default class AdHocCommands extends CustomElement {
     static get properties(): {
         alert: {
@@ -22,7 +32,7 @@ export default class AdHocCommands extends CustomElement {
     view: string;
     fetching: boolean;
     showform: string;
-    commands: any[];
+    commands: AdHocCommandUIProps[];
     render(): import("lit-html").TemplateResult<1>;
     /**
      * @param {SubmitEvent} ev
@@ -37,5 +47,15 @@ export default class AdHocCommands extends CustomElement {
     note: any;
     cancel(ev: any): Promise<void>;
 }
+export type AdHocCommand = import('@converse/headless/types/plugins/adhoc/utils').AdHocCommand;
+export type AdHocCommandFields = import('@converse/headless/types/plugins/adhoc/utils').AdHocCommandFields;
+export type UIProps = {
+    instructions: string;
+    jid: string;
+    alert?: string;
+    alert_type?: 'danger' | 'primary';
+    name: 'cancel' | 'complete' | 'execute' | 'next' | 'prev';
+};
+export type AdHocCommandUIProps = AdHocCommand & AdHocCommandFields & UIProps;
 import { CustomElement } from "shared/components/element.js";
 //# sourceMappingURL=adhoc-commands.d.ts.map

+ 3 - 1
src/types/plugins/adhoc-views/templates/ad-hoc-command-form.d.ts

@@ -1,3 +1,5 @@
-declare function _default(el: any, command: any): import("lit-html").TemplateResult<1>;
+declare function _default(el: AdHocCommands, command: AdHocCommandUIProps): import("lit-html").TemplateResult<1>;
 export default _default;
+export type AdHocCommands = import('../adhoc-commands').default;
+export type AdHocCommandUIProps = import('../adhoc-commands').AdHocCommandUIProps;
 //# sourceMappingURL=ad-hoc-command-form.d.ts.map

+ 4 - 1
src/types/plugins/adhoc-views/templates/ad-hoc-command.d.ts

@@ -1,3 +1,6 @@
-declare function _default(el: any, command: any): import("lit-html").TemplateResult<1>;
+declare function _default(el: AdHocCommands, command: AdHocCommandUIProps): import("lit-html").TemplateResult<1>;
 export default _default;
+export type AdHocCommand = import('@converse/headless/types/plugins/adhoc/utils').AdHocCommand;
+export type AdHocCommands = import('../adhoc-commands').default;
+export type AdHocCommandUIProps = import('../adhoc-commands').AdHocCommandUIProps;
 //# sourceMappingURL=ad-hoc-command.d.ts.map

+ 2 - 1
src/types/plugins/adhoc-views/templates/ad-hoc.d.ts

@@ -1,3 +1,4 @@
-declare function _default(el: any): import("lit-html").TemplateResult<1>;
+declare function _default(el: AdHocCommands): import("lit-html").TemplateResult<1>;
 export default _default;
+export type AdHocCommands = import('../adhoc-commands').default;
 //# sourceMappingURL=ad-hoc.d.ts.map