UNPKG

@itwin/core-frontend

Version:
116 lines 4.79 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module Extensions */ Object.defineProperty(exports, "__esModule", { value: true }); exports.ExtensionAdmin = void 0; const core_bentley_1 = require("@itwin/core-bentley"); const FrontendLoggerCategory_1 = require("../common/FrontendLoggerCategory"); /** The Extension Admin controls the list of currently loaded Extensions. * * @alpha */ class ExtensionAdmin { /** Defines the set of extensions that are currently known and can be invoked during activation events. */ _extensions = new Map(); _hosts; /** Fired when an Extension has been added or removed. * @internal */ onStartup = async () => { await this.activateExtensionEvents("onStartup"); }; constructor() { this._hosts = []; } /** * Adds an extension. * The manifest will be fetched and the extension will be activated on an activation event. * @param provider * @alpha */ async addExtension(provider) { if (provider.hostname) { const hostName = provider.hostname; if (this._hosts.length > 0 && this._hosts.indexOf(hostName) < 0) { throw new Error(`Error loading extension: ${hostName} was not registered.`); } } try { const manifest = await provider.getManifest(); this._extensions.set(manifest.name, { manifest, provider, }); // TODO - temporary fix to execute the missed startup event if (manifest.activationEvents.includes("onStartup")) provider.execute(); // eslint-disable-line @typescript-eslint/no-floating-promises } catch (e) { throw new Error(`Failed to get extension manifest ${provider.hostname ? `at ${provider.hostname}` : ""}: ${e}`); } } /** * Adds a list of extensions * @param providers * @alpha */ async addExtensions(providers) { return Promise.all(providers.map(async (provider) => this.addExtension(provider))); } /** * Registers a hostname for an extension. * Once a hostname has been registered, only remote extensions from registered hosts are permitted to be added. * @param hostUrl (string) Accepts both URLs and hostnames (e.g., http://localhost:3000, yourdomain.com, https://www.yourdomain.com, etc.). */ registerHost(hostUrl) { const hostname = this.getHostName(hostUrl); if (this._hosts.indexOf(hostname) < 0) { this._hosts.push(hostname); } } /** Returns the hostname of an input string. Throws an error if input is not a valid hostname (or URL). */ getHostName(inputUrl) { // inputs without a protocol (e.g., http://) will throw an error in URL constructor const inputWithProtocol = /(http|https):\/\//.test(inputUrl) ? inputUrl : `https://${inputUrl}`; try { const hostname = new URL(inputWithProtocol).hostname.replace("www.", ""); return hostname; } catch (e) { if (e instanceof TypeError) { throw new Error("Argument hostUrl should be a valid URL or hostname (i.e. http://localhost:3000, yourdomain.com, etc.)."); } throw e; } } /** Loops over all enabled Extensions and triggers each one if the provided event is defined. */ async activateExtensionEvents(event) { for (const extension of this._extensions.values()) { if (!extension.manifest.activationEvents) continue; for (const activationEvent of extension.manifest.activationEvents) { if (activationEvent === event) { this._execute(extension); // eslint-disable-line @typescript-eslint/no-floating-promises } } } } /** Executes the extension. Catches and logs any errors (so that an extension will not crash the main application). */ async _execute(extension) { try { await extension.provider.execute(); } catch (e) { core_bentley_1.Logger.logError(FrontendLoggerCategory_1.FrontendLoggerCategory.Extensions, `Error executing extension ${extension.manifest.name}: ${e}`); } } } exports.ExtensionAdmin = ExtensionAdmin; //# sourceMappingURL=ExtensionAdmin.js.map