Minimal H(TTP) framework built for high performance and portability across multiple JavaScript runtimes.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Adapters for integrating H3 with different JavaScript runtimes and deployment platforms including Node.js, Web standards, and legacy systems.
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));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 });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" };
});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}`);
});
}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 });
}
};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")
});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)
});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));
}
});/**
* 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>;/**
* 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;
};
}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 () => {});
});
}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);
}
});