Skip to main content
The ResponseHandler class provides a fluent API for creating type-safe JSON, binary, text, and error responses. Use createResponseHandler to instantiate a handler with custom options.

createResponseHandler

Factory function to create a ResponseHandler instance with custom configuration.
import { createResponseHandler, options } from '@apisr/response';

const handler = createResponseHandler((opts) => ({
  json: opts.json({
    mapData: (data) => ({ data, success: true })
  }),
  meta: opts.meta({
    default: () => ({ timestamp: Date.now() })
  })
}));

Parameters

opts
Options | (options) => Options
required
Configuration object or function that receives option builders and returns configuration.
  • meta - Metadata options for responses
  • json - JSON response configuration
  • binary - Binary response configuration
  • error - Error handling configuration

Returns

Returns a configured ResponseHandler instance.

ResponseHandler Class

The main response handler class that provides methods for creating different types of responses.

Constructor

Prefer using createResponseHandler instead of calling the constructor directly.
options
Options
required
Handler configuration options
errors
ErrorRegistry
Optional pre-defined error registry
preasignedMeta
Partial<Meta>
Optional meta merged into each response

Methods

json()

Create a JSON response with automatic serialization and validation.
const response = handler.json(
  { users: [{ id: 1, name: 'Alice' }] },
  { status: 200 }
);
input
IInput
required
JSON-serializable data to include in the response body
options
JsonResponse.Options
Optional response configuration
  • status - HTTP status code (default: 200)
  • statusText - HTTP status text
  • headers - Additional HTTP headers
Returns: JsonResponse.Base<IInput> - JSON response instance

binary()

Create a binary response for files, images, or streams.
const blob = new Blob(['Hello'], { type: 'text/plain' });
const response = handler.binary(blob, {
  status: 200,
  headers: { 'Content-Disposition': 'attachment; filename="hello.txt"' }
});
binary
Binary
required
Binary payload: Blob, ArrayBuffer, Uint8Array, or ReadableStream
options
BinaryResponse.Options
Optional response configuration
  • status - HTTP status code (default: 200)
  • statusText - HTTP status text
  • headers - Additional HTTP headers
Returns: BinaryResponse.Base - Binary response instance

text()

Create a plain text response.
const response = handler.text('Hello, World!', { status: 200 });
text
string
required
Raw text response body
options
TextResponse.Options
Optional response configuration
Returns: TextResponse.Base - Text response instance

fail()

Create an error response by name. Supports both built-in default errors and custom errors defined via defineError.
// Built-in error
const response = handler.fail('notFound');

// Custom error with input
const response = handler.fail('validationError', {
  field: 'email',
  message: 'Invalid email format'
});
name
string
required
Error name (registered via defineError or built-in default type)Built-in error types:
  • unauthorized - 401 Unauthorized
  • forbidden - 403 Forbidden
  • notFound - 404 Not Found
  • badRequest - 400 Bad Request
  • conflict - 409 Conflict
  • tooMany - 429 Too Many Requests
  • internal - 500 Internal Server Error
input
TInput
Optional error payload to validate (if error has an input schema)
Returns: ErrorResponse.Base - Error response instance

defineError()

Define a custom error handler. Returns a new ResponseHandler instance with the error registered.
import { z } from '@apisr/zod';

const handlerWithError = handler.defineError(
  'validationError',
  ({ input }) => ({
    message: input.message,
    field: input.field,
    code: 'VALIDATION_ERROR'
  }),
  {
    status: 422,
    statusText: 'Unprocessable Entity',
    input: z.object({
      field: z.string(),
      message: z.string()
    })
  }
);

// Now you can use it
const response = handlerWithError.fail('validationError', {
  field: 'email',
  message: 'Invalid format'
});
name
string
required
Error name to register
handler
ErrorHandler | ErrorOutput
required
Error handler function or static error output object
options
ErrorHandlerOptions
Error configuration
  • status - HTTP status code
  • statusText - HTTP status text
  • input - Input schema for validation
  • validationType - Validation type (“parse” or “assert”)
Returns: New ResponseHandler instance with the error registered

withMeta()

Create a new handler with preassigned metadata that will be merged into each response.
const handlerWithMeta = handler.withMeta({
  requestId: 'req-123',
  userId: 'user-456'
});

const response = handlerWithMeta.json({ message: 'Success' });
// Response includes requestId and userId in metadata
meta
Partial<Meta>
required
Partial metadata that will be merged into each response
Returns: New ResponseHandler instance with preassigned metadata

Example Usage

Basic JSON Response

import { createResponseHandler } from '@apisr/response';

const handler = createResponseHandler({});

export const GET = async () => {
  const users = await db.users.findMany();
  return handler.json({ users });
};

With Custom Configuration

import { createResponseHandler, options } from '@apisr/response';
import { z } from '@apisr/zod';

const handler = createResponseHandler((opts) => ({
  json: opts.json({
    mapData: (data) => ({
      data,
      success: true,
      timestamp: Date.now()
    })
  }),
  meta: opts.meta({
    schema: z.object({
      requestId: z.string(),
      version: z.string()
    }),
    default: () => ({
      requestId: crypto.randomUUID(),
      version: '1.0'
    })
  })
}));

Error Handling

import { createResponseHandler } from '@apisr/response';
import { z } from '@apisr/zod';

const handler = createResponseHandler({}).defineError(
  'resourceNotFound',
  ({ input }) => ({
    message: `${input.resource} not found`,
    code: 'RESOURCE_NOT_FOUND',
    resource: input.resource
  }),
  {
    status: 404,
    statusText: 'Not Found',
    input: z.object({ resource: z.string() })
  }
);

export const GET = async ({ params }) => {
  const user = await db.users.findById(params.id);
  
  if (!user) {
    return handler.fail('resourceNotFound', { resource: 'User' });
  }
  
  return handler.json({ user });
};

Binary Response

import { createResponseHandler } from '@apisr/response';

const handler = createResponseHandler({});

export const GET = async () => {
  const pdfBuffer = await generatePDF();
  
  return handler.binary(pdfBuffer, {
    headers: {
      'Content-Type': 'application/pdf',
      'Content-Disposition': 'attachment; filename="report.pdf"'
    }
  });
};

Build docs developers (and LLMs) love