Decorators

@system-inc/base-foundation · 515c140 · 11 symbols

@HttpBody

decorator

Injects the request body into a route handler parameter.

Without arguments, the body is provided as a ReadableStream. This is useful for file uploads and streaming use cases.

With a TypeFunc, the body is parsed as JSON and deserialized to the given type.

With an HttpBodyOptions mode, the body is provided in the specified format (stream, formData, text, arrayBuffer, or blob).

HttpBody(): ParameterDecorator
HttpBody(type: TypeFunc): ParameterDecorator
HttpBody(options: HttpBodyOptions): ParameterDecorator
// Raw stream (default for no arguments)
async upload(@HttpBody() body: ReadableStream) { ... }

// Typed JSON
async create(@HttpBody(() => CreateInput) input: CreateInput) { ... }

// Multipart form data
async webhook(@HttpBody({ mode: 'formData' }) form: FormData) { ... }

// Plain text
async log(@HttpBody({ mode: 'text' }) body: string) { ... }

View source ↗

@HttpCookie

decorator

Injects a cookie value into a route handler parameter.

With a name, injects that single cookie's value — as a string, or converted when a TypeFunc is also given. With only a TypeFunc, all cookies are serialized into the given type.

HttpCookie(nameOrType: string | TypeFunc, type?: TypeFunc): ParameterDecorator
  • nameOrType

    The name of the cookie, or the type to serialize all cookies into.

  • type

    The type to convert the named cookie to.

@HttpRoute('GET', '/me')
async me(@HttpCookie('sessionId') sessionId: string): Promise<Response> { ... }

// All cookies as one object
@HttpRoute('GET', '/me')
async me(@HttpCookie(() => SessionCookies) cookies: SessionCookies): Promise<Response> { ... }

View source ↗

@HttpHeader

decorator

Injects a request header into a route handler parameter.

With a name, injects that single header's value. With a TypeFunc, all request headers are serialized into the given type.

HttpHeader(nameOrType: string | TypeFunc, type?: TypeFunc): ParameterDecorator
  • nameOrType

    The name of the header, or the type to serialize all headers into.

  • type

    The type to convert the named header to.

@HttpRoute('POST', '/webhooks/github')
async webhook(@HttpHeader('x-hub-signature') signature: string): Promise<Response> { ... }

// All headers as one object
@HttpRoute('GET', '/debug')
async debug(@HttpHeader(() => TraceHeaders) headers: TraceHeaders): Promise<Response> { ... }

View source ↗

@HttpPath

decorator

Injects a path parameter into a route handler parameter.

With a name, injects that single :name segment of the route path — as a string, or converted when a TypeFunc is also given. With only a TypeFunc, all path parameters are serialized into the given type. Values are URL-decoded by default (HttpPathOptions).

HttpPath(nameOrType: string | TypeFunc, typeOrOptions?: TypeFunc | HttpPathOptions, options?: HttpPathOptions): ParameterDecorator
  • nameOrType

    The name of the path parameter, or the type to serialize all path parameters into.

  • typeOrOptions

    The type to convert the named parameter to, or options for the parameter.

  • options

    Options for the parameter (only used when the second argument is a type).

@HttpRoute('GET', '/accounts/:id')
async get(@HttpPath('id') id: string): Promise<Response> { ... }

// Typed conversion
@HttpRoute('GET', '/orders/:index')
async order(@HttpPath('index', () => Number) index: number): Promise<Response> { ... }

// All path parameters as one object
@HttpRoute('GET', '/repos/:owner/:name')
async repo(@HttpPath(() => RepoPath) path: RepoPath): Promise<Response> { ... }

View source ↗

@HttpQuery

decorator

Injects a query-string parameter into a route handler parameter.

With a name, injects that single query parameter — as a string, or converted when a TypeFunc is also given. With only a TypeFunc, all query parameters are serialized into the given type. Values are URL-decoded by default (HttpQueryOptions).

HttpQuery(nameOrType: string | TypeFunc, typeOrOptions?: TypeFunc | HttpQueryOptions, options?: HttpQueryOptions): ParameterDecorator
  • nameOrType

    The name of the query parameter, or the type to serialize all query parameters into.

  • typeOrOptions

    The type to convert the named parameter to, or options for the parameter.

  • options

    Options for the parameter (only used when the second argument is a type).

@HttpRoute('GET', '/search')
async search(
    @HttpQuery('term') term: string,
    @HttpQuery('limit', () => Number) limit: number,
): Promise<Response> { ... }

// All query parameters as one object
@HttpRoute('GET', '/search')
async search(@HttpQuery(() => SearchQuery) query: SearchQuery): Promise<Response> { ... }

View source ↗

@HttpRoute

decorator

Registers a method of an @HttpService class as the handler for an HTTP route. Path parameters are declared as :name segments and read with @HttpPath.

HttpRoute(method: "GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "OPTIONS" | "PATCH" | "ALL" | ("GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "OPTIONS" | "PATCH" | "ALL")[], route: string): MethodDecorator
  • method

    The HTTP method for the route, a list of methods to match, or `'ALL'` to match every method.

  • route

    The path for the route, e.g. `/accounts/:id`.

@HttpRoute('GET', '/accounts/:id')
async get(@HttpPath('id') id: string): Promise<Response> { ... }

// One handler for multiple methods
@HttpRoute(['GET', 'POST'], '/echo')
async echo(@InjectRequestContext() rc: RequestContext): Promise<Response> {
    return new Response(rc.method);
}

View source ↗

@HttpService

decorator

Marks a class as an HTTP service — the entry point for the @HttpRoute handlers defined within it.

List the class in a module's (or the worker's) services; its routes are bound at boot, and a fresh instance is resolved from the request-scoped container for each incoming request.

HttpService(): ClassDecorator
@HttpService()
export class AccountService {
    @HttpRoute('GET', '/accounts/:id')
    async get(@HttpPath('id') id: string): Promise<Response> {
        return Response.json({ id });
    }
}

View source ↗

Parameter decorator that injects the RequestContext or a specific value from it into a method parameter.

Works universally across HTTP routes, RPC handlers, and GraphQL resolvers. Without a key it injects the entire RequestContext; with a RequestContextKey it extracts that specific extension value from the context's typed bag.

InjectRequestContext(): ParameterDecorator
InjectRequestContext(key: RequestContextKey<T>): ParameterDecorator
// Without a key — the entire RequestContext
@HttpRoute('GET', '/api/foo')
async getFoo(
    @HttpPath('id') id: string,
    @InjectRequestContext() rc: RequestContext,
): Promise<Response> {
    rc.deviceId;
    rc.headers.get('x-custom');
}

// With a key — a specific extension value
const DeviceId = RequestContextKey.create<string>('deviceId');

@Rpc()
async doThing(
    input: Input,
    @InjectRequestContext(DeviceId) deviceId?: string,
): Promise<Output> { ... }

View source ↗

Resolves all @InjectRequestContext() decorated parameters for a method. Call this from dispatch sites (Router, RpcDispatcher, GqlDispatcher/TypeGraphQL) to populate the args array with RequestContext data.

resolveRequestContextParams(prototype: object, methodName: string | symbol, requestContext: RequestContext, args: unknown[]): void
  • prototype

    The prototype of the service instance

  • methodName

    The name of the method being called

  • requestContext

    The RequestContext for the current request

  • args

    The arguments array to populate

View source ↗

Decorator to add handler-scoped middleware to a class or method.

Accepts either a middleware function or a middleware class constructor, or an array of them. Classes are resolved from the DI container.

The middleware runs after the dispatcher has resolved rc.handler, so implementations receive a HandlerRequestContext in which rc.handler is guaranteed to be set.

WithMiddleware(middleware: HandlerMiddlewareRegistration | HandlerMiddlewareRegistration[]): ClassDecorator & MethodDecorator

View source ↗

Builds a method decorator that runs a guard against the current RequestContext before invoking the decorated method.

Internally this registers an @InjectRequestContext() at a trailing slot just past the method's declared arity. The dispatcher fills that slot with the RC, the wrapper reads it, trims it off the args, runs the guard, and then forwards the original args to the underlying method.

Multiple decorators using this helper can be stacked on the same method — each one gets its own trailing slot (the metadata is an array) and the RC is written into every slot.

Use this when a decorator only needs to pre-inspect the RC. For post-invocation work or argument transformation, write a bespoke decorator.

withRequestContext(guard: RequestContextGuard): MethodDecorator
export function RequireDeviceId(): MethodDecorator {
    return withRequestContext((rc) => {
        if (!rc.get(DeviceIdRequestContextKey)) {
            throw requireDeviceIdError();
        }
    });
}

View source ↗