Custom Decorator
Vercube provides a powerful decorator system that allows you to create custom decorators for your application. Custom decorators extend the BaseDecorator class and can be used to add metadata, modify behavior, or inject dependencies into your classes and methods.
How Decorators Work
Decorators in Vercube are created using the createDecorator() factory function. Each decorator is a class that extends BaseDecorator and is instantiated by the IOC container, which means you can use dependency injection inside your decorators.
import { BaseDecorator, createDecorator, Inject } from '@vercube/di';
class MyDecorator extends BaseDecorator<MyOptions> {
@Inject(SomeService)
private someService!: SomeService;
public override created(): void {
// Called when decorator is initialized
}
public override destroyed(): void {
// Called when decorator is cleaned up
}
}
export function MyDecorator(options?: MyOptions): Function {
return createDecorator(MyDecorator, options);
}
BaseDecorator Class
The BaseDecorator class is the foundation for all custom decorators. It provides access to the decorated element and lifecycle hooks.
Properties
| Property | Type | Description |
|---|---|---|
options | T | Options object passed to the decorator |
instance | any | The class instance that is decorated |
prototype | P | The class prototype that is decorated |
propertyName | string | Name of the decorated property or method |
descriptor | PropertyDescriptor | Property descriptor of the decorated element |
propertyIndex | number | Parameter index (for parameter decorators) |
Lifecycle Methods
created()
Called when the decorator is created and ready to be used. Use this to set up event listeners, register hooks, or perform initialization logic.
public override created(): void {
// Initialize your decorator
console.log(`Decorator applied to ${this.propertyName}`);
}
destroyed()
Called when the decorator is destroyed. Use this for cleanup tasks like unregistering listeners or clearing timers. This is called at the end of SSR requests or when a component is destroyed.
public override destroyed(): void {
// Cleanup resources
this.unsubscribe();
}
Creating a Custom Decorator
Basic Example
Here's a simple decorator that logs method calls:
import { BaseDecorator, createDecorator } from '@vercube/di';
interface LogDecoratorOptions {
level?: 'debug' | 'info' | 'warn';
prefix?: string;
}
class LogMethodDecorator extends BaseDecorator<LogDecoratorOptions> {
private originalMethod!: Function;
public override created(): void {
// Store the original method
this.originalMethod = this.descriptor.value;
// Replace with wrapped version
const options = this.options;
const methodName = this.propertyName;
this.descriptor.value = function(...args: any[]) {
const prefix = options?.prefix || '';
console.log(`${prefix}[${methodName}] called with:`, args);
const result = this.originalMethod.apply(this, args);
console.log(`${prefix}[${methodName}] returned:`, result);
return result;
};
}
}
/**
* Logs method calls with arguments and return values
*/
export function LogMethod(options?: LogDecoratorOptions): Function {
return createDecorator(LogMethodDecorator, options);
}
Usage:
import { Controller, Get } from '@vercube/core';
import { LogMethod } from './decorators/LogMethod';
@Controller('/users')
export class UserController {
@LogMethod({ prefix: '[UserController] ' })
@Get('/:id')
async getUser(req: Request, params: { id: string }) {
return { id: params.id, name: 'John' };
}
}
API Reference
createDecorator()
Factory function to create a decorator from a BaseDecorator class.
function createDecorator<T>(
DecoratorClass: typeof BaseDecorator<T>,
options?: T
): Function
Parameters:
| Parameter | Type | Description |
|---|---|---|
DecoratorClass | typeof BaseDecorator<T> | The decorator class to instantiate |
options | T | Options to pass to the decorator |
Returns: A decorator function that can be applied to classes, methods, or parameters.
BaseDecorator<T, P>
Abstract base class for all decorators.
abstract class BaseDecorator<T = any, P = any> {
public options: T;
public instance: any;
public prototype: P;
public propertyName: string;
public descriptor: PropertyDescriptor;
public propertyIndex: number;
public created(): void;
public destroyed(): void;
}
Type Parameters:
| Parameter | Description |
|---|---|
T | Type of the options object |
P | Type of the prototype (for advanced use cases) |