Skip to content

Instantly share code, notes, and snippets.

@kaplan81
Last active June 28, 2022 09:45
Show Gist options
  • Save kaplan81/77c5a27b3a5c77bf6631740d91530f07 to your computer and use it in GitHub Desktop.
Save kaplan81/77c5a27b3a5c77bf6631740d91530f07 to your computer and use it in GitHub Desktop.
import { Constructor } from '../../models/constructor.model';
import { isWindow } from '../../utils/window/window.util';
/**
* // constructor.model.ts
* export type Constructor<T = unknown> = new (...args: any[]) => T;
*
* // window.util.ts
* export const isWindow = (element: typeof globalThis | Window | HTMLElement | null): boolean => {
* return element !== null
* ? typeof window !== 'undefined' && Object.prototype.hasOwnProperty.call(element, 'self')
* : false;
*
* // requester.model.ts
* export interface EnvironmentInjectorRequester {
* customElementTagName: string;
* providerKeys: string[];
* requestInstance(key: string): any | never;
* }
*
* @example
* export interface RequesterComponent extends EnvironmentInjectorRequester {}
* @Requester('app-provider', ['my-service'])
* @Component({
* changeDetection: ChangeDetectionStrategy.OnPush,
* selector: 'app-requester',
* standalone: true,
* templateUrl: './requester.component.html',
* })
* export class RequesterComponent implements OnInit {
* [...]
*/
export const Requester = (
customElementTagName: string,
providerKeys: string[],
): ((c: Constructor) => void) => {
return (requesterConstructor: Constructor) => {
/**
* By default these properties are configurable = enumerable = writable = false
*/
Object.defineProperty(requesterConstructor.prototype, 'customElementTagName', {
value: customElementTagName,
});
Object.defineProperty(requesterConstructor.prototype, 'providerKeys', {
value: providerKeys,
});
requesterConstructor.prototype.requestInstance = function (key: string): any | never {
if (isWindow(globalThis)) {
const event = new CustomEvent('request-instance', {
bubbles: true,
cancelable: true,
detail: { key },
});
globalThis.dispatchEvent(event);
return (event.detail as { instance?: any; key: string }).instance;
}
throw Error('globalThis must be Window');
};
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment