Installation
Initialization
registerWorker
Register the worker with a iii instance, returns a connected worker client. The WebSocket connection is established automatically. Signature- Parameters
- Example
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
- Parameters
- Example
call
Invokes a function: by id, or the target of an observer of a function this worker hosts ({ observer, payload }).
Signature
- Parameters
- Example
CallRequest<TInput>
required
The call request:
function_id (or observer), payload, and optional action/timeoutobserve
Observes a function: every call ofsource 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
- Parameters
- Example
trigger
Invokes a function using a request object. SignatureParameters
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- Parameters
- Example
(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), orundefined 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. aWORKER_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. SignatureParameters
string
required
Partial<Call<unknown, unknown>>
observers
The active observers of a function this worker hosts (empty for any other). SignatureParameters
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
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
onObserverAdded
Runshook 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
onObserverRemoved
Runshook 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. SignatureExample
withInvocation
Runsfn 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
Theiii-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 isOBSERVE_REJECTED; after 30 s it is rejected with
OWNER_TIMEOUT.
ApiRequest
The HTTP request anhttp::on-request route’s target receives.
ApiResponse
The response anhttp::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 observeoutput,
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 beforeWorkerRegistered 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 thecreateChannel 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 withiii.observe(EngineSources.X, target).
None takes args; filter on the event (input) instead.
EnqueueResult
Result returned when a function is called withCallAction.Enqueue.
Filter
A declarative filter overinput, 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 WebSocketIIIReconnectionConfig
Configuration for WebSocket reconnection behaviorInitOptions
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-readablecode: 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’scapture 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 anonObserverAdded 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
Whatiii.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 ofiii.observe: what is observed.
OnFunctionRegistrationInput
Input passed to theon_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 theon_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 viagetFatalError() 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 ofiii.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 theiii-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)
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 (whenpath 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 (whenpath 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 bystate::update / stream::update.