CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-h3

Minimal H(TTP) framework built for high performance and portability across multiple JavaScript runtimes.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

handlers-middleware.mddocs/

Handler and Middleware System

H3's handler and middleware system provides type-safe handler definition with middleware support, validation, lazy loading, and dynamic routing capabilities.

Capabilities

Handler Definition

Define type-safe event handlers with optional middleware integration.

/**
 * Define an event handler function
 * @param handler - Event handler function
 * @returns Event handler with fetch method
 */
function defineHandler<Req, Res>(handler: EventHandler<Req, Res>): EventHandlerWithFetch<Req, Res>;

/**
 * Define an event handler with middleware and hooks
 * @param def - Handler definition object with middleware
 * @returns Event handler with fetch method
 */
function defineHandler<Req, Res>(def: EventHandlerObject<Req, Res>): EventHandlerWithFetch<Req, Res>;

Usage Examples:

import { defineHandler } from "h3";

// Simple handler
const simpleHandler = defineHandler(async (event) => {
  return { message: "Hello World" };
});

// Handler with middleware
const handlerWithMiddleware = defineHandler({
  onRequest: [
    (event) => {
      console.log(`Request: ${event.method} ${event.url}`);
    }
  ],
  handler: async (event) => {
    const body = await readBody(event);
    return { received: body };
  },
  onResponse: [
    (response, event) => {
      console.log(`Response sent for ${event.url}`);
    }
  ],
  onError: [
    (error, event) => {
      console.error(`Error in ${event.url}:`, error);
    }
  ]
});

Lazy Event Handlers

Create handlers that are loaded on-demand for better performance.

/**
 * Create a lazy-loaded event handler
 * @param load - Function that returns handler when called
 * @returns Event handler that loads on first request
 */
function defineLazyEventHandler(
  load: () => Promise<EventHandler> | EventHandler
): EventHandlerWithFetch;

Usage Examples:

import { defineLazyEventHandler } from "h3";

// Lazy load handler module
const lazyHandler = defineLazyEventHandler(async () => {
  const { heavyHandler } = await import("./heavy-handler");
  return heavyHandler;
});

// Lazy load with dynamic imports
const dynamicHandler = defineLazyEventHandler(async () => {
  const module = await import("./api/users");
  return module.default;
});

// Use in routes
app.get("/heavy", lazyHandler);
app.get("/api/users", dynamicHandler);

Dynamic Event Handlers

Create handlers that can be changed at runtime.

/**
 * Create a dynamic event handler that can be updated at runtime
 * @param initial - Optional initial handler
 * @returns Dynamic handler interface
 */
function dynamicEventHandler(initial?: EventHandler): DynamicEventHandler;

interface DynamicEventHandler {
  /**
   * Update the handler function
   * @param handler - New handler function
   */
  set(handler: EventHandler): void;
  
  /**
   * The current handler function
   */
  handler: EventHandler;
}

Usage Examples:

import { dynamicEventHandler } from "h3";

// Create dynamic handler
const dynamic = dynamicEventHandler(() => ({ message: "Initial handler" }));

// Update handler at runtime
dynamic.set(async (event) => {
  const data = await fetchExternalData();
  return { data };
});

// Use in application
app.get("/dynamic", dynamic.handler);

// Update again based on conditions
if (process.env.NODE_ENV === "development") {
  dynamic.set(() => ({ message: "Development mode" }));
}

Validated Handlers (Experimental)

Define handlers with built-in validation support.

/**
 * Define a handler with validation (experimental)
 * @param def - Handler definition with validation schema
 * @returns Validated event handler
 */
function defineValidatedHandler<Schema>(def: {
  handler: EventHandler;
  validate?: {
    body?: Schema;
    query?: Schema;
    params?: Schema;
  };
}): EventHandlerWithFetch;

Usage Examples:

import { defineValidatedHandler } from "h3";
import { z } from "zod"; // Example with Zod

// Handler with validation
const validatedHandler = defineValidatedHandler({
  validate: {
    body: z.object({
      name: z.string().min(1),
      email: z.string().email(),
      age: z.number().min(18)
    }),
    query: z.object({
      page: z.string().transform(Number).optional(),
      limit: z.string().transform(Number).optional()
    })
  },
  handler: async (event) => {
    // Body and query are automatically validated
    const body = await readValidatedBody(event, (data) => data);
    const query = getValidatedQuery(event, (data) => data);
    
    return { body, query };
  }
});

Middleware System

Middleware Definition

Define reusable middleware functions.

/**
 * Define a middleware function
 * @param input - Middleware function
 * @returns Middleware function
 */
function defineMiddleware(input: Middleware): Middleware;

Usage Examples:

import { defineMiddleware } from "h3";

// Logging middleware
const loggingMiddleware = defineMiddleware((event) => {
  console.log(`${event.method} ${event.url} - ${new Date().toISOString()}`);
});

// Authentication middleware
const authMiddleware = defineMiddleware(async (event) => {
  const token = getHeader(event, "authorization");
  if (!token) {
    throw HTTPError.status(401, "Authorization required");
  }
  
  const user = await verifyToken(token);
  event.context.user = user;
});

// Rate limiting middleware
const rateLimitMiddleware = defineMiddleware((event) => {
  const ip = getRequestIP(event);
  if (isRateLimited(ip)) {
    throw HTTPError.status(429, "Too Many Requests");
  }
  recordRequest(ip);
});

// Use middleware
app.use(loggingMiddleware);
app.use("/api", authMiddleware);
app.use(rateLimitMiddleware);

Lifecycle Hooks

Middleware hooks for different phases of request processing.

/**
 * Register middleware to run on every request
 * @param hook - Function to execute on request
 * @returns Middleware function
 */
function onRequest(hook: (event: H3Event) => void | Promise<void>): Middleware;

/**
 * Register middleware to run on every response
 * @param hook - Function to execute on response
 * @returns Middleware function
 */
function onResponse(
  hook: (response: Response, event: H3Event) => MaybePromise<void | Response>
): Middleware;

/**
 * Register middleware to run on errors
 * @param hook - Function to execute on error
 * @returns Middleware function
 */
function onError(
  hook: (error: HTTPError, event: H3Event) => MaybePromise<void | unknown>
): Middleware;

Usage Examples:

import { onRequest, onResponse, onError } from "h3";

// Request timing
const timingMiddleware = onRequest((event) => {
  event.context.startTime = Date.now();
});

// Add response headers
const headersMiddleware = onResponse((response, event) => {
  const duration = Date.now() - event.context.startTime;
  response.headers.set("X-Response-Time", `${duration}ms`);
  response.headers.set("X-Powered-By", "H3");
  return response;
});

// Error handling
const errorMiddleware = onError((error, event) => {
  console.error(`Error in ${event.url}:`, error);
  
  // Return custom error response
  if (error.status === 404) {
    return { error: "Not Found", path: event.url.pathname };
  }
});

// Register middleware
app.use(timingMiddleware);
app.use(headersMiddleware);
app.use(errorMiddleware);

Handler Types

Core Handler Types

Type definitions for event handlers and middleware.

/**
 * Event handler function type
 */
type EventHandler<RequestT = any, ResponseT = any> = (
  event: H3Event
) => ResponseT | Promise<ResponseT>;

/**
 * Event handler with fetch method
 */
interface EventHandlerWithFetch<RequestT = any, ResponseT = any> extends EventHandler<RequestT, ResponseT> {
  /**
   * Fetch-compatible interface
   */
  fetch: (request: ServerRequest, context?: H3EventContext) => Promise<Response>;
}

/**
 * Handler object with middleware hooks
 */
interface EventHandlerObject<RequestT = any, ResponseT = any> {
  /**
   * Main handler function
   */
  handler: EventHandler<RequestT, ResponseT>;
  
  /**
   * Middleware to run before handler
   */
  onRequest?: Middleware[];
  
  /**
   * Middleware to run after handler
   */
  onResponse?: Middleware[];
  
  /**
   * Middleware to run on errors
   */
  onError?: Middleware[];
}

/**
 * Middleware function type
 */
type Middleware = (event: H3Event) => void | Promise<void>;

/**
 * Lazy event handler type
 */
type LazyEventHandler = () => Promise<EventHandler> | EventHandler;

Request and Response Types

Types for inferring request and response types from handlers.

/**
 * Handler request interface
 */
interface EventHandlerRequest {
  body?: any;
  query?: Record<string, string>;
  params?: Record<string, string>;
  headers?: Record<string, string>;
}

/**
 * Handler response type
 */
type EventHandlerResponse<T = any> = T | Promise<T>;

/**
 * Type helper for inferring event input types
 */
type InferEventInput<Key extends keyof EventHandlerRequest, Event, T = any> = 
  Event extends { [K in Key]: infer U } ? U : T;

Advanced Handler Patterns

Middleware Composition

Compose multiple middleware functions into reusable units.

// Example composition pattern
function composeMiddleware(...middlewares: Middleware[]): Middleware {
  return defineMiddleware(async (event) => {
    for (const middleware of middlewares) {
      await middleware(event);
    }
  });
}

Usage Examples:

// Compose authentication and authorization
const authFlow = composeMiddleware(
  authMiddleware,        // Authenticate user
  permissionsMiddleware, // Check permissions
  rateLimitMiddleware    // Apply rate limiting
);

// Use composed middleware
app.use("/admin", authFlow);

// Compose request processing
const requestProcessing = composeMiddleware(
  corsMiddleware,
  loggingMiddleware,
  validationMiddleware
);

app.use(requestProcessing);

Handler Factories

Create handler factories for common patterns.

// Example handler factory
function createCRUDHandler<T>(resource: string) {
  return {
    list: defineHandler(() => findAll(resource)),
    get: defineHandler((event) => {
      const id = getRouterParam(event, "id");
      return findById(resource, id);
    }),
    create: defineHandler(async (event) => {
      const data = await readBody(event);
      return create(resource, data);
    }),
    update: defineHandler(async (event) => {
      const id = getRouterParam(event, "id");
      const data = await readBody(event);
      return update(resource, id, data);
    }),
    delete: defineHandler((event) => {
      const id = getRouterParam(event, "id");
      return remove(resource, id);
    })
  };
}

Usage Examples:

// Create CRUD handlers for users
const userHandlers = createCRUDHandler("users");

// Register routes
app.get("/users", userHandlers.list);
app.get("/users/:id", userHandlers.get);
app.post("/users", userHandlers.create);
app.put("/users/:id", userHandlers.update);
app.delete("/users/:id", userHandlers.delete);

docs

advanced-features.md

core-framework.md

error-handling.md

event-handling.md

handlers-middleware.md

index.md

request-processing.md

response-handling.md

runtime-adapters.md

web-utilities.md

tile.json