Skip to content

Response Helpers

bxn provides built-in helper functions for creating HTTP responses with full type safety.

Returns a JSON response with status 200 OK.

import { json } from '@buildxn/http';
json(data: T, headers?: Record<string, string>): Ok<T>
// Simple JSON response
return json({ message: 'Success' });
// With custom headers
return json(
{ users: [...] },
{ 'Cache-Control': 'max-age=3600' }
);
// Type-safe response
interface User { id: string; name: string }
return json<User[]>([...users]); // Ok<User[]>

Alias for json() with status 200 OK.

import { ok } from '@buildxn/http';
ok(data: T, headers?: Record<string, string>): Ok<T>
return ok({ status: 'healthy' });

Returns a 201 Created response with optional Location header.

import { created } from '@buildxn/http';
created(
data: T,
location?: string,
headers?: Record<string, string>
): Created<T>
// Created with location
const user = db.users.create(req.body);
return created(user, `/users/${user.id}`);
// Created with custom headers
return created({ id: '123' }, '/users/123', { 'X-Request-ID': 'abc123' });

Returns a 204 No Content response (empty body).

import { noContent } from '@buildxn/http';
noContent(headers?: Record<string, string>): NoContent
// After successful DELETE
db.users.delete(userId);
return noContent();
// With custom headers
return noContent({ 'X-Deleted-Count': '1' });

Returns a 400 Bad Request response.

import { badRequest } from '@buildxn/http';
badRequest(
data: T,
headers?: Record<string, string>
): BadRequest<T>
// Simple error
return badRequest({ error: 'Invalid input' });
// Validation errors
return badRequest({
errors: ['Name is required', 'Email must be valid'],
});
// With custom headers
return badRequest({ error: 'Invalid token' }, { 'WWW-Authenticate': 'Bearer' });

Returns a 404 Not Found response.

import { notFound } from '@buildxn/http';
notFound(
data: T,
headers?: Record<string, string>
): NotFound<T>
// Simple not found
return notFound({ error: 'User not found' });
// With details
return notFound({
error: 'Resource not found',
resource: 'user',
id: userId,
});
// With custom headers
return notFound({ error: 'Page not found' }, { 'X-Reason': 'deleted' });

Returns a response with a custom HTTP status code.

import { status } from '@buildxn/http';
status(
code: number,
data?: T,
headers?: Record<string, string>
): HttpResult<T>
// Custom status code
return status(418); // I'm a teapot
// With data
return status(429, { error: 'Too many requests' });
// With headers
return status(503, { error: 'Service unavailable' }, { 'Retry-After': '60' });
// Common custom status codes
return status(401, { error: 'Unauthorized' });
return status(403, { error: 'Forbidden' });
return status(409, { error: 'Conflict' });
return status(422, { error: 'Unprocessable Entity' });
return status(500, { error: 'Internal Server Error' });

Returns a streaming response for real-time data.

import { stream } from '@buildxn/http';
import type { Readable } from 'node:stream';
stream(
readable: Readable,
contentType?: string,
headers?: Record<string, string>
): HttpResult<Readable>
import { stream } from '@buildxn/http';
import { Readable } from 'node:stream';
// Server-Sent Events
const readable = new Readable({
read() {
this.push(`data: ${JSON.stringify({ time: Date.now() })}\n\n`);
},
});
return stream(readable, 'text/event-stream');
// File streaming
const fileStream = fs.createReadStream('large-file.json');
return stream(fileStream, 'application/json');
// Custom headers
return stream(readable, 'text/event-stream', { 'Cache-Control': 'no-cache' });

All response helpers return typed results that can be used in your handler signatures:

import type {
Ok, // 200 OK
Created, // 201 Created
NoContent, // 204 No Content
BadRequest, // 400 Bad Request
NotFound, // 404 Not Found
HttpResult, // Generic response type
} from '@buildxn/http';
import { route, json, notFound, badRequest, StatusCode } from '@buildxn/http';
import { Type } from '@sinclair/typebox';
const UserSchema = Type.Object({
id: Type.String(),
name: Type.String(),
});
export default route()
.params(Type.Object({ userId: Type.String() }))
.response({
[StatusCode.Ok]: { body: UserSchema },
[StatusCode.NotFound]: { body: Type.Object({ error: Type.String() }) },
[StatusCode.BadRequest]: { body: Type.Object({ errors: Type.Array(Type.String()) }) },
})
.handle((req) => {
// TypeScript enforces that you can only return these types
if (validationErrors.length > 0) {
return badRequest({ errors: validationErrors });
}
const user = db.users.get(req.params.userId);
if (!user) {
return notFound({ error: 'User not found' });
}
return json(user);
});

All response helpers accept an optional headers parameter:

// CORS headers
return json(
{ data: [...] },
{
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE'
}
);
// Caching headers
return json(
{ users: [...] },
{
'Cache-Control': 'public, max-age=3600',
'ETag': '"abc123"'
}
);
// Security headers
return json(
{ data: [...] },
{
'X-Content-Type-Options': 'nosniff',
'X-Frame-Options': 'DENY'
}
);
import { route, json, created, noContent, notFound, badRequest, StatusCode } from '@buildxn/http';
import { Type } from '@sinclair/typebox';
const UserSchema = Type.Object({
id: Type.String(),
name: Type.String(),
email: Type.String(),
});
// GET /users/:userId
export const getUser = route()
.params(Type.Object({ userId: Type.String() }))
.response({
[StatusCode.Ok]: { body: UserSchema },
[StatusCode.NotFound]: { body: Type.Object({ error: Type.String() }) },
})
.handle((req) => {
const user = db.users.get(req.params.userId);
if (!user) {
return notFound({ error: 'User not found' });
}
return json(user);
});
// POST /users
export const createUser = route()
.body(
Type.Object({
name: Type.String(),
email: Type.String(),
}),
)
.response({
[StatusCode.Created]: { body: UserSchema },
[StatusCode.BadRequest]: { body: Type.Object({ errors: Type.Array(Type.String()) }) },
})
.handle((req) => {
const errors = validate(req.body);
if (errors.length > 0) {
return badRequest({ errors });
}
const user = db.users.create(req.body);
return created(user, `/users/${user.id}`);
});
// DELETE /users/:userId
export const deleteUser = route()
.params(Type.Object({ userId: Type.String() }))
.response({
[StatusCode.NoContent]: {},
[StatusCode.NotFound]: { body: Type.Object({ error: Type.String() }) },
})
.handle((req) => {
const deleted = db.users.delete(req.params.userId);
if (!deleted) {
return notFound({ error: 'User not found' });
}
return noContent();
});
  • Learn about Type Safety for type-safe responses
  • See Examples for complete API implementations