broad implementation
This commit is contained in:
@@ -61,7 +61,7 @@ describe('UmbExtensionRegistry', () => {
|
||||
it('should get an extension by alias', (done) => {
|
||||
const alias = 'Umb.Test.Section.1';
|
||||
extensionRegistry
|
||||
.getByAlias(alias)
|
||||
.getByTypeAndAlias('section', alias)
|
||||
.subscribe((extension) => {
|
||||
expect(extension?.alias).to.eq(alias);
|
||||
done();
|
||||
@@ -85,31 +85,29 @@ describe('UmbExtensionRegistry', () => {
|
||||
});
|
||||
|
||||
// TODO: What kind of weighting would we like to use?
|
||||
/*
|
||||
it('should return extensions ordered by weight', (done) => {
|
||||
extensionRegistry
|
||||
.extensionsOfType(type)
|
||||
.subscribe((extensions) => {
|
||||
expect(extensions?.[0]?.weight).to.eq(200);
|
||||
expect(extensions?.[0]?.weight).to.eq(1);
|
||||
expect(extensions?.[1]?.weight).to.eq(25);
|
||||
expect(extensions?.[2]?.weight).to.eq(1);
|
||||
expect(extensions?.[2]?.weight).to.eq(200);
|
||||
done();
|
||||
})
|
||||
.unsubscribe();
|
||||
});
|
||||
*/
|
||||
});
|
||||
});
|
||||
|
||||
describe('UmbExtensionRegistry with kinds', () => {
|
||||
let extensionRegistry: UmbExtensionRegistry;
|
||||
let kinds: Array<ManifestKind>;
|
||||
let manifests: Array<ManifestTypes>;
|
||||
let manifests: Array<ManifestTypes | ManifestKind>;
|
||||
|
||||
beforeEach(() => {
|
||||
extensionRegistry = new UmbExtensionRegistry();
|
||||
kinds = [
|
||||
manifests = [
|
||||
{
|
||||
type: 'kind',
|
||||
matchType: 'section',
|
||||
matchKind: 'test-kind',
|
||||
manifest: {
|
||||
@@ -117,8 +115,6 @@ describe('UmbExtensionRegistry with kinds', () => {
|
||||
elementName: 'my-kind-element',
|
||||
},
|
||||
},
|
||||
];
|
||||
manifests = [
|
||||
{
|
||||
type: 'section',
|
||||
kind: 'test-kind',
|
||||
@@ -161,13 +157,12 @@ describe('UmbExtensionRegistry with kinds', () => {
|
||||
},
|
||||
];
|
||||
|
||||
kinds.forEach((kind) => extensionRegistry.defineKind(kind));
|
||||
manifests.forEach((manifest) => extensionRegistry.register(manifest));
|
||||
});
|
||||
|
||||
it('should merge with kinds', (done) => {
|
||||
extensionRegistry
|
||||
.getByTypeWithKinds('section')
|
||||
.extensionsOfType('section')
|
||||
.subscribe((extensions) => {
|
||||
expect(extensions).to.have.lengthOf(3);
|
||||
expect(extensions?.[0]?.elementName).to.eq('my-kind-element');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BehaviorSubject, withLatestFrom, map, Observable } from 'rxjs';
|
||||
import { BehaviorSubject, withLatestFrom, map, find, Observable } from 'rxjs';
|
||||
import type {
|
||||
ManifestTypes,
|
||||
ManifestTypeMap,
|
||||
@@ -16,11 +16,6 @@ export class UmbExtensionRegistry {
|
||||
// TODO: Use UniqueBehaviorSubject, as we don't want someone to edit data of extensions.
|
||||
private _extensions = new BehaviorSubject<Array<ManifestBase>>([]);
|
||||
public readonly extensions = this._extensions.asObservable();
|
||||
/*
|
||||
public readonly entryPoints = this._extensions.pipe(
|
||||
map((extensions) => extensions.filter((e) => e.type === 'entrypoint'))
|
||||
);
|
||||
*/
|
||||
|
||||
private _kinds = new BehaviorSubject<Array<ManifestKind>>([]);
|
||||
public readonly kinds = this._kinds.asObservable();
|
||||
@@ -35,16 +30,21 @@ export class UmbExtensionRegistry {
|
||||
this._kinds.next(nextData);
|
||||
}
|
||||
|
||||
register(manifest: ManifestTypes, rootHost?: UmbControllerHostInterface): void {
|
||||
const extensionsValues = this._extensions.getValue();
|
||||
const extension = extensionsValues.find((extension) => extension.alias === manifest.alias);
|
||||
|
||||
if (extension) {
|
||||
console.error(`Extension with alias ${manifest.alias} is already registered`);
|
||||
register(manifest: ManifestTypes | ManifestKind, rootHost?: UmbControllerHostInterface): void {
|
||||
if (manifest.type === 'kind') {
|
||||
this.defineKind(manifest as ManifestKind);
|
||||
return;
|
||||
}
|
||||
|
||||
this._extensions.next([...extensionsValues, manifest]);
|
||||
const extensionsValues = this._extensions.getValue();
|
||||
const extension = extensionsValues.find((extension) => extension.alias === (manifest as ManifestTypes).alias);
|
||||
|
||||
if (extension) {
|
||||
console.error(`Extension with alias ${(manifest as ManifestTypes).alias} is already registered`);
|
||||
return;
|
||||
}
|
||||
|
||||
this._extensions.next([...extensionsValues, manifest as ManifestTypes]);
|
||||
|
||||
// If entrypoint extension, we should load and run it immediately
|
||||
if (manifest.type === 'entrypoint') {
|
||||
@@ -75,25 +75,48 @@ export class UmbExtensionRegistry {
|
||||
return values.some((ext) => ext.alias === alias);
|
||||
}
|
||||
|
||||
/*
|
||||
getByAlias(alias: string) {
|
||||
// TODO: make pipes prettier/simpler/reuseable
|
||||
return this.extensions.pipe(map((extensions) => extensions.find((extension) => extension.alias === alias) || null));
|
||||
}
|
||||
*/
|
||||
|
||||
kindsOfType<Key extends keyof ManifestTypeMap | string>(type: Key) {
|
||||
private _kindsOfType<Key extends keyof ManifestTypeMap | string>(type: Key) {
|
||||
return this.kinds.pipe(map((kinds) => kinds.filter((kind) => kind.matchType === type)));
|
||||
// TODO: DisctinctUntilChanged by using aliases?
|
||||
}
|
||||
private _extensionsOfType<Key extends keyof ManifestTypeMap | string>(type: Key) {
|
||||
return this.extensions.pipe(map((exts) => exts.filter((ext) => ext.type === type)));
|
||||
// TODO: DisctinctUntilChanged by using aliases?
|
||||
}
|
||||
private _kindsOfTypes(types: string[]) {
|
||||
return this.kinds.pipe(map((kinds) => kinds.filter((kind) => types.indexOf(kind.matchType) !== -1)));
|
||||
// TODO: DisctinctUntilChanged by using aliases?
|
||||
}
|
||||
private _extensionsOfTypes<ExtensionType = ManifestBase>(types: string[]): Observable<Array<ExtensionType>> {
|
||||
return this.extensions.pipe(map((exts) => exts.filter((ext) => types.indexOf(ext.type) !== -1))) as Observable<
|
||||
Array<ExtensionType>
|
||||
>;
|
||||
// TODO: DisctinctUntilChanged by using aliases?
|
||||
}
|
||||
|
||||
getByTypeWithKinds<Key extends keyof ManifestTypeMap | string, T = SpecificManifestTypeOrManifestBase<Key>>(
|
||||
type: Key
|
||||
getByTypeAndAlias<Key extends keyof ManifestTypeMap | string, T = SpecificManifestTypeOrManifestBase<Key>>(
|
||||
type: Key,
|
||||
alias: string
|
||||
) {
|
||||
/*
|
||||
return this.extensionsOfType(type).pipe(
|
||||
map((extensions) => extensions.find((extension) => extension.alias === alias) || null)
|
||||
);
|
||||
*/
|
||||
return this.extensionsOfType(type).pipe(
|
||||
withLatestFrom(this.kindsOfType(type)),
|
||||
return this.extensions.pipe(
|
||||
map((exts) => exts.find((ext) => ext.type === type && ext.alias === alias)),
|
||||
withLatestFrom(this._kindsOfType(type)),
|
||||
map(([ext, kinds]) => {
|
||||
return ext ? { ...kinds.find((kind) => kind.matchKind === ext.kind)?.manifest, ...ext } : undefined;
|
||||
})
|
||||
) as Observable<T | undefined>;
|
||||
}
|
||||
|
||||
extensionsOfType<Key extends keyof ManifestTypeMap | string, T = SpecificManifestTypeOrManifestBase<Key>>(type: Key) {
|
||||
return this._extensionsOfType(type).pipe(
|
||||
withLatestFrom(this._kindsOfType(type)),
|
||||
map(([exts, kinds]) =>
|
||||
exts
|
||||
.map((ext) => {
|
||||
@@ -103,40 +126,30 @@ export class UmbExtensionRegistry {
|
||||
)
|
||||
) as Observable<Array<T>>;
|
||||
//
|
||||
// TODO: DisctinctUntilChanged by using aliases?
|
||||
}
|
||||
|
||||
getByTypeAndAlias<Key extends keyof ManifestTypeMap | string, T = SpecificManifestTypeOrManifestBase<Key>>(
|
||||
type: Key,
|
||||
alias: string
|
||||
) {
|
||||
/*
|
||||
return this.extensionsOfType(type).pipe(
|
||||
map((extensions) => extensions.find((extension) => extension.alias === alias) || null)
|
||||
);
|
||||
*/
|
||||
return this.extensions.pipe(
|
||||
map((exts) =>
|
||||
exts.filter((ext) => ext.type === type && ext.alias === alias).sort((a, b) => (a.weight || 0) - (b.weight || 0))
|
||||
extensionsOfTypes<ExtensionTypes = ManifestBase>(types: string[]): Observable<Array<ExtensionTypes>> {
|
||||
return this._extensionsOfTypes(types).pipe(
|
||||
withLatestFrom(this._kindsOfTypes(types)),
|
||||
map(([exts, kinds]) =>
|
||||
exts
|
||||
.map((ext) => {
|
||||
return { ...kinds.find((kind) => kind.matchKind === ext.kind)?.manifest, ...ext };
|
||||
})
|
||||
.sort((a, b) => (a.weight || 0) - (b.weight || 0))
|
||||
)
|
||||
) as Observable<Array<T>>;
|
||||
) as Observable<Array<ExtensionTypes>>;
|
||||
//
|
||||
// TODO: DisctinctUntilChanged by using aliases?
|
||||
}
|
||||
|
||||
extensionsOfType<Key extends keyof ManifestTypeMap | string, T = SpecificManifestTypeOrManifestBase<Key>>(type: Key) {
|
||||
return this.extensions.pipe(map((exts) => exts.filter((ext) => ext.type === type))) as Observable<Array<T>>;
|
||||
//.sort((a, b) => (b.weight || 0) - (a.weight || 0))
|
||||
}
|
||||
|
||||
extensionsOfTypes<ExtensionType = ManifestBase>(types: string[]): Observable<Array<ExtensionType>> {
|
||||
return this.extensions.pipe(
|
||||
map((exts) =>
|
||||
exts.filter((ext) => types.indexOf(ext.type) !== -1).sort((a, b) => (a.weight || 0) - (b.weight || 0))
|
||||
)
|
||||
) as Observable<Array<ExtensionType>>;
|
||||
//
|
||||
}
|
||||
|
||||
extensionsSortedByTypeAndWeight<ExtensionType = ManifestBase>(): Observable<Array<ExtensionType>> {
|
||||
// TODO: consider moving this method to the extension view?
|
||||
/**
|
||||
* Gets all the extensions registrations, but does not merge with kinds.
|
||||
* @returns
|
||||
*/
|
||||
extensionRegistrationsSortedByTypeAndWeight<ExtensionType = ManifestBase>(): Observable<Array<ExtensionType>> {
|
||||
return this.extensions.pipe(
|
||||
map((exts) =>
|
||||
exts.sort((a, b) => {
|
||||
|
||||
@@ -105,6 +105,7 @@ export interface ManifestBase {
|
||||
}
|
||||
|
||||
export interface ManifestKind {
|
||||
type: 'kind';
|
||||
matchType: string;
|
||||
matchKind: string;
|
||||
manifest: Partial<ManifestTypes>;
|
||||
|
||||
Reference in New Issue
Block a user