or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cli.mdindex.mdruntime.mdserver.md
tile.json

server.mddocs/

Server Integration

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.

Capabilities

HTTP Handler Creation

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();
});

Complete Server Management

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);

Stream Processing Utilities

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();
});

Request Processing Pipeline

The server integration handles the complete request/response lifecycle with proper header transformation and error handling.

Request Processing Flow:

  1. Request Transformation: Converts Node.js IncomingMessage to Web API Request
  2. Body Stream Handling: Manages request body streams with cloning for middleware
  3. Runtime Dispatch: Sends request to Edge Runtime via dispatchFetch
  4. Response Processing: Transforms Web API Response back to Node.js HTTP response
  5. Stream Piping: Efficiently streams response body with backpressure handling
  6. Error Handling: Catches and converts runtime errors to HTTP responses

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 responses

Node.js HTTP Types

Node.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;
}

Logger Interface

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();