Server utilities for integrating Edge Runtime with Node.js HTTP servers, providing request handling, response streaming, and comprehensive HTTP server management with backpressure handling and efficient resource utilization.
Creates an HTTP handler that can be used with Node.js HTTP servers to process requests through Edge Runtime.
/**
* Creates an HTTP handler for Node.js HTTP server integration
* @param options - Configuration options for the handler
* @returns Handler object with request handler and waitUntil utility
*/
function createHandler<T extends EdgeContext>(options: {
/** Optional logger interface for request/response logging */
logger?: Logger;
/** The EdgeRuntime instance to handle requests */
runtime: EdgeRuntime<T>;
}): {
/** HTTP request handler function */
handler: (req: IncomingMessage, res: ServerResponse) => Promise<void>;
/** Wait for all pending effects to complete */
waitUntil: () => Promise<unknown[]>;
};Usage Examples:
import { EdgeRuntime, createHandler } from "edge-runtime";
import http from "http";
// Create runtime with edge function
const runtime = new EdgeRuntime({
initialCode: `
addEventListener('fetch', event => {
const url = new URL(event.request.url);
const response = new Response(
JSON.stringify({
method: event.request.method,
path: url.pathname,
timestamp: Date.now()
}),
{ headers: { 'content-type': 'application/json' } }
);
event.respondWith(response);
});
`
});
// Create handler
const { handler, waitUntil } = createHandler({
runtime,
logger: console
});
// Create and start server
const server = http.createServer(handler);
server.listen(3000);
// Graceful shutdown
process.on('SIGTERM', async () => {
await waitUntil(); // Wait for pending requests
server.close();
});Creates and starts a complete HTTP server with automatic port handling and graceful shutdown capabilities.
/**
* Creates and starts an HTTP server with Edge Runtime handler
* @param options - Server configuration including listen options and runtime
* @returns Promise resolving to server management interface
*/
function runServer<T extends EdgeContext>(
options: ListenOptions & {
/** Optional logger interface */
logger?: Logger;
/** The EdgeRuntime instance to handle requests */
runtime: EdgeRuntime<T>;
}
): Promise<EdgeRuntimeServer>;
interface EdgeRuntimeServer {
/** The server URL (e.g., "http://localhost:3000") */
url: string;
/** Close server and wait for all effects to complete */
close: () => Promise<void>;
/** Wait for all current effects to complete */
waitUntil: () => Promise<any[]>;
}Usage Examples:
import { EdgeRuntime, runServer } from "edge-runtime";
// Create runtime
const runtime = new EdgeRuntime({
initialCode: `
addEventListener('fetch', event => {
event.respondWith(new Response('Server is running!'));
});
`
});
// Start server with automatic port allocation
const server = await runServer({
runtime,
port: 0, // Use random available port
logger: console
});
console.log(`Server running at ${server.url}`);
// Close server gracefully
setTimeout(async () => {
await server.close();
console.log('Server closed');
}, 10000);Utilities for handling request and response body streams with proper backpressure handling and error management.
/**
* Creates async iterator from ReadableStream ensuring Uint8Array chunks
* @param body - Optional ReadableStream to consume
* @yields Uint8Array chunks from the stream
* @throws TypeError if stream doesn't return bytes
*/
async function* consumeUint8ArrayReadableStream(
body?: ReadableStream
): AsyncGenerator<Uint8Array, void, unknown>;
/**
* Pipes ReadableStream chunks to HTTP response with backpressure handling
* @param body - Source ReadableStream or null
* @param res - Target writable stream (HTTP response)
* @returns Promise that resolves when piping is complete
*/
async function pipeBodyStreamToResponse(
body: ReadableStream<Uint8Array> | null,
res: Writable
): Promise<void>;Usage Examples:
import { consumeUint8ArrayReadableStream, pipeBodyStreamToResponse } from "edge-runtime";
import { createReadableStream } from "node:stream/web";
// Consume a readable stream
const stream = new ReadableStream({
start(controller) {
controller.enqueue(new TextEncoder().encode('Hello '));
controller.enqueue(new TextEncoder().encode('World!'));
controller.close();
}
});
// Process each chunk
for await (const chunk of consumeUint8ArrayReadableStream(stream)) {
console.log(new TextDecoder().decode(chunk));
}
// Pipe stream to HTTP response
import http from "http";
const server = http.createServer(async (req, res) => {
const responseStream = new ReadableStream({
start(controller) {
controller.enqueue(new TextEncoder().encode('Streaming response...'));
controller.close();
}
});
res.setHeader('content-type', 'text/plain');
await pipeBodyStreamToResponse(responseStream, res);
res.end();
});The server integration handles the complete request/response lifecycle with proper header transformation and error handling.
Request Processing Flow:
Usage Examples:
import { EdgeRuntime, createHandler } from "edge-runtime";
const runtime = new EdgeRuntime({
initialCode: `
addEventListener('fetch', async event => {
const request = event.request;
const url = new URL(request.url);
// Handle different routes
if (url.pathname === '/api/echo') {
const body = await request.text();
event.respondWith(new Response(body, {
headers: { 'content-type': 'text/plain' }
}));
} else if (url.pathname === '/api/json') {
event.respondWith(Response.json({
method: request.method,
headers: Object.fromEntries(request.headers),
url: request.url
}));
} else {
event.respondWith(new Response('Not Found', { status: 404 }));
}
});
`
});
const { handler } = createHandler({ runtime });
// The handler automatically:
// - Converts req/res to Request/Response
// - Handles body streams and headers
// - Manages async operations
// - Provides proper error responsesNode.js HTTP server types used in the server integration.
interface IncomingMessage {
// From Node.js 'http' module
method?: string;
url?: string;
headers: Record<string, string | string[] | undefined>;
socket: any;
}
interface ServerResponse {
// From Node.js 'http' module
statusCode: number;
statusMessage: string;
setHeader(name: string, value: string | string[]): void;
end(): void;
write(chunk: any): boolean;
writableEnded: boolean;
destroyed: boolean;
}
interface Writable {
// From Node.js 'stream' module
write(chunk: any): boolean;
destroyed: boolean;
end(): void;
}Optional logging interface for request/response monitoring and debugging.
interface Logger {
/** Main logging function */
(message: string, opts?: LoggerOptions): void;
/** Warning messages */
warn(message: string, opts?: LoggerOptions): void;
/** Debug messages */
debug(message: string, opts?: LoggerOptions): void;
/** Error messages */
error(message: string, opts?: LoggerOptions): void;
/** Info messages */
info(message: string, opts?: LoggerOptions): void;
/** Quote strings for display */
quotes(str: string): string;
}
interface LoggerOptions {
/** Color name from picocolors */
color?: keyof Colors;
/** Include header in log output */
withHeader?: boolean;
/** Add line break before message */
withBreakline?: boolean;
}
/**
* Creates a CLI-compatible logger instance with colored output
* @returns Logger instance with standard CLI formatting
*/
function createLogger(): Logger;Usage Examples:
// Custom logger implementation
const logger = {
(message, opts) => console.log(`[SERVER] ${message}`),
warn: (message) => console.warn(`[WARN] ${message}`),
debug: (message) => console.debug(`[DEBUG] ${message}`),
error: (message) => console.error(`[ERROR] ${message}`),
info: (message) => console.info(`[INFO] ${message}`),
quotes: (str) => `"${str}"`
};
// Use with server
const server = await runServer({
runtime,
port: 3000,
logger
});
// Built-in logger from CLI
import { createLogger } from "edge-runtime/cli/logger";
const cliLogger = createLogger();