import "../core/metadata.ts"; import { defineMetadata, getMetadata } from "../core/metadata.ts"; import type { AbstractType, ProviderScope, Token, Type, } from "../core/container.ts"; export const MODULE_METADATA_KEY = "muddle:module"; export interface ModuleOptions { /** Controllers instantiated by this module. */ controllers?: Type[]; /** Providers available inside this module. */ providers?: (Type | AbstractType | ProviderDefinitionLike)[]; /** Modules whose exported providers are visible here. */ imports?: Type[]; /** Tokens (or modules) re-exported to importers of this module. */ exports?: Token[]; } export interface ProviderDefinitionLike { provide?: Token; useValue?: unknown; useClass?: AbstractType; useFactory?: (...dependencies: unknown[]) => unknown; inject?: Token[]; scope?: ProviderScope; } /** Marks a class as injectable and therefore eligible for type based injection. */ export const INJECTABLE_METADATA_KEY = "muddle:injectable"; export function Injectable( options: { scope?: ProviderScope } = {}, ): ClassDecorator { return (target) => { defineMetadata(INJECTABLE_METADATA_KEY, options, target as object); return target; }; } /** Declares a module. */ export function Module(options: ModuleOptions): ClassDecorator { return (target) => { defineMetadata(MODULE_METADATA_KEY, options, target as object); return target; }; } /** Reads the options of a `@Module()` decorated class. */ export function getModuleOptions(target: object): ModuleOptions { return ( (getMetadata(MODULE_METADATA_KEY, target) as ModuleOptions | undefined) ?? {} ); } /** Reads the options of an `@Injectable()` decorated class. */ export function getInjectableOptions(target: object): { scope?: ProviderScope; } { return ( (getMetadata(INJECTABLE_METADATA_KEY, target) as | { scope?: ProviderScope } | undefined) ?? {} ); }