Skip to main content

Utils

createRouteValueMetadataUtils

createRouteValueMetadataUtils is a factory function that creates a [decorator, getter] pair for attaching custom key-value metadata to routes and reading it from the request at runtime. This is useful for scenarios like role-based access control, rate limiting, feature flags, or any custom per-route configuration that middleware or guards need to access.

Each adapter package exports its own createRouteValueMetadataUtils with a getter typed to the adapter's native request type.

function createRouteValueMetadataUtils<T>(
key: string | symbol,
): [
decorator: (value: T) => MethodDecorator,
getter: (request: Request) => T | undefined,
]

Parameters

  • key: A unique string or symbol that identifies the metadata entry. Each metadata key should be unique across your application to avoid collisions.

Returns

A tuple with two elements:

  • decorator: A method decorator factory. Call it with a value to create a decorator that attaches that value as metadata on a controller method.
  • getter: A function that retrieves the metadata value from the request object. Returns undefined if the metadata is not present on the current route.

:::info How it works

The decorator stores metadata on the controller class using reflect-metadata. At request time, the adapter's internal middleware populates the metadata on the request object before any user-defined middleware, guards, or interceptors execute. The getter reads from this request-level storage.

:::

Example

The following example demonstrates creating a Roles decorator and getRoles getter, then using them in a middleware to read route-level role metadata and set a response header.

import { ApplyMiddleware, Controller, Get } from '@inversifyjs/http-core';
import {
createRouteValueMetadataUtils,
type ExpressMiddleware,
} from '@inversifyjs/http-express-v4';
import { type NextFunction, type Request, type Response } from 'express4';

// eslint-disable-next-line @typescript-eslint/naming-convention
const [Roles, getRoles]: [
decorator: (value: string[]) => MethodDecorator,
getter: (request: Request) => string[] | undefined,
] = createRouteValueMetadataUtils<string[]>('ROLES');

export class RolesMiddleware implements ExpressMiddleware {
public execute(
request: Request,
response: Response,
next: NextFunction,
): void {
const roles: string[] | undefined = getRoles(request);

if (roles !== undefined) {
response.setHeader('x-route-roles', roles.join(','));
}

next();
}
}

@Controller('/users')
export class UsersController {
@Roles(['admin', 'user'])
@ApplyMiddleware(RolesMiddleware)
@Get()
public async getUsers(): Promise<string> {
return 'users';
}
}
note
  • Route value metadata is read-only at request time — it is set once at route registration and cannot be mutated during request handling.
  • Metadata is only available at the method level. To share metadata across all routes in a controller, apply the decorator to each method individually.
  • The metadata middleware is prepended before any user-defined middleware, so the getter is available in @ApplyMiddleware handlers, guards, and interceptors.