npm package: @revas-hq/kit-http
Description: 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
Latest version: 0.0.16

# 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

```bash
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

```typescript
export interface TransportError {
    code: number; // Typically HTTP status code
    message: string;
    details?: unknown;
}
```

### Request Processing (Before Endpoint)

- **RequestFunction**  
  Signature:  
  ```typescript
  (args: { context, request, params }) => Promise<RequestFunctionResult>
  ```
  Result:  
  ```typescript
  type RequestFunctionResult =
    | { success: true, context: Context }
    | { success: false, error: TransportError }
  ```
  Purpose: Modify context based on the incoming request. Chainable.

- **DecodeRequestFunction<TRequest>**  
  Signature:  
  ```typescript
  (args: { context, request, params }) => Promise<DecodeRequestFunctionResult<TRequest>>
  ```
  Result:  
  ```typescript
  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:  
  ```typescript
  (args: { context, init: ResponseInit }) => Promise<ResponseFunctionResult>
  ```
  Result:  
  ```typescript
  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<TResponse>**  
  Signature:  
  ```typescript
  (args: { context, response: TResponse, init: ResponseInit }) => Promise<EncodeResponseFunctionResult>
  ```
  Result:  
  ```typescript
  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:  
  ```typescript
  (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)

```typescript
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.