or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

advanced-features.mdcore-framework.mderror-handling.mdevent-handling.mdhandlers-middleware.mdindex.mdrequest-processing.mdresponse-handling.mdruntime-adapters.mdweb-utilities.md
tile.json

runtime-adapters.mddocs/

Runtime Adapters

Adapters for integrating H3 with different JavaScript runtimes and deployment platforms including Node.js, Web standards, and legacy systems.

Capabilities

Node.js Adapters

Convert H3 applications to work with Node.js HTTP servers and Connect-style middleware.

/**
 * Convert H3 app to Node.js HTTP handler
 * @param app - H3 application instance
 * @returns Node.js HTTP request handler
 */
function toNodeHandler(app: H3): NodeHandler;

/**
 * Convert Node.js handler to H3 event handler
 * @param handler - Node.js handler or middleware
 * @returns H3 event handler
 */
function fromNodeHandler(handler: NodeHandler | NodeMiddleware): EventHandler;

/**
 * Define Node.js HTTP handler
 * @param handler - Node.js handler function
 * @returns Node.js handler function
 */
function defineNodeHandler(handler: NodeHandler): NodeHandler;

/**
 * Define Node.js middleware
 * @param handler - Node.js middleware function
 * @returns Node.js middleware function
 */
function defineNodeMiddleware(handler: NodeMiddleware): NodeMiddleware;

Usage Examples:

import { H3, toNodeHandler, fromNodeHandler } from "h3";
import { createServer } from "http";
import express from "express";

// Convert H3 to Node.js
const app = new H3();
app.get("/", () => ({ message: "Hello from H3" }));
app.post("/users", async (event) => {
  const body = await readBody(event);
  return { user: body };
});

// Create Node.js server
const nodeHandler = toNodeHandler(app);
const server = createServer(nodeHandler);
server.listen(3000);

// Use with Express
const expressApp = express();
expressApp.use("/api", nodeHandler);
expressApp.listen(3001);

// Convert Express middleware to H3
const expressMiddleware = (req, res, next) => {
  console.log(`${req.method} ${req.url}`);
  next();
};

const h3Middleware = fromNodeHandler(expressMiddleware);
app.use(h3Middleware);

// Legacy Connect middleware
const connectMiddleware = (req, res, next) => {
  res.setHeader("X-Powered-By", "H3");
  next();
};

app.use(fromNodeHandler(connectMiddleware));

Web Standard Adapters

Convert between H3 and Web API standard handlers (Fetch API).

/**
 * Convert H3 app to Web API handler (Deprecated - use app.fetch instead)
 * @param app - H3 application instance
 * @returns Web API fetch handler
 */
function toWebHandler(app: H3): (
  request: ServerRequest,
  context?: H3EventContext
) => Promise<Response>;

/**
 * Convert Web API handler to H3 event handler
 * @param handler - Web API fetch handler
 * @returns H3 event handler
 */
function fromWebHandler(
  handler: (request: ServerRequest, context?: H3EventContext) => Promise<Response>
): EventHandler;

Usage Examples:

import { H3, fromWebHandler } from "h3";

// Use Web API handler in H3
const webApiHandler = async (request: Request) => {
  const url = new URL(request.url);
  
  if (url.pathname === "/api/time") {
    return new Response(JSON.stringify({ time: Date.now() }), {
      headers: { "Content-Type": "application/json" }
    });
  }
  
  return new Response("Not Found", { status: 404 });
};

const app = new H3();
app.use("/web-api", fromWebHandler(webApiHandler));

// Convert existing fetch handler
const fetchHandler = async (request: Request, context?: any) => {
  const body = await request.json();
  return new Response(JSON.stringify({ received: body }), {
    headers: { "Content-Type": "application/json" }
  });
};

app.post("/fetch-handler", fromWebHandler(fetchHandler));

// Use H3 with Cloudflare Workers
export default {
  async fetch(request: Request, env: any, ctx: any): Promise<Response> {
    const app = new H3();
    
    app.get("/worker", () => ({
      message: "Hello from Cloudflare Worker",
      env: env.ENVIRONMENT
    }));
    
    return await app.fetch(request, { env, ctx });
  }
};

// Use with Deno
import { serve } from "https://deno.land/std/http/server.ts";

const app = new H3();
app.get("/deno", () => ({ runtime: "Deno", version: Deno.version.deno }));

serve((request) => app.fetch(request), { port: 8000 });

Runtime Detection

Adapt behavior based on the JavaScript runtime environment.

// Runtime detection patterns
const runtimeAwareHandler = defineHandler((event) => {
  const runtime = event.runtime;
  
  switch (runtime?.name) {
    case "node":
      return handleNodeJs(event);
    case "deno":
      return handleDeno(event);
    case "bun":
      return handleBun(event);
    case "cloudflare":
      return handleCloudflareWorkers(event);
    case "workerd":
      return handleWorkerd(event);
    default:
      return handleGeneric(event);
  }
});

Usage Examples:

// Platform-specific features
const platformHandler = defineHandler((event) => {
  const platform = event.runtime?.platform || "unknown";
  
  const features = {
    filesystem: ["node", "deno", "bun"].includes(platform),
    crypto: true, // Available in all modern runtimes
    streams: true,
    workers: platform === "cloudflare"
  };
  
  return { platform, features };
});

// Environment-specific configuration
const configHandler = defineHandler((event) => {
  const runtime = event.runtime?.name || "generic";
  
  const config = {
    node: {
      port: process.env.PORT || 3000,
      workers: require("os").cpus().length
    },
    deno: {
      port: Deno.env.get("PORT") || 8000,
      permissions: Deno.permissions
    },
    bun: {
      port: process.env.PORT || 3000,
      version: Bun.version
    },
    cloudflare: {
      region: event.context.cf?.colo,
      country: event.context.cf?.country
    }
  };
  
  return config[runtime] || { runtime: "generic" };
});

Deployment Examples

Node.js Deployment

import { H3, toNodeHandler } from "h3";
import { createServer } from "http";
import cluster from "cluster";
import { cpus } from "os";

// Create H3 app
const app = new H3();

// Routes
app.get("/", () => ({ message: "Node.js + H3" }));
app.get("/health", () => ({ status: "healthy", pid: process.pid }));

// Cluster setup
if (cluster.isPrimary) {
  const numCPUs = cpus().length;
  
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
  
  cluster.on("exit", (worker) => {
    console.log(`Worker ${worker.process.pid} died`);
    cluster.fork();
  });
} else {
  const server = createServer(toNodeHandler(app));
  const port = process.env.PORT || 3000;
  
  server.listen(port, () => {
    console.log(`Worker ${process.pid} listening on port ${port}`);
  });
}

Cloudflare Workers Deployment

import { H3 } from "h3/cloudflare";

const app = new H3();

app.get("/", () => ({
  message: "Hello from Cloudflare Workers",
  location: "Edge"
}));

app.get("/geo", (event) => ({
  country: event.context.cf?.country,
  city: event.context.cf?.city,
  timezone: event.context.cf?.timezone
}));

app.post("/kv", async (event) => {
  const { key, value } = await readBody(event);
  await event.context.env.MY_KV.put(key, value);
  return { stored: true };
});

export default {
  async fetch(request: Request, env: any, ctx: any): Promise<Response> {
    return await app.fetch(request, { env, ctx, cf: request.cf });
  }
};

Deno Deployment

import { H3 } from "h3/deno";
import { serve } from "https://deno.land/std/http/server.ts";

const app = new H3();

app.get("/", () => ({
  message: "Hello from Deno",
  version: Deno.version.deno
}));

app.get("/file/:filename", async (event) => {
  const filename = getRouterParam(event, "filename");
  
  try {
    const content = await Deno.readTextFile(`./files/${filename}`);
    return { filename, content };
  } catch (error) {
    throw HTTPError.status(404, "File not found");
  }
});

// Start server
serve((request) => app.fetch(request), {
  port: parseInt(Deno.env.get("PORT") || "8000")
});

Bun Deployment

import { H3 } from "h3/bun";

const app = new H3();

app.get("/", () => ({
  message: "Hello from Bun",
  version: Bun.version
}));

app.post("/upload", async (event) => {
  const formData = await readBody(event);
  const file = formData.get("file") as File;
  
  if (file) {
    await Bun.write(`./uploads/${file.name}`, file);
    return { uploaded: file.name, size: file.size };
  }
  
  throw HTTPError.status(400, "No file provided");
});

// Start Bun server
Bun.serve({
  port: process.env.PORT || 3000,
  fetch: (request) => app.fetch(request)
});

Service Worker Deployment

import { H3 } from "h3/service-worker";

const app = new H3();

app.get("/sw", () => ({
  message: "Hello from Service Worker",
  scope: self.registration?.scope
}));

app.get("/cache/:key", async (event) => {
  const key = getRouterParam(event, "key");
  const cache = await caches.open("api-cache");
  const response = await cache.match(`/data/${key}`);
  
  if (response) {
    return await response.json();
  }
  
  throw HTTPError.status(404, "Not in cache");
});

// Service Worker event handlers
self.addEventListener("fetch", (event) => {
  if (event.request.url.includes("/api/")) {
    event.respondWith(app.fetch(event.request));
  }
});

Type Definitions

Node.js Types

/**
 * Node.js HTTP handler type
 */
type NodeHandler = (
  req: IncomingMessage,
  res: ServerResponse
) => void | Promise<void>;

/**
 * Node.js middleware type
 */
type NodeMiddleware = (
  req: IncomingMessage,
  res: ServerResponse,
  next: (error?: any) => void
) => void | Promise<void>;

Runtime Context Types

/**
 * Server runtime context
 */
interface ServerRuntimeContext {
  /**
   * Runtime name (node, deno, bun, cloudflare, etc.)
   */
  name?: string;
  
  /**
   * Runtime version
   */
  version?: string;
  
  /**
   * Platform information
   */
  platform?: string;
  
  /**
   * Additional runtime-specific data
   */
  [key: string]: any;
}

/**
 * Cloudflare-specific context
 */
interface CloudflareContext {
  /**
   * Cloudflare environment variables
   */
  env: {
    [key: string]: any;
  };
  
  /**
   * Execution context
   */
  ctx: {
    waitUntil: (promise: Promise<any>) => void;
    passThroughOnException: () => void;
  };
  
  /**
   * Request CF properties
   */
  cf?: {
    country?: string;
    city?: string;
    region?: string;
    timezone?: string;
    colo?: string;
    [key: string]: any;
  };
}

Advanced Integration Patterns

Middleware Bridge

Create bridges between different middleware ecosystems.

// Express to H3 bridge
function expressToH3(expressMiddleware: any) {
  return defineMiddleware(async (event) => {
    return new Promise((resolve, reject) => {
      const req = event.req as any;
      const res = event.res as any;
      
      // Add Express-like methods
      res.json = (data: any) => {
        event.res.setHeader("Content-Type", "application/json");
        return JSON.stringify(data);
      };
      
      res.status = (code: number) => {
        event.res.setStatus(code);
        return res;
      };
      
      expressMiddleware(req, res, (error?: any) => {
        if (error) reject(error);
        else resolve();
      });
    });
  });
}

// Koa to H3 bridge
function koaToH3(koaMiddleware: any) {
  return defineMiddleware(async (event) => {
    const ctx = {
      request: event.req,
      response: event.res,
      state: event.context
    };
    
    await koaMiddleware(ctx, async () => {});
  });
}

Performance Optimization

Runtime-specific optimizations.

// Runtime-optimized handlers
const optimizedHandler = defineHandler((event) => {
  const runtime = event.runtime?.name;
  
  switch (runtime) {
    case "bun":
      // Use Bun-specific optimizations
      return handleWithBunOptimizations(event);
    case "node":
      // Use Node.js-specific optimizations
      return handleWithNodeOptimizations(event);
    case "cloudflare":
      // Use edge-specific optimizations
      return handleWithEdgeOptimizations(event);
    default:
      return handleGeneric(event);
  }
});