Skip to main content

Installation

Initialization

registerWorker

Register the worker with a iii instance, returns a connected worker client. The WebSocket connection is established automatically. Signature
string
required
WebSocket URL of the III engine (e.g. ws://localhost:49135).
InitOptions
Optional InitOptions for worker name, timeouts, and reconnection.

Methods

registerFunction

Registers a new function with a local handler that runs in the browser session. HTTP invocation configs are a Node.js SDK feature. The handler’s return value is what the function’s observers observe; an event source’s handler returns the event it is called with. Every call of the function, local or routed, runs the handler and then goes to the observers that want it (onObservationMatch; by default all of them): the function’s onObservationDeliver hook delivers it, or iii does, to those whose capture and filters match. iii evaluates capture and filters where the call is: the engine for a call it routes to this worker, and the SDK for a call this worker makes to its own function in-process, through an index of the filters’ equality conditions. What the worker does when the function is observed is set with the hooks (onObserverAdded, onObserverRemoved, onObservationMatch, onObservationDeliver), by id or on the returned FunctionRef. The SDK acks no observer before this call returns, so a hook set by id before it, chained on its result, or set later in the same synchronous block runs for every observer. A function that sets args_format, private: true, observable: false, an onObservationMatch hook or an onObservationDeliver hook needs an engine with observe.v2: it is registered once the connection’s engine advertised it, and against an older engine it stays unregistered (logged once, UNSUPPORTED). Signature
string
required
Unique function identifier
RemoteFunctionHandler<I, O>
required
Handler executed when the function is invoked
RegisterFunctionOptions
Optional RegisterFunctionOptions: description, request/response formats, metadata, args_format, private, observable, localDispatch

call

Invokes a function: by id, or the target of an observer of a function this worker hosts ({ observer, payload }). Signature
CallRequest<TInput>
required
The call request: function_id (or observer), payload, and optional action/timeout

observe

Observes a function: every call of source that passes its filters runs target, a registered function. Returns synchronously (also before the connection is up); the observer is replayed with the same id on reconnect. Errors show up as state error and reject ready(); against an engine without observe that is UNSUPPORTED. An error answer to its observe is the engine’s refusal, the handle’s final answer: the engine holds no observer for it, it is not replayed, and its dispose() sends nothing. Signature
string | ObserveSource
required
What is observed: a function id, or function_id, args (read by the worker that hosts the function), filters, capture.
Target
required
The function to invoke.
ObserverOptions
id, max_fires, expires_in_ms, max_in_flight, metadata.

trigger

Deprecated. Use ISdk.call, the same function.
Invokes a function using a request object. Signature

Parameters

CallRequest<TInput>
required

addConnectionStateListener

Subscribe to connection-state transitions. The handler is fired immediately with the current state, then on every transition. Multiple listeners are supported. Returns an unsubscribe function. Signature
(state: IIIConnectionState) => void
required
Callback invoked with the new connection state whenever it changes.

currentInvocation

The invocation the calling code runs in (remote or local handler, or the function’s deliver hook), or undefined outside any handler. Browsers have no AsyncLocalStorage: the SDK knows the invocation while the handler runs synchronously, up to its first await; after it this returns undefined. Read it before awaiting, and re-enter it with ISdk.withInvocation for calls made after. Code after an await, outside ISdk.withInvocation, runs outside any invocation, but its calls are not treated as new chains: they carry the observe_depth of the deepest invocation running on this page, so the engine’s loop guard (max_observe_depth) still stops an observer cycle whose target awaits before calling back. With several invocations running this over-counts, and a legitimate chain may stop early. They carry a caller and traceparent only when that is unambiguous (one invocation is running, and it is an observe activation or its function’s deliver hook is running); otherwise none. An invocation that never settles stops counting as running after 10 minutes (a local call: at its timeout). Local calls nest the same way: a self-recursion that awaits before each call goes through the engine past 64 levels, while calls started together count as one level. A limitation: local calls started in separate ticks while earlier ones still run also look nested, so a long, wide fan-out may send some through the engine (same results). While the socket is closed none is: a function this worker hosts then runs here up to 256 local calls deep, and past that the call fails at once with LOCAL_DEPTH_EXCEEDED (a runaway recursion must not freeze the page). Signature

Example


getFatalError

The fatal registration rejection that terminated this connection, if any (e.g. a WORKER_NAMESPACE_CONFLICT); undefined while healthy. Mirrors the Node/Python/Rust SDKs. Signature

isObserved

Whether a call of a function this worker hosts would reach anyone. Without a call: any active observer. With a call, on a function matched by keys: an observer filed under one of the call’s keys. On any other function the call is not read. Signature

Parameters

string
required
Partial<Call<unknown, unknown>>

observers

The active observers of a function this worker hosts (empty for any other). Signature

Parameters

string
required

onObservationDeliver

Delivers each call of a function itself: hook receives the call and the observers that matched it (a snapshot taken when the call started), and what it returns (or throws) is what the caller gets back. iii delivers nothing for that function: the hook calls through observers and applies their filters with obs.matches(call). Without it, iii delivers every call to the matching observers whose capture and filters accept it, and the caller gets the handler’s result. null removes the hook. A function with a deliver hook needs an engine with observe.v2: against an older one it stays unregistered, and the SDK logs UNSUPPORTED once. The hook runs in the function’s invocation: up to its first await in its scope, and after it as the invocation the page falls back to while it is the only one running (see ISdk.withInvocation). Signature
string
required
DeliverHook<I, O, R> | null
required

onObservationMatch

Says which observers want each call of a function. By default every observer wants every call. A predicate (obs, call) => boolean is asked once per observation (for every call, once for each active observer); { observer, call } key functions are computed once per observer, when it is accepted, and once per call, and an observer wants a call when they share a key (the SDK keeps an index). The observers’ capture, filters and policy still apply. A hook set while observers are active rebuilds the index from them. null removes the hook, predicate or keys: every observer gets every call again. A function with a match hook needs an engine with observe.v2: against an older one it stays unregistered, and the SDK logs UNSUPPORTED once. Signature
string
required
MatchHook<I, O> | null
required

onObserverAdded

Runs hook when an observer of any function this worker hosts is added, before the SDK acks it; with a function id, for that function only. When both are set, the worker’s runs first. Throw to reject the observer. null removes the hook. Hooks set by id stay in place across unregister() and a later registration of the same id. A hook set while the function already has active observers runs for each of them at once (a throw late-rejects that observer), and the SDK logs a warning. Signature
string
AddedHook | null
required

onObserverRemoved

Runs hook once for every accepted observer when it is removed (on unobserve, disposal, unregister, late rejection); with a function id, for that function only. When both are set, the function’s runs first. An error it throws is logged. null removes the hook. Signature

Parameters

string
RemovedHook | null
required

shutdown

Gracefully shutdown the iii, cleaning up all resources. Signature

Example


withInvocation

Runs fn inside invocation (what ISdk.currentInvocation returned), and returns what fn returns. Calls fn makes before its own first await (call, currentInvocation) belong to that invocation: they carry its caller, observe_depth and traceparent. When fn returns a promise, the invocation counts as running until it settles, so fn’s code after an await gets the fallback below. undefined runs fn outside any invocation. Code after an await, outside withInvocation, runs outside any invocation, but its calls are not treated as new chains: they carry the observe_depth of the deepest invocation running on this page, so the engine’s loop guard (max_observe_depth) still stops an observer cycle whose target awaits before calling back. With several invocations running this over-counts, and a legitimate chain may stop early. They carry a caller and traceparent only when that is unambiguous (one invocation is running, and it is an observe activation or its function’s deliver hook is running); otherwise none. An invocation that never settles stops counting as running after 10 minutes (a local call: at its timeout). Local calls nest the same way: a self-recursion that awaits before each call goes through the engine past 64 levels, while calls started together count as one level. A limitation: local calls started in separate ticks while earlier ones still run also look nested, so a long, wide fan-out may send some through the engine (same results). While the socket is closed none is: a function this worker hosts then runs here up to 256 local calls deep, and past that the call fails at once with LOCAL_DEPTH_EXCEEDED (a runaway recursion must not freeze the page). Signature

Parameters

InvocationContext | undefined
() => T
required

Subpath Exports

The iii-browser-sdk package provides additional entry points:

Types

iii-browser-sdk

AddedHook · ApiRequest · ApiResponse · AuthInput · AuthResult · Call · CallAction · Caller · CallerInfo · CallRequest · Capture · Channel · ChannelReader · ChannelWriter · DeliverHook · EngineFunctions · EngineSources · EnqueueResult · Filter · FunctionRef · IIIConnectionState · IIIReconnectionConfig · InitOptions · InvocationContext · InvocationError · InvocationErrorInit · Key · MatchHook · MatchKeys · MatchPredicate · MessageType · MiddlewareFunctionInput · Observed · Observer · ObserveReason · ObserveRejection · ObserverHandle · ObserverOptions · ObserverState · ObserveSource · OnFunctionRegistrationInput · OnFunctionRegistrationResult · OpenEnum · RegisterFunctionFormat · RegisterFunctionInput · RegisterFunctionMessage · RegisterFunctionOptions · RegistrationRejectedError · RegistrationRejectedInit · RemoteFunctionHandler · RemovedHook · StreamChannelRef · Target

AddedHook

Runs when an observer of a function is added, before the SDK acks it. Throw to reject the observer: an ObserveRejection sets the code, anything else is OBSERVE_REJECTED; after 30 s it is rejected with OWNER_TIMEOUT.

ApiRequest

The HTTP request an http::on-request route’s target receives.

ApiResponse

The response an http::on-request route’s target returns.

AuthInput

Input passed to the RBAC auth function during WebSocket upgrade. Contains the HTTP headers, query parameters, and client IP from the connecting worker’s upgrade request.

AuthResult

Return value from the RBAC auth function. Controls which functions the authenticated worker can invoke and what context is forwarded to the middleware.

Call

One call of a function, as its host delivers it: what the handler was called with and what it returned (or threw). Observers observe output, the handler’s return value.

CallAction

Factory object that constructs routing actions for ISdk.call.

Caller

Who started an invocation: the worker (worker_id / worker_name, stamped by the engine), and the function and invocation the call was made from.

CallerInfo

A caller as the SDK knows it: every field may be missing (a top-level call has no function; a call made before WorkerRegistered has no worker id).

CallRequest

Request object passed to ISdk.call: a function by id, or the target of an observer.

Capture

A field an observer captures. Default ['input', 'output', 'caller'].

Channel

A streaming channel pair for worker-to-worker data transfer. Created via the createChannel helper from iii-browser-sdk/helpers.

ChannelReader

Read end of a streaming channel. Uses native browser WebSocket.

ChannelWriter

Write end of a streaming channel. Uses native browser WebSocket.

DeliverHook

Delivers each call of a function itself (onObservationDeliver): it receives the call and the observers that matched it (a snapshot taken when the call started), and what it returns (or throws) is what the caller gets back. A thrown ObserveRejection, or the error of a call it made, reaches the caller with its code; any other error as invocation_failed. iii delivers nothing for that function; the hook calls through observers (worker.call({ observer, payload })) and applies their filters with obs.matches(call). It runs inside the function’s invocation, so the calls it makes have that invocation as their caller. Browsers have no AsyncLocalStorage: the hook runs in the invocation’s scope up to its first await. A call it makes after one still has the invocation as its caller while that invocation is the only one running on the page; to be sure, read iii.currentInvocation() first and re-enter it with iii.withInvocation(inv, fn). A call through an observer is routed to the observer’s target either way.

EngineFunctions

Engine function paths for internal operations.

EngineSources

The event sources the engine hosts: private functions whose handler returns the event, observed with iii.observe(EngineSources.X, target). None takes args; filter on the event (input) instead.

EnqueueResult

Result returned when a function is called with CallAction.Enqueue.

Filter

A declarative filter over input, output, error, caller and metadata, with explicit operators only: { 'input.amount': { $gte: 500 } }. See the filter language reference.

FunctionRef

Handle returned by ISdk.registerFunction: the client’s hook methods with the function id filled in. Each method returns the handle, so calls chain.

IIIConnectionState

Connection state for the III WebSocket

IIIReconnectionConfig

Configuration for WebSocket reconnection behavior

InitOptions

Configuration options passed to registerWorker.

InvocationContext

The invocation the current code runs in, in every handler, remote or local (iii.currentInvocation()). Browsers have no AsyncLocalStorage, so the SDK knows it only while the handler runs synchronously: up to its first await. To keep it across an await, read it first and re-enter it with iii.withInvocation(inv, fn).

InvocationError

An error the SDK raises itself for an invocation, with a machine-readable code: LOCAL_DEPTH_EXCEEDED (a local call nested too deep while the socket is closed) and payload_too_large. Mirrors the Node SDK. A call the engine answers with an error rejects with the engine’s error body ({ code, message, stacktrace? }), and so does a locally dispatched call whose handler or deliver hook throws: both paths reject with the same value.

InvocationErrorInit

Fields used to construct an InvocationError.

Key

A match key, or several: an observer wants a call when they share one.

MatchHook

Which observers want each call of a function (onObservationMatch). By default every observer wants every call. A predicate is asked once per observation: for every call, once for each active observer (a throw counts as no match for that observer). Keys are computed once per observer, when it is accepted, and once per call. The observers’ capture, filters and policy still apply. Setting it to null removes it: every observer gets every call again.

MatchKeys

onObservationMatch as keys: an observer wants a call when they share a key, and the SDK keeps an index instead of asking every observer.

MatchPredicate

onObservationMatch as a predicate: whether this observer wants this call.

MessageType


MiddlewareFunctionInput

Input passed to the RBAC middleware function on every function invocation through the RBAC port. The middleware can inspect, modify, or reject the call before it reaches the target function.

Observed

What an observer’s target receives when iii delivers: the top-level fields, plus whichever of the observer’s capture apply to the outcome. Fields not captured, or that do not apply, are absent.

Observer

An observer as the worker that hosts its function sees it (the hooks, FunctionRef.observers()): its args, filters, target and capture. Who observes, the observer’s metadata and its policy stay with the engine.

ObserveReason

A state reason or an error: a machine-readable code and a message.

ObserveRejection

Thrown by an onObserverAdded hook to reject an observer with a code of its own (HTTP_ROUTE_CONFLICT, INVALID_CRON_EXPRESSION, …); any other error rejects it with OBSERVE_REJECTED. Also the error ObserverHandle.ready() rejects with when the observer turns error or disposed.

ObserverHandle

What iii.observe returns, synchronously.

ObserverOptions

The observer itself: its id, policy and metadata.

ObserverState

An observer’s lifecycle: pending (no host yet, waiting for the host’s ack, or no target yet) → active or error; suspended while its worker or target is away; disposed at the end.

ObserveSource

The left side of iii.observe: what is observed.

OnFunctionRegistrationInput

Input passed to the on_function_registration_function_id hook when a worker attempts to register a function through the RBAC port. Return an OnFunctionRegistrationResult with the (possibly mapped) fields, or throw to deny the registration.

OnFunctionRegistrationResult

Result returned from the on_function_registration_function_id hook. All fields are optional; omitted fields keep the original value from the registration request.

OpenEnum

A wire enum that a newer peer may extend: decoders keep a value they do not know instead of failing the frame.

RegisterFunctionFormat


RegisterFunctionInput


RegisterFunctionMessage


RegisterFunctionOptions

Options of ISdk.registerFunction: what describes the function to the engine (description, formats, metadata, args_format, private, observable), and what the SDK does with it (localDispatch). What the worker does when the function is observed is set with hooks.

RegistrationRejectedError

A terminal registration rejection from the engine. Thrown into every pending invocation and exposed via getFatalError() when a worker-name collision (or other non-retryable rejection) closes the connection for good.

RegistrationRejectedInit


RemoteFunctionHandler

Handler of a registered function. Receives the invocation payload and its metadata (CallRequest.metadata of the call, or an observer’s metadata sidecar on an activation) and returns the result (or a promise of it). The return value is what the function’s observers observe.

RemovedHook

Runs once for every accepted observer when it is removed. An error it throws is logged.

StreamChannelRef

Serializable reference to one end of a streaming channel. Can be included in invocation payloads to pass channel endpoints between workers.

Target

The right side of iii.observe: a registered function.

iii-browser-sdk/state

DeleteResult · IState · StateDeleteInput · StateDeleteResult · StateEventData · StateEventType · StateGetInput · StateListInput · StateSetInput · StateSetResult · StateUpdateInput · StateUpdateResult

DeleteResult

Result of a state delete operation.

IState

Interface for state management operations. Available via the iii-browser-sdk/state subpath export.

StateDeleteInput

Input for deleting a state value.

StateDeleteResult

Result of a state delete operation.

StateEventData

Payload for state change events.

StateEventType

Types of state change events.

StateGetInput

Input for retrieving a state value.

StateListInput

Input for listing all values in a state scope.

StateSetInput

Input for setting a state value.

StateSetResult

Result of a state set operation.

StateUpdateInput

Input for atomically updating a state value.

StateUpdateResult

Result of a state update operation.

iii-browser-sdk/stream

MergePath · UpdateAppend · UpdateDecrement · UpdateIncrement · UpdateMerge · UpdateOp · UpdateOpError · UpdateRemove · UpdateSet

MergePath

Path target for a UpdateMerge op. Accepts:
  • a single string (legacy / first-level field)
  • an array of literal segments (nested path; each element is one literal key, dots are NOT interpreted as separators)
Omit path, pass "", or pass [] to target the root value.

UpdateAppend

Append an element to an array, concatenate a string, or push a new value at a nested path. The target is the root (when path is omitted, empty, or []), a single first-level key (when path is a non-empty string), or an arbitrary nested location (when path is an array of literal segments). See MergePath. Engine semantics: missing/null intermediates along a nested path are auto-created; missing leaves on a nested path always become arrays (no string-concat tier); existing object/scalar leaves return append.type_mismatch. Each path segment is a literal key, ["a.b"] targets a single key named "a.b", not a → b.

UpdateDecrement

Decrement a numeric field by a given amount.

UpdateIncrement

Increment a numeric field by a given amount.

UpdateMerge

Shallow-merge an object into the target. The target is the root (when path is omitted/empty) or an arbitrary nested location specified by an array of literal segments. See MergePath. Validation: invalid paths/values (depth > 32, segment > 256 bytes, value depth > 16, > 1024 top-level keys, or any __proto__/constructor/prototype segment or top-level key) are rejected with a structured error in the response’s errors array.

UpdateOp

Union of all atomic update operations supported by streams.

UpdateOpError

Per-op error returned by state::update / stream::update.

UpdateRemove

Remove a field at the given path.

UpdateSet

Set a field at the given path to a value.