From e5cdf7d369fa598dcfb391f487958a01abc00443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 5 Jun 2023 22:58:02 +0200 Subject: [PATCH] Bundle extension type --- .../src/apps/backoffice/backoffice.element.ts | 6 +++- .../bundle-extension-initializer.ts | 33 +++++++++++++++++++ .../src/libs/extension-api/index.ts | 13 ++++---- .../src/libs/extension-api/types.ts | 24 ++++++++++++-- .../packages/documents/package-entry-point.ts | 6 ---- .../src/packages/documents/umbraco-package.ts | 8 ++--- 6 files changed, 70 insertions(+), 20 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/libs/extension-api/bundle-extension-initializer.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/package-entry-point.ts diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts index 1c9be757c1..983b190c0a 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts @@ -3,7 +3,10 @@ import { UmbBackofficeContext, UMB_BACKOFFICE_CONTEXT_TOKEN } from './backoffice import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { UmbEntryPointExtensionInitializer } from '@umbraco-cms/backoffice/extension-api'; +import { + UmbBundleExtensionInitializer, + UmbEntryPointExtensionInitializer, +} from '@umbraco-cms/backoffice/extension-api'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import './components/index.js'; @@ -31,6 +34,7 @@ export class UmbBackofficeElement extends UmbLitElement { constructor() { super(); this.provideContext(UMB_BACKOFFICE_CONTEXT_TOKEN, new UmbBackofficeContext()); + new UmbBundleExtensionInitializer(this, umbExtensionsRegistry); new UmbEntryPointExtensionInitializer(this, umbExtensionsRegistry); new UmbExtensionInitializer(this, umbExtensionsRegistry); this.#extensionInitializer.setLocalPackages(CORE_PACKAGES); diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/bundle-extension-initializer.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/bundle-extension-initializer.ts new file mode 100644 index 0000000000..11407f5020 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/bundle-extension-initializer.ts @@ -0,0 +1,33 @@ +import type { ManifestBundle } from './types.js'; +import { loadExtension } from './load-extension.function.js'; +import { UmbExtensionRegistry } from './registry/extension.registry.js'; +import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; + +export class UmbBundleExtensionInitializer { + #host; + #extensionRegistry; + #bundleMap = new Map(); + + constructor(host: UmbControllerHostElement, extensionRegistry: UmbExtensionRegistry) { + this.#host = host; + this.#extensionRegistry = extensionRegistry; + extensionRegistry.extensionsOfType('bundle').subscribe((bundles) => { + bundles.forEach((bundle) => { + if (this.#bundleMap.has(bundle.alias)) return; + this.#bundleMap.set(bundle.alias, bundle); + // TODO: Should we unInit a entry point if is removed? + this.instantiateBundle(bundle); + }); + }); + } + + async instantiateBundle(manifest: ManifestBundle) { + const js = await loadExtension(manifest); + + if (js) { + Object.keys(js).forEach((key) => { + this.#extensionRegistry.registerMany(js[key]); + }); + } + } +} diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/index.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/index.ts index b1b67865e7..53457d7459 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/index.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/index.ts @@ -1,11 +1,12 @@ -export * from './registry/extension.registry.js'; -export * from './type-guards/index.js'; +export * from './bundle-extension-initializer.js'; +export * from './create-extension-class.function.js'; +export * from './create-extension-element-or-fallback.function.js'; export * from './create-extension-element.function.js'; +export * from './entry-point-extension-initializer.js'; export * from './has-default-export.function.js'; export * from './has-init-export.function.js'; export * from './load-extension.function.js'; -export * from './create-extension-element-or-fallback.function.js'; -export * from './create-extension-class.function.js'; -export * from './umb-lifecycle.interface.js'; -export * from './entry-point-extension-initializer.js'; +export * from './registry/extension.registry.js'; +export * from './type-guards/index.js'; export * from './types.js'; +export * from './umb-lifecycle.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/types.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/types.ts index c3d1ff5187..a4e677b047 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/types.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/types.ts @@ -1,3 +1,7 @@ +import { UmbBackofficeExtensionRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbExtensionRegistry } from './registry/extension.registry.js'; +import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; + // eslint-disable-next-line @typescript-eslint/no-explicit-any export type HTMLElementConstructor = new (...args: any[]) => T; @@ -71,7 +75,6 @@ export interface ManifestWithLoader extends ManifestBase { */ export interface ManifestClass extends ManifestWithLoader<{ default: ClassConstructor }> { - /** * @TJS-ignore */ @@ -101,7 +104,6 @@ export interface ManifestClassWithClassConstructor extends Manifest export interface ManifestElement extends ManifestWithLoader<{ default: ClassConstructor } | Omit> { - /** * @TJS-ignore */ @@ -157,7 +159,10 @@ export interface ManifestWithMeta extends ManifestBase { * This type of extension gives full control and will simply load the specified JS file * You could have custom logic to decide which extensions to load/register by using extensionRegistry */ -export interface ManifestEntryPoint extends ManifestBase { +export interface ManifestEntryPoint + extends ManifestWithLoader<{ + onInit: (host: UmbControllerHostElement, extensionApi: UmbBackofficeExtensionRegistry) => void; + }> { type: 'entryPoint'; /** @@ -165,3 +170,16 @@ export interface ManifestEntryPoint extends ManifestBase { */ js: string; } + +/** + * This type of extension takes a JS module and registers all exported manifests from the pointed JS file. + */ +export interface ManifestBundle + extends ManifestWithLoader<{ [key: string]: Array }> { + type: 'bundle'; + + /** + * The file location of the javascript file to load in the backoffice + */ + js: string; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/package-entry-point.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/package-entry-point.ts deleted file mode 100644 index 9b5ff0c59e..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/package-entry-point.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { manifests } from './manifests.js'; -import type { UmbEntryPointOnInit } from '@umbraco-cms/backoffice/extension-api'; - -export const onInit: UmbEntryPointOnInit = (_host, extensionRegistry) => { - extensionRegistry.registerMany(manifests); -}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/umbraco-package.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/umbraco-package.ts index a0b11b8baf..260460b442 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/umbraco-package.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/umbraco-package.ts @@ -1,9 +1,9 @@ export const name = 'Umbraco.Core.DocumentManagement'; export const extensions = [ { - name: 'Document Management Entry Point', - alias: 'Umb.EntryPoint.DocumentManagement', - type: 'entryPoint', - loader: () => import('./package-entry-point.js'), + name: 'Document Management Bundle', + alias: 'Umb.Bundle.DocumentManagement', + type: 'bundle', + loader: () => import('./manifests.js'), }, ];