UNPKG

@kinvolk/headlamp-plugin

Version:

The needed infrastructure for building Headlamp plugins.

170 lines (169 loc) 6.71 kB
/* * Copyright 2025 The Kubernetes 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. */ /** * A wrapper class for initiating calls to Electron via desktopApi for managing plugins. */ export class PluginManager { /** * Adds a listener with limitations to the 'plugin-manager' event. * The listener will be removed after receiving a response with the matching identifier or after reaching the message limit. * If no response is received within a reasonable time, the promise will be rejected with a timeout error. * * @param {string} identifier - The unique identifier for the plugin. * @returns {Promise<ProgressResp>} - A promise that resolves with the response if a matching one is received, or rejects with an error if the message limit or timeout is exceeded. * @private * */ static async addListenerWithLimitations(identifier) { const waitCount = 10; let count = 0; return new Promise((resolve, reject) => { const handleResponse = (response) => { const parsedResponse = JSON.parse(response); if (parsedResponse.identifier === identifier) { clearTimeout(timeoutId); window.desktopApi.removeListener('plugin-manager', handleResponse); resolve(parsedResponse); } else if (++count >= waitCount) { clearTimeout(timeoutId); window.desktopApi.removeListener('plugin-manager', handleResponse); reject(new Error('Message limit exceeded without a matching response')); } }; window.desktopApi.receive('plugin-manager', handleResponse); // Add a timeout to ensure the promise is rejected if no response is received within a reasonable time const timeoutId = setTimeout(() => { window.desktopApi.removeListener('plugin-manager', handleResponse); reject(new Error('Timeout exceeded without a matching response')); }, 10000); }); } /** * Sends a request to install a plugin from the specified ArtifactHub URL. * * @param {string} identifier - The unique identifier for the plugin. * @param {string} name - The name of the plugin to be installed. * @param {string} URL - The URL from where the plugin will be installed. * @static * @example * PluginManager.install('pluginID', ' https://artifacthub.io/packages/headlamp/<repo_name>/<plugin_name>'); */ static install(identifier, name, URL) { window.desktopApi.send('plugin-manager', JSON.stringify({ action: 'INSTALL', identifier, URL, pluginName: name, })); } /** * Sends a request to update a plugin with the specified identifier and name. * * @param {string} identifier - The unique identifier for the plugin. * @param {string} name - The name of the plugin to be updated. * @static * @example * PluginManager.update('pluginID', 'my-plugin'); */ static update(identifier, name) { window.desktopApi.send('plugin-manager', JSON.stringify({ action: 'UPDATE', identifier, pluginName: name, })); } /** * Sends a request to uninstall a plugin with the specified identifier and name. * * @param {string} identifier - The unique identifier for the plugin. * @param {string} name - The name of the plugin to be uninstalled. * @static * @example * PluginManager.uninstall('pluginID', 'my-plugin'); */ static uninstall(identifier, name) { window.desktopApi.send('plugin-manager', JSON.stringify({ action: 'UNINSTALL', identifier, pluginName: name, })); } /** * Sends a request to cancel the operation (install, update, uninstall) for a plugin with the specified identifier. * * @param {string} identifier - The unique identifier for the plugin. * @static * @async * @example * PluginManager.cancel('pluginID'); */ static async cancel(identifier) { window.desktopApi.send('plugin-manager', JSON.stringify({ action: 'CANCEL', identifier, })); } /** * Sends a request to list all installed plugins. * * @returns {Promise<Record<string, any> | undefined>} - A promise that resolves with a record of all installed plugins, or undefined if there was an error. * @throws {Error} - Throws an error if the response type is 'error'. * @static * @async * @example * try { * const plugins = await PluginManager.list(); * console.log('Installed plugins:', plugins); * } catch (error) { * console.error('Error:', error.message); * } */ static async list() { const identifier = 'list-plugins'; window.desktopApi.send('plugin-manager', JSON.stringify({ action: 'LIST', identifier, })); const data = await this.addListenerWithLimitations(identifier); if (data.type === 'error') { throw new Error(data.message); } return data.data; } /** * Sends a request to get the status of a plugin with the specified identifier. * * @param {string} identifier - The unique identifier for the plugin. * @returns {Promise<ProgressResp>} - A promise that resolves with the status of the plugin, or rejects with an error if the message limit or timeout is exceeded. * @static * @async * @example * try { * const status = await PluginManager.getStatus('pluginID'); * console.log('Plugin status:', status); * } catch (error) { * console.error('Error:', error.message); * } */ static async getStatus(identifier) { window.desktopApi.send('plugin-manager', JSON.stringify({ action: 'GET', identifier, })); return await this.addListenerWithLimitations(identifier); } }