UNPKG

@joist/di

Version:

Dependency Injection for Vanilla JS classes

59 lines (50 loc) 1.44 kB
import { injectableEl } from "./dom/injectable-el.js"; import { INJECTOR, Injector } from "./injector.js"; import type { ConstructableToken, InjectionToken, Provider, } from "./provider.js"; export interface InjectableOpts { name?: string; providers?: Iterable<Provider<any>>; provideSelfAs?: InjectionToken<any>[]; } export function injectable(opts?: InjectableOpts) { return function injectableDecorator<T extends ConstructableToken<any>>( Base: T, ctx: ClassDecoratorContext, ): T { const def = { [Base.name]: class extends Base { [INJECTOR]: Injector; constructor(...args: any[]) { super(...args); this[INJECTOR] = new Injector(opts); this[INJECTOR].providers.set(Injector, { factory: () => this[INJECTOR], }); if (opts?.provideSelfAs) { for (const token of opts.provideSelfAs) { this[INJECTOR].providers.set(token, { factory: () => this, }); } } } }, }; // Only apply custom element bootstrap logic if the decorated class is an HTMLElement if ("HTMLElement" in globalThis) { if ( Object.prototype.isPrototypeOf.call( HTMLElement.prototype, Base.prototype, ) ) { return injectableEl(def[Base.name], ctx); } } return def[Base.name]; }; }