Stone.jsDocs
Paradigm

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

src/decorators/Feature.tsts
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.

src/decorators/Cache.tsts
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.

HelperTypeDescription
addMetadata(ctx, key, value)writeRecord a value on the class metadata (Symbol.metadata).
addBlueprint(Class, ctx, ...bp)writeContribute Blueprint fragments from a decorator.
hasMetadata / getMetadatareadRead metadata back during the build phase.
isMetaModule / isMetaClassModule …guardsClassify meta-modules when processing them.

Stone.js

Your app exists in every runtime. Until you run it.

An open-source project by Stone Foundation
Created by Mr. Stone (Evens Pierre)