0.0.14 • Published 7 months ago

@revas-hq/kit-http v0.0.14

Weekly downloads
-
License
MIT
Repository
github
Last release
7 months ago

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 like node-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-context for 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:

  1. RequestFunction (Optional, Chainable):
    Runs first. Modifies the Context based on the incoming Request (e.g., add auth info, trace IDs).
  2. DecodeRequestFunction:
    Decodes the HTTP Request (body, params, headers) into a domain-specific request object (TRequest) needed by the Endpoint.
  3. 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.
  4. ResponseFunction (Optional, Chainable):
    Runs after a successful endpoint call. Modifies HTTP response metadata (ResponseInit headers, status) based on the final Context.
  5. EncodeResponseFunction:
    Encodes the successful domain response (TResponse) into an HTTP Response body and merges final metadata.
  6. 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 success property.

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:
    (args: { context, error: unknown, init: ResponseInit }) => Promise<Response>
    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 (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.

0.0.10

7 months ago

0.0.11

7 months ago

0.0.12

7 months ago

0.0.13

7 months ago

0.0.14

7 months ago

0.0.9

7 months ago

0.0.8

7 months ago

0.0.5

8 months ago

0.0.4

8 months ago

0.0.7

7 months ago

0.0.6

8 months ago

0.0.3

1 year ago

0.0.1

1 year ago