Response Helpers
bxn provides built-in helper functions for creating HTTP responses with full type safety.
json()
Section titled “json()”Returns a JSON response with status 200 OK.
import { json } from '@buildxn/http';
json(data: T, headers?: Record<string, string>): Ok<T>Examples
Section titled “Examples”// Simple JSON responsereturn json({ message: 'Success' });
// With custom headersreturn json( { users: [...] }, { 'Cache-Control': 'max-age=3600' });
// Type-safe responseinterface 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>Example
Section titled “Example”return ok({ status: 'healthy' });created()
Section titled “created()”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>Examples
Section titled “Examples”// Created with locationconst user = db.users.create(req.body);return created(user, `/users/${user.id}`);
// Created with custom headersreturn created({ id: '123' }, '/users/123', { 'X-Request-ID': 'abc123' });noContent()
Section titled “noContent()”Returns a 204 No Content response (empty body).
import { noContent } from '@buildxn/http';
noContent(headers?: Record<string, string>): NoContentExample
Section titled “Example”// After successful DELETEdb.users.delete(userId);return noContent();
// With custom headersreturn noContent({ 'X-Deleted-Count': '1' });badRequest()
Section titled “badRequest()”Returns a 400 Bad Request response.
import { badRequest } from '@buildxn/http';
badRequest( data: T, headers?: Record<string, string>): BadRequest<T>Examples
Section titled “Examples”// Simple errorreturn badRequest({ error: 'Invalid input' });
// Validation errorsreturn badRequest({ errors: ['Name is required', 'Email must be valid'],});
// With custom headersreturn badRequest({ error: 'Invalid token' }, { 'WWW-Authenticate': 'Bearer' });notFound()
Section titled “notFound()”Returns a 404 Not Found response.
import { notFound } from '@buildxn/http';
notFound( data: T, headers?: Record<string, string>): NotFound<T>Examples
Section titled “Examples”// Simple not foundreturn notFound({ error: 'User not found' });
// With detailsreturn notFound({ error: 'Resource not found', resource: 'user', id: userId,});
// With custom headersreturn notFound({ error: 'Page not found' }, { 'X-Reason': 'deleted' });status()
Section titled “status()”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>Examples
Section titled “Examples”// Custom status codereturn status(418); // I'm a teapot
// With datareturn status(429, { error: 'Too many requests' });
// With headersreturn status(503, { error: 'Service unavailable' }, { 'Retry-After': '60' });
// Common custom status codesreturn 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' });stream()
Section titled “stream()”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>Examples
Section titled “Examples”import { stream } from '@buildxn/http';import { Readable } from 'node:stream';
// Server-Sent Eventsconst readable = new Readable({ read() { this.push(`data: ${JSON.stringify({ time: Date.now() })}\n\n`); },});
return stream(readable, 'text/event-stream');
// File streamingconst fileStream = fs.createReadStream('large-file.json');return stream(fileStream, 'application/json');
// Custom headersreturn stream(readable, 'text/event-stream', { 'Cache-Control': 'no-cache' });Response Types
Section titled “Response Types”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';Usage Example
Section titled “Usage Example”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); });Custom Headers
Section titled “Custom Headers”All response helpers accept an optional headers parameter:
// CORS headersreturn json( { data: [...] }, { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE' });
// Caching headersreturn json( { users: [...] }, { 'Cache-Control': 'public, max-age=3600', 'ETag': '"abc123"' });
// Security headersreturn json( { data: [...] }, { 'X-Content-Type-Options': 'nosniff', 'X-Frame-Options': 'DENY' });Complete Example
Section titled “Complete Example”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/:userIdexport 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 /usersexport 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/:userIdexport 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(); });Next Steps
Section titled “Next Steps”- Learn about Type Safety for type-safe responses
- See Examples for complete API implementations