-
Notifications
You must be signed in to change notification settings - Fork 0
Decorators
Shamoo has exactly 37 core decorators. The canonical import for every decorator on this page is @shamoo/decorators; focused packages such as @shamoo/lifecycle, @shamoo/commands, @shamoo/scheduler, @shamoo/guards, and @shamoo/validation re-export their relevant decorators.
import { Plugin, OnEnable } from '@shamoo/decorators';shamooc resolves imported symbols rather than trusting local function names. It stores decorator arguments as deterministic JSON-compatible values and does not use emitDecoratorMetadata. The decorator factories are intentionally permissive at the TypeScript surface; the tables describe the arguments consumed by the compiler or expected by framework contracts.
| Decorator and import | Target | Arguments | Example |
|---|---|---|---|
Plugin from @shamoo/decorators
|
Class | Optional declaration object; commonly { name }
|
@Plugin({ name: 'welcome' }) class Welcome {} |
Module from @shamoo/decorators
|
Class |
{ imports?, providers?, exports? }; arrays contain declaration values; forwardRef() is supported for intentional import cycles |
@Module({ providers: [Greeter], exports: [Greeter] }) class AppModule {} |
Component from @shamoo/decorators
|
Class | Optional declaration object | @Component() class JoinListener {} |
Injectable from @shamoo/decorators
|
Class | Optional declaration object; compiler kind is the same component kind as Component
|
@Injectable() class Formatter {} |
Service from @shamoo/decorators
|
Class | Optional { scope?: Scope, token?: ServiceIdentifier }
|
@Service({ scope: Scope.PLUGIN }) class Economy {} |
Global from @shamoo/decorators
|
Class | None; meaningful with a module declaration | @Module() @Global() class SharedModule {} |
Primary from @shamoo/decorators
|
Class | None; marks the preferred provider declaration | @Service() @Primary() class MainEconomy {} |
Only one of Plugin, Module, Component, Injectable, and Service may appear on a class. Global and Primary are modifiers, not substitutes for a declaration.
Current runtime limit: the compiler emits class/module/provider metadata, and @shamoo/di can execute explicit provider metadata. The bundled deployment adapter does not build that DI/module graph. It locates exported constructors by name and only constructs components with zero constructor dependencies. Global, Primary, service scope/token options, module visibility, and constructor injection therefore have no automatic deployed effect through that adapter.
All eight target a constructor/method parameter or property.
| Decorator and import | Target | Arguments | Example |
|---|---|---|---|
Inject from @shamoo/decorators
|
Parameter/property | Required ServiceIdentifier: class, token, string, or symbol |
constructor(@Inject(LOGGER) logger: Logger) {} |
Optional from @shamoo/decorators
|
Parameter/property | None; modifies dependency resolution | constructor(@Optional() logger?: Logger) {} |
InjectAll from @shamoo/decorators
|
Parameter/property | None; requests all visible providers | constructor(@InjectAll() hooks: Hook[]) {} |
Lazy from @shamoo/decorators
|
Parameter/property | None; defers resolution | constructor(@Lazy() cache: Cache) {} |
Named from @shamoo/decorators
|
Parameter/property | Name string/expression | constructor(@Named('audit') logger: Logger) {} |
Qualifier from @shamoo/decorators
|
Parameter/property | Qualifier string/expression | constructor(@Qualifier('primary') store: Store) {} |
ConfigValue from @shamoo/decorators
|
Parameter/property | Configuration key | public start(@ConfigValue('motd') motd: string): void {} |
Context from @shamoo/decorators
|
Parameter/property | Optional invocation-context key; no argument is recorded as the internal value key |
public run(@Context('event') event: unknown): void {} |
Optional, InjectAll, Lazy, Named, and Qualifier may modify the same dependency. Inject, ConfigValue, Argument, Option, Sender, and Context are competing binding sources and cannot be combined on one target. Interfaces, aliases, primitives, and type-only imports have no runtime identity and require @Inject(createToken<T>(...)).
Current runtime limit: @shamoo/di and loadRuntimeMetadata() support explicit optional, multi, lazy, named, qualified, and context dependencies. The bundled adapter does not resolve constructor/property injection or method parameter metadata. It passes the host callback's raw data argument directly. @shamoo/config defines source/decoder contracts but no file loader, reload manager, or automatic ConfigValue source.
All are imported from @shamoo/decorators or @shamoo/lifecycle, target methods, and take no required arguments.
| Decorator | Target | Arguments | Example |
|---|---|---|---|
OnLoad from @shamoo/decorators or @shamoo/lifecycle
|
Method | None | @OnLoad() load(): void {} |
OnEnable from @shamoo/decorators or @shamoo/lifecycle
|
Method | None | @OnEnable() enable(): void {} |
OnReady from @shamoo/decorators or @shamoo/lifecycle
|
Method | None | @OnReady() ready(): void {} |
OnDrain from @shamoo/decorators or @shamoo/lifecycle
|
Method | None | @OnDrain() drain(): void {} |
OnDisable from @shamoo/decorators or @shamoo/lifecycle
|
Method | None | @OnDisable() disable(): void {} |
OnUnload from @shamoo/decorators or @shamoo/lifecycle
|
Method | None | @OnUnload() unload(): void {} |
Startup order is load, enable, ready. Shutdown/replacement order is drain, disable, unload. Only one lifecycle decorator may appear on a method.
Current runtime limit: lifecycle methods are called by the bundled adapter, in metadata component order, with no injected arguments. The standalone lifecycle runtime supports deterministic ordering, DI parameters, timeout signals, idempotence, and aggregate cleanup errors, but those richer parameter semantics are not wired by the bundled adapter. There is no OnReload; development changes replace a complete generation.
| Decorator and import | Target | Arguments | Example |
|---|---|---|---|
EventHandler from @shamoo/decorators or @shamoo/events
|
Method | Compiler records all arguments; the bundled adapter recognizes a first string as the event ID, otherwise uses the method name | @EventHandler('org.bukkit.event.server.ServerLoadEvent') onLoadEvent(data: unknown) {} |
Command from @shamoo/decorators or @shamoo/commands
|
Method | First string is the command name; otherwise method name | @Command('status') status(context: PaperCommandContext) {} |
Subcommand from @shamoo/decorators or @shamoo/commands
|
Method | First string is currently treated as a command name | @Subcommand('admin') admin(): boolean { return true; } |
These conflict with task declarations on the same method. Platform-generated event decorators are covered in Paper Event Decorators and Velocity Event Decorators.
Current runtime limit: direct event and command registration works. Paper event callbacks receive { type, asynchronous }; Velocity callbacks receive { type }, not generated live JVM objects. Generic event options such as priority and cancellation are not interpreted by the bundled adapter: Paper uses NORMAL and does not request cancelled events; Velocity uses order 0. Command aliases and subcommand trees are not derived from decorator metadata. Paper commands do receive the supported data-only PaperCommandContext; Velocity command payloads remain the basic copied host values.
All are imported from @shamoo/decorators or @shamoo/commands and target parameters or properties.
| Decorator | Target | Arguments | Example |
|---|---|---|---|
Argument from @shamoo/decorators or @shamoo/commands
|
Parameter/property | Argument name/index value | greet(@Argument('name') name: string): void {} |
Option from @shamoo/decorators or @shamoo/commands
|
Parameter/property | Option name value | list(@Option('verbose') verbose: boolean): void {} |
Sender from @shamoo/decorators or @shamoo/commands
|
Parameter/property | No required argument; compiler maps it to context key sender
|
run(@Sender() sender: unknown): void {} |
Current runtime limit: these bindings are compiler metadata and are supported by the standalone invocation runtime when a host supplies a context. The bundled adapter does not perform parameter binding. Use the direct PaperCommandContext argument for currently deployed Paper commands.
All are imported from @shamoo/decorators or @shamoo/scheduler and target methods.
| Decorator | Target | Arguments | Example |
|---|---|---|---|
Scheduled from @shamoo/decorators or @shamoo/scheduler
|
Method | Conventionally a schedule object { delay, unit, repeat? }; repeatable |
@Scheduled({ delay: 20, unit: 'ticks' }) heartbeat() {} |
Interval from @shamoo/decorators or @shamoo/scheduler
|
Method | Interval value/options recorded as metadata | @Interval({ delay: 5, unit: 'seconds' }) poll() {} |
Timeout from @shamoo/decorators or @shamoo/scheduler
|
Method | One-shot delay value/options recorded as metadata | @Timeout({ delay: 1, unit: 'minutes' }) expire() {} |
Supported TimeUnit values in @shamoo/scheduler are milliseconds, seconds, minutes, hours, and ticks.
Current runtime limit: the bundled adapter registers every task as immediate/global work. Paper uses the global scheduler callback; Velocity schedules with delay 0. It does not interpret delay, repeat, interval, timeout, region, or entity ownership metadata. Use explicit host scheduler integration when timing and Folia ownership matter.
| Decorator and import | Target | Arguments | Example |
|---|---|---|---|
Requires from @shamoo/decorators or @shamoo/conditions
|
Class/method | One or more condition values/types; repeatable | @Requires(PaperOnly) class Listener {} |
RequiresExpression from @shamoo/decorators or @shamoo/conditions
|
Class/method | One expression string | @RequiresExpression("platform == 'paper'") class Listener {} |
UseInterceptors from @shamoo/decorators or @shamoo/interceptors
|
Class/method | Interceptor types, in declaration order; repeatable | @UseInterceptors(TimingInterceptor) run() {} |
UseGuards from @shamoo/decorators or @shamoo/guards
|
Class/method | Guard types, in declaration order; repeatable | @UseGuards(AdminGuard) run() {} |
UsePipes from @shamoo/decorators or @shamoo/pipes
|
Class/method | Pipe types, in declaration order; repeatable | @UsePipes(TrimPipe) run(value: string) {} |
Catch from @shamoo/decorators or @shamoo/filters
|
Class/method | Exception filter types; repeatable | @Catch(LogFilter) run() {} |
The standalone invocation order is parameter resolution, pipes and validators, guards, interceptors, handler/result transformation, error transformation and filters, then scope disposal. Interceptor proceed() is single-use.
Current runtime limit: the compiler records these declarations, but the bundled adapter neither evaluates conditions nor resolves/runs pipeline classes. It invokes handlers directly. These decorators are not an authorization or validation boundary in a normal deployed bundle today. See Custom Decorators for supported extension interfaces and wiring details.
| Decorator and import | Target | Arguments | Example |
|---|---|---|---|
Validate from @shamoo/decorators or @shamoo/validation
|
Parameter/property | One or more validator/rule values; repeatable | run(@Argument('value') @Validate(NonEmptyValidator) value: string): void {} |
Validator<T>.validate(value) returns validation issues and may be asynchronous. The helper aggregates issues into ValidationError.
Current runtime limit: validation helpers execute when explicitly composed with InvocationRuntime; the bundled adapter does not resolve validators from metadata or call them.
- Non-repeatable duplicate decorators are errors. Repeatable decorators are
Requires,Validate,Scheduled,UseInterceptors,UseGuards,UsePipes, andCatch. - Lifecycle decorators conflict with one another on a method.
-
EventHandler,Command,Subcommand,Scheduled,Interval, andTimeoutconflict on one method. - Parameter decorators need
experimentalDecorators; class/method/property-only projects may use standard decorators. - Runtime reflection is explicit:
getRuntimeDeclarations(target)from@shamoo/reflectionreturns recorded declarations. It does not infer types.
Source: all 37 decorator implementations and compiler discovery.