Bundle extension type

This commit is contained in:
Niels Lyngsø
2023-06-05 22:58:02 +02:00
parent f4e9af1e02
commit e5cdf7d369
6 changed files with 70 additions and 20 deletions

View File

@@ -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);

View File

@@ -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<ManifestBundle>) {
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]);
});
}
}
}

View File

@@ -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';

View File

@@ -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<T = HTMLElement> = new (...args: any[]) => T;
@@ -71,7 +75,6 @@ export interface ManifestWithLoader<LoaderReturnType> extends ManifestBase {
*/
export interface ManifestClass<ClassType = unknown>
extends ManifestWithLoader<{ default: ClassConstructor<ClassType> }> {
/**
* @TJS-ignore
*/
@@ -101,7 +104,6 @@ export interface ManifestClassWithClassConstructor<T = unknown> extends Manifest
export interface ManifestElement<ElementType extends HTMLElement = HTMLElement>
extends ManifestWithLoader<{ default: ClassConstructor<ElementType> } | Omit<object, 'default'>> {
/**
* @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<UmbBackofficeExtensionRegistry['MANIFEST_TYPES']> }> {
type: 'bundle';
/**
* The file location of the javascript file to load in the backoffice
*/
js: string;
}

View File

@@ -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);
};

View File

@@ -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'),
},
];