muddle/decorators/Module.ts
2026-10-23 08:53:07 -04:00

69 lines
1.8 KiB
TypeScript

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) ?? {}
);
}