Embed the discriminator method in ContextToken
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { expect, oneEvent } from '@open-wc/testing';
|
||||
import { UmbContextProvider } from '../provide/context-provider.js';
|
||||
import { UmbContextToken } from '../token/context-token.js';
|
||||
import { UmbContextConsumer } from './context-consumer.js';
|
||||
import { UmbContextRequestEventImplementation, umbContextRequestEventType } from './context-request.event.js';
|
||||
|
||||
@@ -111,10 +112,14 @@ describe('UmbContextConsumer with discriminator test', () => {
|
||||
|
||||
it('discriminator determines the instance type', async () => {
|
||||
|
||||
const localConsumer = new UmbContextConsumer(document.body, testContextAlias, (instance: A) => { console.log(instance)}, discriminator);
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
document.body,
|
||||
new UmbContextToken(testContextAlias, discriminator),
|
||||
(instance: A) => { console.log(instance)}
|
||||
);
|
||||
localConsumer.hostConnected();
|
||||
|
||||
// This bit of code is just to make sure the type is correct.
|
||||
// This bit of code is not really a test but it serves as a TypeScript type test, making sure the given type is matches the one given from the Discriminator method.
|
||||
type TestType = Exclude<(typeof localConsumer.instance), undefined> extends A ? true : never;
|
||||
const test: TestType = true;
|
||||
expect(test).to.be.true;
|
||||
@@ -131,14 +136,13 @@ describe('UmbContextConsumer with discriminator test', () => {
|
||||
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
testContextAlias,
|
||||
new UmbContextToken(testContextAlias, discriminator),
|
||||
(_instance) => {
|
||||
expect(_instance.prop).to.eq('value from provider');
|
||||
done();
|
||||
localConsumer.hostDisconnected();
|
||||
provider.hostDisconnected();
|
||||
},
|
||||
discriminator
|
||||
}
|
||||
);
|
||||
localConsumer.hostConnected();
|
||||
});
|
||||
@@ -152,11 +156,10 @@ describe('UmbContextConsumer with discriminator test', () => {
|
||||
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
testContextAlias,
|
||||
new UmbContextToken(testContextAlias, badDiscriminator),
|
||||
(_instance) => {
|
||||
expect(_instance.prop).to.eq('this must not happen!');
|
||||
},
|
||||
badDiscriminator
|
||||
}
|
||||
);
|
||||
localConsumer.hostConnected();
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { UmbContextToken } from '../token/context-token.js';
|
||||
import { UmbContextDiscriminator, UmbContextToken } from '../token/context-token.js';
|
||||
import {
|
||||
isUmbContextProvideEventType,
|
||||
//isUmbContextUnprovidedEventType,
|
||||
@@ -7,25 +7,23 @@ import {
|
||||
} from '../provide/context-provide.event.js';
|
||||
import { UmbContextRequestEventImplementation, UmbContextCallback } from './context-request.event.js';
|
||||
|
||||
export type UmbContextDiscriminator<T, DiscriminatorResult extends T = T> = (instance: T) => instance is DiscriminatorResult;
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @class UmbContextConsumer
|
||||
*/
|
||||
export class UmbContextConsumer<T = unknown, D extends T = T> {
|
||||
#callback?: UmbContextCallback<D>;
|
||||
#promise?: Promise<D>;
|
||||
#promiseResolver?: (instance: D) => void;
|
||||
export class UmbContextConsumer<BaseType = unknown, DiscriminatedType extends BaseType = BaseType> {
|
||||
#callback?: UmbContextCallback<DiscriminatedType>;
|
||||
#promise?: Promise<DiscriminatedType>;
|
||||
#promiseResolver?: (instance: DiscriminatedType) => void;
|
||||
|
||||
#instance?: D;
|
||||
#instance?: DiscriminatedType;
|
||||
get instance() {
|
||||
return this.#instance;
|
||||
}
|
||||
|
||||
#contextAlias: string;
|
||||
|
||||
#discriminator?: UmbContextDiscriminator<T, D>;
|
||||
#discriminator?: UmbContextDiscriminator<BaseType, DiscriminatedType>;
|
||||
|
||||
/**
|
||||
* Creates an instance of UmbContextConsumer.
|
||||
@@ -36,13 +34,12 @@ export class UmbContextConsumer<T = unknown, D extends T = T> {
|
||||
*/
|
||||
constructor(
|
||||
protected hostElement: EventTarget,
|
||||
contextAlias: string | UmbContextToken<T>,
|
||||
callback?: UmbContextCallback<D>,
|
||||
discriminator?: UmbContextDiscriminator<T, D>
|
||||
contextAlias: string | UmbContextToken<BaseType, DiscriminatedType>,
|
||||
callback?: UmbContextCallback<DiscriminatedType>
|
||||
) {
|
||||
this.#contextAlias = contextAlias.toString();
|
||||
this.#callback = callback;
|
||||
this.#discriminator = discriminator;
|
||||
this.#discriminator = (contextAlias as any).getDiscriminator?.();
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +48,7 @@ export class UmbContextConsumer<T = unknown, D extends T = T> {
|
||||
The reason for such would be to have some who are more specific than others. For example, some might just need the current workspace-context, others might need the closest handling a certain entityType.
|
||||
As I'm writing this is not relevant, but I wanted to keep the idea as we have had some circumstance that might be solved with this approach.
|
||||
*/
|
||||
protected _onResponse = (instance: T) => {
|
||||
protected _onResponse = (instance: BaseType) => {
|
||||
if (this.#instance === instance) {
|
||||
return;
|
||||
}
|
||||
@@ -61,11 +58,11 @@ export class UmbContextConsumer<T = unknown, D extends T = T> {
|
||||
this.setInstance(instance);
|
||||
}
|
||||
} else {
|
||||
this.setInstance(instance as D);
|
||||
this.setInstance(instance as DiscriminatedType);
|
||||
}
|
||||
};
|
||||
|
||||
protected setInstance(instance: D) {
|
||||
protected setInstance(instance: DiscriminatedType) {
|
||||
this.#instance = instance;
|
||||
this.#callback?.(instance);
|
||||
if (instance !== undefined) {
|
||||
@@ -77,7 +74,7 @@ export class UmbContextConsumer<T = unknown, D extends T = T> {
|
||||
public asPromise() {
|
||||
return (
|
||||
this.#promise ??
|
||||
(this.#promise = new Promise<D>((resolve) => {
|
||||
(this.#promise = new Promise<DiscriminatedType>((resolve) => {
|
||||
this.#instance ? resolve(this.#instance) : (this.#promiseResolver = resolve);
|
||||
}))
|
||||
);
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
export class UmbContextToken<T = unknown> {
|
||||
|
||||
export type UmbContextDiscriminator<BaseType, DiscriminatorResult extends BaseType = BaseType> = (instance: BaseType) => instance is DiscriminatorResult;
|
||||
|
||||
export class UmbContextToken<BaseType = unknown, DiscriminatedType extends BaseType = BaseType> {
|
||||
|
||||
#discriminator: UmbContextDiscriminator<BaseType, DiscriminatedType> | undefined;
|
||||
/**
|
||||
* Get the type of the token
|
||||
*
|
||||
@@ -8,15 +13,18 @@ export class UmbContextToken<T = unknown> {
|
||||
* @example `typeof MyToken.TYPE`
|
||||
* @returns undefined
|
||||
*/
|
||||
readonly TYPE: T = undefined as never;
|
||||
readonly TYPE: DiscriminatedType = undefined as never;
|
||||
|
||||
/**
|
||||
* @param alias Unique identifier for the token,
|
||||
* @param _desc Description for the token,
|
||||
* used only for debugging purposes,
|
||||
* it should but does not need to be unique
|
||||
* @param alias Unique identifier for the token
|
||||
*/
|
||||
constructor(protected alias: string, protected _desc?: string) {}
|
||||
constructor(protected alias: string, discriminator?: UmbContextDiscriminator<BaseType, DiscriminatedType>) {
|
||||
this.#discriminator = discriminator;
|
||||
}
|
||||
|
||||
getDiscriminator(): UmbContextDiscriminator<BaseType, DiscriminatedType> | undefined {
|
||||
return this.#discriminator;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method must always return the unique alias of the token since that
|
||||
@@ -27,4 +35,6 @@ export class UmbContextToken<T = unknown> {
|
||||
toString(): string {
|
||||
return this.alias;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user