CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-undici-types

A stand-alone types package for Undici HTTP client library

Pending
Overview
Eval results
Files

web-standards.mddocs/

Web Standards APIs

Web-compatible implementations of fetch, WebSocket, FormData and related APIs that follow standard web specifications. These APIs provide familiar interfaces for developers coming from browser environments.

Capabilities

Fetch API

Standards-compliant fetch implementation for HTTP requests.

/**
 * Perform HTTP requests using the standard web fetch API
 * @param input - URL string or Request object
 * @param init - Request configuration options
 * @returns Promise resolving to Response object
 */
function fetch(
  input: RequestInfo,
  init?: RequestInit
): Promise<Response>;

type RequestInfo = Request | string | URL;

interface RequestInit {
  method?: string;
  headers?: HeadersInit;
  body?: BodyInit;
  mode?: RequestMode;
  credentials?: RequestCredentials;
  cache?: RequestCache;
  redirect?: RequestRedirect;
  referrer?: string;
  referrerPolicy?: ReferrerPolicy;
  integrity?: string;
  keepalive?: boolean;
  signal?: AbortSignal;
  window?: null;
  duplex?: RequestDuplex;  
}

type RequestMode = "cors" | "no-cors" | "same-origin" | "navigate";
type RequestCredentials = "omit" | "same-origin" | "include";
type RequestCache = "default" | "no-store" | "reload" | "no-cache" | "force-cache" | "only-if-cached";
type RequestRedirect = "follow" | "error" | "manual";
type RequestDuplex = "half";

Usage Examples:

import { fetch } from "undici-types";

// Simple GET request
const response = await fetch("https://api.example.com/users");
const users = await response.json();

// POST request with JSON
const response = await fetch("https://api.example.com/users", {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    name: "John Doe",
    email: "john@example.com"  
  })
});

// Request with AbortController
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);

try {
  const response = await fetch("https://api.example.com/slow", {
    signal: controller.signal
  });
} catch (error) {
  if (error.name === 'AbortError') {
    console.log('Request was aborted');
  }
}

Request Class

Represents an HTTP request with full configuration options.

/**
 * Represents an HTTP request
 */
class Request implements BodyMixin {
  constructor(input: RequestInfo, init?: RequestInit);
  
  readonly method: string;
  readonly url: string;
  readonly headers: Headers;
  readonly body: ReadableStream<Uint8Array> | null;
  readonly bodyUsed: boolean;
  readonly cache: RequestCache;
  readonly credentials: RequestCredentials;
  readonly destination: RequestDestination;
  readonly integrity: string;
  readonly keepalive: boolean; 
  readonly mode: RequestMode;
  readonly redirect: RequestRedirect;
  readonly referrer: string;
  readonly referrerPolicy: ReferrerPolicy;
  readonly signal: AbortSignal;
  
  clone(): Request;
  
  // BodyMixin methods
  arrayBuffer(): Promise<ArrayBuffer>;
  blob(): Promise<Blob>;
  formData(): Promise<FormData>;
  json(): Promise<any>;
  text(): Promise<string>;
}

type RequestDestination = "" | "audio" | "audioworklet" | "document" | "embed" | "font" | "frame" | "iframe" | "image" | "manifest" | "object" | "paintworklet" | "report" | "script" | "serviceworker" | "sharedworker" | "style" | "track" | "video" | "worker" | "xslt";

Usage Examples:

import { Request, fetch } from "undici-types";

// Create reusable request
const apiRequest = new Request("https://api.example.com/data", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer token123"
  },
  body: JSON.stringify({ query: "users" })
});

// Use request multiple times
const response1 = await fetch(apiRequest.clone());
const response2 = await fetch(apiRequest.clone());

// Access request properties
console.log(apiRequest.method); // "POST"
console.log(apiRequest.url); // "https://api.example.com/data"
console.log(apiRequest.headers.get("Content-Type")); // "application/json"

Response Class

Represents an HTTP response with body parsing methods.

/**
 * Represents an HTTP response
 */
class Response implements BodyMixin {
  constructor(body?: BodyInit | null, init?: ResponseInit);
  
  readonly type: ResponseType;
  readonly url: string;
  readonly redirected: boolean;
  readonly status: number;
  readonly ok: boolean;
  readonly statusText: string;
  readonly headers: Headers;
  readonly body: ReadableStream<Uint8Array> | null;
  readonly bodyUsed: boolean;
  
  clone(): Response;
  
  // BodyMixin methods  
  arrayBuffer(): Promise<ArrayBuffer>;
  blob(): Promise<Blob>;
  formData(): Promise<FormData>;
  json(): Promise<any>;
  text(): Promise<string>;
  
  // Static methods
  static error(): Response;
  static json(data: any, init?: ResponseInit): Response;
  static redirect(url: string | URL, status?: ResponseRedirectStatus): Response;
}

interface ResponseInit {
  status?: number;
  statusText?: string;
  headers?: HeadersInit;
}

type ResponseType = "basic" | "cors" | "default" | "error" | "opaque" | "opaqueredirect";
type ResponseRedirectStatus = 300 | 301 | 302 | 303 | 307 | 308;

Usage Examples:

import { fetch, Response } from "undici-types";

// Handle response
const response = await fetch("https://api.example.com/users");

if (response.ok) {
  const contentType = response.headers.get("content-type");
  
  if (contentType?.includes("application/json")) {
    const data = await response.json();
    console.log(data);
  } else {
    const text = await response.text();
    console.log(text);
  }
} else {
  console.error(`Error: ${response.status} ${response.statusText}`);
}

// Create custom responses
const jsonResponse = Response.json({ message: "Hello" }, {
  status: 200,
  headers: { "Custom-Header": "value" }
});

const redirectResponse = Response.redirect("https://example.com/new-location", 301);

Headers Class

HTTP headers manipulation following web standards.

/**
 * HTTP headers collection with case-insensitive access
 */
class Headers {
  constructor(init?: HeadersInit);
  
  append(name: string, value: string): void;
  delete(name: string): void;
  get(name: string): string | null;
  getSetCookie(): string[];
  has(name: string): boolean;
  set(name: string, value: string): void;
  
  forEach(callback: (value: string, key: string, parent: Headers) => void, thisArg?: any): void;
  keys(): IterableIterator<string>;
  values(): IterableIterator<string>;
  entries(): IterableIterator<[string, string]>;
  [Symbol.iterator](): IterableIterator<[string, string]>;
}

type HeadersInit = Headers | Record<string, string | string[]> | Iterable<readonly [string, string]>;

Usage Examples:

import { Headers, fetch } from "undici-types";

// Create headers object
const headers = new Headers();
headers.set("Content-Type", "application/json");
headers.set("Authorization", "Bearer token123");
headers.append("Accept", "application/json");

// Use with fetch
const response = await fetch("https://api.example.com/data", {
  method: "POST",
  headers: headers,
  body: JSON.stringify({ data: "example" })
});

// Iterate headers
for (const [name, value] of headers) {
  console.log(`${name}: ${value}`);
}

// Create from object
const headers2 = new Headers({
  "Content-Type": "text/plain",
  "Custom-Header": "custom-value"
});

// Create from array
const headers3 = new Headers([
  ["Content-Type", "application/xml"],
  ["Accept", "application/xml"]
]);

WebSocket

WebSocket client implementation following web standards.

/**
 * WebSocket client implementation
 */
class WebSocket extends EventTarget {
  constructor(url: string | URL, protocols?: string | string[], options?: WebSocketInit);
  
  static readonly CONNECTING: 0;
  static readonly OPEN: 1;
  static readonly CLOSING: 2;
  static readonly CLOSED: 3;
  
  readonly CONNECTING: 0;
  readonly OPEN: 1;
  readonly CLOSING: 2;
  readonly CLOSED: 3;
  
  readonly url: string;
  readonly readyState: number;
  readonly extensions: string;
  readonly protocol: string;
  
  binaryType: BinaryType;
  
  onopen: ((this: WebSocket, ev: Event) => any) | null;
  onmessage: ((this: WebSocket, ev: MessageEvent) => any) | null;
  onerror: ((this: WebSocket, ev: ErrorEvent) => any) | null;
  onclose: ((this: WebSocket, ev: CloseEvent) => any) | null;
  
  send(data: string | ArrayBuffer | ArrayBufferView | Blob): void;
  close(code?: number, reason?: string): void;
  
  addEventListener<K extends keyof WebSocketEventMap>(
    type: K,
    listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any,
    options?: boolean | AddEventListenerOptions
  ): void;
  
  removeEventListener<K extends keyof WebSocketEventMap>(
    type: K,
    listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any,
    options?: boolean | EventListenerOptions
  ): void;
}

interface WebSocketInit {
  protocols?: string | string[];
  dispatcher?: Dispatcher;
  headers?: HeadersInit;
  followRedirects?: boolean;
}

type BinaryType = "blob" | "arraybuffer";

interface WebSocketEventMap {
  "close": CloseEvent;
  "error": ErrorEvent;  
  "message": MessageEvent;
  "open": Event;
}

interface CloseEvent extends Event {
  readonly code: number;
  readonly reason: string;
  readonly wasClean: boolean;
}

interface MessageEvent extends Event {
  readonly data: any;
  readonly lastEventId: string;
  readonly origin: string;
  readonly ports: readonly MessagePort[];
  readonly source: MessageEventSource | null;
}

interface ErrorEvent extends Event {
  readonly message: string;
  readonly filename: string;
  readonly lineno: number;
  readonly colno: number;
  readonly error: any;
}

Usage Examples:

import { WebSocket } from "undici-types";

// Basic WebSocket connection
const ws = new WebSocket("ws://localhost:8080");

ws.onopen = (event) => {
  console.log("WebSocket connected");
  ws.send("Hello Server!");
};

ws.onmessage = (event) => {
  console.log("Received:", event.data);
};

ws.onclose = (event) => {
  console.log(`WebSocket closed: ${event.code} ${event.reason}`);
};

ws.onerror = (event) => {
  console.error("WebSocket error:", event.error);
};

// WebSocket with protocols and headers
const ws2 = new WebSocket("wss://api.example.com/ws", ["protocol1", "protocol2"], {
  headers: {
    "Authorization": "Bearer token123"
  }
});

// Send different data types
ws2.onopen = () => {
  ws2.send("text message");
  ws2.send(new ArrayBuffer(8));
  ws2.send(new Uint8Array([1, 2, 3, 4]));
};

// Handle binary data
ws2.binaryType = "arraybuffer";
ws2.onmessage = (event) => {
  if (event.data instanceof ArrayBuffer) {
    console.log("Received binary data:", new Uint8Array(event.data));
  } else {
    console.log("Received text:", event.data);
  }
};

WebSocket Utilities

Additional WebSocket utilities for advanced operations.

/**
 * Send a ping frame to a WebSocket
 * @param ws - The WebSocket instance
 * @param data - Optional ping payload  
 * @returns Promise that resolves when ping is sent
 */
function ping(ws: WebSocket, data?: Buffer | ArrayBuffer | ArrayBufferView): Promise<void>;

/**
 * WebSocket stream interface for streaming operations
 */
class WebSocketStream {
  constructor(url: string | URL, options?: WebSocketStreamOptions);
  
  readonly url: string;
  readonly readyState: number;
  readonly extensions: string;
  readonly protocol: string;
  
  readonly readable: ReadableStream;
  readonly writable: WritableStream;
  
  close(closeInfo?: WebSocketCloseInfo): Promise<void>;
}

interface WebSocketStreamOptions {
  protocols?: string | string[];
  signal?: AbortSignal;
}

interface WebSocketCloseInfo {
  code?: number;
  reason?: string;
}

Usage Examples:

import { WebSocket, WebSocketStream, ping } from "undici-types";

// Ping a WebSocket
const ws = new WebSocket("ws://localhost:8080");
ws.onopen = async () => {
  await ping(ws, Buffer.from("ping-data"));
  console.log("Ping sent");
};

// Use WebSocket streams
const wsStream = new WebSocketStream("ws://localhost:8080/stream");

const writer = wsStream.writable.getWriter();
await writer.write("Hello from stream");

const reader = wsStream.readable.getReader();
const { value, done } = await reader.read();
if (!done) {
  console.log("Received:", value);
}

// Close stream
await wsStream.close({ code: 1000, reason: "Done" });

FormData

Form data construction and parsing for multipart/form-data.

/**
 * Represents form data for multipart/form-data encoding
 */
class FormData {
  append(name: string, value: string | Blob, fileName?: string): void;
  delete(name: string): void;
  get(name: string): FormDataEntryValue | null;
  getAll(name: string): FormDataEntryValue[];
  has(name: string): boolean;
  set(name: string, value: string | Blob, fileName?: string): void;
  
  forEach(
    callback: (value: FormDataEntryValue, key: string, parent: FormData) => void,
    thisArg?: any
  ): void;
  
  keys(): IterableIterator<string>;
  values(): IterableIterator<FormDataEntryValue>;
  entries(): IterableIterator<[string, FormDataEntryValue]>;
  [Symbol.iterator](): IterableIterator<[string, FormDataEntryValue]>;
}

type FormDataEntryValue = File | string;

interface File extends Blob {
  readonly lastModified: number;
  readonly name: string;
  readonly webkitRelativePath: string;
}

interface Blob {
  readonly size: number;
  readonly type: string;
  
  arrayBuffer(): Promise<ArrayBuffer>;
  slice(start?: number, end?: number, contentType?: string): Blob;
  stream(): ReadableStream<Uint8Array>;
  text(): Promise<string>;
}

Usage Examples:

import { FormData, fetch } from "undici-types";

// Create form data
const formData = new FormData();
formData.append("username", "john_doe");
formData.append("email", "john@example.com");
formData.append("avatar", new Blob(["image data"], { type: "image/jpeg" }), "avatar.jpg");

// Send form data
const response = await fetch("https://api.example.com/upload", {
  method: "POST",
  body: formData
});

// Iterate form data
for (const [key, value] of formData) {
  console.log(`${key}:`, value);
}

// Check and manipulate form data
if (formData.has("username")) {
  console.log("Username:", formData.get("username"));
}

formData.set("username", "jane_doe"); // Replace existing value
formData.delete("email"); // Remove field

EventSource

Server-Sent Events (SSE) client implementation for receiving real-time updates from servers.

/**
 * EventSource client for Server-Sent Events (SSE)
 * Maintains a persistent connection to receive server events
 */
class EventSource extends EventTarget {
  constructor(url: string | URL, init?: EventSourceInit);
  
  static readonly CLOSED: 2;
  static readonly CONNECTING: 0;
  static readonly OPEN: 1;
  
  readonly CLOSED: 2;
  readonly CONNECTING: 0;
  readonly OPEN: 1;
  
  /** Current connection state */
  readonly readyState: 0 | 1 | 2;
  
  /** Event source URL */
  readonly url: string;
  
  /** Whether credentials are included in requests */
  readonly withCredentials: boolean;
  
  /** Event handler for connection errors */
  onerror: ((this: EventSource, ev: ErrorEvent) => any) | null;
  
  /** Event handler for received messages */
  onmessage: ((this: EventSource, ev: MessageEvent) => any) | null;
  
  /** Event handler for connection open */
  onopen: ((this: EventSource, ev: Event) => any) | null;
  
  /** Close the connection */
  close(): void;
  
  addEventListener<K extends keyof EventSourceEventMap>(
    type: K,
    listener: (this: EventSource, ev: EventSourceEventMap[K]) => any,
    options?: boolean | AddEventListenerOptions
  ): void;
  
  removeEventListener<K extends keyof EventSourceEventMap>(
    type: K,
    listener: (this: EventSource, ev: EventSourceEventMap[K]) => any,
    options?: boolean | EventListenerOptions
  ): void;
}

interface EventSourceInit {
  /** Include credentials with requests */
  withCredentials?: boolean;
  
  /** Custom dispatcher for the connection */
  dispatcher?: Dispatcher;
  
  /** Node.js specific options */
  node?: {
    /** Custom dispatcher for Node.js */
    dispatcher?: Dispatcher;
    
    /** Reconnection delay in milliseconds */
    reconnectionTime?: number;
  };
}

interface EventSourceEventMap {
  /** Connection error event */
  error: ErrorEvent;
  
  /** Message received event */
  message: MessageEvent;
  
  /** Connection opened event */
  open: Event;
}

Usage Examples:

import { EventSource } from "undici-types";

// Basic EventSource connection
const eventSource = new EventSource("https://api.example.com/events");

// Handle connection events
eventSource.onopen = (event) => {
  console.log("EventSource connection opened");
  console.log("Ready state:", eventSource.readyState); // 1 (OPEN)
};

eventSource.onmessage = (event) => {
  console.log("Received message:", event.data);
  
  // Parse JSON data if expected
  try {
    const data = JSON.parse(event.data);
    console.log("Parsed data:", data);
  } catch (e) {
    console.log("Plain text message:", event.data);
  }
};

eventSource.onerror = (event) => {
  console.error("EventSource error:", event);
  
  if (eventSource.readyState === EventSource.CLOSED) {
    console.log("Connection closed");
  } else {
    console.log("Connection error, will retry...");
  }
};

// EventSource with credentials and custom options
const authEventSource = new EventSource("https://api.example.com/private-events", {
  withCredentials: true,
  node: {
    reconnectionTime: 5000 // 5 second reconnection delay
  }
});

// Listen for custom event types
authEventSource.addEventListener("user-update", (event) => {
  console.log("User update received:", event.data);
});

authEventSource.addEventListener("notification", (event) => {
  const notification = JSON.parse(event.data);
  showNotification(notification.title, notification.message);
});

// Graceful shutdown
window.addEventListener("beforeunload", () => {
  eventSource.close();
  authEventSource.close();
});

// Manual connection management
function connectWithRetry(url: string, maxRetries = 3) {
  let retryCount = 0;
  
  function connect() {
    const es = new EventSource(url);
    
    es.onerror = (event) => {
      if (es.readyState === EventSource.CLOSED && retryCount < maxRetries) {
        console.log(`Retrying connection... (${retryCount + 1}/${maxRetries})`);
        retryCount++;
        setTimeout(connect, 1000 * Math.pow(2, retryCount)); // Exponential backoff
      } else if (retryCount >= maxRetries) {
        console.error("Max retries reached, giving up");
      }
    };
    
    es.onopen = () => {
      retryCount = 0; // Reset retry count on successful connection
      console.log("Connected successfully");
    };
    
    return es;
  }
  
  return connect();
}

const resilientEventSource = connectWithRetry("https://api.example.com/stream");

BodyMixin Interface

Common interface providing body parsing methods for Request and Response classes.

/**
 * Common body parsing methods for Request and Response
 */
interface BodyMixin {
  /** Raw body stream */
  readonly body: ReadableStream<Uint8Array> | null;
  
  /** Whether the body has been consumed */
  readonly bodyUsed: boolean;
  
  /** Parse body as ArrayBuffer */
  arrayBuffer(): Promise<ArrayBuffer>;
  
  /** Parse body as Blob */
  blob(): Promise<Blob>;
  
  /** Parse body as Uint8Array */
  bytes(): Promise<Uint8Array>;
  
  /** Parse body as FormData (deprecated for server parsing) */
  formData(): Promise<FormData>;
  
  /** Parse body as JSON */
  json(): Promise<unknown>;
  
  /** Parse body as text string */
  text(): Promise<string>;
}

type BodyInit = 
  | ArrayBuffer 
  | AsyncIterable<Uint8Array>
  | Blob 
  | FormData 
  | Iterable<Uint8Array>
  | NodeJS.ArrayBufferView 
  | URLSearchParams 
  | null 
  | string;

Install with Tessl CLI

npx tessl i tessl/npm-undici-types

docs

connection-management.md

cookies.md

error-handling.md

http-api.md

http-clients.md

index.md

interceptors.md

testing-mocking.md

utilities.md

web-standards.md

tile.json