Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

capnweb

Package Overview
Dependencies
Maintainers
1
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

capnweb - npm Package Compare versions

Comparing version
0.0.0-1c87560
to
0.0.0-25baebf
dist/index-bun.cjs

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

+125
import { _ as __RPC_TARGET_BRAND, R as RpcTransport, a as RpcTargetBranded, b as RpcSessionOptions, c as RpcCompatible, d as RpcStub$1 } from './index-workers-CiDKhXAE.cjs';
export { e as RpcPromise, f as RpcSession, g as RpcTarget, h as deserialize, n as newHttpBatchRpcResponse, i as newHttpBatchRpcSession, j as newMessagePortRpcSession, k as newWebSocketRpcSession, l as newWorkersRpcResponse, m as newWorkersWebSocketRpcResponse, o as nodeHttpBatchRpcResponse, s as serialize } from './index-workers-CiDKhXAE.cjs';
import { ServerWebSocket } from 'bun';
import 'node:http';
interface RpcTarget {
[__RPC_TARGET_BRAND]: never;
}
declare let RpcTarget: any;
type PropertyPath = (string | number)[];
declare abstract class StubHook {
abstract call(path: PropertyPath, args: RpcPayload): StubHook;
stream(path: PropertyPath, args: RpcPayload): {
promise: Promise<void>;
size?: number;
};
abstract map(path: PropertyPath, captures: StubHook[], instructions: unknown[]): StubHook;
abstract get(path: PropertyPath): StubHook;
abstract dup(): StubHook;
abstract pull(): RpcPayload | Promise<RpcPayload>;
abstract ignoreUnhandledRejections(): void;
abstract dispose(): void;
abstract onBroken(callback: (error: any) => void): void;
}
declare let RAW_STUB: symbol;
interface RpcStub extends Disposable {
}
declare class RpcStub extends RpcTarget {
[RAW_STUB]: this;
constructor(hook: StubHook, pathIfPromise?: PropertyPath);
hook: StubHook;
pathIfPromise?: PropertyPath;
dup(): RpcStub;
onRpcBroken(callback: (error: any) => void): void;
map(func: (value: RpcPromise) => unknown): RpcPromise;
toString(): string;
}
declare class RpcPromise extends RpcStub {
constructor(hook: StubHook, pathIfPromise: PropertyPath);
then(onfulfilled?: ((value: unknown) => unknown) | undefined | null, onrejected?: ((reason: any) => unknown) | undefined | null): Promise<unknown>;
catch(onrejected?: ((reason: any) => unknown) | undefined | null): Promise<unknown>;
finally(onfinally?: (() => void) | undefined | null): Promise<unknown>;
toString(): string;
}
type LocatedPromise = {
parent: object;
property: string | number;
promise: RpcPromise;
};
declare class RpcPayload {
value: unknown;
private source;
private hooks?;
private promises?;
static fromAppParams(value: unknown): RpcPayload;
static fromAppReturn(value: unknown): RpcPayload;
static fromArray(array: RpcPayload[]): RpcPayload;
static forEvaluate(hooks: StubHook[], promises: LocatedPromise[]): RpcPayload;
static deepCopyFrom(value: unknown, oldParent: object | undefined, owner: RpcPayload | null): RpcPayload;
private constructor();
private rpcTargets?;
getHookForRpcTarget(target: RpcTarget | Function, parent: object | undefined, dupStubs?: boolean): StubHook;
getHookForWritableStream(stream: WritableStream, parent: object | undefined, dupStubs?: boolean): StubHook;
getHookForReadableStream(stream: ReadableStream, parent: object | undefined, dupStubs?: boolean): StubHook;
private deepCopy;
ensureDeepCopied(): void;
private deliverTo;
private static deliverRpcPromiseTo;
deliverCall(func: Function, thisArg: object | undefined): Promise<RpcPayload>;
deliverResolve(): Promise<unknown>;
dispose(): void;
private disposeImpl;
ignoreUnhandledRejections(): void;
private ignoreUnhandledRejectionsImpl;
}
type WsData = {
__capnwebTransport: BunWebSocketTransport<WsData>;
__capnwebStub: RpcStub;
};
/**
* Create a Bun `WebSocketHandler` object that manages RPC sessions automatically.
*
* The returned object can be passed directly as the `websocket` option to `Bun.serve()`.
* A fresh `localMain` is created for each connection via the `createMain` callback.
* The transport is stored on `ws.data.__capnwebTransport`.
*
* @param createMain Called once per connection to create the main RPC interface for that client.
* @param options Optional RPC session options applied to every connection.
*/
declare function newBunWebSocketRpcHandler(createMain: () => RpcTargetBranded, options?: RpcSessionOptions): {
open(ws: ServerWebSocket<WsData>): void;
message(ws: ServerWebSocket<WsData>, message: string | Buffer): void;
close(ws: ServerWebSocket<WsData>, code: number, reason: string): void;
error(ws: ServerWebSocket<WsData>, error: Error): void;
};
declare class BunWebSocketTransport<T = undefined> implements RpcTransport {
#private;
constructor(ws: ServerWebSocket<T>);
send(message: string): Promise<void>;
receive(): Promise<string>;
abort?(reason: any): void;
dispatchMessage(data: string | Buffer): void;
dispatchClose(code: number, reason: string): void;
dispatchError(error: Error): void;
}
interface Empty {
}
/**
* Start an RPC session over a Bun ServerWebSocket.
*
* Returns both the RPC stub and the transport. The transport exposes `dispatchMessage`,
* `dispatchClose`, and `dispatchError` methods that must be wired to Bun's `WebSocketHandler`
* callbacks. For a zero-wiring alternative, use `newBunWebSocketRpcHandler` instead.
*
* @param ws The Bun ServerWebSocket from the `open` callback.
* @param localMain The main RPC interface to expose to the peer.
*/
declare let newBunWebSocketRpcSession: <T extends RpcCompatible<T> = Empty, D = undefined>(ws: ServerWebSocket<D>, localMain?: any, options?: RpcSessionOptions) => {
stub: RpcStub$1<T>;
transport: BunWebSocketTransport<D>;
};
export { BunWebSocketTransport, RpcCompatible, RpcSessionOptions, RpcStub$1 as RpcStub, RpcTransport, newBunWebSocketRpcHandler, newBunWebSocketRpcSession };
import { _ as __RPC_TARGET_BRAND, R as RpcTransport, a as RpcTargetBranded, b as RpcSessionOptions, c as RpcCompatible, d as RpcStub$1 } from './index-workers-CiDKhXAE.js';
export { e as RpcPromise, f as RpcSession, g as RpcTarget, h as deserialize, n as newHttpBatchRpcResponse, i as newHttpBatchRpcSession, j as newMessagePortRpcSession, k as newWebSocketRpcSession, l as newWorkersRpcResponse, m as newWorkersWebSocketRpcResponse, o as nodeHttpBatchRpcResponse, s as serialize } from './index-workers-CiDKhXAE.js';
import { ServerWebSocket } from 'bun';
import 'node:http';
interface RpcTarget {
[__RPC_TARGET_BRAND]: never;
}
declare let RpcTarget: any;
type PropertyPath = (string | number)[];
declare abstract class StubHook {
abstract call(path: PropertyPath, args: RpcPayload): StubHook;
stream(path: PropertyPath, args: RpcPayload): {
promise: Promise<void>;
size?: number;
};
abstract map(path: PropertyPath, captures: StubHook[], instructions: unknown[]): StubHook;
abstract get(path: PropertyPath): StubHook;
abstract dup(): StubHook;
abstract pull(): RpcPayload | Promise<RpcPayload>;
abstract ignoreUnhandledRejections(): void;
abstract dispose(): void;
abstract onBroken(callback: (error: any) => void): void;
}
declare let RAW_STUB: symbol;
interface RpcStub extends Disposable {
}
declare class RpcStub extends RpcTarget {
[RAW_STUB]: this;
constructor(hook: StubHook, pathIfPromise?: PropertyPath);
hook: StubHook;
pathIfPromise?: PropertyPath;
dup(): RpcStub;
onRpcBroken(callback: (error: any) => void): void;
map(func: (value: RpcPromise) => unknown): RpcPromise;
toString(): string;
}
declare class RpcPromise extends RpcStub {
constructor(hook: StubHook, pathIfPromise: PropertyPath);
then(onfulfilled?: ((value: unknown) => unknown) | undefined | null, onrejected?: ((reason: any) => unknown) | undefined | null): Promise<unknown>;
catch(onrejected?: ((reason: any) => unknown) | undefined | null): Promise<unknown>;
finally(onfinally?: (() => void) | undefined | null): Promise<unknown>;
toString(): string;
}
type LocatedPromise = {
parent: object;
property: string | number;
promise: RpcPromise;
};
declare class RpcPayload {
value: unknown;
private source;
private hooks?;
private promises?;
static fromAppParams(value: unknown): RpcPayload;
static fromAppReturn(value: unknown): RpcPayload;
static fromArray(array: RpcPayload[]): RpcPayload;
static forEvaluate(hooks: StubHook[], promises: LocatedPromise[]): RpcPayload;
static deepCopyFrom(value: unknown, oldParent: object | undefined, owner: RpcPayload | null): RpcPayload;
private constructor();
private rpcTargets?;
getHookForRpcTarget(target: RpcTarget | Function, parent: object | undefined, dupStubs?: boolean): StubHook;
getHookForWritableStream(stream: WritableStream, parent: object | undefined, dupStubs?: boolean): StubHook;
getHookForReadableStream(stream: ReadableStream, parent: object | undefined, dupStubs?: boolean): StubHook;
private deepCopy;
ensureDeepCopied(): void;
private deliverTo;
private static deliverRpcPromiseTo;
deliverCall(func: Function, thisArg: object | undefined): Promise<RpcPayload>;
deliverResolve(): Promise<unknown>;
dispose(): void;
private disposeImpl;
ignoreUnhandledRejections(): void;
private ignoreUnhandledRejectionsImpl;
}
type WsData = {
__capnwebTransport: BunWebSocketTransport<WsData>;
__capnwebStub: RpcStub;
};
/**
* Create a Bun `WebSocketHandler` object that manages RPC sessions automatically.
*
* The returned object can be passed directly as the `websocket` option to `Bun.serve()`.
* A fresh `localMain` is created for each connection via the `createMain` callback.
* The transport is stored on `ws.data.__capnwebTransport`.
*
* @param createMain Called once per connection to create the main RPC interface for that client.
* @param options Optional RPC session options applied to every connection.
*/
declare function newBunWebSocketRpcHandler(createMain: () => RpcTargetBranded, options?: RpcSessionOptions): {
open(ws: ServerWebSocket<WsData>): void;
message(ws: ServerWebSocket<WsData>, message: string | Buffer): void;
close(ws: ServerWebSocket<WsData>, code: number, reason: string): void;
error(ws: ServerWebSocket<WsData>, error: Error): void;
};
declare class BunWebSocketTransport<T = undefined> implements RpcTransport {
#private;
constructor(ws: ServerWebSocket<T>);
send(message: string): Promise<void>;
receive(): Promise<string>;
abort?(reason: any): void;
dispatchMessage(data: string | Buffer): void;
dispatchClose(code: number, reason: string): void;
dispatchError(error: Error): void;
}
interface Empty {
}
/**
* Start an RPC session over a Bun ServerWebSocket.
*
* Returns both the RPC stub and the transport. The transport exposes `dispatchMessage`,
* `dispatchClose`, and `dispatchError` methods that must be wired to Bun's `WebSocketHandler`
* callbacks. For a zero-wiring alternative, use `newBunWebSocketRpcHandler` instead.
*
* @param ws The Bun ServerWebSocket from the `open` callback.
* @param localMain The main RPC interface to expose to the peer.
*/
declare let newBunWebSocketRpcSession: <T extends RpcCompatible<T> = Empty, D = undefined>(ws: ServerWebSocket<D>, localMain?: any, options?: RpcSessionOptions) => {
stub: RpcStub$1<T>;
transport: BunWebSocketTransport<D>;
};
export { BunWebSocketTransport, RpcCompatible, RpcSessionOptions, RpcStub$1 as RpcStub, RpcTransport, newBunWebSocketRpcHandler, newBunWebSocketRpcSession };

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

import { IncomingMessage, ServerResponse, OutgoingHttpHeaders, OutgoingHttpHeader } from 'node:http';
// Copyright (c) 2025 Cloudflare, Inc.
// Licensed under the MIT license found in the LICENSE.txt file or at:
// https://opensource.org/license/mit
// This file borrows heavily from `types/defines/rpc.d.ts` in workerd.
// Branded types for identifying `WorkerEntrypoint`/`DurableObject`/`Target`s.
// TypeScript uses *structural* typing meaning anything with the same shape as type `T` is a `T`.
// For the classes exported by `cloudflare:workers` we want *nominal* typing (i.e. we only want to
// accept `WorkerEntrypoint` from `cloudflare:workers`, not any other class with the same shape)
declare const __RPC_STUB_BRAND: '__RPC_STUB_BRAND';
declare const __RPC_TARGET_BRAND: '__RPC_TARGET_BRAND';
// Distinguishes mapper placeholders from regular values so param unwrapping can accept them.
declare const __RPC_MAP_VALUE_BRAND: unique symbol;
interface RpcTargetBranded {
[__RPC_TARGET_BRAND]: never;
}
// Types that can be used through `Stub`s
// `never[]` preserves compatibility with strongly-typed function signatures without introducing
// `any` into inference.
type Stubable = RpcTargetBranded | ((...args: never[]) => unknown);
type IsUnknown<T> = unknown extends T ? ([T] extends [unknown] ? true : false) : false;
// Types that can be passed over RPC
// The reason for using a generic type here is to build a serializable subset of structured
// cloneable composite types. This allows types defined with the "interface" keyword to pass the
// serializable check as well. Otherwise, only types defined with the "type" keyword would pass.
type RpcCompatible<T> =
// Allow `unknown` as a leaf so records/interfaces with `unknown` fields remain compatible.
| (IsUnknown<T> extends true ? unknown : never)
// Structured cloneables
| BaseType
// Structured cloneable composites
| Map<
T extends Map<infer U, unknown> ? RpcCompatible<U> : never,
T extends Map<unknown, infer U> ? RpcCompatible<U> : never
>
| Set<T extends Set<infer U> ? RpcCompatible<U> : never>
| Array<T extends Array<infer U> ? RpcCompatible<U> : never>
| ReadonlyArray<T extends ReadonlyArray<infer U> ? RpcCompatible<U> : never>
| {
[K in keyof T as K extends string | number ? K : never]: RpcCompatible<T[K]>;
}
| Promise<T extends Promise<infer U> ? RpcCompatible<U> : never>
// Special types
| Stub<Stubable>
// Serialized as stubs, see `Stubify`
| Stubable;
// Base type for all RPC stubs, including common memory management methods.
// `T` is used as a marker type for unwrapping `Stub`s later.
interface StubBase<T = unknown> extends Disposable {
[__RPC_STUB_BRAND]: T;
dup(): this;
onRpcBroken(callback: (error: any) => void): void;
}
type Stub<T extends RpcCompatible<T>> =
T extends object ? Provider<T> & StubBase<T> : StubBase<T>;
type TypedArray =
| Uint8Array
| Uint8ClampedArray
| Uint16Array
| Uint32Array
| Int8Array
| Int16Array
| Int32Array
| BigUint64Array
| BigInt64Array
| Float32Array
| Float64Array;
// This represents all the types that can be sent as-is over an RPC boundary
type BaseType =
| void
| undefined
| null
| boolean
| number
| bigint
| string
| TypedArray
| ArrayBuffer
| DataView
| Date
| Error
| RegExp
| Blob
| ReadableStream<Uint8Array>
| WritableStream<any> // Chunk type can be any RPC-compatible type
| Request
| Response
| Headers;
// Recursively rewrite all `Stubable` types with `Stub`s, and resolve promises.
// prettier-ignore
type Stubify<T> =
T extends Stubable ? Stub<T>
: T extends Promise<infer U> ? Stubify<U>
: T extends StubBase<any> ? T
: T extends Map<infer K, infer V> ? Map<Stubify<K>, Stubify<V>>
: T extends Set<infer V> ? Set<Stubify<V>>
: T extends [] ? []
: T extends [infer Head, ...infer Tail] ? [Stubify<Head>, ...Stubify<Tail>]
: T extends readonly [] ? readonly []
: T extends readonly [infer Head, ...infer Tail] ? readonly [Stubify<Head>, ...Stubify<Tail>]
: T extends Array<infer V> ? Array<Stubify<V>>
: T extends ReadonlyArray<infer V> ? ReadonlyArray<Stubify<V>>
: T extends BaseType ? T
// When using "unknown" instead of "any", interfaces are not stubified.
: T extends { [key: string | number]: any } ? { [K in keyof T as K extends string | number ? K : never]: Stubify<T[K]> }
: T;
// Recursively rewrite all `Stub<T>`s with the corresponding `T`s.
// Note we use `StubBase` instead of `Stub` here to avoid circular dependencies:
// `Stub` depends on `Provider`, which depends on `Unstubify`, which would depend on `Stub`.
// prettier-ignore
type UnstubifyInner<T> =
// Preserve local RpcTarget acceptance, but avoid needless `Stub | Value` unions when the stub
// is already assignable to the value type (important for callback contextual typing).
T extends StubBase<infer V> ? (T extends V ? UnstubifyInner<V> : (T | UnstubifyInner<V>))
: T extends Promise<infer U> ? UnstubifyInner<U>
: T extends Map<infer K, infer V> ? Map<Unstubify<K>, Unstubify<V>>
: T extends Set<infer V> ? Set<Unstubify<V>>
: T extends [] ? []
: T extends [infer Head, ...infer Tail] ? [Unstubify<Head>, ...Unstubify<Tail>]
: T extends readonly [] ? readonly []
: T extends readonly [infer Head, ...infer Tail] ? readonly [Unstubify<Head>, ...Unstubify<Tail>]
: T extends Array<infer V> ? Array<Unstubify<V>>
: T extends ReadonlyArray<infer V> ? ReadonlyArray<Unstubify<V>>
: T extends BaseType ? T
: T extends { [key: string | number]: unknown } ? { [K in keyof T as K extends string | number ? K : never]: Unstubify<T[K]> }
: T;
// You can put promises anywhere in the params and they'll be resolved before delivery.
// (This also covers RpcPromise, because it's defined as being a Promise.)
// Map placeholders are also allowed so primitive map callback inputs can be forwarded directly
// into RPC params.
//
// Keep raw non-stub members so generic assignability still works when UnstubifyInner<T> is deferred.
// Remove stub members from mixed unions so callback params don’t get both stub and unstubbed signatures.
// Marker carried by map() callback inputs. This lets primitive placeholders flow through params.
type Unstubify<T> =
| NonStubMembers<T>
| UnstubifyInner<T>
| Promise<UnstubifyInner<T>>
| MapValuePlaceholder<UnstubifyInner<T>>;
type UnstubifyAll<A extends readonly unknown[]> = { [I in keyof A]: Unstubify<A[I]> };
interface MapValuePlaceholder<T> {
[__RPC_MAP_VALUE_BRAND]: T;
}
type NonStubMembers<T> = Exclude<T, StubBase<any>>;
// Utility type for adding `Disposable`s to `object` types only.
// Note `unknown & T` is equivalent to `T`.
type MaybeDisposable<T> = T extends object ? Disposable : unknown;
// Type for method return or property on an RPC interface.
// - Stubable types are replaced by stubs.
// - RpcCompatible types are passed by value, with stubable types replaced by stubs
// and a top-level `Disposer`.
// Everything else can't be passed over RPC.
// Technically, we use custom thenables here, but they quack like `Promise`s.
// Intersecting with `(Maybe)Provider` allows pipelining.
// prettier-ignore
type Result<R> =
IsAny<R> extends true ? UnknownResult
: IsUnknown<R> extends true ? UnknownResult
: R extends Stubable ? Promise<Stub<R>> & Provider<R> & StubBase<R>
: R extends RpcCompatible<R> ? Promise<Stubify<R> & MaybeDisposable<R>> & Provider<R> & StubBase<R>
: never;
type IsAny<T> = 0 extends (1 & T) ? true : false;
type UnknownResult = Promise<unknown> & Provider<unknown> & StubBase<unknown>;
// Type for method or property on an RPC interface.
// For methods, unwrap `Stub`s in parameters, and rewrite returns to be `Result`s.
// Unwrapping `Stub`s allows calling with `Stubable` arguments.
// For properties, rewrite types to be `Result`s.
// In each case, unwrap `Promise`s.
type MethodOrProperty<V> = V extends (...args: infer P) => infer R
? (...args: UnstubifyAll<P>) => IsAny<R> extends true ? UnknownResult : Result<Awaited<R>>
: Result<Awaited<V>>;
// Type for the callable part of an `Provider` if `T` is callable.
// This is intersected with methods/properties.
type MaybeCallableProvider<T> = T extends (...args: any[]) => any
? MethodOrProperty<T>
: unknown;
type TupleIndexKeys<T extends ReadonlyArray<unknown>> = Extract<keyof T, `${number}`>;
type MapCallbackValue<T> =
// `Omit` removes call signatures, so re-intersect callable provider behavior.
T extends unknown
? Omit<Result<T>, keyof Promise<unknown>> &
MaybeCallableProvider<T> &
MapValuePlaceholder<T>
: never;
type InvalidNativePromiseInMapResult<T, Seen = never> =
T extends unknown ? InvalidNativePromiseInMapResultImpl<T, Seen> : never;
type InvalidNativePromiseInMapResultImpl<T, Seen> =
[T] extends [Seen] ? never
// RpcPromise is modeled as Promise & StubBase, so allow promise-like stub values.
: T extends StubBase<any> ? never
// Native thenables cannot be represented in map recordings, even when typed as PromiseLike.
: T extends PromiseLike<unknown> ? T
: T extends Map<infer K, infer V>
? InvalidNativePromiseInMapResult<K, Seen | T> |
InvalidNativePromiseInMapResult<V, Seen | T>
: T extends Set<infer V> ? InvalidNativePromiseInMapResult<V, Seen | T>
: T extends readonly [] ? never
: T extends readonly [infer Head, ...infer Tail]
? InvalidNativePromiseInMapResult<Head, Seen | T> |
InvalidNativePromiseInMapResult<Tail[number], Seen | T>
: T extends ReadonlyArray<infer V> ? InvalidNativePromiseInMapResult<V, Seen | T>
: T extends { [key: string | number]: unknown }
? InvalidNativePromiseInMapResult<
T[Extract<keyof T, string | number>],
Seen | T
>
: never;
type MapCallbackReturn<T> =
InvalidNativePromiseInMapResult<T> extends never ? T : never;
type ArrayProvider<E> = {
[K in number]: MethodOrProperty<E>;
} & {
map<V>(callback: (elem: MapCallbackValue<E>) => MapCallbackReturn<V>): Result<Array<V>>;
};
type TupleProvider<T extends ReadonlyArray<unknown>> = {
[K in TupleIndexKeys<T>]: MethodOrProperty<T[K]>;
} & ArrayProvider<T[number]>;
// Base type for all other types providing RPC-like interfaces.
// Rewrites all methods/properties to be `MethodOrProperty`s, while preserving callable types.
type Provider<T> = MaybeCallableProvider<T> &
(T extends ReadonlyArray<unknown>
? number extends T["length"] ? ArrayProvider<T[number]> : TupleProvider<T>
: {
[K in Exclude<
keyof T,
symbol | keyof StubBase<never>
>]: MethodOrProperty<T[K]>;
} & {
map<V>(
callback: (value: MapCallbackValue<NonNullable<T>>) => MapCallbackReturn<V>
): Result<Array<V>>;
});
/**
* Serialize a value, using Cap'n Web's underlying serialization. This won't be able to serialize
* RPC stubs, but it will support basic data types.
*/
declare function serialize(value: unknown): string;
/**
* Deserialize a value serialized using serialize().
*/
declare function deserialize(value: string): unknown;
/**
* Interface for an RPC transport, which is a simple bidirectional message stream. Implement this
* interface if the built-in transports (e.g. for HTTP batch and WebSocket) don't meet your needs.
*/
interface RpcTransport {
/**
* Sends a message to the other end.
*/
send(message: string): Promise<void>;
/**
* Receives a message sent by the other end.
*
* If and when the transport becomes disconnected, this will reject. The thrown error will be
* propagated to all outstanding calls and future calls on any stubs associated with the session.
* If there are no outstanding calls (and none are made in the future), then the error does not
* propagate anywhere -- this is considered a "clean" shutdown.
*/
receive(): Promise<string>;
/**
* Indicates that the RPC system has suffered an error that prevents the session from continuing.
* The transport should ideally try to send any queued messages if it can, and then close the
* connection. (It's not strictly necessary to deliver queued messages, but the last message sent
* before abort() is called is often an "abort" message, which communicates the error to the
* peer, so if that is dropped, the peer may have less information about what happened.)
*/
abort?(reason: any): void;
}
/**
* Options to customize behavior of an RPC session. All functions which start a session should
* optionally accept this.
*/
type RpcSessionOptions = {
/**
* If provided, this function will be called whenever an `Error` object is serialized (for any
* reason, not just because it was thrown). This can be used to log errors, and also to redact
* them.
*
* If `onSendError` returns an Error object, than object will be substituted in place of the
* original. If it has a stack property, the stack will be sent to the client.
*
* If `onSendError` doesn't return anything (or is not provided at all), the default behavior is
* to serialize the error with the stack omitted.
*/
onSendError?: (error: Error) => Error | void;
};
/**
* For use in Cloudflare Workers: Construct an HTTP response that starts a WebSocket RPC session
* with the given `localMain`.
*/
declare function newWorkersWebSocketRpcResponse(request: Request, localMain?: any, options?: RpcSessionOptions): Response;
/**
* Implements the server end of an HTTP batch session, using standard Fetch API types to represent
* HTTP requests and responses.
*
* @param request The request received from the client initiating the session.
* @param localMain The main stub or RpcTarget which the server wishes to expose to the client.
* @param options Optional RPC session options.
* @returns The HTTP response to return to the client. Note that the returned object has mutable
* headers, so you can modify them using e.g. `response.headers.set("Foo", "bar")`.
*/
declare function newHttpBatchRpcResponse(request: Request, localMain: any, options?: RpcSessionOptions): Promise<Response>;
/**
* Implements the server end of an HTTP batch session using traditional Node.js HTTP APIs.
*
* @param request The request received from the client initiating the session.
* @param response The response object, to which the response should be written.
* @param localMain The main stub or RpcTarget which the server wishes to expose to the client.
* @param options Optional RPC session options. You can also pass headers to set on the response.
*/
declare function nodeHttpBatchRpcResponse(request: IncomingMessage, response: ServerResponse, localMain: any, options?: RpcSessionOptions & {
headers?: OutgoingHttpHeaders | OutgoingHttpHeader[];
}): Promise<void>;
/**
* Represents a reference to a remote object, on which methods may be remotely invoked via RPC.
*
* `RpcStub` can represent any interface (when using TypeScript, you pass the specific interface
* type as `T`, but this isn't known at runtime). The way this works is, `RpcStub` is actually a
* `Proxy`. It makes itself appear as if every possible method / property name is defined. You can
* invoke any method name, and the invocation will be sent to the server. If it turns out that no
* such method exists on the remote object, an exception is thrown back. But the client does not
* actually know, until that point, what methods exist.
*/
type RpcStub<T extends RpcCompatible<T>> = Stub<T>;
declare const RpcStub: {
new <T extends RpcCompatible<T>>(value: T): RpcStub<T>;
};
/**
* Represents the result of an RPC call.
*
* Also used to represent properties. That is, `stub.foo` evaluates to an `RpcPromise` for the
* value of `foo`.
*
* This isn't actually a JavaScript `Promise`. It does, however, have `then()`, `catch()`, and
* `finally()` methods, like `Promise` does, and because it has a `then()` method, JavaScript will
* allow you to treat it like a promise, e.g. you can `await` it.
*
* An `RpcPromise` is also a proxy, just like `RpcStub`, where calling methods or awaiting
* properties will make a pipelined network request.
*
* Note that and `RpcPromise` is "lazy": the actual final result is not requested from the server
* until you actually `await` the promise (or call `then()`, etc. on it). This is an optimization:
* if you only intend to use the promise for pipelining and you never await it, then there's no
* need to transmit the resolution!
*/
type RpcPromise<T extends RpcCompatible<T>> = Stub<T> & Promise<Stubify<T>>;
declare const RpcPromise: {};
/**
* Use to construct an `RpcSession` on top of a custom `RpcTransport`.
*
* Most people won't use this. You only need it if you've implemented your own `RpcTransport`.
*/
interface RpcSession<T extends RpcCompatible<T> = undefined> {
getRemoteMain(): RpcStub<T>;
getStats(): {
imports: number;
exports: number;
};
drain(): Promise<void>;
}
declare const RpcSession: {
new <T extends RpcCompatible<T> = undefined>(transport: RpcTransport, localMain?: any, options?: RpcSessionOptions): RpcSession<T>;
};
/**
* Classes which are intended to be passed by reference and called over RPC must extend
* `RpcTarget`. A class which does not extend `RpcTarget` (and which doesn't have built-in support
* from the RPC system) cannot be passed in an RPC message at all; an exception will be thrown.
*
* Note that on Cloudflare Workers, this `RpcTarget` is an alias for the one exported from the
* "cloudflare:workers" module, so they can be used interchangably.
*/
interface RpcTarget extends RpcTargetBranded {
}
declare const RpcTarget: {
new (): RpcTarget;
};
/**
* Empty interface used as default type parameter for sessions where the other side doesn't
* necessarily export a main interface.
*/
interface Empty {
}
/**
* Start a WebSocket session given either an already-open WebSocket or a URL.
*
* @param webSocket Either the `wss://` URL to connect to, or an already-open WebSocket object to
* use.
* @param localMain The main RPC interface to expose to the peer. Returns a stub for the main
* interface exposed from the peer.
*/
declare let newWebSocketRpcSession: <T extends RpcCompatible<T> = Empty>(webSocket: WebSocket | string, localMain?: any, options?: RpcSessionOptions) => RpcStub<T>;
/**
* Initiate an HTTP batch session from the client side.
*
* The parameters to this method have exactly the same signature as `fetch()`, but the return
* value is an RpcStub. You can customize anything about the request except for the method
* (it will always be set to POST) and the body (which the RPC system will fill in).
*/
declare let newHttpBatchRpcSession: <T extends RpcCompatible<T>>(urlOrRequest: string | Request, options?: RpcSessionOptions) => RpcStub<T>;
/**
* Initiate an RPC session over a MessagePort, which is particularly useful for communicating
* between an iframe and its parent frame in a browser context. Each side should call this function
* on its own end of the MessageChannel.
*/
declare let newMessagePortRpcSession: <T extends RpcCompatible<T> = Empty>(port: MessagePort, localMain?: any, options?: RpcSessionOptions) => RpcStub<T>;
/**
* Implements unified handling of HTTP-batch and WebSocket responses for the Cloudflare Workers
* Runtime.
*
* SECURITY WARNING: This function accepts cross-origin requests. If you do not want this, you
* should validate the `Origin` header before calling this, or use `newHttpBatchRpcSession()` and
* `newWebSocketRpcSession()` directly with appropriate security measures for each type of request.
* But if your API uses in-band authorization (i.e. it has an RPC method that takes the user's
* credentials as parameters and returns the authorized API), then cross-origin requests should
* be safe.
*/
declare function newWorkersRpcResponse(request: Request, localMain: any): Promise<Response>;
export { type RpcTransport as R, __RPC_TARGET_BRAND as _, type RpcTargetBranded as a, type RpcSessionOptions as b, type RpcCompatible as c, RpcStub as d, RpcPromise as e, RpcSession as f, RpcTarget as g, deserialize as h, newHttpBatchRpcSession as i, newMessagePortRpcSession as j, newWebSocketRpcSession as k, newWorkersRpcResponse as l, newWorkersWebSocketRpcResponse as m, newHttpBatchRpcResponse as n, nodeHttpBatchRpcResponse as o, serialize as s };
import { IncomingMessage, ServerResponse, OutgoingHttpHeaders, OutgoingHttpHeader } from 'node:http';
// Copyright (c) 2025 Cloudflare, Inc.
// Licensed under the MIT license found in the LICENSE.txt file or at:
// https://opensource.org/license/mit
// This file borrows heavily from `types/defines/rpc.d.ts` in workerd.
// Branded types for identifying `WorkerEntrypoint`/`DurableObject`/`Target`s.
// TypeScript uses *structural* typing meaning anything with the same shape as type `T` is a `T`.
// For the classes exported by `cloudflare:workers` we want *nominal* typing (i.e. we only want to
// accept `WorkerEntrypoint` from `cloudflare:workers`, not any other class with the same shape)
declare const __RPC_STUB_BRAND: '__RPC_STUB_BRAND';
declare const __RPC_TARGET_BRAND: '__RPC_TARGET_BRAND';
// Distinguishes mapper placeholders from regular values so param unwrapping can accept them.
declare const __RPC_MAP_VALUE_BRAND: unique symbol;
interface RpcTargetBranded {
[__RPC_TARGET_BRAND]: never;
}
// Types that can be used through `Stub`s
// `never[]` preserves compatibility with strongly-typed function signatures without introducing
// `any` into inference.
type Stubable = RpcTargetBranded | ((...args: never[]) => unknown);
type IsUnknown<T> = unknown extends T ? ([T] extends [unknown] ? true : false) : false;
// Types that can be passed over RPC
// The reason for using a generic type here is to build a serializable subset of structured
// cloneable composite types. This allows types defined with the "interface" keyword to pass the
// serializable check as well. Otherwise, only types defined with the "type" keyword would pass.
type RpcCompatible<T> =
// Allow `unknown` as a leaf so records/interfaces with `unknown` fields remain compatible.
| (IsUnknown<T> extends true ? unknown : never)
// Structured cloneables
| BaseType
// Structured cloneable composites
| Map<
T extends Map<infer U, unknown> ? RpcCompatible<U> : never,
T extends Map<unknown, infer U> ? RpcCompatible<U> : never
>
| Set<T extends Set<infer U> ? RpcCompatible<U> : never>
| Array<T extends Array<infer U> ? RpcCompatible<U> : never>
| ReadonlyArray<T extends ReadonlyArray<infer U> ? RpcCompatible<U> : never>
| {
[K in keyof T as K extends string | number ? K : never]: RpcCompatible<T[K]>;
}
| Promise<T extends Promise<infer U> ? RpcCompatible<U> : never>
// Special types
| Stub<Stubable>
// Serialized as stubs, see `Stubify`
| Stubable;
// Base type for all RPC stubs, including common memory management methods.
// `T` is used as a marker type for unwrapping `Stub`s later.
interface StubBase<T = unknown> extends Disposable {
[__RPC_STUB_BRAND]: T;
dup(): this;
onRpcBroken(callback: (error: any) => void): void;
}
type Stub<T extends RpcCompatible<T>> =
T extends object ? Provider<T> & StubBase<T> : StubBase<T>;
type TypedArray =
| Uint8Array
| Uint8ClampedArray
| Uint16Array
| Uint32Array
| Int8Array
| Int16Array
| Int32Array
| BigUint64Array
| BigInt64Array
| Float32Array
| Float64Array;
// This represents all the types that can be sent as-is over an RPC boundary
type BaseType =
| void
| undefined
| null
| boolean
| number
| bigint
| string
| TypedArray
| ArrayBuffer
| DataView
| Date
| Error
| RegExp
| Blob
| ReadableStream<Uint8Array>
| WritableStream<any> // Chunk type can be any RPC-compatible type
| Request
| Response
| Headers;
// Recursively rewrite all `Stubable` types with `Stub`s, and resolve promises.
// prettier-ignore
type Stubify<T> =
T extends Stubable ? Stub<T>
: T extends Promise<infer U> ? Stubify<U>
: T extends StubBase<any> ? T
: T extends Map<infer K, infer V> ? Map<Stubify<K>, Stubify<V>>
: T extends Set<infer V> ? Set<Stubify<V>>
: T extends [] ? []
: T extends [infer Head, ...infer Tail] ? [Stubify<Head>, ...Stubify<Tail>]
: T extends readonly [] ? readonly []
: T extends readonly [infer Head, ...infer Tail] ? readonly [Stubify<Head>, ...Stubify<Tail>]
: T extends Array<infer V> ? Array<Stubify<V>>
: T extends ReadonlyArray<infer V> ? ReadonlyArray<Stubify<V>>
: T extends BaseType ? T
// When using "unknown" instead of "any", interfaces are not stubified.
: T extends { [key: string | number]: any } ? { [K in keyof T as K extends string | number ? K : never]: Stubify<T[K]> }
: T;
// Recursively rewrite all `Stub<T>`s with the corresponding `T`s.
// Note we use `StubBase` instead of `Stub` here to avoid circular dependencies:
// `Stub` depends on `Provider`, which depends on `Unstubify`, which would depend on `Stub`.
// prettier-ignore
type UnstubifyInner<T> =
// Preserve local RpcTarget acceptance, but avoid needless `Stub | Value` unions when the stub
// is already assignable to the value type (important for callback contextual typing).
T extends StubBase<infer V> ? (T extends V ? UnstubifyInner<V> : (T | UnstubifyInner<V>))
: T extends Promise<infer U> ? UnstubifyInner<U>
: T extends Map<infer K, infer V> ? Map<Unstubify<K>, Unstubify<V>>
: T extends Set<infer V> ? Set<Unstubify<V>>
: T extends [] ? []
: T extends [infer Head, ...infer Tail] ? [Unstubify<Head>, ...Unstubify<Tail>]
: T extends readonly [] ? readonly []
: T extends readonly [infer Head, ...infer Tail] ? readonly [Unstubify<Head>, ...Unstubify<Tail>]
: T extends Array<infer V> ? Array<Unstubify<V>>
: T extends ReadonlyArray<infer V> ? ReadonlyArray<Unstubify<V>>
: T extends BaseType ? T
: T extends { [key: string | number]: unknown } ? { [K in keyof T as K extends string | number ? K : never]: Unstubify<T[K]> }
: T;
// You can put promises anywhere in the params and they'll be resolved before delivery.
// (This also covers RpcPromise, because it's defined as being a Promise.)
// Map placeholders are also allowed so primitive map callback inputs can be forwarded directly
// into RPC params.
//
// Keep raw non-stub members so generic assignability still works when UnstubifyInner<T> is deferred.
// Remove stub members from mixed unions so callback params don’t get both stub and unstubbed signatures.
// Marker carried by map() callback inputs. This lets primitive placeholders flow through params.
type Unstubify<T> =
| NonStubMembers<T>
| UnstubifyInner<T>
| Promise<UnstubifyInner<T>>
| MapValuePlaceholder<UnstubifyInner<T>>;
type UnstubifyAll<A extends readonly unknown[]> = { [I in keyof A]: Unstubify<A[I]> };
interface MapValuePlaceholder<T> {
[__RPC_MAP_VALUE_BRAND]: T;
}
type NonStubMembers<T> = Exclude<T, StubBase<any>>;
// Utility type for adding `Disposable`s to `object` types only.
// Note `unknown & T` is equivalent to `T`.
type MaybeDisposable<T> = T extends object ? Disposable : unknown;
// Type for method return or property on an RPC interface.
// - Stubable types are replaced by stubs.
// - RpcCompatible types are passed by value, with stubable types replaced by stubs
// and a top-level `Disposer`.
// Everything else can't be passed over RPC.
// Technically, we use custom thenables here, but they quack like `Promise`s.
// Intersecting with `(Maybe)Provider` allows pipelining.
// prettier-ignore
type Result<R> =
IsAny<R> extends true ? UnknownResult
: IsUnknown<R> extends true ? UnknownResult
: R extends Stubable ? Promise<Stub<R>> & Provider<R> & StubBase<R>
: R extends RpcCompatible<R> ? Promise<Stubify<R> & MaybeDisposable<R>> & Provider<R> & StubBase<R>
: never;
type IsAny<T> = 0 extends (1 & T) ? true : false;
type UnknownResult = Promise<unknown> & Provider<unknown> & StubBase<unknown>;
// Type for method or property on an RPC interface.
// For methods, unwrap `Stub`s in parameters, and rewrite returns to be `Result`s.
// Unwrapping `Stub`s allows calling with `Stubable` arguments.
// For properties, rewrite types to be `Result`s.
// In each case, unwrap `Promise`s.
type MethodOrProperty<V> = V extends (...args: infer P) => infer R
? (...args: UnstubifyAll<P>) => IsAny<R> extends true ? UnknownResult : Result<Awaited<R>>
: Result<Awaited<V>>;
// Type for the callable part of an `Provider` if `T` is callable.
// This is intersected with methods/properties.
type MaybeCallableProvider<T> = T extends (...args: any[]) => any
? MethodOrProperty<T>
: unknown;
type TupleIndexKeys<T extends ReadonlyArray<unknown>> = Extract<keyof T, `${number}`>;
type MapCallbackValue<T> =
// `Omit` removes call signatures, so re-intersect callable provider behavior.
T extends unknown
? Omit<Result<T>, keyof Promise<unknown>> &
MaybeCallableProvider<T> &
MapValuePlaceholder<T>
: never;
type InvalidNativePromiseInMapResult<T, Seen = never> =
T extends unknown ? InvalidNativePromiseInMapResultImpl<T, Seen> : never;
type InvalidNativePromiseInMapResultImpl<T, Seen> =
[T] extends [Seen] ? never
// RpcPromise is modeled as Promise & StubBase, so allow promise-like stub values.
: T extends StubBase<any> ? never
// Native thenables cannot be represented in map recordings, even when typed as PromiseLike.
: T extends PromiseLike<unknown> ? T
: T extends Map<infer K, infer V>
? InvalidNativePromiseInMapResult<K, Seen | T> |
InvalidNativePromiseInMapResult<V, Seen | T>
: T extends Set<infer V> ? InvalidNativePromiseInMapResult<V, Seen | T>
: T extends readonly [] ? never
: T extends readonly [infer Head, ...infer Tail]
? InvalidNativePromiseInMapResult<Head, Seen | T> |
InvalidNativePromiseInMapResult<Tail[number], Seen | T>
: T extends ReadonlyArray<infer V> ? InvalidNativePromiseInMapResult<V, Seen | T>
: T extends { [key: string | number]: unknown }
? InvalidNativePromiseInMapResult<
T[Extract<keyof T, string | number>],
Seen | T
>
: never;
type MapCallbackReturn<T> =
InvalidNativePromiseInMapResult<T> extends never ? T : never;
type ArrayProvider<E> = {
[K in number]: MethodOrProperty<E>;
} & {
map<V>(callback: (elem: MapCallbackValue<E>) => MapCallbackReturn<V>): Result<Array<V>>;
};
type TupleProvider<T extends ReadonlyArray<unknown>> = {
[K in TupleIndexKeys<T>]: MethodOrProperty<T[K]>;
} & ArrayProvider<T[number]>;
// Base type for all other types providing RPC-like interfaces.
// Rewrites all methods/properties to be `MethodOrProperty`s, while preserving callable types.
type Provider<T> = MaybeCallableProvider<T> &
(T extends ReadonlyArray<unknown>
? number extends T["length"] ? ArrayProvider<T[number]> : TupleProvider<T>
: {
[K in Exclude<
keyof T,
symbol | keyof StubBase<never>
>]: MethodOrProperty<T[K]>;
} & {
map<V>(
callback: (value: MapCallbackValue<NonNullable<T>>) => MapCallbackReturn<V>
): Result<Array<V>>;
});
/**
* Serialize a value, using Cap'n Web's underlying serialization. This won't be able to serialize
* RPC stubs, but it will support basic data types.
*/
declare function serialize(value: unknown): string;
/**
* Deserialize a value serialized using serialize().
*/
declare function deserialize(value: string): unknown;
/**
* Interface for an RPC transport, which is a simple bidirectional message stream. Implement this
* interface if the built-in transports (e.g. for HTTP batch and WebSocket) don't meet your needs.
*/
interface RpcTransport {
/**
* Sends a message to the other end.
*/
send(message: string): Promise<void>;
/**
* Receives a message sent by the other end.
*
* If and when the transport becomes disconnected, this will reject. The thrown error will be
* propagated to all outstanding calls and future calls on any stubs associated with the session.
* If there are no outstanding calls (and none are made in the future), then the error does not
* propagate anywhere -- this is considered a "clean" shutdown.
*/
receive(): Promise<string>;
/**
* Indicates that the RPC system has suffered an error that prevents the session from continuing.
* The transport should ideally try to send any queued messages if it can, and then close the
* connection. (It's not strictly necessary to deliver queued messages, but the last message sent
* before abort() is called is often an "abort" message, which communicates the error to the
* peer, so if that is dropped, the peer may have less information about what happened.)
*/
abort?(reason: any): void;
}
/**
* Options to customize behavior of an RPC session. All functions which start a session should
* optionally accept this.
*/
type RpcSessionOptions = {
/**
* If provided, this function will be called whenever an `Error` object is serialized (for any
* reason, not just because it was thrown). This can be used to log errors, and also to redact
* them.
*
* If `onSendError` returns an Error object, than object will be substituted in place of the
* original. If it has a stack property, the stack will be sent to the client.
*
* If `onSendError` doesn't return anything (or is not provided at all), the default behavior is
* to serialize the error with the stack omitted.
*/
onSendError?: (error: Error) => Error | void;
};
/**
* For use in Cloudflare Workers: Construct an HTTP response that starts a WebSocket RPC session
* with the given `localMain`.
*/
declare function newWorkersWebSocketRpcResponse(request: Request, localMain?: any, options?: RpcSessionOptions): Response;
/**
* Implements the server end of an HTTP batch session, using standard Fetch API types to represent
* HTTP requests and responses.
*
* @param request The request received from the client initiating the session.
* @param localMain The main stub or RpcTarget which the server wishes to expose to the client.
* @param options Optional RPC session options.
* @returns The HTTP response to return to the client. Note that the returned object has mutable
* headers, so you can modify them using e.g. `response.headers.set("Foo", "bar")`.
*/
declare function newHttpBatchRpcResponse(request: Request, localMain: any, options?: RpcSessionOptions): Promise<Response>;
/**
* Implements the server end of an HTTP batch session using traditional Node.js HTTP APIs.
*
* @param request The request received from the client initiating the session.
* @param response The response object, to which the response should be written.
* @param localMain The main stub or RpcTarget which the server wishes to expose to the client.
* @param options Optional RPC session options. You can also pass headers to set on the response.
*/
declare function nodeHttpBatchRpcResponse(request: IncomingMessage, response: ServerResponse, localMain: any, options?: RpcSessionOptions & {
headers?: OutgoingHttpHeaders | OutgoingHttpHeader[];
}): Promise<void>;
/**
* Represents a reference to a remote object, on which methods may be remotely invoked via RPC.
*
* `RpcStub` can represent any interface (when using TypeScript, you pass the specific interface
* type as `T`, but this isn't known at runtime). The way this works is, `RpcStub` is actually a
* `Proxy`. It makes itself appear as if every possible method / property name is defined. You can
* invoke any method name, and the invocation will be sent to the server. If it turns out that no
* such method exists on the remote object, an exception is thrown back. But the client does not
* actually know, until that point, what methods exist.
*/
type RpcStub<T extends RpcCompatible<T>> = Stub<T>;
declare const RpcStub: {
new <T extends RpcCompatible<T>>(value: T): RpcStub<T>;
};
/**
* Represents the result of an RPC call.
*
* Also used to represent properties. That is, `stub.foo` evaluates to an `RpcPromise` for the
* value of `foo`.
*
* This isn't actually a JavaScript `Promise`. It does, however, have `then()`, `catch()`, and
* `finally()` methods, like `Promise` does, and because it has a `then()` method, JavaScript will
* allow you to treat it like a promise, e.g. you can `await` it.
*
* An `RpcPromise` is also a proxy, just like `RpcStub`, where calling methods or awaiting
* properties will make a pipelined network request.
*
* Note that and `RpcPromise` is "lazy": the actual final result is not requested from the server
* until you actually `await` the promise (or call `then()`, etc. on it). This is an optimization:
* if you only intend to use the promise for pipelining and you never await it, then there's no
* need to transmit the resolution!
*/
type RpcPromise<T extends RpcCompatible<T>> = Stub<T> & Promise<Stubify<T>>;
declare const RpcPromise: {};
/**
* Use to construct an `RpcSession` on top of a custom `RpcTransport`.
*
* Most people won't use this. You only need it if you've implemented your own `RpcTransport`.
*/
interface RpcSession<T extends RpcCompatible<T> = undefined> {
getRemoteMain(): RpcStub<T>;
getStats(): {
imports: number;
exports: number;
};
drain(): Promise<void>;
}
declare const RpcSession: {
new <T extends RpcCompatible<T> = undefined>(transport: RpcTransport, localMain?: any, options?: RpcSessionOptions): RpcSession<T>;
};
/**
* Classes which are intended to be passed by reference and called over RPC must extend
* `RpcTarget`. A class which does not extend `RpcTarget` (and which doesn't have built-in support
* from the RPC system) cannot be passed in an RPC message at all; an exception will be thrown.
*
* Note that on Cloudflare Workers, this `RpcTarget` is an alias for the one exported from the
* "cloudflare:workers" module, so they can be used interchangably.
*/
interface RpcTarget extends RpcTargetBranded {
}
declare const RpcTarget: {
new (): RpcTarget;
};
/**
* Empty interface used as default type parameter for sessions where the other side doesn't
* necessarily export a main interface.
*/
interface Empty {
}
/**
* Start a WebSocket session given either an already-open WebSocket or a URL.
*
* @param webSocket Either the `wss://` URL to connect to, or an already-open WebSocket object to
* use.
* @param localMain The main RPC interface to expose to the peer. Returns a stub for the main
* interface exposed from the peer.
*/
declare let newWebSocketRpcSession: <T extends RpcCompatible<T> = Empty>(webSocket: WebSocket | string, localMain?: any, options?: RpcSessionOptions) => RpcStub<T>;
/**
* Initiate an HTTP batch session from the client side.
*
* The parameters to this method have exactly the same signature as `fetch()`, but the return
* value is an RpcStub. You can customize anything about the request except for the method
* (it will always be set to POST) and the body (which the RPC system will fill in).
*/
declare let newHttpBatchRpcSession: <T extends RpcCompatible<T>>(urlOrRequest: string | Request, options?: RpcSessionOptions) => RpcStub<T>;
/**
* Initiate an RPC session over a MessagePort, which is particularly useful for communicating
* between an iframe and its parent frame in a browser context. Each side should call this function
* on its own end of the MessageChannel.
*/
declare let newMessagePortRpcSession: <T extends RpcCompatible<T> = Empty>(port: MessagePort, localMain?: any, options?: RpcSessionOptions) => RpcStub<T>;
/**
* Implements unified handling of HTTP-batch and WebSocket responses for the Cloudflare Workers
* Runtime.
*
* SECURITY WARNING: This function accepts cross-origin requests. If you do not want this, you
* should validate the `Origin` header before calling this, or use `newHttpBatchRpcSession()` and
* `newWebSocketRpcSession()` directly with appropriate security measures for each type of request.
* But if your API uses in-band authorization (i.e. it has an RPC method that takes the user's
* credentials as parameters and returns the authorized API), then cross-origin requests should
* be safe.
*/
declare function newWorkersRpcResponse(request: Request, localMain: any): Promise<Response>;
export { type RpcTransport as R, __RPC_TARGET_BRAND as _, type RpcTargetBranded as a, type RpcSessionOptions as b, type RpcCompatible as c, RpcStub as d, RpcPromise as e, RpcSession as f, RpcTarget as g, deserialize as h, newHttpBatchRpcSession as i, newMessagePortRpcSession as j, newWebSocketRpcSession as k, newWorkersRpcResponse as l, newWorkersWebSocketRpcResponse as m, newHttpBatchRpcResponse as n, nodeHttpBatchRpcResponse as o, serialize as s };
+1
-1

@@ -1,2 +0,2 @@

export { RpcCompatible, RpcPromise, RpcSession, RpcSessionOptions, RpcStub, RpcTarget, RpcTransport, deserialize, newHttpBatchRpcResponse, newHttpBatchRpcSession, newMessagePortRpcSession, newWebSocketRpcSession, newWorkersRpcResponse, newWorkersWebSocketRpcResponse, nodeHttpBatchRpcResponse, serialize } from './index.cjs';
export { c as RpcCompatible, e as RpcPromise, f as RpcSession, b as RpcSessionOptions, d as RpcStub, g as RpcTarget, R as RpcTransport, h as deserialize, n as newHttpBatchRpcResponse, i as newHttpBatchRpcSession, j as newMessagePortRpcSession, k as newWebSocketRpcSession, l as newWorkersRpcResponse, m as newWorkersWebSocketRpcResponse, o as nodeHttpBatchRpcResponse, s as serialize } from './index-workers-CiDKhXAE.cjs';
import 'node:http';

@@ -1,2 +0,2 @@

export { RpcCompatible, RpcPromise, RpcSession, RpcSessionOptions, RpcStub, RpcTarget, RpcTransport, deserialize, newHttpBatchRpcResponse, newHttpBatchRpcSession, newMessagePortRpcSession, newWebSocketRpcSession, newWorkersRpcResponse, newWorkersWebSocketRpcResponse, nodeHttpBatchRpcResponse, serialize } from './index.js';
export { c as RpcCompatible, e as RpcPromise, f as RpcSession, b as RpcSessionOptions, d as RpcStub, g as RpcTarget, R as RpcTransport, h as deserialize, n as newHttpBatchRpcResponse, i as newHttpBatchRpcSession, j as newMessagePortRpcSession, k as newWebSocketRpcSession, l as newWorkersRpcResponse, m as newWorkersWebSocketRpcResponse, o as nodeHttpBatchRpcResponse, s as serialize } from './index-workers-CiDKhXAE.js';
import 'node:http';

@@ -1,372 +0,2 @@

import { IncomingMessage, ServerResponse, OutgoingHttpHeaders, OutgoingHttpHeader } from 'node:http';
// Copyright (c) 2025 Cloudflare, Inc.
// Licensed under the MIT license found in the LICENSE.txt file or at:
// https://opensource.org/license/mit
// This file borrows heavily from `types/defines/rpc.d.ts` in workerd.
// Branded types for identifying `WorkerEntrypoint`/`DurableObject`/`Target`s.
// TypeScript uses *structural* typing meaning anything with the same shape as type `T` is a `T`.
// For the classes exported by `cloudflare:workers` we want *nominal* typing (i.e. we only want to
// accept `WorkerEntrypoint` from `cloudflare:workers`, not any other class with the same shape)
declare const __RPC_STUB_BRAND: '__RPC_STUB_BRAND';
declare const __RPC_TARGET_BRAND: '__RPC_TARGET_BRAND';
interface RpcTargetBranded {
[__RPC_TARGET_BRAND]: never;
}
// Types that can be used through `Stub`s
type Stubable = RpcTargetBranded | ((...args: any[]) => any);
// Types that can be passed over RPC
// The reason for using a generic type here is to build a serializable subset of structured
// cloneable composite types. This allows types defined with the "interface" keyword to pass the
// serializable check as well. Otherwise, only types defined with the "type" keyword would pass.
type RpcCompatible<T> =
// Structured cloneables
| BaseType
// Structured cloneable composites
| Map<
T extends Map<infer U, unknown> ? RpcCompatible<U> : never,
T extends Map<unknown, infer U> ? RpcCompatible<U> : never
>
| Set<T extends Set<infer U> ? RpcCompatible<U> : never>
| Array<T extends Array<infer U> ? RpcCompatible<U> : never>
| ReadonlyArray<T extends ReadonlyArray<infer U> ? RpcCompatible<U> : never>
| {
[K in keyof T]: K extends number | string ? RpcCompatible<T[K]> : never;
}
| Promise<T extends Promise<infer U> ? RpcCompatible<U> : never>
// Special types
| Stub<Stubable>
// Serialized as stubs, see `Stubify`
| Stubable;
// Base type for all RPC stubs, including common memory management methods.
// `T` is used as a marker type for unwrapping `Stub`s later.
interface StubBase<T extends RpcCompatible<T>> extends Disposable {
[__RPC_STUB_BRAND]: T;
dup(): this;
onRpcBroken(callback: (error: any) => void): void;
}
type Stub<T extends RpcCompatible<T>> =
T extends object ? Provider<T> & StubBase<T> : StubBase<T>;
type TypedArray =
| Uint8Array
| Uint8ClampedArray
| Uint16Array
| Uint32Array
| Int8Array
| Int16Array
| Int32Array
| BigUint64Array
| BigInt64Array
| Float32Array
| Float64Array;
// This represents all the types that can be sent as-is over an RPC boundary
type BaseType =
| void
| undefined
| null
| boolean
| number
| bigint
| string
| TypedArray
| ArrayBuffer
| DataView
| Date
| Error
| RegExp
| ReadableStream<Uint8Array>
| WritableStream<Uint8Array>
| Request
| Response
| Headers;
// Recursively rewrite all `Stubable` types with `Stub`s, and resolve promises.
// prettier-ignore
type Stubify<T> =
T extends Stubable ? Stub<T>
: T extends Promise<infer U> ? Stubify<U>
: T extends StubBase<any> ? T
: T extends Map<infer K, infer V> ? Map<Stubify<K>, Stubify<V>>
: T extends Set<infer V> ? Set<Stubify<V>>
: T extends [] ? []
: T extends [infer Head, ...infer Tail] ? [Stubify<Head>, ...Stubify<Tail>]
: T extends readonly [] ? readonly []
: T extends readonly [infer Head, ...infer Tail] ? readonly [Stubify<Head>, ...Stubify<Tail>]
: T extends Array<infer V> ? Array<Stubify<V>>
: T extends ReadonlyArray<infer V> ? ReadonlyArray<Stubify<V>>
: T extends BaseType ? T
// When using "unknown" instead of "any", interfaces are not stubified.
: T extends { [key: string | number]: any } ? { [K in keyof T]: Stubify<T[K]> }
: T;
// Recursively rewrite all `Stub<T>`s with the corresponding `T`s.
// Note we use `StubBase` instead of `Stub` here to avoid circular dependencies:
// `Stub` depends on `Provider`, which depends on `Unstubify`, which would depend on `Stub`.
// prettier-ignore
type UnstubifyInner<T> =
T extends StubBase<infer V> ? (T | V) // can provide either stub or local RpcTarget
: T extends Map<infer K, infer V> ? Map<Unstubify<K>, Unstubify<V>>
: T extends Set<infer V> ? Set<Unstubify<V>>
: T extends [] ? []
: T extends [infer Head, ...infer Tail] ? [Unstubify<Head>, ...Unstubify<Tail>]
: T extends readonly [] ? readonly []
: T extends readonly [infer Head, ...infer Tail] ? readonly [Unstubify<Head>, ...Unstubify<Tail>]
: T extends Array<infer V> ? Array<Unstubify<V>>
: T extends ReadonlyArray<infer V> ? ReadonlyArray<Unstubify<V>>
: T extends BaseType ? T
: T extends { [key: string | number]: unknown } ? { [K in keyof T]: Unstubify<T[K]> }
: T;
// You can put promises anywhere in the params and they'll be resolved before delivery.
// (This also covers RpcPromise, because it's defined as being a Promise.)
type Unstubify<T> = UnstubifyInner<T> | Promise<UnstubifyInner<T>>
type UnstubifyAll<A extends any[]> = { [I in keyof A]: Unstubify<A[I]> };
// Utility type for adding `Disposable`s to `object` types only.
// Note `unknown & T` is equivalent to `T`.
type MaybeDisposable<T> = T extends object ? Disposable : unknown;
// Type for method return or property on an RPC interface.
// - Stubable types are replaced by stubs.
// - RpcCompatible types are passed by value, with stubable types replaced by stubs
// and a top-level `Disposer`.
// Everything else can't be passed over RPC.
// Technically, we use custom thenables here, but they quack like `Promise`s.
// Intersecting with `(Maybe)Provider` allows pipelining.
// prettier-ignore
type Result<R> =
R extends Stubable ? Promise<Stub<R>> & Provider<R> & StubBase<R>
: R extends RpcCompatible<R> ? Promise<Stubify<R> & MaybeDisposable<R>> & Provider<R> & StubBase<R>
: never;
// Type for method or property on an RPC interface.
// For methods, unwrap `Stub`s in parameters, and rewrite returns to be `Result`s.
// Unwrapping `Stub`s allows calling with `Stubable` arguments.
// For properties, rewrite types to be `Result`s.
// In each case, unwrap `Promise`s.
type MethodOrProperty<V> = V extends (...args: infer P) => infer R
? (...args: UnstubifyAll<P>) => Result<Awaited<R>>
: Result<Awaited<V>>;
// Type for the callable part of an `Provider` if `T` is callable.
// This is intersected with methods/properties.
type MaybeCallableProvider<T> = T extends (...args: any[]) => any
? MethodOrProperty<T>
: unknown;
// Base type for all other types providing RPC-like interfaces.
// Rewrites all methods/properties to be `MethodOrProperty`s, while preserving callable types.
type Provider<T> = MaybeCallableProvider<T> &
(T extends Array<infer U>
? {
[key: number]: MethodOrProperty<U>;
} & {
map<V>(callback: (elem: U) => V): Result<Array<V>>;
}
: {
[K in Exclude<
keyof T,
symbol | keyof StubBase<never>
>]: MethodOrProperty<T[K]>;
} & {
map<V>(callback: (value: NonNullable<T>) => V): Result<Array<V>>;
});
/**
* Serialize a value, using Cap'n Web's underlying serialization. This won't be able to serialize
* RPC stubs, but it will support basic data types.
*/
declare function serialize(value: unknown): string;
/**
* Deserialize a value serialized using serialize().
*/
declare function deserialize(value: string): unknown;
/**
* Interface for an RPC transport, which is a simple bidirectional message stream. Implement this
* interface if the built-in transports (e.g. for HTTP batch and WebSocket) don't meet your needs.
*/
interface RpcTransport {
/**
* Sends a message to the other end.
*/
send(message: string): Promise<void>;
/**
* Receives a message sent by the other end.
*
* If and when the transport becomes disconnected, this will reject. The thrown error will be
* propagated to all outstanding calls and future calls on any stubs associated with the session.
* If there are no outstanding calls (and none are made in the future), then the error does not
* propagate anywhere -- this is considered a "clean" shutdown.
*/
receive(): Promise<string>;
/**
* Indicates that the RPC system has suffered an error that prevents the session from continuing.
* The transport should ideally try to send any queued messages if it can, and then close the
* connection. (It's not strictly necessary to deliver queued messages, but the last message sent
* before abort() is called is often an "abort" message, which communicates the error to the
* peer, so if that is dropped, the peer may have less information about what happened.)
*/
abort?(reason: any): void;
}
/**
* Options to customize behavior of an RPC session. All functions which start a session should
* optionally accept this.
*/
type RpcSessionOptions = {
/**
* If provided, this function will be called whenever an `Error` object is serialized (for any
* reason, not just because it was thrown). This can be used to log errors, and also to redact
* them.
*
* If `onSendError` returns an Error object, than object will be substituted in place of the
* original. If it has a stack property, the stack will be sent to the client.
*
* If `onSendError` doesn't return anything (or is not provided at all), the default behavior is
* to serialize the error with the stack omitted.
*/
onSendError?: (error: Error) => Error | void;
};
/**
* For use in Cloudflare Workers: Construct an HTTP response that starts a WebSocket RPC session
* with the given `localMain`.
*/
declare function newWorkersWebSocketRpcResponse(request: Request, localMain?: any, options?: RpcSessionOptions): Response;
/**
* Implements the server end of an HTTP batch session, using standard Fetch API types to represent
* HTTP requests and responses.
*
* @param request The request received from the client initiating the session.
* @param localMain The main stub or RpcTarget which the server wishes to expose to the client.
* @param options Optional RPC session options.
* @returns The HTTP response to return to the client. Note that the returned object has mutable
* headers, so you can modify them using e.g. `response.headers.set("Foo", "bar")`.
*/
declare function newHttpBatchRpcResponse(request: Request, localMain: any, options?: RpcSessionOptions): Promise<Response>;
/**
* Implements the server end of an HTTP batch session using traditional Node.js HTTP APIs.
*
* @param request The request received from the client initiating the session.
* @param response The response object, to which the response should be written.
* @param localMain The main stub or RpcTarget which the server wishes to expose to the client.
* @param options Optional RPC session options. You can also pass headers to set on the response.
*/
declare function nodeHttpBatchRpcResponse(request: IncomingMessage, response: ServerResponse, localMain: any, options?: RpcSessionOptions & {
headers?: OutgoingHttpHeaders | OutgoingHttpHeader[];
}): Promise<void>;
/**
* Represents a reference to a remote object, on which methods may be remotely invoked via RPC.
*
* `RpcStub` can represent any interface (when using TypeScript, you pass the specific interface
* type as `T`, but this isn't known at runtime). The way this works is, `RpcStub` is actually a
* `Proxy`. It makes itself appear as if every possible method / property name is defined. You can
* invoke any method name, and the invocation will be sent to the server. If it turns out that no
* such method exists on the remote object, an exception is thrown back. But the client does not
* actually know, until that point, what methods exist.
*/
type RpcStub<T extends RpcCompatible<T>> = Stub<T>;
declare const RpcStub: {
new <T extends RpcCompatible<T>>(value: T): RpcStub<T>;
};
/**
* Represents the result of an RPC call.
*
* Also used to represent properties. That is, `stub.foo` evaluates to an `RpcPromise` for the
* value of `foo`.
*
* This isn't actually a JavaScript `Promise`. It does, however, have `then()`, `catch()`, and
* `finally()` methods, like `Promise` does, and because it has a `then()` method, JavaScript will
* allow you to treat it like a promise, e.g. you can `await` it.
*
* An `RpcPromise` is also a proxy, just like `RpcStub`, where calling methods or awaiting
* properties will make a pipelined network request.
*
* Note that and `RpcPromise` is "lazy": the actual final result is not requested from the server
* until you actually `await` the promise (or call `then()`, etc. on it). This is an optimization:
* if you only intend to use the promise for pipelining and you never await it, then there's no
* need to transmit the resolution!
*/
type RpcPromise<T extends RpcCompatible<T>> = Stub<T> & Promise<Stubify<T>>;
declare const RpcPromise: {};
/**
* Use to construct an `RpcSession` on top of a custom `RpcTransport`.
*
* Most people won't use this. You only need it if you've implemented your own `RpcTransport`.
*/
interface RpcSession<T extends RpcCompatible<T> = undefined> {
getRemoteMain(): RpcStub<T>;
getStats(): {
imports: number;
exports: number;
};
drain(): Promise<void>;
}
declare const RpcSession: {
new <T extends RpcCompatible<T> = undefined>(transport: RpcTransport, localMain?: any, options?: RpcSessionOptions): RpcSession<T>;
};
/**
* Classes which are intended to be passed by reference and called over RPC must extend
* `RpcTarget`. A class which does not extend `RpcTarget` (and which doesn't have built-in support
* from the RPC system) cannot be passed in an RPC message at all; an exception will be thrown.
*
* Note that on Cloudflare Workers, this `RpcTarget` is an alias for the one exported from the
* "cloudflare:workers" module, so they can be used interchangably.
*/
interface RpcTarget extends RpcTargetBranded {
}
declare const RpcTarget: {
new (): RpcTarget;
};
/**
* Empty interface used as default type parameter for sessions where the other side doesn't
* necessarily export a main interface.
*/
interface Empty {
}
/**
* Start a WebSocket session given either an already-open WebSocket or a URL.
*
* @param webSocket Either the `wss://` URL to connect to, or an already-open WebSocket object to
* use.
* @param localMain The main RPC interface to expose to the peer. Returns a stub for the main
* interface exposed from the peer.
*/
declare let newWebSocketRpcSession: <T extends RpcCompatible<T> = Empty>(webSocket: WebSocket | string, localMain?: any, options?: RpcSessionOptions) => RpcStub<T>;
/**
* Initiate an HTTP batch session from the client side.
*
* The parameters to this method have exactly the same signature as `fetch()`, but the return
* value is an RpcStub. You can customize anything about the request except for the method
* (it will always be set to POST) and the body (which the RPC system will fill in).
*/
declare let newHttpBatchRpcSession: <T extends RpcCompatible<T>>(urlOrRequest: string | Request, options?: RpcSessionOptions) => RpcStub<T>;
/**
* Initiate an RPC session over a MessagePort, which is particularly useful for communicating
* between an iframe and its parent frame in a browser context. Each side should call this function
* on its own end of the MessageChannel.
*/
declare let newMessagePortRpcSession: <T extends RpcCompatible<T> = Empty>(port: MessagePort, localMain?: any, options?: RpcSessionOptions) => RpcStub<T>;
/**
* Implements unified handling of HTTP-batch and WebSocket responses for the Cloudflare Workers
* Runtime.
*
* SECURITY WARNING: This function accepts cross-origin requests. If you do not want this, you
* should validate the `Origin` header before calling this, or use `newHttpBatchRpcSession()` and
* `newWebSocketRpcSession()` directly with appropriate security measures for each type of request.
* But if your API uses in-band authorization (i.e. it has an RPC method that takes the user's
* credentials as parameters and returns the authorized API), then cross-origin requests should
* be safe.
*/
declare function newWorkersRpcResponse(request: Request, localMain: any): Promise<Response>;
export { type RpcCompatible, RpcPromise, RpcSession, type RpcSessionOptions, RpcStub, RpcTarget, type RpcTransport, deserialize, newHttpBatchRpcResponse, newHttpBatchRpcSession, newMessagePortRpcSession, newWebSocketRpcSession, newWorkersRpcResponse, newWorkersWebSocketRpcResponse, nodeHttpBatchRpcResponse, serialize };
export { c as RpcCompatible, e as RpcPromise, f as RpcSession, b as RpcSessionOptions, d as RpcStub, g as RpcTarget, R as RpcTransport, h as deserialize, n as newHttpBatchRpcResponse, i as newHttpBatchRpcSession, j as newMessagePortRpcSession, k as newWebSocketRpcSession, l as newWorkersRpcResponse, m as newWorkersWebSocketRpcResponse, o as nodeHttpBatchRpcResponse, s as serialize } from './index-workers-CiDKhXAE.cjs';
import 'node:http';

@@ -1,372 +0,2 @@

import { IncomingMessage, ServerResponse, OutgoingHttpHeaders, OutgoingHttpHeader } from 'node:http';
// Copyright (c) 2025 Cloudflare, Inc.
// Licensed under the MIT license found in the LICENSE.txt file or at:
// https://opensource.org/license/mit
// This file borrows heavily from `types/defines/rpc.d.ts` in workerd.
// Branded types for identifying `WorkerEntrypoint`/`DurableObject`/`Target`s.
// TypeScript uses *structural* typing meaning anything with the same shape as type `T` is a `T`.
// For the classes exported by `cloudflare:workers` we want *nominal* typing (i.e. we only want to
// accept `WorkerEntrypoint` from `cloudflare:workers`, not any other class with the same shape)
declare const __RPC_STUB_BRAND: '__RPC_STUB_BRAND';
declare const __RPC_TARGET_BRAND: '__RPC_TARGET_BRAND';
interface RpcTargetBranded {
[__RPC_TARGET_BRAND]: never;
}
// Types that can be used through `Stub`s
type Stubable = RpcTargetBranded | ((...args: any[]) => any);
// Types that can be passed over RPC
// The reason for using a generic type here is to build a serializable subset of structured
// cloneable composite types. This allows types defined with the "interface" keyword to pass the
// serializable check as well. Otherwise, only types defined with the "type" keyword would pass.
type RpcCompatible<T> =
// Structured cloneables
| BaseType
// Structured cloneable composites
| Map<
T extends Map<infer U, unknown> ? RpcCompatible<U> : never,
T extends Map<unknown, infer U> ? RpcCompatible<U> : never
>
| Set<T extends Set<infer U> ? RpcCompatible<U> : never>
| Array<T extends Array<infer U> ? RpcCompatible<U> : never>
| ReadonlyArray<T extends ReadonlyArray<infer U> ? RpcCompatible<U> : never>
| {
[K in keyof T]: K extends number | string ? RpcCompatible<T[K]> : never;
}
| Promise<T extends Promise<infer U> ? RpcCompatible<U> : never>
// Special types
| Stub<Stubable>
// Serialized as stubs, see `Stubify`
| Stubable;
// Base type for all RPC stubs, including common memory management methods.
// `T` is used as a marker type for unwrapping `Stub`s later.
interface StubBase<T extends RpcCompatible<T>> extends Disposable {
[__RPC_STUB_BRAND]: T;
dup(): this;
onRpcBroken(callback: (error: any) => void): void;
}
type Stub<T extends RpcCompatible<T>> =
T extends object ? Provider<T> & StubBase<T> : StubBase<T>;
type TypedArray =
| Uint8Array
| Uint8ClampedArray
| Uint16Array
| Uint32Array
| Int8Array
| Int16Array
| Int32Array
| BigUint64Array
| BigInt64Array
| Float32Array
| Float64Array;
// This represents all the types that can be sent as-is over an RPC boundary
type BaseType =
| void
| undefined
| null
| boolean
| number
| bigint
| string
| TypedArray
| ArrayBuffer
| DataView
| Date
| Error
| RegExp
| ReadableStream<Uint8Array>
| WritableStream<Uint8Array>
| Request
| Response
| Headers;
// Recursively rewrite all `Stubable` types with `Stub`s, and resolve promises.
// prettier-ignore
type Stubify<T> =
T extends Stubable ? Stub<T>
: T extends Promise<infer U> ? Stubify<U>
: T extends StubBase<any> ? T
: T extends Map<infer K, infer V> ? Map<Stubify<K>, Stubify<V>>
: T extends Set<infer V> ? Set<Stubify<V>>
: T extends [] ? []
: T extends [infer Head, ...infer Tail] ? [Stubify<Head>, ...Stubify<Tail>]
: T extends readonly [] ? readonly []
: T extends readonly [infer Head, ...infer Tail] ? readonly [Stubify<Head>, ...Stubify<Tail>]
: T extends Array<infer V> ? Array<Stubify<V>>
: T extends ReadonlyArray<infer V> ? ReadonlyArray<Stubify<V>>
: T extends BaseType ? T
// When using "unknown" instead of "any", interfaces are not stubified.
: T extends { [key: string | number]: any } ? { [K in keyof T]: Stubify<T[K]> }
: T;
// Recursively rewrite all `Stub<T>`s with the corresponding `T`s.
// Note we use `StubBase` instead of `Stub` here to avoid circular dependencies:
// `Stub` depends on `Provider`, which depends on `Unstubify`, which would depend on `Stub`.
// prettier-ignore
type UnstubifyInner<T> =
T extends StubBase<infer V> ? (T | V) // can provide either stub or local RpcTarget
: T extends Map<infer K, infer V> ? Map<Unstubify<K>, Unstubify<V>>
: T extends Set<infer V> ? Set<Unstubify<V>>
: T extends [] ? []
: T extends [infer Head, ...infer Tail] ? [Unstubify<Head>, ...Unstubify<Tail>]
: T extends readonly [] ? readonly []
: T extends readonly [infer Head, ...infer Tail] ? readonly [Unstubify<Head>, ...Unstubify<Tail>]
: T extends Array<infer V> ? Array<Unstubify<V>>
: T extends ReadonlyArray<infer V> ? ReadonlyArray<Unstubify<V>>
: T extends BaseType ? T
: T extends { [key: string | number]: unknown } ? { [K in keyof T]: Unstubify<T[K]> }
: T;
// You can put promises anywhere in the params and they'll be resolved before delivery.
// (This also covers RpcPromise, because it's defined as being a Promise.)
type Unstubify<T> = UnstubifyInner<T> | Promise<UnstubifyInner<T>>
type UnstubifyAll<A extends any[]> = { [I in keyof A]: Unstubify<A[I]> };
// Utility type for adding `Disposable`s to `object` types only.
// Note `unknown & T` is equivalent to `T`.
type MaybeDisposable<T> = T extends object ? Disposable : unknown;
// Type for method return or property on an RPC interface.
// - Stubable types are replaced by stubs.
// - RpcCompatible types are passed by value, with stubable types replaced by stubs
// and a top-level `Disposer`.
// Everything else can't be passed over RPC.
// Technically, we use custom thenables here, but they quack like `Promise`s.
// Intersecting with `(Maybe)Provider` allows pipelining.
// prettier-ignore
type Result<R> =
R extends Stubable ? Promise<Stub<R>> & Provider<R> & StubBase<R>
: R extends RpcCompatible<R> ? Promise<Stubify<R> & MaybeDisposable<R>> & Provider<R> & StubBase<R>
: never;
// Type for method or property on an RPC interface.
// For methods, unwrap `Stub`s in parameters, and rewrite returns to be `Result`s.
// Unwrapping `Stub`s allows calling with `Stubable` arguments.
// For properties, rewrite types to be `Result`s.
// In each case, unwrap `Promise`s.
type MethodOrProperty<V> = V extends (...args: infer P) => infer R
? (...args: UnstubifyAll<P>) => Result<Awaited<R>>
: Result<Awaited<V>>;
// Type for the callable part of an `Provider` if `T` is callable.
// This is intersected with methods/properties.
type MaybeCallableProvider<T> = T extends (...args: any[]) => any
? MethodOrProperty<T>
: unknown;
// Base type for all other types providing RPC-like interfaces.
// Rewrites all methods/properties to be `MethodOrProperty`s, while preserving callable types.
type Provider<T> = MaybeCallableProvider<T> &
(T extends Array<infer U>
? {
[key: number]: MethodOrProperty<U>;
} & {
map<V>(callback: (elem: U) => V): Result<Array<V>>;
}
: {
[K in Exclude<
keyof T,
symbol | keyof StubBase<never>
>]: MethodOrProperty<T[K]>;
} & {
map<V>(callback: (value: NonNullable<T>) => V): Result<Array<V>>;
});
/**
* Serialize a value, using Cap'n Web's underlying serialization. This won't be able to serialize
* RPC stubs, but it will support basic data types.
*/
declare function serialize(value: unknown): string;
/**
* Deserialize a value serialized using serialize().
*/
declare function deserialize(value: string): unknown;
/**
* Interface for an RPC transport, which is a simple bidirectional message stream. Implement this
* interface if the built-in transports (e.g. for HTTP batch and WebSocket) don't meet your needs.
*/
interface RpcTransport {
/**
* Sends a message to the other end.
*/
send(message: string): Promise<void>;
/**
* Receives a message sent by the other end.
*
* If and when the transport becomes disconnected, this will reject. The thrown error will be
* propagated to all outstanding calls and future calls on any stubs associated with the session.
* If there are no outstanding calls (and none are made in the future), then the error does not
* propagate anywhere -- this is considered a "clean" shutdown.
*/
receive(): Promise<string>;
/**
* Indicates that the RPC system has suffered an error that prevents the session from continuing.
* The transport should ideally try to send any queued messages if it can, and then close the
* connection. (It's not strictly necessary to deliver queued messages, but the last message sent
* before abort() is called is often an "abort" message, which communicates the error to the
* peer, so if that is dropped, the peer may have less information about what happened.)
*/
abort?(reason: any): void;
}
/**
* Options to customize behavior of an RPC session. All functions which start a session should
* optionally accept this.
*/
type RpcSessionOptions = {
/**
* If provided, this function will be called whenever an `Error` object is serialized (for any
* reason, not just because it was thrown). This can be used to log errors, and also to redact
* them.
*
* If `onSendError` returns an Error object, than object will be substituted in place of the
* original. If it has a stack property, the stack will be sent to the client.
*
* If `onSendError` doesn't return anything (or is not provided at all), the default behavior is
* to serialize the error with the stack omitted.
*/
onSendError?: (error: Error) => Error | void;
};
/**
* For use in Cloudflare Workers: Construct an HTTP response that starts a WebSocket RPC session
* with the given `localMain`.
*/
declare function newWorkersWebSocketRpcResponse(request: Request, localMain?: any, options?: RpcSessionOptions): Response;
/**
* Implements the server end of an HTTP batch session, using standard Fetch API types to represent
* HTTP requests and responses.
*
* @param request The request received from the client initiating the session.
* @param localMain The main stub or RpcTarget which the server wishes to expose to the client.
* @param options Optional RPC session options.
* @returns The HTTP response to return to the client. Note that the returned object has mutable
* headers, so you can modify them using e.g. `response.headers.set("Foo", "bar")`.
*/
declare function newHttpBatchRpcResponse(request: Request, localMain: any, options?: RpcSessionOptions): Promise<Response>;
/**
* Implements the server end of an HTTP batch session using traditional Node.js HTTP APIs.
*
* @param request The request received from the client initiating the session.
* @param response The response object, to which the response should be written.
* @param localMain The main stub or RpcTarget which the server wishes to expose to the client.
* @param options Optional RPC session options. You can also pass headers to set on the response.
*/
declare function nodeHttpBatchRpcResponse(request: IncomingMessage, response: ServerResponse, localMain: any, options?: RpcSessionOptions & {
headers?: OutgoingHttpHeaders | OutgoingHttpHeader[];
}): Promise<void>;
/**
* Represents a reference to a remote object, on which methods may be remotely invoked via RPC.
*
* `RpcStub` can represent any interface (when using TypeScript, you pass the specific interface
* type as `T`, but this isn't known at runtime). The way this works is, `RpcStub` is actually a
* `Proxy`. It makes itself appear as if every possible method / property name is defined. You can
* invoke any method name, and the invocation will be sent to the server. If it turns out that no
* such method exists on the remote object, an exception is thrown back. But the client does not
* actually know, until that point, what methods exist.
*/
type RpcStub<T extends RpcCompatible<T>> = Stub<T>;
declare const RpcStub: {
new <T extends RpcCompatible<T>>(value: T): RpcStub<T>;
};
/**
* Represents the result of an RPC call.
*
* Also used to represent properties. That is, `stub.foo` evaluates to an `RpcPromise` for the
* value of `foo`.
*
* This isn't actually a JavaScript `Promise`. It does, however, have `then()`, `catch()`, and
* `finally()` methods, like `Promise` does, and because it has a `then()` method, JavaScript will
* allow you to treat it like a promise, e.g. you can `await` it.
*
* An `RpcPromise` is also a proxy, just like `RpcStub`, where calling methods or awaiting
* properties will make a pipelined network request.
*
* Note that and `RpcPromise` is "lazy": the actual final result is not requested from the server
* until you actually `await` the promise (or call `then()`, etc. on it). This is an optimization:
* if you only intend to use the promise for pipelining and you never await it, then there's no
* need to transmit the resolution!
*/
type RpcPromise<T extends RpcCompatible<T>> = Stub<T> & Promise<Stubify<T>>;
declare const RpcPromise: {};
/**
* Use to construct an `RpcSession` on top of a custom `RpcTransport`.
*
* Most people won't use this. You only need it if you've implemented your own `RpcTransport`.
*/
interface RpcSession<T extends RpcCompatible<T> = undefined> {
getRemoteMain(): RpcStub<T>;
getStats(): {
imports: number;
exports: number;
};
drain(): Promise<void>;
}
declare const RpcSession: {
new <T extends RpcCompatible<T> = undefined>(transport: RpcTransport, localMain?: any, options?: RpcSessionOptions): RpcSession<T>;
};
/**
* Classes which are intended to be passed by reference and called over RPC must extend
* `RpcTarget`. A class which does not extend `RpcTarget` (and which doesn't have built-in support
* from the RPC system) cannot be passed in an RPC message at all; an exception will be thrown.
*
* Note that on Cloudflare Workers, this `RpcTarget` is an alias for the one exported from the
* "cloudflare:workers" module, so they can be used interchangably.
*/
interface RpcTarget extends RpcTargetBranded {
}
declare const RpcTarget: {
new (): RpcTarget;
};
/**
* Empty interface used as default type parameter for sessions where the other side doesn't
* necessarily export a main interface.
*/
interface Empty {
}
/**
* Start a WebSocket session given either an already-open WebSocket or a URL.
*
* @param webSocket Either the `wss://` URL to connect to, or an already-open WebSocket object to
* use.
* @param localMain The main RPC interface to expose to the peer. Returns a stub for the main
* interface exposed from the peer.
*/
declare let newWebSocketRpcSession: <T extends RpcCompatible<T> = Empty>(webSocket: WebSocket | string, localMain?: any, options?: RpcSessionOptions) => RpcStub<T>;
/**
* Initiate an HTTP batch session from the client side.
*
* The parameters to this method have exactly the same signature as `fetch()`, but the return
* value is an RpcStub. You can customize anything about the request except for the method
* (it will always be set to POST) and the body (which the RPC system will fill in).
*/
declare let newHttpBatchRpcSession: <T extends RpcCompatible<T>>(urlOrRequest: string | Request, options?: RpcSessionOptions) => RpcStub<T>;
/**
* Initiate an RPC session over a MessagePort, which is particularly useful for communicating
* between an iframe and its parent frame in a browser context. Each side should call this function
* on its own end of the MessageChannel.
*/
declare let newMessagePortRpcSession: <T extends RpcCompatible<T> = Empty>(port: MessagePort, localMain?: any, options?: RpcSessionOptions) => RpcStub<T>;
/**
* Implements unified handling of HTTP-batch and WebSocket responses for the Cloudflare Workers
* Runtime.
*
* SECURITY WARNING: This function accepts cross-origin requests. If you do not want this, you
* should validate the `Origin` header before calling this, or use `newHttpBatchRpcSession()` and
* `newWebSocketRpcSession()` directly with appropriate security measures for each type of request.
* But if your API uses in-band authorization (i.e. it has an RPC method that takes the user's
* credentials as parameters and returns the authorized API), then cross-origin requests should
* be safe.
*/
declare function newWorkersRpcResponse(request: Request, localMain: any): Promise<Response>;
export { type RpcCompatible, RpcPromise, RpcSession, type RpcSessionOptions, RpcStub, RpcTarget, type RpcTransport, deserialize, newHttpBatchRpcResponse, newHttpBatchRpcSession, newMessagePortRpcSession, newWebSocketRpcSession, newWorkersRpcResponse, newWorkersWebSocketRpcResponse, nodeHttpBatchRpcResponse, serialize };
export { c as RpcCompatible, e as RpcPromise, f as RpcSession, b as RpcSessionOptions, d as RpcStub, g as RpcTarget, R as RpcTransport, h as deserialize, n as newHttpBatchRpcResponse, i as newHttpBatchRpcSession, j as newMessagePortRpcSession, k as newWebSocketRpcSession, l as newWorkersRpcResponse, m as newWorkersWebSocketRpcResponse, o as nodeHttpBatchRpcResponse, s as serialize } from './index-workers-CiDKhXAE.js';
import 'node:http';
{
"name": "capnweb",
"version": "0.0.0-1c87560",
"version": "0.0.0-25baebf",
"description": "JavaScript/TypeScript-native RPC library with Promise Pipelining",

@@ -14,11 +14,15 @@ "main": "dist/index.js",

".": {
"workerd": {
"types": "./dist/index.d.ts",
"import": "./dist/index-workers.js",
"require": "./dist/index-workers.cjs"
},
"bun": {
"types": "./dist/index-bun.d.ts",
"import": "./dist/index-bun.js",
"require": "./dist/index-bun.cjs"
},
"types": "./dist/index.d.ts",
"import": {
"workerd": "./dist/index-workers.js",
"default": "./dist/index.js"
},
"require": {
"workerd": "./dist/index-workers.cjs",
"default": "./dist/index.cjs"
}
"import": "./dist/index.js",
"require": "./dist/index.cjs"
}

@@ -31,6 +35,9 @@ },

"scripts": {
"build": "tsup --format esm,cjs",
"build:watch": "tsup --watch --format esm,cjs",
"build": "tsup",
"build:watch": "tsup --watch",
"test": "vitest run",
"test:bun": "bun test __tests__/bun.test.ts",
"test:ci": "vitest run && bun test __tests__/bun.test.ts",
"test:watch": "vitest",
"test:types": "tsc -p __type-tests__/tsconfig.json --noEmit",
"prepublishOnly": "npm run build"

@@ -41,4 +48,5 @@ },

"@changesets/cli": "^2.29.8",
"@cloudflare/vitest-pool-workers": "^0.10.15",
"@cloudflare/workers-types": "^4.20251216.0",
"@cloudflare/vitest-pool-workers": "^0.12.10",
"@cloudflare/workers-types": "^4.20260205.0",
"@types/bun": "^1.2.0",
"@types/ws": "^8.18.1",

@@ -52,3 +60,3 @@ "@vitest/browser": "^3.2.4",

"vitest": "^3.2.4",
"ws": "^8.18.3"
"ws": "^8.19.0"
},

@@ -55,0 +63,0 @@ "repository": {

@@ -9,3 +9,3 @@ # Cap'n Web: A JavaScript-native RPC system

* It works over HTTP, WebSocket, and postMessage() out-of-the-box, with the ability to extend it to other transports easily.
* It works in all major browsers, Cloudflare Workers, Node.js, and other modern JavaScript runtimes.
* It works in all major browsers, Cloudflare Workers, Node.js, Bun, Deno, and other modern JavaScript runtimes.
The whole thing compresses (minify+gzip) to under 10kB with no dependencies.

@@ -205,2 +205,5 @@

* `Error` and its well-known subclasses
* `Blob`
* `ReadableStream` and `WritableStream`, with automatic flow control.
* `Headers`, `Request`, and `Response` from the Fetch API.

@@ -211,4 +214,2 @@ The following types are not supported as of this writing, but may be added in the future:

* `RegExp`
* `ReadableStream` and `WritableStream`, with automatic flow control.
* `Headers`, `Request`, and `Response`

@@ -311,2 +312,6 @@ The following are intentionally NOT supported:

### Streaming with flow control
You may pass a `ReadableStream` or `WritableStream` over RPC. When doing so, the RPC system automatically creates an equivalent stream at the other end and pumps bytes (or arbitrarily-typed chunks) across. This is done in such a way as to ensure the available bandwidth is fully utilized while minimizing buffer bloat, by observing the bandwidth-delay product and applying backpressure when too much is written. Multiple streams can be sent across the same connection -- they will be multiplexed appropriately, similar to HTTP/2 stream multiplexing.
### Cloudflare Workers RPC interoperability

@@ -535,2 +540,10 @@

#### Compatibility with Workers' built-in RPC
Cloudflare Workers has long featured [a built-in RPC system with semantics similar to Cap'n Web](https://developers.cloudflare.com/workers/runtime-apis/rpc/).
Cap'n Web is designed to be compatible with Workers RPC, meaning you can pass Cap'n Web RPC stubs over Workers RPC and vice versa. The system will automatically wrap one stub type in the other and arrange to proxy calls.
For best compatibility, make sure to set your [Workers compatibilty date](https://developers.cloudflare.com/workers/configuration/compatibility-dates/) to at least `2026-01-20`, or enable the [compatibility flag](https://developers.cloudflare.com/workers/configuration/compatibility-flags/) `rpc_params_dup_stubs`. (As of this writing, `2026-01-20` is in the future, so you will need to use the flag for now.)
### HTTP server on Node.js

@@ -626,2 +639,41 @@

### HTTP server on Bun
Bun's server-side WebSocket API uses [callback-based handlers](https://bun.sh/docs/runtime/http/websockets) instead of the standard `addEventListener` interface. Cap'n Web provides `newBunWebSocketRpcHandler()` which returns a handler object you can pass directly to `Bun.serve()`.
```ts
import { RpcTarget, newBunWebSocketRpcHandler, newHttpBatchRpcResponse } from "capnweb";
class MyApiImpl extends RpcTarget implements MyApi {
// ... define API, same as above ...
}
// Create a WebSocket handler that manages RPC sessions automatically.
// The callback is invoked once per connection to create a fresh API instance.
let rpcHandler = newBunWebSocketRpcHandler(() => new MyApiImpl());
Bun.serve({
async fetch(req, server) {
let url = new URL(req.url);
if (url.pathname === "/api") {
// Upgrade WebSocket requests.
if (req.headers.get("upgrade")?.toLowerCase() === "websocket") {
if (server.upgrade(req)) return;
return new Response("WebSocket upgrade failed", { status: 500 });
}
// Handle HTTP batch requests.
let response = await newHttpBatchRpcResponse(req, new MyApiImpl());
response.headers.set("Access-Control-Allow-Origin", "*");
return response;
}
return new Response("Not Found", { status: 404 });
},
// Pass the handler directly — no manual wiring needed.
websocket: rpcHandler,
});
```
### HTTP server on other runtimes

@@ -628,0 +680,0 @@

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display