22 * Extend this interface to add typed `subscribe` callbacks and `send` payloads
33 * for your deployed Actors.
44 *
5- * This is separate from { @link ActorNameRegistry} (which is auto-generated
5+ * This is separate from ` ActorNameRegistry` (which is auto-generated
66 * by `base44 types generate`), so there are no conflicts.
77 *
88 * @example
99 * ```typescript
10+ * // Declare message types for a deployed actor
1011 * declare module "@base44/sdk" {
1112 * interface ActorRegistry {
1213 * ChatRoom: {
@@ -21,7 +22,7 @@ export interface ActorRegistry {}
2122
2223/**
2324 * Auto-populated by `base44 types generate` with the names of your deployed actors.
24- * Do not edit this interface manually. Use { @link ActorRegistry} for message types.
25+ * Do not edit this interface manually. Use ` ActorRegistry` for message types.
2526 */
2627export interface ActorNameRegistry { }
2728
@@ -39,83 +40,210 @@ type ToServerFor<N extends string> = N extends keyof ActorRegistry
3940 : unknown
4041 : unknown ;
4142
42- /** Options for { @link ActorRef. connect} . */
43+ /** Options for [ connect()](#connect) . */
4344export interface ActorConnectOptions {
4445 /**
45- * The connection id, used as the actor's `conn.id`. Supply a stable value
46- * (e.g. persisted per tab) so a reconnect reuses the same server-side
47- * identity; omit for an auto-generated per-connection id.
46+ * The connection id, used as the actor's `conn.id`. Supply a stable value,
47+ * such as one persisted per tab, so a reconnect reuses the same server-side
48+ * identity. Omit it for an auto-generated per-connection id.
4849 */
4950 id ?: string ;
5051}
5152
52- /** Handle for one listener registered via { @link Connection. subscribe} . */
53+ /** Handle for one listener registered via ` subscribe()` . */
5354export interface ActorSubscription {
54- /** Remove this listener; other listeners and the socket stay live. */
55+ /**
56+ * Removes this listener. Other listeners on the same connection, and the
57+ * connection itself, stay live. To close the connection as well, call
58+ * [close()](#close).
59+ *
60+ * @example
61+ * ```typescript
62+ * // Stop listening without closing the connection
63+ * const sub = conn.subscribe((msg) => console.log(msg));
64+ * sub.unsubscribe();
65+ * ```
66+ */
5567 unsubscribe ( ) : void ;
5668}
5769
5870/**
59- * A live connection to an actor instance, returned by { @link ActorRef. connect} .
71+ * A live connection to an actor instance, returned by [ connect()](#connect) .
6072 * `subscribe`/`send` are always valid. You only get a `Connection` once the
6173 * socket has been opened, so there's no pre-connect state to guard against.
6274 */
6375export interface Connection < N extends string = string > {
64- /** The connection id ( the value the actor sees as `conn.id`) . */
76+ /** The connection id, which is the value the actor sees as `conn.id`. */
6577 readonly id : string ;
6678
67- /** Register a message listener. Multiple are allowed; returns a per-listener unsubscribe. */
79+ /**
80+ * Registers a listener for messages sent by the actor. Any number of
81+ * listeners can be registered on one connection, and each receives every
82+ * message.
83+ *
84+ * The callback payload is typed when the actor is declared in
85+ * [ActorRegistry](#actorregistry), and is `unknown` otherwise.
86+ *
87+ * @param callback - Called with each message the actor sends to this client.
88+ * @returns An `ActorSubscription` that removes this one listener.
89+ *
90+ * @example
91+ * ```typescript
92+ * // Listen for messages from the actor
93+ * const sub = conn.subscribe((msg) => {
94+ * if (msg.type === "message") console.log(msg.text);
95+ * });
96+ * ```
97+ */
6898 subscribe ( callback : ( data : ToClientFor < N > ) => void ) : ActorSubscription ;
6999
70- /** Send a message. Buffered by the socket until it's open; dropped after
71- * {@link close}. */
100+ /**
101+ * Sends a message to the actor.
102+ *
103+ * Messages sent before the socket finishes opening are buffered and flushed
104+ * on open. Messages sent after {@link close} are dropped silently.
105+ *
106+ * The payload is typed when the actor is declared in
107+ * [ActorRegistry](#actorregistry), and is `unknown` otherwise.
108+ *
109+ * @param data - The message to send to the actor.
110+ *
111+ * @example
112+ * ```typescript
113+ * // Send a message to the actor
114+ * conn.send({ type: "message", text: "hi" });
115+ * ```
116+ */
72117 send ( data : ToServerFor < N > ) : void ;
73118
74119 /**
75- * Tear down the socket, heartbeat, and all listeners. Safe to call more
76- * than once. A connection also closes itself when it fails permanently.
77- * See {@link ActorRef.connect}.
120+ * Closes the connection, tearing down the socket, the heartbeat, and every
121+ * listener registered on it. Safe to call more than once.
122+ *
123+ * A connection also closes itself when it fails permanently. See
124+ * [connect()](#connect) for how to recover from that.
125+ *
126+ * @example
127+ * ```typescript
128+ * // Close when the view that opened the connection goes away.
129+ * useEffect(() => {
130+ * const conn = base44.actors.ChatRoom(roomId).connect();
131+ * conn.subscribe(setMessage);
132+ * return () => conn.close();
133+ * }, [roomId]);
134+ * ```
78135 */
79136 close ( ) : void ;
80137}
81138
82139/**
83140 * A handle to one actor instance, obtained from `base44.actors.MyActor(id)`. Call
84- * {@link connect} to open the socket and get a { @link Connection} .
141+ * {@link connect} to open the socket and get a [ Connection](#connection) .
85142 */
86143export interface ActorRef < N extends string = string > {
87144 /**
88- * Open the WebSocket and return the {@link Connection}. Idempotent while the
89- * connection is open.
145+ * Opens the WebSocket to this actor instance and returns the
146+ * [Connection](#connection). Idempotent while the connection is open, so calling it
147+ * again returns the same connection rather than opening a second socket.
148+ *
149+ * The returned connection is usable straight away. Messages passed to
150+ * [send()](#send) before the socket finishes opening are buffered and
151+ * flushed on open.
152+ *
153+ * A connection that fails permanently, for example because the actor doesn't
154+ * exist or the caller isn't allowed to connect, closes itself and reports the
155+ * error to the client's `onError` handler. Call `connect()` again once the
156+ * cause is fixed to get a fresh [Connection](#connection), then re-subscribe, as
157+ * listeners do not carry over.
158+ *
159+ * @param options - Connection options. See [ActorConnectOptions](#actorconnectoptions).
160+ * @returns A live [Connection](#connection) to this actor instance.
161+ *
162+ * @example
163+ * ```typescript
164+ * // Connect to an actor instance
165+ * const conn = base44.actors.ChatRoom("room-1").connect();
166+ * ```
167+ *
168+ * @example
169+ * ```typescript
170+ * // Reuse a stable connection id so a reconnect keeps the same
171+ * // server-side identity.
172+ * let id = sessionStorage.getItem("chat-conn-id") ?? crypto.randomUUID();
173+ * sessionStorage.setItem("chat-conn-id", id);
90174 *
91- * A connection that fails permanently (for example, the actor doesn't exist
92- * or the caller isn't allowed to connect) closes itself and reports the
93- * error to the client's `onError` handler. Call `connect()` again after
94- * fixing the cause to get a fresh {@link Connection}, and re-subscribe.
175+ * const conn = base44.actors.ChatRoom("room-1").connect({ id });
176+ * ```
95177 */
96178 connect ( options ?: ActorConnectOptions ) : Connection < N > ;
97179}
98180
99181/**
100182 * Client for a single named Actor. Call it with an instance id to get an
101- * { @link ActorRef} . Typed automatically when the actor is registered in
102- * { @link ActorRegistry} .
183+ * [ ActorRef](#actorref) . Typed automatically when the actor is registered in
184+ * [ ActorRegistry](#actorregistry) .
103185 */
104186export interface ActorClient < N extends string = string > {
105187 ( instanceId : string ) : ActorRef < N > ;
106188}
107189
108190/**
109- * The actors module provides access to Cloudflare Durable Object-backed
191+ * Actors module for real-time messaging with Cloudflare Durable Object-backed
110192 * Actors deployed by the Base44 platform.
111193 *
194+ * An Actor is a named server-side object with persistent state. Each instance
195+ * is addressed by an id, so `base44.actors.ChatRoom("room-1")` and
196+ * `base44.actors.ChatRoom("room-2")` are separate instances with separate
197+ * state. Clients open a WebSocket to an instance and exchange messages with it.
198+ *
199+ * This module provides:
200+ * - Per-instance WebSocket connections, opened with [connect()](#connect)
201+ * - Message listeners, registered with [subscribe()](#subscribe)
202+ * - Message sending, with [send()](#send)
203+ * - Automatic reconnection with backoff, including recovery from half-open
204+ * sockets that stop delivering messages without emitting a close event
205+ * - End-to-end typing of message payloads through [ActorRegistry](#actorregistry)
206+ *
207+ * This module is available to use with a client in anonymous and user
208+ * authentication modes. It is not available on `base44.asServiceRole`.
209+ *
210+ * Connections stay open until you call [close()](#close), so close them
211+ * when the view that opened them goes away.
212+ *
213+ * @example
112214 * ```typescript
113- * const conn = base44.actors.MyActor("room-1").connect();
114- * const sub = conn.subscribe((msg) => console.log(msg)); // typed via ActorRegistry
215+ * // Open a connection to one instance of the ChatRoom actor.
216+ * const conn = base44.actors.ChatRoom("room-1").connect();
217+ *
218+ * const sub = conn.subscribe((msg) => {
219+ * console.log(msg);
220+ * });
221+ *
115222 * conn.send({ type: "message", text: "hi" });
223+ *
224+ * // Later, when the view goes away.
116225 * sub.unsubscribe();
117226 * conn.close();
118227 * ```
228+ *
229+ * @example
230+ * ```typescript
231+ * // Register the actor to type both directions of the conversation.
232+ * declare module "@base44/sdk" {
233+ * interface ActorRegistry {
234+ * ChatRoom: {
235+ * toClient: { type: "joined" | "message"; from?: string; text?: string };
236+ * toServer: { type: "message"; text: string };
237+ * };
238+ * }
239+ * }
240+ *
241+ * const conn = base44.actors.ChatRoom("room-1").connect();
242+ * conn.subscribe((msg) => {
243+ * // msg is typed as the toClient union.
244+ * if (msg.type === "message") console.log(msg.text);
245+ * });
246+ * ```
119247 */
120248export type ActorsModule = {
121249 [ K in AllActorNames ] : K extends keyof ActorRegistry
0 commit comments