@revas-hq/kit-http v0.0.14
Revas Kit: HTTP Transport (@revas-hq/kit-http)
The @revas-hq/kit-http package provides TypeScript types and interfaces for defining the HTTP transport layer for Revas Kit endpoints. It outlines a structured request/response lifecycle, enabling separation between HTTP handling and core business logic (Endpoint).
This package defines the contracts for functions that decode HTTP requests into domain requests, encode domain responses/errors into HTTP responses, and manipulate context based on HTTP details. Implementations of these functions bridge the gap between raw HTTP and your type-safe endpoints.
Note on Web APIs & SSR:
This package uses standard Web API types (Request,Response,URLSearchParams,ResponseInit,Headers). Implementations must ensure these APIs are available in the target environment (browsers, Deno, Node.js via polyfills likenode-fetch/undici, or server adapters).
Installation
npm install @revas-hq/kit-http @revas-hq/kit-context @revas-hq/kit-endpoint
# or
yarn add @revas-hq/kit-http @revas-hq/kit-context @revas-hq/kit-endpoint(Requires
@revas-hq/kit-contextfor Context and often used with@revas-hq/kit-endpoint)
Core Concepts: The HTTP Request Lifecycle
This package defines functions that typically execute in the following order for a successful request:
- RequestFunction (Optional, Chainable):
Runs first. Modifies the Context based on the incoming Request (e.g., add auth info, trace IDs). - DecodeRequestFunction:
Decodes the HTTP Request (body, params, headers) into a domain-specific request object (TRequest) needed by the Endpoint. - Endpoint (from
@revas-hq/kit-endpoint):
Executes the core business logic using the decoded request and context. Returns a domain-specific response (TResponse) or an EndpointError. - ResponseFunction (Optional, Chainable):
Runs after a successful endpoint call. Modifies HTTP response metadata (ResponseInitheaders, status) based on the final Context. - EncodeResponseFunction:
Encodes the successful domain response (TResponse) into an HTTP Response body and merges final metadata. - EncodeErrorFunction (Error Path):
If any step above fails (returns{ success: false, error: ... }or throws), this function runs to encode the error into a final HTTP Response.
Key Types and Functions
Note: Result types use discriminated unions. Check the
successproperty.
Transport Error
export interface TransportError {
code: number; // Typically HTTP status code
message: string;
details?: unknown;
}Request Processing (Before Endpoint)
RequestFunction
Signature:(args: { context, request, params }) => Promise<RequestFunctionResult>Result:
type RequestFunctionResult = | { success: true, context: Context } | { success: false, error: TransportError }Purpose: Modify context based on the incoming request. Chainable.
DecodeRequestFunction
Signature:(args: { context, request, params }) => Promise<DecodeRequestFunctionResult<TRequest>>Result:
type DecodeRequestFunctionResult<TRequest> = | { success: true, request: TRequest } | { success: false, error: TransportError }Purpose: Extract and validate the domain request (
TRequest) from the HTTP request.
Response Processing (After Endpoint Success)
ResponseFunction
Signature:(args: { context, init: ResponseInit }) => Promise<ResponseFunctionResult>Result:
type ResponseFunctionResult = | { success: true, context: Context, init: ResponseInit } | { success: false, context: Context, error: TransportError }Purpose: Modify response headers/status based on context before encoding the body. Chainable.
EncodeResponseFunction
Signature:(args: { context, response: TResponse, init: ResponseInit }) => Promise<EncodeResponseFunctionResult>Result:
type EncodeResponseFunctionResult = | { success: true, context: Context, response: Response | ResponseInit } | { success: false, context: Context, error: TransportError }Purpose: Convert the domain response (
TResponse) into an HTTP Response body and finalize metadata. Flexibility to return full Response or just ResponseInit.
Error Handling
- EncodeErrorFunction
Signature:
Purpose: Convert any error captured during the lifecycle into a final HTTP Response. Receives the context at the time of error and the error itself ((args: { context, error: unknown, init: ResponseInit }) => Promise<Response>unknown). Must always return a Response.
Middleware Types
Types like DecodeRequestFunctionMiddleware are also available for wrapping specific lifecycle functions, though often endpoint middleware (@revas-hq/kit-endpoint) is sufficient.
Usage
This package primarily defines types. You (or adapter packages like kit-http-react-router) provide implementations for these functions to handle specific data formats (e.g., JSON), authentication methods, and framework requirements.
Example Implementation Snippet (JSON Decoder)
import type { DecodeRequestFunction, DecodeRequestFunctionResult, TransportError } from '@revas-hq/kit-http';
import type { SomeRequestType } from './my-types'; // Your specific type
export const decodeJsonRequest: DecodeRequestFunction<SomeRequestType> = async ({ request, context }): Promise<DecodeRequestFunctionResult<SomeRequestType>> => {
if (request.method === 'GET' || !request.headers.get('content-type')?.includes('application/json')) {
// Or handle based on endpoint needs
return { success: true, request: {} as SomeRequestType }; // Example: Empty object for GET
}
try {
const body = await request.json();
// TODO: Add validation (e.g., using Zod)
if (/* validation fails */) {
return { success: false, error: { code: 400, message: 'Invalid request body format.' } };
}
return { success: true, request: body as SomeRequestType };
} catch (e) {
const error: TransportError = {
code: 400,
message: 'Failed to parse JSON request body.',
details: e instanceof Error ? e.message : String(e),
};
return { success: false, error: error };
}
};See adapter packages like @revas-hq/kit-http-react-router for examples of how these functions are wired together in a specific framework context.
License
This project is licensed under the MIT License. See the LICENSE file for details.