Decorators

Custom & CLI Decorators

Extend AxilJS semantic metadata with custom consumers, inspect decorator contracts from the CLI, and build framework-independent tooling.

5 min readDocumentationEdit this page

Custom & CLI

AxilJS decorators are designed as metadata declarations rather than framework-bound runtime components. This makes the decorator system extensible: applications and tooling can inspect the same metadata without coupling business code to a specific framework.

This page covers the decorator contract, metadata registry, custom consumers, and CLI introspection.

The Decorator Contract

Every AxilJS decorator exposes a TDecoratorInfo contract. The contract describes what the decorator means, where it can be applied, what metadata it produces, and how it composes with other decorators.

typescript
interface TDecoratorInfo {
  name: string
  description: string
  purpose: string
  why: string
  whenToUse: string
  whenNotToUse?: string
  category: string
  targets: Array<'class' | 'method' | 'property' | 'parameter'>
  options?: Record<string, unknown>
  runtimeBehavior?: string
  metadataProduced?: string[]
  consumedBy?: string[]
  composesWith?: string[]
  conflictsWith?: string[]
  securityImpact?: string
  performanceImpact?: string
  examples: string[]
}

The contract is enforced at build time. It is not merely documentation metadata. This gives tooling a structured representation of every semantic decorator.

The contract enables:

  • CLI introspection
  • IDE contextual tooltips
  • build-time composition validation
  • static analysis

For example:

Terminal
axil decorator info tDatabase

This command can explain a decorator without requiring the application to be running.

Metadata Registry

The metadata registry is the shared boundary between decorators and their consumers.

Decorators write semantic metadata to the registry. Consumers read that metadata and implement the corresponding behavior.

typescript
import {
  registerMetadata,
  getMetadata,
  getAllMetadata,
  hasMetadata
} from '@axiljs/decorator'
 
registerMetadata(
  'tDatabase',
  target,
  'findUser',
  { operation: 'read' }
)
 
const meta = getMetadata(
  'tDatabase',
  target,
  'findUser'
)
 
const all = getAllMetadata(
  target,
  'findUser'
)

A method can therefore expose multiple independent semantic declarations:

typescript
{
  tHttp: { ... },
  tDatabase: { ... },
  tCache: { ... }
}

The registry is designed to provide immutability, type safety, serializability, and framework independence.

Writing a Custom Consumer

A consumer is any component that reads AxilJS metadata and acts on it.

AxilJS provides built-in consumers for HTTP, security, database access, queues, events, resilience, observability, AI, and other capabilities. You can also implement your own consumer for application-specific behavior.

A custom consumer can inspect all metadata attached to a method:

typescript
import { getAllMetadata } from '@axiljs/decorator'
 
class MyConsumer {
  scan(target: object, method: string) {
    const meta = getAllMetadata(target, method)
 
    if (meta.tDatabase?.operation === 'write') {
      this.instrumentWrite(target, method)
    }
  }
}

The important boundary is that the decorator does not need to know what the consumer does with its metadata. The consumer decides how that semantic declaration is interpreted.

This allows application-specific tooling such as:

  • internal policy engines
  • custom telemetry integrations
  • deployment analysis
  • architecture validation
  • code-generation tools
  • organization-specific compliance checks

CLI Introspection

Because decorators expose structured metadata, AxilJS tooling can inspect them without executing application logic.

Terminal
axil decorator info tDatabase

CLI introspection is useful when you need to understand a decorator's purpose, supported targets, options, composition rules, and other contract information directly from the command line.

The same metadata model can also support IDE tooling and static analysis, allowing documentation and developer tooling to consume the decorator contract rather than relying on duplicated descriptions.

Framework-Independent Tooling

AxilJS separates declarations from consumers.

text
Application Code
       |
       v
Semantic Decorators
       |
       v
Metadata Registry
       |
       +--------+--------+--------+--------+
       |        |        |        |        |
       v        v        v        v        v
      HTTP     ORM    Security    AI   Observability

Application code declares intent. The registry stores that intent. Independent consumers interpret the metadata.

This means a consumer can be added, removed, or replaced without changing the semantic declarations in application code.

Composing Custom Tooling with Existing Metadata

A custom consumer does not need to introduce a new decorator for every requirement. It can inspect existing semantic metadata and derive additional behavior.

For example:

typescript
const metadata = getAllMetadata(target, 'createOrder')
 
if (metadata.tHttp && metadata.tAudit) {
  this.registerAuditedEndpoint(target, 'createOrder')
}

This preserves the separation between declarations and implementation while allowing tooling to reason about combinations of existing semantics.

Installation

Install the AxilJS decorator package:

Terminal
npm install @axiljs/decorator

Design Principle

The AxilJS decorator system follows a simple boundary:

Decorators describe intent. The metadata registry stores intent. Consumers implement behavior.

This makes semantic metadata reusable across runtimes, tooling, and infrastructure without requiring application code to depend on a single framework implementation.

Reference

The core APIs relevant to custom tooling are:

APIPurpose
TDecoratorInfoDescribes a decorator's contract
registerMetadata()Registers semantic metadata
getMetadata()Reads metadata for a specific decorator
getAllMetadata()Reads all metadata attached to a target
hasMetadata()Checks whether metadata exists

The same registry is used by independent AxilJS consumers, making it the integration boundary between semantic declarations and runtime behavior.

With the complete decorator documentation set, AxilJS provides semantic declarations across HTTP, security, data, reliability, concurrency, distributed systems, messaging, caching, observability, compliance, runtime behavior, AI, validation, and custom tooling.

Help improve the documentation

AxilJS is open source and documentation improvements are welcome.

AxilJS DocumentationMIT License · Built by SyntaxilitY