@onerjs/shared-ui-components 8.50.1 → 8.50.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/modularTool/extensibility/extensionManager.js +1 -1
  2. package/modularTool/extensibility/extensionManager.js.map +1 -1
  3. package/modularTool/modularBridge.d.ts +53 -0
  4. package/modularTool/modularBridge.js +42 -0
  5. package/modularTool/modularBridge.js.map +1 -0
  6. package/modularTool/modularTool.d.ts +3 -2
  7. package/modularTool/modularTool.js +17 -10
  8. package/modularTool/modularTool.js.map +1 -1
  9. package/modularTool/modularity/serviceContainer.d.ts +6 -7
  10. package/modularTool/modularity/serviceContainer.js +13 -23
  11. package/modularTool/modularity/serviceContainer.js.map +1 -1
  12. package/modularTool/modularity/serviceDefinition.d.ts +3 -4
  13. package/modularTool/modularity/serviceDefinition.js.map +1 -1
  14. package/modularTool/services/cli/bridgeCommandRegistry.d.ts +78 -0
  15. package/modularTool/services/cli/bridgeCommandRegistry.js +7 -0
  16. package/modularTool/services/cli/bridgeCommandRegistry.js.map +1 -0
  17. package/modularTool/services/cli/bridgeConnectionStatus.d.ts +29 -0
  18. package/modularTool/services/cli/bridgeConnectionStatus.js +7 -0
  19. package/modularTool/services/cli/bridgeConnectionStatus.js.map +1 -0
  20. package/modularTool/services/cli/bridgeService.d.ts +32 -0
  21. package/modularTool/services/cli/bridgeService.js +204 -0
  22. package/modularTool/services/cli/bridgeService.js.map +1 -0
  23. package/modularTool/services/cli/protocol.d.ts +202 -0
  24. package/modularTool/services/cli/protocol.js +3 -0
  25. package/modularTool/services/cli/protocol.js.map +1 -0
  26. package/nodeGraphSystem/graphNode.js +1 -1
  27. package/nodeGraphSystem/graphNode.js.map +1 -1
  28. package/package.json +1 -1
@@ -188,7 +188,7 @@ export class ExtensionManager {
188
188
  // Register the ServiceDefinitions.
189
189
  let servicesRegistrationToken = null;
190
190
  if (installedExtension.extensionModule.default.serviceDefinitions) {
191
- servicesRegistrationToken = await this._serviceContainer.addServicesAsync(...installedExtension.extensionModule.default.serviceDefinitions);
191
+ servicesRegistrationToken = this._serviceContainer.addServices(...installedExtension.extensionModule.default.serviceDefinitions);
192
192
  }
193
193
  // Create a registration token to for dispose.
194
194
  installedExtension.registrationToken = {
@@ -1 +1 @@
1
- {"version":3,"file":"extensionManager.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/modularTool/extensibility/extensionManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { type IDisposable, type Nullable } from \"core/index\";\r\nimport { type ServiceContainer } from \"../modularity/serviceContainer\";\r\nimport { type IExtensionFeed, type ExtensionMetadata, type ExtensionModule } from \"./extensionFeed\";\r\n\r\nimport { Logger } from \"core/Misc/logger\";\r\n\r\n/**\r\n * Represents a loaded extension.\r\n */\r\nexport interface IExtension {\r\n /**\r\n * The metadata for the extension.\r\n */\r\n readonly metadata: ExtensionMetadata;\r\n\r\n /**\r\n * Whether the extension is currently being installed, uninstalled, enabled, or disabled.\r\n */\r\n readonly isStateChanging: boolean;\r\n\r\n /**\r\n * Whether the extension is enabled.\r\n */\r\n readonly isInstalled: boolean;\r\n\r\n /**\r\n * Installs the extension.\r\n */\r\n installAsync(): Promise<void>;\r\n\r\n /**\r\n * Uninstalls the extension.\r\n */\r\n uninstallAsync(): Promise<void>;\r\n\r\n /**\r\n * Adds a handler that is called when the state of the extension changes.\r\n * @param handler The handler to add.\r\n * @returns A disposable that removes the handler when disposed.\r\n */\r\n addStateChangedHandler(handler: () => void): IDisposable;\r\n}\r\n\r\n/**\r\n * Provides information about an extension installation failure.\r\n */\r\nexport type InstallFailedInfo = {\r\n /**\r\n * The metadata of the extension that failed to install.\r\n */\r\n extension: ExtensionMetadata;\r\n\r\n /**\r\n * The error that occurred during the installation.\r\n */\r\n error: unknown;\r\n};\r\n\r\ntype InstalledExtension = {\r\n metadata: ExtensionMetadata;\r\n feed: IExtensionFeed;\r\n isStateChanging: boolean;\r\n extensionModule?: ExtensionModule;\r\n registrationToken?: IDisposable;\r\n};\r\n\r\nconst InstalledExtensionsKey = \"Extensions/InstalledExtensions\";\r\n\r\nconst ExtensionInstalledKeyPrefix = \"Extensions/IsExtensionInstalled\";\r\nfunction GetExtensionInstalledKey(name: string): string {\r\n return `${ExtensionInstalledKeyPrefix}/${name}`;\r\n}\r\n\r\n/**\r\n * Represents a query for loaded extensions.\r\n */\r\nexport interface IExtensionQuery {\r\n /**\r\n * The total number of extensions that satisfy the query.\r\n */\r\n readonly totalCount: number;\r\n\r\n /**\r\n * Fetches a range of extensions from the query.\r\n * @param index The index of the first extension to fetch.\r\n * @param count The number of extensions to fetch.\r\n * @returns A promise that resolves to the extensions.\r\n */\r\n getExtensionsAsync(index: number, count: number): Promise<IExtension[]>;\r\n}\r\n\r\nfunction GetExtensionIdentity(feed: string, name: string) {\r\n return `${feed}/${name}`;\r\n}\r\n\r\n/**\r\n * Manages the installation, uninstallation, enabling, and disabling of extensions.\r\n */\r\nexport class ExtensionManager implements IDisposable {\r\n private readonly _installedExtensions = new Map<string, InstalledExtension>();\r\n\r\n private readonly _stateChangedHandlers = new Map<string, Set<() => void>>();\r\n\r\n private constructor(\r\n private readonly _namespace: string,\r\n private readonly _serviceContainer: ServiceContainer,\r\n private readonly _feeds: readonly IExtensionFeed[],\r\n private readonly _onInstallFailed: (info: InstallFailedInfo) => void\r\n ) {}\r\n\r\n /**\r\n * Creates a new instance of the ExtensionManager.\r\n * This will automatically rehydrate previously installed and enabled extensions.\r\n * @param namespace The namespace to use for storing extension state in local storage.\r\n * @param serviceContainer The service container to use.\r\n * @param feeds The extension feeds to include.\r\n * @param onInstallFailed A callback that is called when an extension installation fails.\r\n * @returns A promise that resolves to the new instance of the ExtensionManager.\r\n */\r\n public static async CreateAsync(\r\n namespace: string,\r\n serviceContainer: ServiceContainer,\r\n feeds: readonly IExtensionFeed[],\r\n onInstallFailed: (info: InstallFailedInfo) => void\r\n ): Promise<ExtensionManager> {\r\n namespace = `Babylon/${namespace}`;\r\n\r\n const extensionManager = new ExtensionManager(namespace, serviceContainer, feeds, onInstallFailed);\r\n\r\n // Rehydrate installed extensions.\r\n const installedExtensionNames = JSON.parse(localStorage.getItem(`${namespace}/${InstalledExtensionsKey}`) ?? \"[]\") as string[];\r\n for (const installedExtensionName of installedExtensionNames) {\r\n const installedExtensionRaw = localStorage.getItem(`${namespace}/${GetExtensionInstalledKey(installedExtensionName)}`);\r\n if (installedExtensionRaw) {\r\n const installedExtensionData = JSON.parse(installedExtensionRaw) as {\r\n feed: string;\r\n metadata: ExtensionMetadata;\r\n };\r\n\r\n const feed = feeds.find((feed) => feed.name === installedExtensionData.feed);\r\n if (feed) {\r\n const installedExtension = extensionManager._createInstalledExtension(installedExtensionData.metadata, feed);\r\n extensionManager._installedExtensions.set(installedExtension.metadata.name, installedExtension);\r\n }\r\n }\r\n }\r\n\r\n // Load installed and enabled extensions.\r\n const enablePromises: Promise<void>[] = [];\r\n for (const extension of extensionManager._installedExtensions.values()) {\r\n enablePromises.push(\r\n (async () => {\r\n try {\r\n await extensionManager._enableAsync(extension.metadata, false, false);\r\n } catch {\r\n // If enabling the extension fails, uninstall it. The extension install fail callback will still be called,\r\n // so the owner of the ExtensionManager instance can decide what to do with the error.\r\n await extensionManager._uninstallAsync(extension.metadata, false);\r\n }\r\n })()\r\n );\r\n }\r\n\r\n await Promise.all(enablePromises);\r\n\r\n return extensionManager;\r\n }\r\n\r\n /**\r\n * Gets the names of the feeds that are included in the extension manager.\r\n * @returns The names of the feeds.\r\n */\r\n public get feedNames() {\r\n return this._feeds.map((feed) => feed.name);\r\n }\r\n\r\n /**\r\n * Queries the extension manager for extensions.\r\n * @param filter The filter to apply to the query.\r\n * @param feeds The feeds to include in the query.\r\n * @param installedOnly Whether to only include installed extensions.\r\n * @returns A promise that resolves to the extension query.\r\n */\r\n public async queryExtensionsAsync(filter = \"\", feeds: string[] = this.feedNames, installedOnly = false): Promise<IExtensionQuery> {\r\n if (installedOnly) {\r\n const installedExtensions = Array.from(this._installedExtensions.values()).filter((installedExtension) => feeds.includes(installedExtension.feed.name));\r\n return {\r\n totalCount: installedExtensions.length,\r\n getExtensionsAsync: async (index, count) => {\r\n return installedExtensions.slice(index, index + count).map((installedExtension) => this._createExtension(installedExtension.metadata, installedExtension.feed));\r\n },\r\n };\r\n }\r\n\r\n const queries = await Promise.all(\r\n this._feeds.filter((feed) => feeds.includes(feed.name)).map(async (feed) => Object.assign(await feed.queryExtensionsAsync(filter), { feed }))\r\n );\r\n const totalCount = queries.reduce((sum, query) => sum + query.totalCount, 0);\r\n\r\n return {\r\n totalCount,\r\n getExtensionsAsync: async (index, count) => {\r\n const extensions = new Array<IExtension>();\r\n let remaining = count;\r\n\r\n for (const query of queries) {\r\n if (remaining <= 0) {\r\n break;\r\n }\r\n\r\n if (index >= query.totalCount) {\r\n index -= query.totalCount;\r\n continue;\r\n }\r\n\r\n // This is intentionally sequential as we are querying for results until the count of results is met.\r\n // eslint-disable-next-line no-await-in-loop\r\n const metadataSlice = await query.getExtensionMetadataAsync(index, remaining);\r\n extensions.push(...metadataSlice.map((metadata) => this._createExtension(metadata, query.feed)));\r\n remaining -= metadataSlice.length;\r\n index = 0;\r\n }\r\n\r\n return extensions;\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Disposes the extension manager.\r\n */\r\n public dispose() {\r\n for (const installedExtension of this._installedExtensions.values()) {\r\n // eslint-disable-next-line github/no-then\r\n this._disableAsync(installedExtension.metadata, false).catch((error) => {\r\n Logger.Warn(`Failed to disable extension ${installedExtension.metadata.name}: ${error}`);\r\n });\r\n }\r\n\r\n this._stateChangedHandlers.clear();\r\n }\r\n\r\n private _getInstalledExtensionStorageKey(metadata: ExtensionMetadata, feed: IExtensionFeed): string {\r\n return `${this._namespace}/${GetExtensionInstalledKey(GetExtensionIdentity(feed.name, metadata.name))}`;\r\n }\r\n\r\n private _updateInstalledExtensionsStorage() {\r\n localStorage.setItem(\r\n `${this._namespace}/${InstalledExtensionsKey}`,\r\n JSON.stringify(Array.from(this._installedExtensions.values()).map((extension) => GetExtensionIdentity(extension.feed.name, extension.metadata.name)))\r\n );\r\n }\r\n\r\n private async _installAsync(metadata: ExtensionMetadata, feed: IExtensionFeed, isNestedStateChange: boolean): Promise<InstalledExtension> {\r\n let installedExtension = this._installedExtensions.get(metadata.name);\r\n\r\n if (!installedExtension) {\r\n installedExtension = this._createInstalledExtension(metadata, feed);\r\n installedExtension.isStateChanging = true;\r\n this._installedExtensions.set(metadata.name, installedExtension);\r\n\r\n try {\r\n // Enable the extension.\r\n await this._enableAsync(metadata, true, true);\r\n } catch (error) {\r\n this._installedExtensions.delete(metadata.name);\r\n throw error;\r\n } finally {\r\n !isNestedStateChange && (installedExtension.isStateChanging = false);\r\n }\r\n\r\n // Mark the extension as being installed.\r\n localStorage.setItem(\r\n this._getInstalledExtensionStorageKey(metadata, feed),\r\n JSON.stringify({\r\n feed: feed.name,\r\n metadata,\r\n })\r\n );\r\n this._updateInstalledExtensionsStorage();\r\n }\r\n\r\n return installedExtension;\r\n }\r\n\r\n private async _uninstallAsync(metadata: ExtensionMetadata, isNestedStateChange: boolean): Promise<void> {\r\n const installedExtension = this._installedExtensions.get(metadata.name);\r\n if (installedExtension && (isNestedStateChange || !installedExtension.isStateChanging)) {\r\n try {\r\n !isNestedStateChange && (installedExtension.isStateChanging = true);\r\n\r\n // Disable the extension.\r\n await this._disableAsync(metadata, true);\r\n\r\n // Remove the extension from in memory.\r\n this._installedExtensions.delete(metadata.name);\r\n\r\n // Mark the extension as being uninstalled.\r\n localStorage.removeItem(this._getInstalledExtensionStorageKey(metadata, installedExtension.feed));\r\n this._updateInstalledExtensionsStorage();\r\n } finally {\r\n !isNestedStateChange && (installedExtension.isStateChanging = false);\r\n }\r\n }\r\n }\r\n\r\n private async _enableAsync(metadata: ExtensionMetadata, isInitialInstall: boolean, isNestedStateChange: boolean): Promise<void> {\r\n const installedExtension = this._installedExtensions.get(metadata.name);\r\n if (installedExtension && (isNestedStateChange || !installedExtension.isStateChanging)) {\r\n try {\r\n !isNestedStateChange && (installedExtension.isStateChanging = true);\r\n\r\n // If we haven't done so already, load the extension module.\r\n if (!installedExtension.extensionModule) {\r\n installedExtension.extensionModule = await installedExtension.feed.getExtensionModuleAsync(metadata.name);\r\n }\r\n\r\n if (!installedExtension.extensionModule) {\r\n throw new Error(`Unable to load extension module for \"${metadata.name}\" from feed \"${installedExtension.feed.name}\".`);\r\n }\r\n\r\n // Register the ServiceDefinitions.\r\n let servicesRegistrationToken: Nullable<IDisposable> = null;\r\n if (installedExtension.extensionModule.default.serviceDefinitions) {\r\n servicesRegistrationToken = await this._serviceContainer.addServicesAsync(...installedExtension.extensionModule.default.serviceDefinitions);\r\n }\r\n\r\n // Create a registration token to for dispose.\r\n installedExtension.registrationToken = {\r\n dispose: () => {\r\n servicesRegistrationToken?.dispose();\r\n },\r\n };\r\n } catch (error: unknown) {\r\n this._onInstallFailed({\r\n extension: metadata,\r\n error,\r\n });\r\n throw error;\r\n } finally {\r\n !isNestedStateChange && (installedExtension.isStateChanging = false);\r\n }\r\n }\r\n }\r\n\r\n private async _disableAsync(metadata: ExtensionMetadata, isNestedStateChange: boolean): Promise<void> {\r\n const installedExtension = this._installedExtensions.get(metadata.name);\r\n if (installedExtension && (isNestedStateChange || !installedExtension.isStateChanging)) {\r\n try {\r\n !isNestedStateChange && (installedExtension.isStateChanging = true);\r\n\r\n // Unregister the service registrations.\r\n installedExtension.registrationToken?.dispose();\r\n } finally {\r\n !isNestedStateChange && (installedExtension.isStateChanging = false);\r\n }\r\n }\r\n }\r\n\r\n private _addStateChangedHandler(metadata: ExtensionMetadata, handler: () => void): IDisposable {\r\n let stateChangedHandlers = this._stateChangedHandlers.get(metadata.name);\r\n if (!stateChangedHandlers) {\r\n this._stateChangedHandlers.set(metadata.name, (stateChangedHandlers = new Set()));\r\n }\r\n\r\n stateChangedHandlers.add(handler);\r\n\r\n return {\r\n dispose: () => {\r\n stateChangedHandlers.delete(handler);\r\n if (stateChangedHandlers.size === 0) {\r\n this._stateChangedHandlers.delete(metadata.name);\r\n }\r\n },\r\n };\r\n }\r\n\r\n private _createExtension(metadata: ExtensionMetadata, feed: IExtensionFeed): IExtension {\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n const extensionManager = this;\r\n return {\r\n metadata,\r\n get isStateChanging() {\r\n return extensionManager._installedExtensions.get(metadata.name)?.isStateChanging ?? false;\r\n },\r\n get isInstalled() {\r\n return extensionManager._installedExtensions.has(metadata.name);\r\n },\r\n installAsync: async () => {\r\n await extensionManager._installAsync(metadata, feed, false);\r\n },\r\n uninstallAsync: async () => await extensionManager._uninstallAsync(metadata, false),\r\n addStateChangedHandler: (handler: () => void) => extensionManager._addStateChangedHandler(metadata, handler),\r\n };\r\n }\r\n\r\n private _createInstalledExtension(metadata: ExtensionMetadata, feed: IExtensionFeed): InstalledExtension {\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n const extensionManager = this;\r\n let isStateChanging = false;\r\n return {\r\n metadata,\r\n feed,\r\n get isStateChanging() {\r\n return isStateChanging;\r\n },\r\n set isStateChanging(value) {\r\n if (value !== isStateChanging) {\r\n isStateChanging = value;\r\n extensionManager._stateChangedHandlers.get(this.metadata.name)?.forEach((handler) => handler());\r\n }\r\n },\r\n };\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"extensionManager.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/modularTool/extensibility/extensionManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { type IDisposable, type Nullable } from \"core/index\";\r\nimport { type ServiceContainer } from \"../modularity/serviceContainer\";\r\nimport { type IExtensionFeed, type ExtensionMetadata, type ExtensionModule } from \"./extensionFeed\";\r\n\r\nimport { Logger } from \"core/Misc/logger\";\r\n\r\n/**\r\n * Represents a loaded extension.\r\n */\r\nexport interface IExtension {\r\n /**\r\n * The metadata for the extension.\r\n */\r\n readonly metadata: ExtensionMetadata;\r\n\r\n /**\r\n * Whether the extension is currently being installed, uninstalled, enabled, or disabled.\r\n */\r\n readonly isStateChanging: boolean;\r\n\r\n /**\r\n * Whether the extension is enabled.\r\n */\r\n readonly isInstalled: boolean;\r\n\r\n /**\r\n * Installs the extension.\r\n */\r\n installAsync(): Promise<void>;\r\n\r\n /**\r\n * Uninstalls the extension.\r\n */\r\n uninstallAsync(): Promise<void>;\r\n\r\n /**\r\n * Adds a handler that is called when the state of the extension changes.\r\n * @param handler The handler to add.\r\n * @returns A disposable that removes the handler when disposed.\r\n */\r\n addStateChangedHandler(handler: () => void): IDisposable;\r\n}\r\n\r\n/**\r\n * Provides information about an extension installation failure.\r\n */\r\nexport type InstallFailedInfo = {\r\n /**\r\n * The metadata of the extension that failed to install.\r\n */\r\n extension: ExtensionMetadata;\r\n\r\n /**\r\n * The error that occurred during the installation.\r\n */\r\n error: unknown;\r\n};\r\n\r\ntype InstalledExtension = {\r\n metadata: ExtensionMetadata;\r\n feed: IExtensionFeed;\r\n isStateChanging: boolean;\r\n extensionModule?: ExtensionModule;\r\n registrationToken?: IDisposable;\r\n};\r\n\r\nconst InstalledExtensionsKey = \"Extensions/InstalledExtensions\";\r\n\r\nconst ExtensionInstalledKeyPrefix = \"Extensions/IsExtensionInstalled\";\r\nfunction GetExtensionInstalledKey(name: string): string {\r\n return `${ExtensionInstalledKeyPrefix}/${name}`;\r\n}\r\n\r\n/**\r\n * Represents a query for loaded extensions.\r\n */\r\nexport interface IExtensionQuery {\r\n /**\r\n * The total number of extensions that satisfy the query.\r\n */\r\n readonly totalCount: number;\r\n\r\n /**\r\n * Fetches a range of extensions from the query.\r\n * @param index The index of the first extension to fetch.\r\n * @param count The number of extensions to fetch.\r\n * @returns A promise that resolves to the extensions.\r\n */\r\n getExtensionsAsync(index: number, count: number): Promise<IExtension[]>;\r\n}\r\n\r\nfunction GetExtensionIdentity(feed: string, name: string) {\r\n return `${feed}/${name}`;\r\n}\r\n\r\n/**\r\n * Manages the installation, uninstallation, enabling, and disabling of extensions.\r\n */\r\nexport class ExtensionManager implements IDisposable {\r\n private readonly _installedExtensions = new Map<string, InstalledExtension>();\r\n\r\n private readonly _stateChangedHandlers = new Map<string, Set<() => void>>();\r\n\r\n private constructor(\r\n private readonly _namespace: string,\r\n private readonly _serviceContainer: ServiceContainer,\r\n private readonly _feeds: readonly IExtensionFeed[],\r\n private readonly _onInstallFailed: (info: InstallFailedInfo) => void\r\n ) {}\r\n\r\n /**\r\n * Creates a new instance of the ExtensionManager.\r\n * This will automatically rehydrate previously installed and enabled extensions.\r\n * @param namespace The namespace to use for storing extension state in local storage.\r\n * @param serviceContainer The service container to use.\r\n * @param feeds The extension feeds to include.\r\n * @param onInstallFailed A callback that is called when an extension installation fails.\r\n * @returns A promise that resolves to the new instance of the ExtensionManager.\r\n */\r\n public static async CreateAsync(\r\n namespace: string,\r\n serviceContainer: ServiceContainer,\r\n feeds: readonly IExtensionFeed[],\r\n onInstallFailed: (info: InstallFailedInfo) => void\r\n ): Promise<ExtensionManager> {\r\n namespace = `Babylon/${namespace}`;\r\n\r\n const extensionManager = new ExtensionManager(namespace, serviceContainer, feeds, onInstallFailed);\r\n\r\n // Rehydrate installed extensions.\r\n const installedExtensionNames = JSON.parse(localStorage.getItem(`${namespace}/${InstalledExtensionsKey}`) ?? \"[]\") as string[];\r\n for (const installedExtensionName of installedExtensionNames) {\r\n const installedExtensionRaw = localStorage.getItem(`${namespace}/${GetExtensionInstalledKey(installedExtensionName)}`);\r\n if (installedExtensionRaw) {\r\n const installedExtensionData = JSON.parse(installedExtensionRaw) as {\r\n feed: string;\r\n metadata: ExtensionMetadata;\r\n };\r\n\r\n const feed = feeds.find((feed) => feed.name === installedExtensionData.feed);\r\n if (feed) {\r\n const installedExtension = extensionManager._createInstalledExtension(installedExtensionData.metadata, feed);\r\n extensionManager._installedExtensions.set(installedExtension.metadata.name, installedExtension);\r\n }\r\n }\r\n }\r\n\r\n // Load installed and enabled extensions.\r\n const enablePromises: Promise<void>[] = [];\r\n for (const extension of extensionManager._installedExtensions.values()) {\r\n enablePromises.push(\r\n (async () => {\r\n try {\r\n await extensionManager._enableAsync(extension.metadata, false, false);\r\n } catch {\r\n // If enabling the extension fails, uninstall it. The extension install fail callback will still be called,\r\n // so the owner of the ExtensionManager instance can decide what to do with the error.\r\n await extensionManager._uninstallAsync(extension.metadata, false);\r\n }\r\n })()\r\n );\r\n }\r\n\r\n await Promise.all(enablePromises);\r\n\r\n return extensionManager;\r\n }\r\n\r\n /**\r\n * Gets the names of the feeds that are included in the extension manager.\r\n * @returns The names of the feeds.\r\n */\r\n public get feedNames() {\r\n return this._feeds.map((feed) => feed.name);\r\n }\r\n\r\n /**\r\n * Queries the extension manager for extensions.\r\n * @param filter The filter to apply to the query.\r\n * @param feeds The feeds to include in the query.\r\n * @param installedOnly Whether to only include installed extensions.\r\n * @returns A promise that resolves to the extension query.\r\n */\r\n public async queryExtensionsAsync(filter = \"\", feeds: string[] = this.feedNames, installedOnly = false): Promise<IExtensionQuery> {\r\n if (installedOnly) {\r\n const installedExtensions = Array.from(this._installedExtensions.values()).filter((installedExtension) => feeds.includes(installedExtension.feed.name));\r\n return {\r\n totalCount: installedExtensions.length,\r\n getExtensionsAsync: async (index, count) => {\r\n return installedExtensions.slice(index, index + count).map((installedExtension) => this._createExtension(installedExtension.metadata, installedExtension.feed));\r\n },\r\n };\r\n }\r\n\r\n const queries = await Promise.all(\r\n this._feeds.filter((feed) => feeds.includes(feed.name)).map(async (feed) => Object.assign(await feed.queryExtensionsAsync(filter), { feed }))\r\n );\r\n const totalCount = queries.reduce((sum, query) => sum + query.totalCount, 0);\r\n\r\n return {\r\n totalCount,\r\n getExtensionsAsync: async (index, count) => {\r\n const extensions = new Array<IExtension>();\r\n let remaining = count;\r\n\r\n for (const query of queries) {\r\n if (remaining <= 0) {\r\n break;\r\n }\r\n\r\n if (index >= query.totalCount) {\r\n index -= query.totalCount;\r\n continue;\r\n }\r\n\r\n // This is intentionally sequential as we are querying for results until the count of results is met.\r\n // eslint-disable-next-line no-await-in-loop\r\n const metadataSlice = await query.getExtensionMetadataAsync(index, remaining);\r\n extensions.push(...metadataSlice.map((metadata) => this._createExtension(metadata, query.feed)));\r\n remaining -= metadataSlice.length;\r\n index = 0;\r\n }\r\n\r\n return extensions;\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Disposes the extension manager.\r\n */\r\n public dispose() {\r\n for (const installedExtension of this._installedExtensions.values()) {\r\n // eslint-disable-next-line github/no-then\r\n this._disableAsync(installedExtension.metadata, false).catch((error) => {\r\n Logger.Warn(`Failed to disable extension ${installedExtension.metadata.name}: ${error}`);\r\n });\r\n }\r\n\r\n this._stateChangedHandlers.clear();\r\n }\r\n\r\n private _getInstalledExtensionStorageKey(metadata: ExtensionMetadata, feed: IExtensionFeed): string {\r\n return `${this._namespace}/${GetExtensionInstalledKey(GetExtensionIdentity(feed.name, metadata.name))}`;\r\n }\r\n\r\n private _updateInstalledExtensionsStorage() {\r\n localStorage.setItem(\r\n `${this._namespace}/${InstalledExtensionsKey}`,\r\n JSON.stringify(Array.from(this._installedExtensions.values()).map((extension) => GetExtensionIdentity(extension.feed.name, extension.metadata.name)))\r\n );\r\n }\r\n\r\n private async _installAsync(metadata: ExtensionMetadata, feed: IExtensionFeed, isNestedStateChange: boolean): Promise<InstalledExtension> {\r\n let installedExtension = this._installedExtensions.get(metadata.name);\r\n\r\n if (!installedExtension) {\r\n installedExtension = this._createInstalledExtension(metadata, feed);\r\n installedExtension.isStateChanging = true;\r\n this._installedExtensions.set(metadata.name, installedExtension);\r\n\r\n try {\r\n // Enable the extension.\r\n await this._enableAsync(metadata, true, true);\r\n } catch (error) {\r\n this._installedExtensions.delete(metadata.name);\r\n throw error;\r\n } finally {\r\n !isNestedStateChange && (installedExtension.isStateChanging = false);\r\n }\r\n\r\n // Mark the extension as being installed.\r\n localStorage.setItem(\r\n this._getInstalledExtensionStorageKey(metadata, feed),\r\n JSON.stringify({\r\n feed: feed.name,\r\n metadata,\r\n })\r\n );\r\n this._updateInstalledExtensionsStorage();\r\n }\r\n\r\n return installedExtension;\r\n }\r\n\r\n private async _uninstallAsync(metadata: ExtensionMetadata, isNestedStateChange: boolean): Promise<void> {\r\n const installedExtension = this._installedExtensions.get(metadata.name);\r\n if (installedExtension && (isNestedStateChange || !installedExtension.isStateChanging)) {\r\n try {\r\n !isNestedStateChange && (installedExtension.isStateChanging = true);\r\n\r\n // Disable the extension.\r\n await this._disableAsync(metadata, true);\r\n\r\n // Remove the extension from in memory.\r\n this._installedExtensions.delete(metadata.name);\r\n\r\n // Mark the extension as being uninstalled.\r\n localStorage.removeItem(this._getInstalledExtensionStorageKey(metadata, installedExtension.feed));\r\n this._updateInstalledExtensionsStorage();\r\n } finally {\r\n !isNestedStateChange && (installedExtension.isStateChanging = false);\r\n }\r\n }\r\n }\r\n\r\n private async _enableAsync(metadata: ExtensionMetadata, isInitialInstall: boolean, isNestedStateChange: boolean): Promise<void> {\r\n const installedExtension = this._installedExtensions.get(metadata.name);\r\n if (installedExtension && (isNestedStateChange || !installedExtension.isStateChanging)) {\r\n try {\r\n !isNestedStateChange && (installedExtension.isStateChanging = true);\r\n\r\n // If we haven't done so already, load the extension module.\r\n if (!installedExtension.extensionModule) {\r\n installedExtension.extensionModule = await installedExtension.feed.getExtensionModuleAsync(metadata.name);\r\n }\r\n\r\n if (!installedExtension.extensionModule) {\r\n throw new Error(`Unable to load extension module for \"${metadata.name}\" from feed \"${installedExtension.feed.name}\".`);\r\n }\r\n\r\n // Register the ServiceDefinitions.\r\n let servicesRegistrationToken: Nullable<IDisposable> = null;\r\n if (installedExtension.extensionModule.default.serviceDefinitions) {\r\n servicesRegistrationToken = this._serviceContainer.addServices(...installedExtension.extensionModule.default.serviceDefinitions);\r\n }\r\n\r\n // Create a registration token to for dispose.\r\n installedExtension.registrationToken = {\r\n dispose: () => {\r\n servicesRegistrationToken?.dispose();\r\n },\r\n };\r\n } catch (error: unknown) {\r\n this._onInstallFailed({\r\n extension: metadata,\r\n error,\r\n });\r\n throw error;\r\n } finally {\r\n !isNestedStateChange && (installedExtension.isStateChanging = false);\r\n }\r\n }\r\n }\r\n\r\n private async _disableAsync(metadata: ExtensionMetadata, isNestedStateChange: boolean): Promise<void> {\r\n const installedExtension = this._installedExtensions.get(metadata.name);\r\n if (installedExtension && (isNestedStateChange || !installedExtension.isStateChanging)) {\r\n try {\r\n !isNestedStateChange && (installedExtension.isStateChanging = true);\r\n\r\n // Unregister the service registrations.\r\n installedExtension.registrationToken?.dispose();\r\n } finally {\r\n !isNestedStateChange && (installedExtension.isStateChanging = false);\r\n }\r\n }\r\n }\r\n\r\n private _addStateChangedHandler(metadata: ExtensionMetadata, handler: () => void): IDisposable {\r\n let stateChangedHandlers = this._stateChangedHandlers.get(metadata.name);\r\n if (!stateChangedHandlers) {\r\n this._stateChangedHandlers.set(metadata.name, (stateChangedHandlers = new Set()));\r\n }\r\n\r\n stateChangedHandlers.add(handler);\r\n\r\n return {\r\n dispose: () => {\r\n stateChangedHandlers.delete(handler);\r\n if (stateChangedHandlers.size === 0) {\r\n this._stateChangedHandlers.delete(metadata.name);\r\n }\r\n },\r\n };\r\n }\r\n\r\n private _createExtension(metadata: ExtensionMetadata, feed: IExtensionFeed): IExtension {\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n const extensionManager = this;\r\n return {\r\n metadata,\r\n get isStateChanging() {\r\n return extensionManager._installedExtensions.get(metadata.name)?.isStateChanging ?? false;\r\n },\r\n get isInstalled() {\r\n return extensionManager._installedExtensions.has(metadata.name);\r\n },\r\n installAsync: async () => {\r\n await extensionManager._installAsync(metadata, feed, false);\r\n },\r\n uninstallAsync: async () => await extensionManager._uninstallAsync(metadata, false),\r\n addStateChangedHandler: (handler: () => void) => extensionManager._addStateChangedHandler(metadata, handler),\r\n };\r\n }\r\n\r\n private _createInstalledExtension(metadata: ExtensionMetadata, feed: IExtensionFeed): InstalledExtension {\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n const extensionManager = this;\r\n let isStateChanging = false;\r\n return {\r\n metadata,\r\n feed,\r\n get isStateChanging() {\r\n return isStateChanging;\r\n },\r\n set isStateChanging(value) {\r\n if (value !== isStateChanging) {\r\n isStateChanging = value;\r\n extensionManager._stateChangedHandlers.get(this.metadata.name)?.forEach((handler) => handler());\r\n }\r\n },\r\n };\r\n }\r\n}\r\n"]}
@@ -0,0 +1,53 @@
1
+ import { type IDisposable } from "@onerjs/core/index.js";
2
+ import { type WeaklyTypedServiceDefinition, ServiceContainer } from "./modularity/serviceContainer.js";
3
+ /**
4
+ * Options for creating a modular bridge container.
5
+ * @experimental
6
+ * @internal
7
+ */
8
+ export type ModularBridgeOptions = {
9
+ /**
10
+ * WebSocket port for the bridge's browser port. Defaults to 4400.
11
+ */
12
+ port?: number;
13
+ /**
14
+ * Session display name reported to the bridge. Defaults to `document.title`.
15
+ */
16
+ name?: string;
17
+ /**
18
+ * Whether the bridge should automatically start trying to connect.
19
+ * Defaults to false.
20
+ */
21
+ autoStart?: boolean;
22
+ /**
23
+ * Additional service definitions to register with the bridge container.
24
+ */
25
+ serviceDefinitions?: readonly WeaklyTypedServiceDefinition[];
26
+ };
27
+ /**
28
+ * A token returned by {@link MakeModularBridge} that owns the headless
29
+ * {@link ServiceContainer}. Dispose it to tear down the bridge and all services.
30
+ * @experimental
31
+ * @internal
32
+ */
33
+ export type ModularBridgeToken = IDisposable & {
34
+ /**
35
+ * The headless ServiceContainer that hosts the bridge.
36
+ */
37
+ readonly serviceContainer: ServiceContainer;
38
+ /**
39
+ * Whether this token has been disposed.
40
+ */
41
+ readonly isDisposed: boolean;
42
+ };
43
+ /**
44
+ * Creates a headless {@link ServiceContainer} that hosts a bridge service.
45
+ *
46
+ * The returned token owns the container. Dispose it to tear down the bridge.
47
+ *
48
+ * @param options Optional configuration for the bridge.
49
+ * @returns A {@link ModularBridgeToken} that owns the container.
50
+ * @experimental
51
+ * @internal
52
+ */
53
+ export declare function MakeModularBridge(options?: ModularBridgeOptions): ModularBridgeToken;
@@ -0,0 +1,42 @@
1
+ import { ServiceContainer } from "./modularity/serviceContainer.js";
2
+ import { MakeBridgeServiceDefinition } from "./services/cli/bridgeService.js";
3
+ const DefaultPort = 4400;
4
+ /**
5
+ * Creates a headless {@link ServiceContainer} that hosts a bridge service.
6
+ *
7
+ * The returned token owns the container. Dispose it to tear down the bridge.
8
+ *
9
+ * @param options Optional configuration for the bridge.
10
+ * @returns A {@link ModularBridgeToken} that owns the container.
11
+ * @experimental
12
+ * @internal
13
+ */
14
+ export function MakeModularBridge(options) {
15
+ const serviceContainer = new ServiceContainer("ModularBridgeContainer");
16
+ const bridgeDefinition = MakeBridgeServiceDefinition({
17
+ port: options?.port ?? DefaultPort,
18
+ get name() {
19
+ return options?.name ?? (typeof document !== "undefined" ? document.title : "Babylon.js Scene");
20
+ },
21
+ autoStart: options?.autoStart ?? false,
22
+ });
23
+ const allDefinitions = [bridgeDefinition];
24
+ if (options?.serviceDefinitions) {
25
+ allDefinitions.push(...options.serviceDefinitions);
26
+ }
27
+ serviceContainer.addServices(...allDefinitions);
28
+ let disposed = false;
29
+ return {
30
+ get serviceContainer() {
31
+ return serviceContainer;
32
+ },
33
+ get isDisposed() {
34
+ return disposed;
35
+ },
36
+ dispose() {
37
+ disposed = true;
38
+ serviceContainer.dispose();
39
+ },
40
+ };
41
+ }
42
+ //# sourceMappingURL=modularBridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modularBridge.js","sourceRoot":"","sources":["../../../../dev/sharedUiComponents/src/modularTool/modularBridge.ts"],"names":[],"mappings":"AACA,OAAO,EAAqC,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACpG,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAE3E,MAAM,WAAW,GAAG,IAAI,CAAC;AAgDzB;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAA8B;IAC5D,MAAM,gBAAgB,GAAG,IAAI,gBAAgB,CAAC,wBAAwB,CAAC,CAAC;IAExE,MAAM,gBAAgB,GAAG,2BAA2B,CAAC;QACjD,IAAI,EAAE,OAAO,EAAE,IAAI,IAAI,WAAW;QAClC,IAAI,IAAI;YACJ,OAAO,OAAO,EAAE,IAAI,IAAI,CAAC,OAAO,QAAQ,KAAK,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC;QACpG,CAAC;QACD,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,KAAK;KACzC,CAAC,CAAC;IAEH,MAAM,cAAc,GAAmC,CAAC,gBAAgB,CAAC,CAAC;IAC1E,IAAI,OAAO,EAAE,kBAAkB,EAAE,CAAC;QAC9B,cAAc,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACvD,CAAC;IAED,gBAAgB,CAAC,WAAW,CAAC,GAAG,cAAc,CAAC,CAAC;IAEhD,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,OAAO;QACH,IAAI,gBAAgB;YAChB,OAAO,gBAAgB,CAAC;QAC5B,CAAC;QACD,IAAI,UAAU;YACV,OAAO,QAAQ,CAAC;QACpB,CAAC;QACD,OAAO;YACH,QAAQ,GAAG,IAAI,CAAC;YAChB,gBAAgB,CAAC,OAAO,EAAE,CAAC;QAC/B,CAAC;KACJ,CAAC;AACN,CAAC","sourcesContent":["import { type IDisposable } from \"core/index\";\r\nimport { type WeaklyTypedServiceDefinition, ServiceContainer } from \"./modularity/serviceContainer\";\r\nimport { MakeBridgeServiceDefinition } from \"./services/cli/bridgeService\";\r\n\r\nconst DefaultPort = 4400;\r\n\r\n/**\r\n * Options for creating a modular bridge container.\r\n * @experimental\r\n * @internal\r\n */\r\nexport type ModularBridgeOptions = {\r\n /**\r\n * WebSocket port for the bridge's browser port. Defaults to 4400.\r\n */\r\n port?: number;\r\n\r\n /**\r\n * Session display name reported to the bridge. Defaults to `document.title`.\r\n */\r\n name?: string;\r\n\r\n /**\r\n * Whether the bridge should automatically start trying to connect.\r\n * Defaults to false.\r\n */\r\n autoStart?: boolean;\r\n\r\n /**\r\n * Additional service definitions to register with the bridge container.\r\n */\r\n serviceDefinitions?: readonly WeaklyTypedServiceDefinition[];\r\n};\r\n\r\n/**\r\n * A token returned by {@link MakeModularBridge} that owns the headless\r\n * {@link ServiceContainer}. Dispose it to tear down the bridge and all services.\r\n * @experimental\r\n * @internal\r\n */\r\nexport type ModularBridgeToken = IDisposable & {\r\n /**\r\n * The headless ServiceContainer that hosts the bridge.\r\n */\r\n readonly serviceContainer: ServiceContainer;\r\n\r\n /**\r\n * Whether this token has been disposed.\r\n */\r\n readonly isDisposed: boolean;\r\n};\r\n\r\n/**\r\n * Creates a headless {@link ServiceContainer} that hosts a bridge service.\r\n *\r\n * The returned token owns the container. Dispose it to tear down the bridge.\r\n *\r\n * @param options Optional configuration for the bridge.\r\n * @returns A {@link ModularBridgeToken} that owns the container.\r\n * @experimental\r\n * @internal\r\n */\r\nexport function MakeModularBridge(options?: ModularBridgeOptions): ModularBridgeToken {\r\n const serviceContainer = new ServiceContainer(\"ModularBridgeContainer\");\r\n\r\n const bridgeDefinition = MakeBridgeServiceDefinition({\r\n port: options?.port ?? DefaultPort,\r\n get name() {\r\n return options?.name ?? (typeof document !== \"undefined\" ? document.title : \"Babylon.js Scene\");\r\n },\r\n autoStart: options?.autoStart ?? false,\r\n });\r\n\r\n const allDefinitions: WeaklyTypedServiceDefinition[] = [bridgeDefinition];\r\n if (options?.serviceDefinitions) {\r\n allDefinitions.push(...options.serviceDefinitions);\r\n }\r\n\r\n serviceContainer.addServices(...allDefinitions);\r\n\r\n let disposed = false;\r\n\r\n return {\r\n get serviceContainer() {\r\n return serviceContainer;\r\n },\r\n get isDisposed() {\r\n return disposed;\r\n },\r\n dispose() {\r\n disposed = true;\r\n serviceContainer.dispose();\r\n },\r\n };\r\n}\r\n"]}
@@ -1,4 +1,3 @@
1
- import { type IDisposable } from "@onerjs/core/index.js";
2
1
  import { type IExtensionFeed } from "./extensibility/extensionFeed.js";
3
2
  import { type WeaklyTypedServiceDefinition, ServiceContainer } from "./modularity/serviceContainer.js";
4
3
  import { type ShellServiceOptions } from "./services/shellService.js";
@@ -39,4 +38,6 @@ export type ModularToolOptions = {
39
38
  * @param options The options for the tool.
40
39
  * @returns A token that can be used to dispose of the tool.
41
40
  */
42
- export declare function MakeModularTool(options: ModularToolOptions): IDisposable;
41
+ export declare function MakeModularTool(options: ModularToolOptions): {
42
+ dispose: () => Promise<void>;
43
+ };
@@ -59,6 +59,8 @@ export function MakeModularTool(options) {
59
59
  if (themeMode) {
60
60
  settingsStore.writeSetting(ThemeModeSettingDescriptor, themeMode);
61
61
  }
62
+ // This deferred resolves once the React effect cleanup (which disposes the ServiceContainer) is complete.
63
+ const disposeDeferred = new Deferred();
62
64
  const modularToolRootComponent = () => {
63
65
  const classes = useStyles();
64
66
  const [extensionManagerContext, setExtensionManagerContext] = useState();
@@ -91,13 +93,13 @@ export function MakeModularTool(options) {
91
93
  const initializeExtensionManagerAsync = async () => {
92
94
  const serviceContainer = new ServiceContainer("ModularToolContainer", parentContainer);
93
95
  // Expose the settings store as a service so other services can read/write settings.
94
- await serviceContainer.addServiceAsync({
96
+ serviceContainer.addService({
95
97
  friendlyName: "Settings Store",
96
98
  produces: [SettingsStoreIdentity],
97
99
  factory: () => settingsStore,
98
100
  });
99
101
  // Expose the react context service so other services can add React context providers.
100
- await serviceContainer.addServiceAsync({
102
+ serviceContainer.addService({
101
103
  friendlyName: "React Context Service",
102
104
  produces: [ReactContextServiceIdentity],
103
105
  factory: () => ({
@@ -116,7 +118,7 @@ export function MakeModularTool(options) {
116
118
  }),
117
119
  });
118
120
  // Expose the toast service so non-React code (e.g. Observable callbacks) can show toasts.
119
- await serviceContainer.addServiceAsync({
121
+ serviceContainer.addService({
120
122
  friendlyName: "Toast Service",
121
123
  produces: [ToastServiceIdentity],
122
124
  factory: () => ({
@@ -126,9 +128,9 @@ export function MakeModularTool(options) {
126
128
  }),
127
129
  });
128
130
  // Register the shell service (top level toolbar/side pane UI layout).
129
- await serviceContainer.addServiceAsync(MakeShellServiceDefinition(options));
131
+ serviceContainer.addService(MakeShellServiceDefinition(options));
130
132
  // Register a service that simply consumes the services we need before first render.
131
- await serviceContainer.addServiceAsync({
133
+ serviceContainer.addService({
132
134
  friendlyName: "Service Bootstrapper",
133
135
  consumes: [RootComponentServiceIdentity],
134
136
  factory: (rootComponent) => {
@@ -140,18 +142,18 @@ export function MakeModularTool(options) {
140
142
  },
141
143
  });
142
144
  // Register the theme service (exposes the current theme to other services).
143
- await serviceContainer.addServiceAsync(ThemeServiceDefinition);
145
+ serviceContainer.addService(ThemeServiceDefinition);
144
146
  // Register the theme selector service (for selecting the theme) if theming is configured.
145
147
  if (showThemeSelector) {
146
- await serviceContainer.addServiceAsync(ThemeSelectorServiceDefinition);
148
+ serviceContainer.addService(ThemeSelectorServiceDefinition);
147
149
  }
148
150
  // Register the extension list service (for browsing/installing extensions) if extension feeds are provided.
149
151
  if (extensionFeeds.length > 0) {
150
152
  const { ExtensionListServiceDefinition } = await import("./services/extensionsListService.js");
151
- await serviceContainer.addServiceAsync(ExtensionListServiceDefinition);
153
+ serviceContainer.addService(ExtensionListServiceDefinition);
152
154
  }
153
155
  // Register all external services (that make up a unique tool).
154
- await serviceContainer.addServicesAsync(...serviceDefinitions);
156
+ serviceContainer.addServices(...serviceDefinitions);
155
157
  // Create the extension manager, passing along the registry for runtime changes to the registered services.
156
158
  const extensionManager = await ExtensionManager.CreateAsync(namespace, serviceContainer, extensionFeeds, setExtensionInstallError);
157
159
  // Check query params for required extensions. This lets users share links with sets of extensions.
@@ -199,7 +201,8 @@ export function MakeModularTool(options) {
199
201
  // eslint-disable-next-line github/no-then
200
202
  .catch((error) => {
201
203
  Logger.Error(`Failed to dispose of the modular tool: ${error}`);
202
- });
204
+ })
205
+ .finally(() => disposeDeferred.resolve());
203
206
  };
204
207
  }, []);
205
208
  const onAcceptRequiredExtensions = useCallback(() => {
@@ -231,6 +234,7 @@ export function MakeModularTool(options) {
231
234
  reactRoot.render(createElement(modularToolRootComponent));
232
235
  let disposed = false;
233
236
  return {
237
+ // eslint-disable-next-line @typescript-eslint/promise-function-async
234
238
  dispose: () => {
235
239
  // Unmount and restore the original container element display.
236
240
  if (!disposed) {
@@ -238,6 +242,9 @@ export function MakeModularTool(options) {
238
242
  reactRoot.unmount();
239
243
  containerElement.style.display = originalContainerElementDisplay;
240
244
  }
245
+ // The promise resolves once the React effect cleanup
246
+ // (which disposes the ServiceContainer) has completed.
247
+ return disposeDeferred.promise;
241
248
  },
242
249
  };
243
250
  }
@@ -1 +1 @@
1
- {"version":3,"file":"modularTool.js","sourceRoot":"","sources":["../../../../dev/sharedUiComponents/src/modularTool/modularTool.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\r\n type ComponentType,\r\n type Context,\r\n type FunctionComponent,\r\n type PropsWithChildren,\r\n type ReactNode,\r\n createElement,\r\n Suspense,\r\n useCallback,\r\n useEffect,\r\n useReducer,\r\n useState,\r\n} from \"react\";\r\n\r\nimport { type IDisposable } from \"core/index\";\r\nimport { type IExtensionFeed } from \"./extensibility/extensionFeed\";\r\nimport { type IExtension, type InstallFailedInfo, ExtensionManager } from \"./extensibility/extensionManager\";\r\nimport { type WeaklyTypedServiceDefinition, ServiceContainer } from \"./modularity/serviceContainer\";\r\nimport { type ISettingsStore, SettingsStore, SettingsStoreIdentity } from \"./services/settingsStore\";\r\nimport { type IRootComponentService, type ShellServiceOptions, MakeShellServiceDefinition, RootComponentServiceIdentity } from \"./services/shellService\";\r\nimport { type ThemeMode, ThemeModeSettingDescriptor, ThemeServiceDefinition } from \"./services/themeService\";\r\n\r\nimport {\r\n Body1,\r\n Button,\r\n Dialog,\r\n DialogActions,\r\n DialogBody,\r\n DialogContent,\r\n DialogSurface,\r\n DialogTitle,\r\n List,\r\n ListItem,\r\n makeStyles,\r\n Spinner,\r\n tokens,\r\n} from \"@fluentui/react-components\";\r\nimport { ErrorCircleRegular } from \"@fluentui/react-icons\";\r\nimport { createRoot } from \"react-dom/client\";\r\n\r\nimport { Deferred } from \"core/Misc/deferred\";\r\nimport { Logger } from \"core/Misc/logger\";\r\nimport { type ToastHandle, type ToastOptions, ToastProvider } from \"shared-ui-components/fluent/primitives/toast\";\r\nimport { type IToastService, ToastServiceIdentity } from \"./services/toastService\";\r\nimport { Theme } from \"./components/theme\";\r\nimport { ExtensionManagerContext } from \"./contexts/extensionManagerContext\";\r\nimport { SettingsStoreContext } from \"./contexts/settingsContext\";\r\nimport { type IReactContextService, type ReactContextHandle, ReactContextServiceIdentity } from \"./services/reactContextService\";\r\nimport { ThemeSelectorServiceDefinition } from \"./services/themeSelectorService\";\r\n\r\nconst useStyles = makeStyles({\r\n app: {\r\n colorScheme: \"light dark\",\r\n flexGrow: 1,\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n backgroundColor: tokens.colorTransparentBackground,\r\n },\r\n spinner: {\r\n flexGrow: 1,\r\n animationDuration: \"1s\",\r\n animationName: {\r\n from: { opacity: 0 },\r\n to: { opacity: 1 },\r\n },\r\n },\r\n extensionErrorTitleDiv: {\r\n display: \"flex\",\r\n flexDirection: \"row\",\r\n alignItems: \"center\",\r\n gap: tokens.spacingHorizontalS,\r\n },\r\n extensionErrorIcon: {\r\n color: tokens.colorPaletteRedForeground1,\r\n },\r\n});\r\n\r\ntype ReactContextEntry = {\r\n provider: Context<unknown>[\"Provider\"];\r\n value: unknown;\r\n order: number;\r\n};\r\n\r\ntype ReactContextAction =\r\n | { type: \"add\"; entry: ReactContextEntry }\r\n | { type: \"remove\"; provider: Context<unknown>[\"Provider\"] }\r\n | { type: \"update\"; provider: Context<unknown>[\"Provider\"]; value: unknown };\r\n\r\nconst ReactContextsWrapper: FunctionComponent<PropsWithChildren<{ contexts: readonly Readonly<ReactContextEntry>[] }>> = ({ contexts, children }) => {\r\n return <>{contexts.reduceRight<ReactNode>((acc, entry) => createElement(entry.provider, { value: entry.value }, acc), children)}</>;\r\n};\r\n\r\nexport type ModularToolOptions = {\r\n /**\r\n * The namespace for the tool, used for scoping persisted settings and other storage.\r\n */\r\n namespace: string;\r\n\r\n /**\r\n * The container element where the tool will be rendered.\r\n */\r\n containerElement: HTMLElement;\r\n\r\n /**\r\n * The service definitions to be registered with the tool.\r\n */\r\n serviceDefinitions: readonly WeaklyTypedServiceDefinition[];\r\n\r\n /**\r\n * The theme mode to use. If not specified, the default is \"system\", which uses the system/browser preference, and the last used mode is persisted.\r\n */\r\n themeMode?: ThemeMode;\r\n\r\n /**\r\n * Whether to show the theme selector in the toolbar. Default is true.\r\n */\r\n showThemeSelector?: boolean;\r\n\r\n /**\r\n * The extension feeds that provide optional extensions the user can install.\r\n */\r\n extensionFeeds?: readonly IExtensionFeed[];\r\n\r\n /**\r\n * An optional parent ServiceContainer. Dependencies not found in the tool's own container\r\n * will be resolved from this parent.\r\n */\r\n parentContainer?: ServiceContainer;\r\n} & ShellServiceOptions;\r\n\r\n/**\r\n * Creates a modular tool with a base set of common tool services, including the toolbar/side pane basic UI layout.\r\n * @param options The options for the tool.\r\n * @returns A token that can be used to dispose of the tool.\r\n */\r\nexport function MakeModularTool(options: ModularToolOptions): IDisposable {\r\n const { namespace, containerElement, serviceDefinitions, themeMode, showThemeSelector = true, extensionFeeds = [], parentContainer } = options;\r\n\r\n // Create the settings store immediately as it will be exposed to services and through React context.\r\n const settingsStore = new SettingsStore(namespace);\r\n\r\n // If a theme mode is provided, just write the setting so it is the active theme.\r\n if (themeMode) {\r\n settingsStore.writeSetting(ThemeModeSettingDescriptor, themeMode);\r\n }\r\n\r\n const modularToolRootComponent: FunctionComponent = () => {\r\n const classes = useStyles();\r\n const [extensionManagerContext, setExtensionManagerContext] = useState<ExtensionManagerContext>();\r\n const [requiredExtensions, setRequiredExtensions] = useState<string[]>();\r\n const [requiredExtensionsDeferred, setRequiredExtensionsDeferred] = useState<Deferred<boolean>>();\r\n const [extensionInstallError, setExtensionInstallError] = useState<InstallFailedInfo>();\r\n\r\n const [toastHandle, setToastHandle] = useState<ToastHandle | null>(null);\r\n const [toastQueue, setToastQueue] = useState<{ message: string; options?: ToastOptions }[]>([]);\r\n\r\n useEffect(() => {\r\n if (toastHandle && toastQueue.length > 0) {\r\n for (const { message, options } of toastQueue) {\r\n toastHandle.showToast(message, options);\r\n }\r\n setToastQueue([]);\r\n }\r\n }, [toastHandle, toastQueue]);\r\n\r\n const [rootComponentService, setRootComponentService] = useState<IRootComponentService>();\r\n\r\n const [contexts, updateContexts] = useReducer((state: ReactContextEntry[], action: ReactContextAction): ReactContextEntry[] => {\r\n switch (action.type) {\r\n case \"add\":\r\n return [...state, action.entry].sort((a, b) => a.order - b.order);\r\n case \"remove\":\r\n return state.filter((e) => e.provider !== action.provider);\r\n case \"update\":\r\n return state.map((e) => (e.provider === action.provider ? { ...e, value: action.value } : e));\r\n }\r\n }, []);\r\n\r\n // This is the main async initialization.\r\n useEffect(() => {\r\n const initializeExtensionManagerAsync = async () => {\r\n const serviceContainer = new ServiceContainer(\"ModularToolContainer\", parentContainer);\r\n\r\n // Expose the settings store as a service so other services can read/write settings.\r\n await serviceContainer.addServiceAsync<[ISettingsStore], []>({\r\n friendlyName: \"Settings Store\",\r\n produces: [SettingsStoreIdentity],\r\n factory: () => settingsStore,\r\n });\r\n\r\n // Expose the react context service so other services can add React context providers.\r\n await serviceContainer.addServiceAsync<[IReactContextService], []>({\r\n friendlyName: \"React Context Service\",\r\n produces: [ReactContextServiceIdentity],\r\n factory: (): IReactContextService => ({\r\n addContext<T>(provider: Context<T>[\"Provider\"], initialValue: T, options?: { order?: number }): ReactContextHandle<T> {\r\n const typedProvider = provider as Context<unknown>[\"Provider\"];\r\n updateContexts({ type: \"add\", entry: { provider: typedProvider, value: initialValue, order: options?.order ?? 0 } });\r\n return {\r\n updateValue: (newValue: T) => {\r\n updateContexts({ type: \"update\", provider: typedProvider, value: newValue });\r\n },\r\n dispose: () => {\r\n updateContexts({ type: \"remove\", provider: typedProvider });\r\n },\r\n };\r\n },\r\n }),\r\n });\r\n\r\n // Expose the toast service so non-React code (e.g. Observable callbacks) can show toasts.\r\n await serviceContainer.addServiceAsync<[IToastService], []>({\r\n friendlyName: \"Toast Service\",\r\n produces: [ToastServiceIdentity],\r\n factory: (): IToastService => ({\r\n showToast: (message, options) => {\r\n setToastQueue((prev) => [...prev, { message, options }]);\r\n },\r\n }),\r\n });\r\n\r\n // Register the shell service (top level toolbar/side pane UI layout).\r\n await serviceContainer.addServiceAsync(MakeShellServiceDefinition(options));\r\n\r\n // Register a service that simply consumes the services we need before first render.\r\n await serviceContainer.addServiceAsync<[], [IRootComponentService]>({\r\n friendlyName: \"Service Bootstrapper\",\r\n consumes: [RootComponentServiceIdentity],\r\n factory: (rootComponent) => {\r\n // Use function syntax for the state setter since the root component may be a function component.\r\n setRootComponentService(() => rootComponent);\r\n return {\r\n dispose: () => setRootComponentService(undefined),\r\n };\r\n },\r\n });\r\n\r\n // Register the theme service (exposes the current theme to other services).\r\n await serviceContainer.addServiceAsync(ThemeServiceDefinition);\r\n\r\n // Register the theme selector service (for selecting the theme) if theming is configured.\r\n if (showThemeSelector) {\r\n await serviceContainer.addServiceAsync(ThemeSelectorServiceDefinition);\r\n }\r\n\r\n // Register the extension list service (for browsing/installing extensions) if extension feeds are provided.\r\n if (extensionFeeds.length > 0) {\r\n const { ExtensionListServiceDefinition } = await import(\"./services/extensionsListService\");\r\n await serviceContainer.addServiceAsync(ExtensionListServiceDefinition);\r\n }\r\n\r\n // Register all external services (that make up a unique tool).\r\n await serviceContainer.addServicesAsync(...serviceDefinitions);\r\n\r\n // Create the extension manager, passing along the registry for runtime changes to the registered services.\r\n const extensionManager = await ExtensionManager.CreateAsync(namespace, serviceContainer, extensionFeeds, setExtensionInstallError);\r\n\r\n // Check query params for required extensions. This lets users share links with sets of extensions.\r\n const queryParams = new URLSearchParams(window.location.search);\r\n const requiredExtensions = queryParams.getAll(\"babylon.requiredExtension\");\r\n const uninstalledExtensions: IExtension[] = [];\r\n for (const requiredExtension of requiredExtensions) {\r\n // These could possibly be parallelized to speed things up, but it's more complex so let's wait and see if we need it.\r\n // eslint-disable-next-line no-await-in-loop\r\n const query = await extensionManager.queryExtensionsAsync(requiredExtension);\r\n // eslint-disable-next-line no-await-in-loop\r\n const extensions = await query.getExtensionsAsync(0, query.totalCount);\r\n for (const extension of extensions) {\r\n if (!extension.isInstalled) {\r\n uninstalledExtensions.push(extension);\r\n }\r\n }\r\n }\r\n\r\n // Check if any required extensions are uninstalled or disabled. If so, show a dialog to the user.\r\n if (uninstalledExtensions.length > 0) {\r\n setRequiredExtensions(uninstalledExtensions.map((extension) => extension.metadata.name));\r\n const deferred = new Deferred<boolean>();\r\n setRequiredExtensionsDeferred(deferred);\r\n if (await deferred.promise) {\r\n for (const extension of uninstalledExtensions) {\r\n // This could possibly be parallelized to speed things up, but it's more complex so let's wait and see if we need it.\r\n // eslint-disable-next-line no-await-in-loop\r\n await extension.installAsync();\r\n }\r\n }\r\n }\r\n\r\n // Set the contexts.\r\n setExtensionManagerContext({ extensionManager });\r\n\r\n return () => {\r\n extensionManager.dispose();\r\n serviceContainer.dispose();\r\n serviceContainer.dispose();\r\n };\r\n };\r\n\r\n const disposePromise = initializeExtensionManagerAsync();\r\n\r\n return () => {\r\n disposePromise\r\n // eslint-disable-next-line github/no-then\r\n .then((dispose) => dispose())\r\n // eslint-disable-next-line github/no-then\r\n .catch((error) => {\r\n Logger.Error(`Failed to dispose of the modular tool: ${error}`);\r\n });\r\n };\r\n }, []);\r\n\r\n const onAcceptRequiredExtensions = useCallback(() => {\r\n setRequiredExtensions(undefined);\r\n requiredExtensionsDeferred?.resolve(true);\r\n }, [setRequiredExtensions, requiredExtensionsDeferred]);\r\n\r\n const onRejectRequiredExtensions = useCallback(() => {\r\n setRequiredExtensions(undefined);\r\n requiredExtensionsDeferred?.resolve(false);\r\n }, [setRequiredExtensions, requiredExtensionsDeferred]);\r\n\r\n const onAcknowledgedExtensionInstallError = useCallback(() => {\r\n setExtensionInstallError(undefined);\r\n }, [setExtensionInstallError]);\r\n\r\n // Show a spinner until a main view has been set.\r\n if (!rootComponentService) {\r\n return (\r\n <ReactContextsWrapper contexts={contexts}>\r\n <SettingsStoreContext.Provider value={settingsStore}>\r\n <Theme className={classes.app}>\r\n <Spinner className={classes.spinner} />\r\n </Theme>\r\n </SettingsStoreContext.Provider>\r\n </ReactContextsWrapper>\r\n );\r\n } else {\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n const Content: ComponentType = rootComponentService.rootComponent;\r\n\r\n return (\r\n <ReactContextsWrapper contexts={contexts}>\r\n {/* Expose the settings store as a React context so that UI components can read/write\r\n settings without the ISettingsService needing to be explicitly passed around. */}\r\n <SettingsStoreContext.Provider value={settingsStore}>\r\n <ExtensionManagerContext.Provider value={extensionManagerContext}>\r\n <Theme className={classes.app}>\r\n <ToastProvider imperativeRef={setToastHandle}>\r\n <Dialog open={!!requiredExtensions} modalType=\"alert\">\r\n <DialogSurface>\r\n <DialogBody>\r\n <DialogTitle>Required Extensions</DialogTitle>\r\n <DialogContent>\r\n Opening this URL requires the following extensions to be installed and enabled:\r\n <ul>\r\n {requiredExtensions?.map((name) => (\r\n <li key={name}>{name}</li>\r\n ))}\r\n </ul>\r\n </DialogContent>\r\n <DialogActions>\r\n <Button appearance=\"primary\" onClick={onAcceptRequiredExtensions}>\r\n Install & Enable\r\n </Button>\r\n <Button appearance=\"secondary\" onClick={onRejectRequiredExtensions}>\r\n No Thanks\r\n </Button>\r\n </DialogActions>\r\n </DialogBody>\r\n </DialogSurface>\r\n </Dialog>\r\n <Dialog open={!!extensionInstallError} modalType=\"alert\">\r\n <DialogSurface>\r\n <DialogBody>\r\n <DialogTitle>\r\n <div className={classes.extensionErrorTitleDiv}>\r\n Extension Install Error\r\n <ErrorCircleRegular className={classes.extensionErrorIcon} />\r\n </div>\r\n </DialogTitle>\r\n <DialogContent>\r\n <List>\r\n <ListItem>\r\n <Body1>{`Extension \"${extensionInstallError?.extension.name}\" failed to install and was removed.`}</Body1>\r\n </ListItem>\r\n <ListItem>\r\n <Body1>{`${extensionInstallError?.error}`}</Body1>\r\n </ListItem>\r\n </List>\r\n </DialogContent>\r\n <DialogActions>\r\n <Button appearance=\"primary\" onClick={onAcknowledgedExtensionInstallError}>\r\n Close\r\n </Button>\r\n </DialogActions>\r\n </DialogBody>\r\n </DialogSurface>\r\n </Dialog>\r\n <Suspense fallback={<Spinner className={classes.spinner} />}>\r\n <Content />\r\n </Suspense>\r\n </ToastProvider>\r\n </Theme>\r\n </ExtensionManagerContext.Provider>\r\n </SettingsStoreContext.Provider>\r\n </ReactContextsWrapper>\r\n );\r\n }\r\n };\r\n\r\n // Set the container element to be a flex container so that the tool can be displayed properly.\r\n const originalContainerElementDisplay = containerElement.style.display;\r\n containerElement.style.display = \"flex\";\r\n\r\n // Create and render the react root component.\r\n const reactRoot = createRoot(containerElement);\r\n reactRoot.render(createElement(modularToolRootComponent));\r\n\r\n let disposed = false;\r\n return {\r\n dispose: () => {\r\n // Unmount and restore the original container element display.\r\n if (!disposed) {\r\n disposed = true;\r\n reactRoot.unmount();\r\n containerElement.style.display = originalContainerElementDisplay;\r\n }\r\n },\r\n };\r\n}\r\n"]}
1
+ {"version":3,"file":"modularTool.js","sourceRoot":"","sources":["../../../../dev/sharedUiComponents/src/modularTool/modularTool.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\r\n type ComponentType,\r\n type Context,\r\n type FunctionComponent,\r\n type PropsWithChildren,\r\n type ReactNode,\r\n createElement,\r\n Suspense,\r\n useCallback,\r\n useEffect,\r\n useReducer,\r\n useState,\r\n} from \"react\";\r\n\r\nimport { type IExtensionFeed } from \"./extensibility/extensionFeed\";\r\nimport { type IExtension, type InstallFailedInfo, ExtensionManager } from \"./extensibility/extensionManager\";\r\nimport { type WeaklyTypedServiceDefinition, ServiceContainer } from \"./modularity/serviceContainer\";\r\nimport { type ISettingsStore, SettingsStore, SettingsStoreIdentity } from \"./services/settingsStore\";\r\nimport { type IRootComponentService, type ShellServiceOptions, MakeShellServiceDefinition, RootComponentServiceIdentity } from \"./services/shellService\";\r\nimport { type ThemeMode, ThemeModeSettingDescriptor, ThemeServiceDefinition } from \"./services/themeService\";\r\n\r\nimport {\r\n Body1,\r\n Button,\r\n Dialog,\r\n DialogActions,\r\n DialogBody,\r\n DialogContent,\r\n DialogSurface,\r\n DialogTitle,\r\n List,\r\n ListItem,\r\n makeStyles,\r\n Spinner,\r\n tokens,\r\n} from \"@fluentui/react-components\";\r\nimport { ErrorCircleRegular } from \"@fluentui/react-icons\";\r\nimport { createRoot } from \"react-dom/client\";\r\n\r\nimport { Deferred } from \"core/Misc/deferred\";\r\nimport { Logger } from \"core/Misc/logger\";\r\nimport { type ToastHandle, type ToastOptions, ToastProvider } from \"shared-ui-components/fluent/primitives/toast\";\r\nimport { type IToastService, ToastServiceIdentity } from \"./services/toastService\";\r\nimport { Theme } from \"./components/theme\";\r\nimport { ExtensionManagerContext } from \"./contexts/extensionManagerContext\";\r\nimport { SettingsStoreContext } from \"./contexts/settingsContext\";\r\nimport { type IReactContextService, type ReactContextHandle, ReactContextServiceIdentity } from \"./services/reactContextService\";\r\nimport { ThemeSelectorServiceDefinition } from \"./services/themeSelectorService\";\r\n\r\nconst useStyles = makeStyles({\r\n app: {\r\n colorScheme: \"light dark\",\r\n flexGrow: 1,\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n backgroundColor: tokens.colorTransparentBackground,\r\n },\r\n spinner: {\r\n flexGrow: 1,\r\n animationDuration: \"1s\",\r\n animationName: {\r\n from: { opacity: 0 },\r\n to: { opacity: 1 },\r\n },\r\n },\r\n extensionErrorTitleDiv: {\r\n display: \"flex\",\r\n flexDirection: \"row\",\r\n alignItems: \"center\",\r\n gap: tokens.spacingHorizontalS,\r\n },\r\n extensionErrorIcon: {\r\n color: tokens.colorPaletteRedForeground1,\r\n },\r\n});\r\n\r\ntype ReactContextEntry = {\r\n provider: Context<unknown>[\"Provider\"];\r\n value: unknown;\r\n order: number;\r\n};\r\n\r\ntype ReactContextAction =\r\n | { type: \"add\"; entry: ReactContextEntry }\r\n | { type: \"remove\"; provider: Context<unknown>[\"Provider\"] }\r\n | { type: \"update\"; provider: Context<unknown>[\"Provider\"]; value: unknown };\r\n\r\nconst ReactContextsWrapper: FunctionComponent<PropsWithChildren<{ contexts: readonly Readonly<ReactContextEntry>[] }>> = ({ contexts, children }) => {\r\n return <>{contexts.reduceRight<ReactNode>((acc, entry) => createElement(entry.provider, { value: entry.value }, acc), children)}</>;\r\n};\r\n\r\nexport type ModularToolOptions = {\r\n /**\r\n * The namespace for the tool, used for scoping persisted settings and other storage.\r\n */\r\n namespace: string;\r\n\r\n /**\r\n * The container element where the tool will be rendered.\r\n */\r\n containerElement: HTMLElement;\r\n\r\n /**\r\n * The service definitions to be registered with the tool.\r\n */\r\n serviceDefinitions: readonly WeaklyTypedServiceDefinition[];\r\n\r\n /**\r\n * The theme mode to use. If not specified, the default is \"system\", which uses the system/browser preference, and the last used mode is persisted.\r\n */\r\n themeMode?: ThemeMode;\r\n\r\n /**\r\n * Whether to show the theme selector in the toolbar. Default is true.\r\n */\r\n showThemeSelector?: boolean;\r\n\r\n /**\r\n * The extension feeds that provide optional extensions the user can install.\r\n */\r\n extensionFeeds?: readonly IExtensionFeed[];\r\n\r\n /**\r\n * An optional parent ServiceContainer. Dependencies not found in the tool's own container\r\n * will be resolved from this parent.\r\n */\r\n parentContainer?: ServiceContainer;\r\n} & ShellServiceOptions;\r\n\r\n/**\r\n * Creates a modular tool with a base set of common tool services, including the toolbar/side pane basic UI layout.\r\n * @param options The options for the tool.\r\n * @returns A token that can be used to dispose of the tool.\r\n */\r\nexport function MakeModularTool(options: ModularToolOptions) {\r\n const { namespace, containerElement, serviceDefinitions, themeMode, showThemeSelector = true, extensionFeeds = [], parentContainer } = options;\r\n\r\n // Create the settings store immediately as it will be exposed to services and through React context.\r\n const settingsStore = new SettingsStore(namespace);\r\n\r\n // If a theme mode is provided, just write the setting so it is the active theme.\r\n if (themeMode) {\r\n settingsStore.writeSetting(ThemeModeSettingDescriptor, themeMode);\r\n }\r\n\r\n // This deferred resolves once the React effect cleanup (which disposes the ServiceContainer) is complete.\r\n const disposeDeferred = new Deferred<void>();\r\n\r\n const modularToolRootComponent: FunctionComponent = () => {\r\n const classes = useStyles();\r\n const [extensionManagerContext, setExtensionManagerContext] = useState<ExtensionManagerContext>();\r\n const [requiredExtensions, setRequiredExtensions] = useState<string[]>();\r\n const [requiredExtensionsDeferred, setRequiredExtensionsDeferred] = useState<Deferred<boolean>>();\r\n const [extensionInstallError, setExtensionInstallError] = useState<InstallFailedInfo>();\r\n\r\n const [toastHandle, setToastHandle] = useState<ToastHandle | null>(null);\r\n const [toastQueue, setToastQueue] = useState<{ message: string; options?: ToastOptions }[]>([]);\r\n\r\n useEffect(() => {\r\n if (toastHandle && toastQueue.length > 0) {\r\n for (const { message, options } of toastQueue) {\r\n toastHandle.showToast(message, options);\r\n }\r\n setToastQueue([]);\r\n }\r\n }, [toastHandle, toastQueue]);\r\n\r\n const [rootComponentService, setRootComponentService] = useState<IRootComponentService>();\r\n\r\n const [contexts, updateContexts] = useReducer((state: ReactContextEntry[], action: ReactContextAction): ReactContextEntry[] => {\r\n switch (action.type) {\r\n case \"add\":\r\n return [...state, action.entry].sort((a, b) => a.order - b.order);\r\n case \"remove\":\r\n return state.filter((e) => e.provider !== action.provider);\r\n case \"update\":\r\n return state.map((e) => (e.provider === action.provider ? { ...e, value: action.value } : e));\r\n }\r\n }, []);\r\n\r\n // This is the main async initialization.\r\n useEffect(() => {\r\n const initializeExtensionManagerAsync = async () => {\r\n const serviceContainer = new ServiceContainer(\"ModularToolContainer\", parentContainer);\r\n\r\n // Expose the settings store as a service so other services can read/write settings.\r\n serviceContainer.addService<[ISettingsStore], []>({\r\n friendlyName: \"Settings Store\",\r\n produces: [SettingsStoreIdentity],\r\n factory: () => settingsStore,\r\n });\r\n\r\n // Expose the react context service so other services can add React context providers.\r\n serviceContainer.addService<[IReactContextService], []>({\r\n friendlyName: \"React Context Service\",\r\n produces: [ReactContextServiceIdentity],\r\n factory: (): IReactContextService => ({\r\n addContext<T>(provider: Context<T>[\"Provider\"], initialValue: T, options?: { order?: number }): ReactContextHandle<T> {\r\n const typedProvider = provider as Context<unknown>[\"Provider\"];\r\n updateContexts({ type: \"add\", entry: { provider: typedProvider, value: initialValue, order: options?.order ?? 0 } });\r\n return {\r\n updateValue: (newValue: T) => {\r\n updateContexts({ type: \"update\", provider: typedProvider, value: newValue });\r\n },\r\n dispose: () => {\r\n updateContexts({ type: \"remove\", provider: typedProvider });\r\n },\r\n };\r\n },\r\n }),\r\n });\r\n\r\n // Expose the toast service so non-React code (e.g. Observable callbacks) can show toasts.\r\n serviceContainer.addService<[IToastService], []>({\r\n friendlyName: \"Toast Service\",\r\n produces: [ToastServiceIdentity],\r\n factory: (): IToastService => ({\r\n showToast: (message, options) => {\r\n setToastQueue((prev) => [...prev, { message, options }]);\r\n },\r\n }),\r\n });\r\n\r\n // Register the shell service (top level toolbar/side pane UI layout).\r\n serviceContainer.addService(MakeShellServiceDefinition(options));\r\n\r\n // Register a service that simply consumes the services we need before first render.\r\n serviceContainer.addService<[], [IRootComponentService]>({\r\n friendlyName: \"Service Bootstrapper\",\r\n consumes: [RootComponentServiceIdentity],\r\n factory: (rootComponent) => {\r\n // Use function syntax for the state setter since the root component may be a function component.\r\n setRootComponentService(() => rootComponent);\r\n return {\r\n dispose: () => setRootComponentService(undefined),\r\n };\r\n },\r\n });\r\n\r\n // Register the theme service (exposes the current theme to other services).\r\n serviceContainer.addService(ThemeServiceDefinition);\r\n\r\n // Register the theme selector service (for selecting the theme) if theming is configured.\r\n if (showThemeSelector) {\r\n serviceContainer.addService(ThemeSelectorServiceDefinition);\r\n }\r\n\r\n // Register the extension list service (for browsing/installing extensions) if extension feeds are provided.\r\n if (extensionFeeds.length > 0) {\r\n const { ExtensionListServiceDefinition } = await import(\"./services/extensionsListService\");\r\n serviceContainer.addService(ExtensionListServiceDefinition);\r\n }\r\n\r\n // Register all external services (that make up a unique tool).\r\n serviceContainer.addServices(...serviceDefinitions);\r\n\r\n // Create the extension manager, passing along the registry for runtime changes to the registered services.\r\n const extensionManager = await ExtensionManager.CreateAsync(namespace, serviceContainer, extensionFeeds, setExtensionInstallError);\r\n\r\n // Check query params for required extensions. This lets users share links with sets of extensions.\r\n const queryParams = new URLSearchParams(window.location.search);\r\n const requiredExtensions = queryParams.getAll(\"babylon.requiredExtension\");\r\n const uninstalledExtensions: IExtension[] = [];\r\n for (const requiredExtension of requiredExtensions) {\r\n // These could possibly be parallelized to speed things up, but it's more complex so let's wait and see if we need it.\r\n // eslint-disable-next-line no-await-in-loop\r\n const query = await extensionManager.queryExtensionsAsync(requiredExtension);\r\n // eslint-disable-next-line no-await-in-loop\r\n const extensions = await query.getExtensionsAsync(0, query.totalCount);\r\n for (const extension of extensions) {\r\n if (!extension.isInstalled) {\r\n uninstalledExtensions.push(extension);\r\n }\r\n }\r\n }\r\n\r\n // Check if any required extensions are uninstalled or disabled. If so, show a dialog to the user.\r\n if (uninstalledExtensions.length > 0) {\r\n setRequiredExtensions(uninstalledExtensions.map((extension) => extension.metadata.name));\r\n const deferred = new Deferred<boolean>();\r\n setRequiredExtensionsDeferred(deferred);\r\n if (await deferred.promise) {\r\n for (const extension of uninstalledExtensions) {\r\n // This could possibly be parallelized to speed things up, but it's more complex so let's wait and see if we need it.\r\n // eslint-disable-next-line no-await-in-loop\r\n await extension.installAsync();\r\n }\r\n }\r\n }\r\n\r\n // Set the contexts.\r\n setExtensionManagerContext({ extensionManager });\r\n\r\n return () => {\r\n extensionManager.dispose();\r\n serviceContainer.dispose();\r\n serviceContainer.dispose();\r\n };\r\n };\r\n\r\n const disposePromise = initializeExtensionManagerAsync();\r\n\r\n return () => {\r\n disposePromise\r\n // eslint-disable-next-line github/no-then\r\n .then((dispose) => dispose())\r\n // eslint-disable-next-line github/no-then\r\n .catch((error) => {\r\n Logger.Error(`Failed to dispose of the modular tool: ${error}`);\r\n })\r\n .finally(() => disposeDeferred.resolve());\r\n };\r\n }, []);\r\n\r\n const onAcceptRequiredExtensions = useCallback(() => {\r\n setRequiredExtensions(undefined);\r\n requiredExtensionsDeferred?.resolve(true);\r\n }, [setRequiredExtensions, requiredExtensionsDeferred]);\r\n\r\n const onRejectRequiredExtensions = useCallback(() => {\r\n setRequiredExtensions(undefined);\r\n requiredExtensionsDeferred?.resolve(false);\r\n }, [setRequiredExtensions, requiredExtensionsDeferred]);\r\n\r\n const onAcknowledgedExtensionInstallError = useCallback(() => {\r\n setExtensionInstallError(undefined);\r\n }, [setExtensionInstallError]);\r\n\r\n // Show a spinner until a main view has been set.\r\n if (!rootComponentService) {\r\n return (\r\n <ReactContextsWrapper contexts={contexts}>\r\n <SettingsStoreContext.Provider value={settingsStore}>\r\n <Theme className={classes.app}>\r\n <Spinner className={classes.spinner} />\r\n </Theme>\r\n </SettingsStoreContext.Provider>\r\n </ReactContextsWrapper>\r\n );\r\n } else {\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n const Content: ComponentType = rootComponentService.rootComponent;\r\n\r\n return (\r\n <ReactContextsWrapper contexts={contexts}>\r\n {/* Expose the settings store as a React context so that UI components can read/write\r\n settings without the ISettingsService needing to be explicitly passed around. */}\r\n <SettingsStoreContext.Provider value={settingsStore}>\r\n <ExtensionManagerContext.Provider value={extensionManagerContext}>\r\n <Theme className={classes.app}>\r\n <ToastProvider imperativeRef={setToastHandle}>\r\n <Dialog open={!!requiredExtensions} modalType=\"alert\">\r\n <DialogSurface>\r\n <DialogBody>\r\n <DialogTitle>Required Extensions</DialogTitle>\r\n <DialogContent>\r\n Opening this URL requires the following extensions to be installed and enabled:\r\n <ul>\r\n {requiredExtensions?.map((name) => (\r\n <li key={name}>{name}</li>\r\n ))}\r\n </ul>\r\n </DialogContent>\r\n <DialogActions>\r\n <Button appearance=\"primary\" onClick={onAcceptRequiredExtensions}>\r\n Install & Enable\r\n </Button>\r\n <Button appearance=\"secondary\" onClick={onRejectRequiredExtensions}>\r\n No Thanks\r\n </Button>\r\n </DialogActions>\r\n </DialogBody>\r\n </DialogSurface>\r\n </Dialog>\r\n <Dialog open={!!extensionInstallError} modalType=\"alert\">\r\n <DialogSurface>\r\n <DialogBody>\r\n <DialogTitle>\r\n <div className={classes.extensionErrorTitleDiv}>\r\n Extension Install Error\r\n <ErrorCircleRegular className={classes.extensionErrorIcon} />\r\n </div>\r\n </DialogTitle>\r\n <DialogContent>\r\n <List>\r\n <ListItem>\r\n <Body1>{`Extension \"${extensionInstallError?.extension.name}\" failed to install and was removed.`}</Body1>\r\n </ListItem>\r\n <ListItem>\r\n <Body1>{`${extensionInstallError?.error}`}</Body1>\r\n </ListItem>\r\n </List>\r\n </DialogContent>\r\n <DialogActions>\r\n <Button appearance=\"primary\" onClick={onAcknowledgedExtensionInstallError}>\r\n Close\r\n </Button>\r\n </DialogActions>\r\n </DialogBody>\r\n </DialogSurface>\r\n </Dialog>\r\n <Suspense fallback={<Spinner className={classes.spinner} />}>\r\n <Content />\r\n </Suspense>\r\n </ToastProvider>\r\n </Theme>\r\n </ExtensionManagerContext.Provider>\r\n </SettingsStoreContext.Provider>\r\n </ReactContextsWrapper>\r\n );\r\n }\r\n };\r\n\r\n // Set the container element to be a flex container so that the tool can be displayed properly.\r\n const originalContainerElementDisplay = containerElement.style.display;\r\n containerElement.style.display = \"flex\";\r\n\r\n // Create and render the react root component.\r\n const reactRoot = createRoot(containerElement);\r\n reactRoot.render(createElement(modularToolRootComponent));\r\n\r\n let disposed = false;\r\n return {\r\n // eslint-disable-next-line @typescript-eslint/promise-function-async\r\n dispose: () => {\r\n // Unmount and restore the original container element display.\r\n if (!disposed) {\r\n disposed = true;\r\n reactRoot.unmount();\r\n containerElement.style.display = originalContainerElementDisplay;\r\n }\r\n // The promise resolves once the React effect cleanup\r\n // (which disposes the ServiceContainer) has completed.\r\n return disposeDeferred.promise;\r\n },\r\n };\r\n}\r\n"]}
@@ -26,20 +26,19 @@ export declare class ServiceContainer implements IDisposable {
26
26
  */
27
27
  constructor(_friendlyName: string, _parent?: ServiceContainer | undefined);
28
28
  /**
29
- * Adds a set of service definitions in the service container.
29
+ * Adds a set of service definitions to the service container.
30
30
  * The services are sorted based on their dependencies.
31
- * @param args The service definitions to register, and optionally an abort signal.
32
- * @returns A disposable that will remove the service definition from the service container.
31
+ * @param serviceDefinitions The service definitions to register.
32
+ * @returns A disposable that will remove the service definitions from the service container.
33
33
  */
34
- addServicesAsync(...args: WeaklyTypedServiceDefinition[] | [...serviceDefinitions: WeaklyTypedServiceDefinition[], abortSignal: AbortSignal]): Promise<IDisposable>;
34
+ addServices(...serviceDefinitions: WeaklyTypedServiceDefinition[]): IDisposable;
35
35
  /**
36
36
  * Registers a service definition in the service container.
37
37
  * @param serviceDefinition The service definition to register.
38
- * @param abortSignal An optional abort signal.
39
38
  * @returns A disposable that will remove the service definition from the service container.
40
39
  */
41
- addServiceAsync<Produces extends IService<symbol>[] = [], Consumes extends IService<symbol>[] = []>(serviceDefinition: ServiceDefinition<Produces, Consumes>, abortSignal?: AbortSignal): Promise<IDisposable>;
42
- private _addServiceAsync;
40
+ addService<Produces extends IService<symbol>[] = [], Consumes extends IService<symbol>[] = []>(serviceDefinition: ServiceDefinition<Produces, Consumes>): IDisposable;
41
+ private _addService;
43
42
  /**
44
43
  * Resolves a dependency by contract identity for a consuming service.
45
44
  * Checks local services first, then walks up the parent chain.