Extending
Create a decorator
A Stone.js decorator does one thing: it records intent as metadata on a class, which the build phase later reads into the Blueprint. It is built on TC39 stage-3 decorators and Symbol.metadata, never the legacy experimental decorators and never reflect-metadata.
#Metadata, not behaviour
The principle
A decorator that mutates a class at define time hides behaviour where it is hard to find. A decorator that only annotates keeps the class plain and defers all wiring to a single, inspectable phase. Declaration and effect stay separate.
In Stone.js
Use addMetadata(context, key, value) to record intent, or addBlueprint(Class, context, ...blueprints) to contribute Blueprint keys directly. The build phase reads it; your decorator itself does nothing at runtime.
#A metadata decorator
import { addMetadata } from '@stone-js/core'
export interface FeatureOptions { flag: string }
// A class decorator (TC39 stage-3): (target, context) => void
export const Feature = (options: FeatureOptions) => (target: unknown, context: ClassDecoratorContext) => {
addMetadata(context, 'feature', options) // records onto context.metadata (Symbol.metadata)
}
// usage:
@Feature({ flag: 'beta-tasks' })
export class TaskController {}#A blueprint decorator
When a decorator should contribute configuration, hand blueprint fragments to addBlueprint. This is how the framework's own @Routing(), @NodeHttp() and friends enable a capability with one annotation.
import { addBlueprint } from '@stone-js/core'
import { cacheBlueprint } from '../blueprint'
export const Cache = (options: { driver?: string } = {}) =>
(target: ClassType, context: ClassDecoratorContext) => {
addBlueprint(target, context, cacheBlueprint, { stone: { cache: options } })
}
// @Cache({ driver: 'redis' }) @StoneApp() class Application {}#Reading it back
Metadata is read during the build phase (a blueprint middleware) or wherever the framework introspects your classes. The isMeta* guards and the metadata key help you find and interpret what decorators recorded.
| Helper | Type | Description |
|---|---|---|
| addMetadata(ctx, key, value) | write | Record a value on the class metadata (Symbol.metadata). |
| addBlueprint(Class, ctx, ...bp) | write | Contribute Blueprint fragments from a decorator. |
| hasMetadata / getMetadata | read | Read metadata back during the build phase. |
| isMetaModule / isMetaClassModule … | guards | Classify meta-modules when processing them. |