Skip to main content

Decorators

This section covers Inversify HTTP decorators used to provide related metadata.

Service Identifiers

Many decorators in this framework accept ServiceIdentifier types for dependency injection. A ServiceIdentifier<T> can be:

  • A class constructor (e.g., MyMiddleware)
  • A string token (e.g., 'my-middleware')
  • A symbol (e.g., Symbol.for('my-middleware'))
  • An abstract class reference

This allows for flexible dependency resolution through the InversifyJS container.

HTTP Request lifecycle

Inversify HTTP decorators can be used to manage the lifecycle of HTTP requests, including middleware execution, request handling, and response generation. This allows for more modular and maintainable code.

ApplyMiddleware

Attaches middleware to a controller class (applies to all its routes) or to a specific route method.

ApplyMiddleware(
...middlewareList: (ServiceIdentifier<Middleware> | ApplyMiddlewareOptions)[],
): ClassDecorator & MethodDecorator

Parameters

  • middlewareList: One or more middleware service identifiers or options objects.
    • ServiceIdentifier<Middleware>: A middleware class, string token, symbol, or abstract class that can be resolved by the DI container.
    • ApplyMiddlewareOptions: Configuration object with middleware and phase settings.

Notes

  • Scope: Place the decorator on the controller class to affect all routes, or on a method to affect only that route.
  • Phase: When passing middleware service identifiers directly (not the options object), they run in the PreHandler phase by default.
  • Order: Within the same phase, middleware execute in the order they are provided.
  • See also: Middleware fundamentals for adapter-specific request/response types and tips.

Example: apply middleware to a controller (all routes)

@ApplyMiddleware(MyMiddleware)
@Controller('/ping')
class PingController {
@Get()
public async get(): Promise<string> {
return 'pong';
}
}

Example: apply middleware to a single route

@Controller('/ping')
class PingController {
@ApplyMiddleware(MyMiddleware)
@Get()
public async get(): Promise<string> {
return 'pong';
}
}

Next

Injects the framework-specific next function into your controller method. Call it to continue a pipeline. For example, a middleware can run first (e.g., to set headers), then your controller can return the response.

Next(): ParameterDecorator

Example: calling next per adapter

@Controller('/next')
export class NextExpress4Controller {
@UseInterceptor(Express4NextInterceptor)
@Get()
public getNext(@Next() next: NextFunction): void {
next();
}
}

UseErrorFilter

Attaches one or more error filters to a controller class or method. Error filters handle exceptions that occur during request processing.

UseErrorFilter(...errorFilterList: Newable<ErrorFilter>[]): ClassDecorator & MethodDecorator

Parameters

  • errorFilterList: One or more error filter classes implementing ErrorFilter.

Notes

  • Scope: Place on the controller class to affect all routes, or on a method to affect only that route.
  • Order: Error filters are processed in the order they are provided.
  • Exception handling: Error filters can catch, transform, or handle exceptions thrown during request processing.

UseGuard

Attaches one or more guards to a controller class or method. All guards must allow for the request to continue.

UseGuard(...guardList: ServiceIdentifier<Guard>[]): ClassDecorator & MethodDecorator

Parameters

  • guardList: One or more guard service identifiers that can be resolved by the DI container.

UseInterceptor

Attaches one or more interceptors to a controller class or method. Interceptors can modify requests before they reach the handler and responses before they are sent.

UseInterceptor(...interceptorList: ServiceIdentifier<Interceptor>[]): ClassDecorator & MethodDecorator

Parameters

  • interceptorList: One or more interceptor service identifiers that can be resolved by the DI container.

HTTP Request message abstraction

Inversify HTTP decorators can be used to abstract HTTP request details, such as headers, query parameters, and request bodies. This allows for cleaner controller code and better separation of concerns.

Body

Reads the HTTP request body, or a specific property of it when a name is provided. The type and shape of the body depends on the Content-Type header of the request and the adapter being used.

Body(
optionsOrPipe?: RouteParameterOptions | (ServiceIdentifier<Pipe> | Pipe),
...parameterPipeList: (ServiceIdentifier<Pipe> | Pipe)[]
): ParameterDecorator

Parameters

  • optionsOrPipe (optional): Either route parameter options or a pipe. When this is RouteParameterOptions, it contains configuration like parameterName. When it's a pipe (service identifier or instance), it's the first pipe in the pipeline.
  • parameterPipeList: Additional pipes to apply to the parameter for transformation and validation.

Content Type Handling

The @Body() decorator automatically parses the request body based on the Content-Type header. Different adapters may require specific configuration options to be enabled.

JSON (application/json)

All adapters support JSON parsing by default (though Express adapters may require the useJson option to be enabled).

@Controller('/users')
export class BodyJsonController {
@Post()
public async createUser(@Body() body: UserPayload): Promise<UserResult> {
// Body is automatically parsed from JSON when Content-Type is application/json
return {
email: body.email,
id: 1,
name: body.name,
};
}
}
URL-encoded Form Data (application/x-www-form-urlencoded)

Form data is parsed into a Record<string, string | string[]> object. Express and Fastify adapters require specific options to be enabled:

  • Express/Express v4: Set useUrlEncoded: true in adapter options
  • Fastify: Set useFormUrlEncoded: true in adapter options
  • Hono/uWebSockets.js: Supported by default
@Controller('/auth')
export class BodyUrlEncodedController {
@Post('/login')
public async login(
@Body() body: Record<string, string | string[]>,
): Promise<FormResult> {
// Body is automatically parsed from URL-encoded form data
// when Content-Type is application/x-www-form-urlencoded
return {
password: body['password'] as string,
username: body['username'] as string,
};
}
}
Plain Text (text/plain, text/*)

Text bodies are received as strings. Express adapters require the useText: true option to be enabled.

@Controller('/documents')
export class BodyTextController {
@Post()
public async createDocument(@Body() body: string): Promise<TextResult> {
// Body is received as a string when Content-Type is text/plain or text/*
return {
content: body,
length: body.length,
};
}
}
Multipart Form Data (multipart/form-data)

Multipart form data handling varies significantly between adapters. The body type and parsing behavior is adapter-specific:

Fastify

Enable with useMultipartFormData: true (or pass multipart options) in adapter options. Returns an AsyncIterableIterator<Multipart>.

@Controller('/uploads')
export class BodyMultipartFastifyController {
@Post()
public async uploadFile(
// Type would be: AsyncIterableIterator<Multipart> | undefined
@Body() body: AsyncIterableIterator<unknown> | undefined,
): Promise<UploadResult> {
// With Fastify, multipart/form-data returns an async iterator of Multipart objects
// when useMultipartFormData option is enabled
let fileName: string = '';
let username: string = '';

if (body !== undefined) {
for await (const field of body) {
const multipartField: {
fieldname: string;
filename: string;
type: string;
value: unknown;
} = field as {
fieldname: string;
filename: string;
type: string;
value: unknown;
};

if (multipartField.type === 'file') {
fileName = multipartField.filename;
} else if (multipartField.fieldname === 'username') {
username = multipartField.value as string;
}
}
}

return { fileName, username };
}
}

Hono

Multipart is supported by default. Returns a FormData object.

@Controller('/uploads')
export class BodyMultipartHonoController {
@Post()
public async uploadFile(@Body() body: FormData): Promise<UploadResult> {
// With Hono, multipart/form-data is automatically parsed into FormData
const file: File | string | null = body.get('file');
const fileName: string = file instanceof File ? file.name : '';
const username: string = (body.get('username') as string | null) ?? '';

return { fileName, username };
}
}

uWebSockets.js

Multipart is supported by default. Returns a MultipartField[] array.

@Controller('/uploads')
export class BodyMultipartUwebsocketsController {
@Post()
public async uploadFile(
// Type would be: MultipartField[] | undefined
@Body() body: unknown[] | undefined,
): Promise<UploadResult> {
// With uWebSockets.js, multipart/form-data is parsed into an array of MultipartField objects
let fileName: string = '';
let username: string = '';

if (body !== undefined) {
const textDecoder: TextDecoder = new TextDecoder();

for (const field of body) {
const multipartField: {
name: string;
filename?: string;
data: Uint8Array;
} = field as {
name: string;
filename?: string;
data: Uint8Array;
};

if (multipartField.filename !== undefined) {
fileName = multipartField.filename;
} else if (multipartField.name === 'username') {
username = textDecoder.decode(multipartField.data);
}
}
}

return { fileName, username };
}
}

Express/Express v4

Multipart Support

Express adapters do not handle multipart/form-data out of the box. You must register a multipart middleware (such as multer) on your Express app before building the InversifyJS HTTP server.

import { Controller, Post, Request } from '@inversifyjs/http-core';
import type express from 'express';

export interface MultipartResult {
fileCount: number;
username: string;
}

/**
* Example showing multipart/form-data handling with Express adapters.
*
* Express adapters require multer middleware to be registered on the Express app
* before building the InversifyJS HTTP server.
*
* With multer, files are in request.files and text fields are in request.body.
*/
@Controller('/users')
export class MultipartExpressController {
@Post()
public createUser(@Request() request: express.Request): MultipartResult {
// With multer's .any(), file uploads are in request.files
// and text form fields are in request.body
const files: Express.Multer.File[] = (request.files ??
[]) as Express.Multer.File[];
const body: { username?: string } = request.body as {
username?: string;
};

return {
fileCount: files.length,
username: body.username ?? '',
};
}
}

Notes

  • The @Body() decorator is asynchronous for some adapters (Fastify, Hono, uWebSockets.js). The framework handles this automatically.
  • When using parameterName, the decorator extracts a specific property from the parsed body object (not supported for multipart bodies that return iterators or FormData).
  • Always validate and sanitize body input using pipes or validation libraries to ensure security.

Headers

Reads HTTP request headers, or a specific header when a name is provided.

Headers(
optionsOrPipe?: RouteParameterOptions | (ServiceIdentifier<Pipe> | Pipe),
...parameterPipeList: (ServiceIdentifier<Pipe> | Pipe)[]
): ParameterDecorator

Parameters

  • optionsOrPipe (optional): Either route parameter options or a pipe. When this is RouteParameterOptions, it contains configuration like header name. When it's a pipe (service identifier or instance), it's the first pipe in the pipeline.
  • parameterPipeList: Additional pipes to apply to the parameter for transformation and validation.

Example: reading the User-Agent header

@Controller('/headers')
export class HeadersController {
@Get()
public async getUserAgent(
@Headers({
name: 'x-client',
})
userAgent: string | undefined,
): Promise<HeadersResult> {
return {
agent: userAgent,
};
}
}

Cookies

Reads HTTP cookies, or a specific cookie when a name is provided.

warning

Remember to enable useCookies option when using express or fastify adapters.

Cookies(
optionsOrPipe?: RouteParameterOptions | (ServiceIdentifier<Pipe> | Pipe),
...parameterPipeList: (ServiceIdentifier<Pipe> | Pipe)[]
): ParameterDecorator

Parameters

  • optionsOrPipe (optional): Either route parameter options or a pipe. When this is RouteParameterOptions, it contains configuration like cookie name. When it's a pipe (service identifier or instance), it's the first pipe in the pipeline.
  • parameterPipeList: Additional pipes to apply to the parameter for transformation and validation.
@Controller('/cookies')
export class CookiesController {
@Get()
public async getCookie(
@Cookies({
name: 'sessionId',
})
sessionId: string | undefined,
): Promise<CookiesResult> {
return {
sessionId,
};
}
}

Params

Reads HTTP route parameters (path parameters), or a specific parameter when a name is provided.

Params(
optionsOrPipe?: RouteParameterOptions | (ServiceIdentifier<Pipe> | Pipe),
...parameterPipeList: (ServiceIdentifier<Pipe> | Pipe)[]
): ParameterDecorator

Parameters

  • optionsOrPipe (optional): Either route parameter options or a pipe. When this is RouteParameterOptions, it contains configuration like parameter name. When it's a pipe (service identifier or instance), it's the first pipe in the pipeline.
  • parameterPipeList: Additional pipes to apply to the parameter for transformation and validation.

Request

Retrieves the native request object of the current adapter. Useful when you need full access to the underlying framework request.

Request(...pipeList: (ServiceIdentifier<Pipe> | Pipe)[]): ParameterDecorator

Example: accessing the native request per adapter

@Controller('/headers')
export class RequestExpressController {
@Get()
public async readHeader(
@Request() request: express.Request,
): Promise<string> {
const value: string | string[] | undefined =
request.headers['x-test-header'];

let parsedValue: string;

if (Array.isArray(value)) {
if (value.length !== 1) {
throw new BadRequestHttpResponse(
{ message: 'Expected a single `x-test-header` value' },
'Expected a single `x-test-header` value',
);
}

[parsedValue] = value as [string];
} else {
parsedValue = value ?? '';
}

return parsedValue;
}
}

Query

Reads HTTP query parameters, or a specific query parameter when a name is provided.

Query(
optionsOrPipe?: RouteParameterOptions | (ServiceIdentifier<Pipe> | Pipe),
...parameterPipeList: (ServiceIdentifier<Pipe> | Pipe)[]
): ParameterDecorator

Parameters

  • optionsOrPipe (optional): Either route parameter options or a pipe. When this is RouteParameterOptions, it contains configuration like parameter name. When it's a pipe (service identifier or instance), it's the first pipe in the pipeline.
  • parameterPipeList: Additional pipes to apply to the parameter for transformation and validation.

HTTP Response message abstraction

Inversify HTTP decorators can also be used to abstract HTTP response details, such as status codes and headers. This allows for more consistent and maintainable response handling across controllers.

Response

Injects the native response object of the current adapter. Use it when you want to write directly to the underlying framework response.

Response(...pipeList: (ServiceIdentifier<Pipe> | Pipe)[]): ParameterDecorator

Notes

  • Type-safe: Type the parameter with the adapter's response type for intellisense and safety.
  • Return type: When you write to the native response, prefer a return type of void. For Hono, return the Response produced by the Context.
  • Hono: Prefer using @Context() from @inversifyjs/http-hono to access Hono's Context object.

Example: sending a response per adapter

@Controller('/message')
export class ResponseExpressController {
@Get()
public async sendMessage(
@Response() response: express.Response,
): Promise<void> {
response.send({ message: 'hello' });
}
}

SetHeader

Sets a HTTP response header.

SetHeader(headerKey: string, value: string): MethodDecorator

Parameters

  • headerKey (string): Name of the header to be set.
  • value (string): Value of the header to be set.

Example: Setting a response header

@Controller('/messages')
export class ContentController {
@Post()
@SetHeader('custom-content-header', 'sample')
public async createMessage(@Body() body: BodyPayload): Promise<BodyResult> {
return {
message: body.message,
};
}
}

StatusCode

Sets the HTTP response status code.

StatusCode(statusCode: HttpStatusCode): MethodDecorator

Parameters

  • statusCode (HttpStatusCode): Status code to be set.

Example: Setting a response status code

@Controller('/messages')
export class ContentController {
@Post()
@StatusCode(HttpStatusCode.CREATED)
public async createMessage(@Body() body: BodyPayload): Promise<BodyResult> {
return {
message: body.message,
};
}
}

Controller

The @Controller decorator marks a class as an HTTP controller and allows you to configure its base path, priority, scope, and service identifier.

Controller(pathOrOptions?: string | ControllerOptions): ClassDecorator

Parameters

  • pathOrOptions (optional): Either a string representing the base path, or a ControllerOptions object with the following properties:
    • path (optional string): Base path for all routes in this controller. Defaults to '/'.
    • priority (optional number): Registration priority. Controllers with higher priority values are registered before those with lower values. Defaults to 0. Useful for controlling route evaluation order, such as ensuring wildcard fallback routes are registered last.
    • scope (optional BindingScope): InversifyJS binding scope (Request, Singleton, or Transient).
    • serviceIdentifier (optional ServiceIdentifier): Custom service identifier for dependency injection.

Notes

  • Route registration order: Controllers are registered in descending order of priority (highest priority first). This is particularly useful when you need specific routes to be evaluated before more general ones (e.g., ensuring /api/users is checked before a wildcard /* fallback).
  • Default priority: Controllers without an explicit priority are assigned 0.

Example: Controller with priority

const PRIORITY_HIGHEST: number = 1000;
const PRIORITY_DEFAULT: number = 0;
const PRIORITY_LOWEST: number = -1000;

const HTTP_STATUS_CREATED: number = 201;
const HTTP_STATUS_NOT_FOUND: number = 404;

// High priority controller - registered first
@Controller({
path: '/api/messages',
priority: PRIORITY_HIGHEST,
})
export class MessagesController {
@Get()
public async getMessages(): Promise<Message[]> {
return [{ content: 'Hello, World!' }];
}

@Post()
@StatusCode(HTTP_STATUS_CREATED)
public async createMessage(
@Body() body: CreateMessageRequest,
): Promise<Message> {
return { content: body.content };
}
}

// Default priority controller
@Controller({
path: '/api/health',
priority: PRIORITY_DEFAULT,
})
export class HealthController {
@Get()
public async healthCheck(): Promise<{ status: string }> {
return { status: 'ok' };
}
}

// Low priority fallback controller - registered last to catch unmatched routes
@Controller({
priority: PRIORITY_LOWEST,
})
export class FallbackController {
@Get('*')
@StatusCode(HTTP_STATUS_NOT_FOUND)
public async notFound(): Promise<{ error: string; message: string }> {
return {
error: 'Not Found',
message: 'The requested resource was not found',
};
}
}

Custom decorators

createCustomParameterDecorator

createCustomParameterDecorator allows you to define your own decorators to be used in route handler parameters.

createCustomParameterDecorator<TRequest, TResponse, TResult>(
handler: CustomParameterDecoratorHandler<TRequest, TResponse, TResult>,
...parameterPipeList: (ServiceIdentifier<Pipe> | Pipe)[]
): ParameterDecorator

Parameters

  • handler (optional): Parameter decorator handler. It takes a request, a response and CustomParameterDecoratorHandlerOptions that can be used to read request values or write response status code or headers.
  • parameterPipeList (optional): List of pipes to be applied.

Example: user custom decorator

Assuming an auth middleware lets user details in a user property of a given request, we can easily create a custom decorator to provide such user details as follows:

const User: () => ParameterDecorator = () =>
createCustomParameterDecorator((request: UserContext): User => request.user);

@Controller('/api/users')
export class UsersController {
@ApplyMiddleware(AuthMiddleware)
@Get('me')
public getMe(@User() me: User): User {
return me;
}
}

createCustomNativeParameterDecorator

createCustomNativeParameterDecorator allows you to define your own decorators to be used in route handler parameters.

Native mode

Using a custom native parameter decorator in a route handler forces the native mode.

createCustomNativeParameterDecorator<
TRequest,
TResponse,
TDecoratorResult,
TResult,
>(
handler: CustomNativeParameterDecoratorHandler<
TRequest,
TResponse,
TDecoratorResult,
TResult
>,
...parameterPipeList: (ServiceIdentifier<Pipe> | Pipe)[]
): ParameterDecorator

Parameters

  • handler (optional): Parameter decorator handler. It takes a request, a response and CustomNativeParameterDecoratorHandlerOptions that can be used to read request values or write response status code, headers or body.
  • parameterPipeList (optional): List of pipes to be applied.

Example: uWebSockets file stream decorator

Streams are often used in http frameworks to handle large files or data transfers efficiently. Using a stream has its downsides. For example, there's no way to tell what's the current size of the file if we just pass it as a stream. No Content-Length header is expected in the http response either. To solve this, we can create a custom decorator that reads the file metadata and uses uWebSockets.js's native response methods to set the appropriate headers before streaming the file content, avoiding using chunked transfer encoding in favor of providing Content-Length.

Since we are using the decorator to write directly a response body, we need to force the native mode by using createCustomNativeParameterDecorator. Otherwise, the framework would try to send status codes and headers after the body has been written, which is simply not possible due to the nature of HTTP.

const FileStream: () => ParameterDecorator = () =>
createCustomNativeParameterDecorator<
HttpRequest,
HttpResponse,
(options: FileStreamOptions) => void,
undefined
>(
(
_request: HttpRequest,
response: HttpResponse,
options: CustomNativeParameterDecoratorHandlerOptions<
HttpRequest,
HttpResponse,
undefined
>,
): ((streamOptions: FileStreamOptions) => Promise<void>) => {
return async (streamOptions: FileStreamOptions): Promise<void> => {
const { contentType, filePath }: FileStreamOptions = streamOptions;

// Get file size for Content-Length header
const fileSize: number = (await stat(filePath)).size;

// Set response headers
options.setStatus(_request, response, HttpStatusCode.OK);
options.setHeader(
_request,
response,
'content-length',
fileSize.toString(),
);
options.setHeader(
_request,
response,
'content-type',
contentType ?? 'application/octet-stream',
);

const fileStream: Readable = createReadStream(filePath);

// Use uWebSockets.js native streaming with known size
// This avoids chunked transfer encoding by providing Content-Length
pipeKnownSizeStreamOverResponse(
response,
fileStream,
fileSize,
undefined,
);
};
},
);

@Controller('/files')
export class FileStreamController {
@Get(':filename')
public async streamFile(
// SECURITY: Always sanitize your inputs. Validate filename to prevent path traversal attacks
@Params({ name: 'filename' }, ValidFilenamePipe) filename: string,
@FileStream() stream: (options: FileStreamOptions) => Promise<void>,
): Promise<void> {
// Stream the file with appropriate content type
await stream({
contentType: 'video/mp4',
filePath: `/var/www/files/${filename}`,
});
}
}

HTTP methods

All

Sets up a route for all HTTP methods.

All(path?: string): MethodDecorator

Parameters

  • path (optional string): Route path mounted under the controller's base path. Defaults to '/'. It binds the method to all HTTP methods for the given path.

Example: decorating a controller method

@Controller('/content')
export class ContentController {
@All()
public async allContent(): Promise<void> {}
}

Delete

Sets up a route for DELETE requests.

Delete(path?: string): MethodDecorator

Parameters

  • path (optional string): Route path mounted under the controller's base path. Defaults to '/'. Example: @Delete('/remove') maps to DELETE <controllerPath>/remove.

Example: decorating a controller method

@Controller('/content')
export class ContentController {
@Delete()
public async deleteContent(
@Query() queryParams: { content: string },
): Promise<Content> {
return {
content: queryParams.content,
};
}
}

Get

Sets up a route for GET requests.

Get(path?: string): MethodDecorator

Parameters

  • path (optional string): Route path mounted under the controller's base path. Defaults to '/'. Example: @Get('/list') maps to GET <controllerPath>/list. When omitted, the method is bound to the controller path itself.

Example: decorating a controller method

@Controller('/content')
export class ContentController {
@Get()
public async getContent(
@Query() queryParams: { content: string },
): Promise<Content> {
return {
content: queryParams.content,
};
}
}

Sets up a route for HEAD requests.

warning

Since hono@4, HEAD routes are no longer allowed, use @Get routes instead if you rely on the Hono adapter.

Head(path?: string): MethodDecorator

Parameters

  • path (optional string): Route path mounted under the controller's base path. Defaults to '/'. Example: @Head('/') maps to HEAD <controllerPath>.

Example: decorating a controller method

@Controller('/content')
export class ContentController {
@Head()
@SetHeader('custom-content-header', 'sample')
public async headContent(): Promise<undefined> {
return undefined;
}
}

Options

Sets up a route for OPTIONS requests.

Options(path?: string): MethodDecorator

Parameters

  • path (optional string): Route path mounted under the controller's base path. Defaults to '/'. Example: @Options('/') maps to OPTIONS <controllerPath>.

Example: decorating a controller method

@Controller('/content')
export class ContentController {
@Options()
public async optionsContent(): Promise<undefined> {
return undefined;
}
}

Patch

Sets up a route for PATCH requests.

Patch(path?: string): MethodDecorator

Parameters

  • path (optional string): Route path mounted under the controller's base path. Defaults to '/'. Example: @Patch('/partial') maps to PATCH <controllerPath>/partial.

Example: decorating a controller method

@Controller('/content')
export class ContentController {
@Patch()
public async patchContent(
@Body() body: { content: string },
): Promise<Content> {
return {
content: body.content,
};
}
}

Post

Sets up a route for POST requests.

Post(path?: string): MethodDecorator

Parameters

  • path (optional string): Route path mounted under the controller's base path. Defaults to '/'. Example: @Post('/create') maps to POST <controllerPath>/create.

Example: decorating a controller method

@Controller('/content')
export class ContentController {
@Post()
public async createContent(
@Body() body: { content: string },
): Promise<Content> {
return {
content: body.content,
};
}
}

Put

Sets up a route for PUT requests.

Put(path?: string): MethodDecorator

Parameters

  • path (optional string): Route path mounted under the controller's base path. Defaults to '/'. Example: @Put('/update') maps to PUT <controllerPath>/update.

Notes

  • Use @Body to read the request payload for PUT.

Example: decorating a controller method

@Controller('/content')
export class ContentController {
@Put()
public async updateContent(
@Body() body: { content: string },
): Promise<Content> {
return {
content: body.content,
};
}
}