11/**
2- * A subscription handle returned by {@link RealtimeHandlerClient.subscribe}.
2+ * Extend this interface to add typed `subscribe` callbacks and `send` payloads
3+ * for your deployed RealtimeHandlers.
4+ *
5+ * This is separate from {@link RealtimeHandlerNameRegistry} (which is auto-generated
6+ * by `base44 types generate`), so there are no conflicts.
7+ *
8+ * @example
9+ * ```typescript
10+ * declare module "@base44/sdk" {
11+ * interface RealtimeHandlerRegistry {
12+ * ChatRoom: {
13+ * inbound: { type: "joined" | "left" | "message"; userId?: string; from?: string; text?: string };
14+ * outbound: { text: string };
15+ * };
16+ * }
17+ * }
18+ * ```
319 */
4- export interface RealtimeSubscription {
5- /** Send a message to all subscribers of this instance. */
6- send ( data : unknown ) : void ;
7- /** Close the WebSocket connection and remove the subscription. */
8- close ( ) : void ;
9- }
20+ export interface RealtimeHandlerRegistry { }
21+
22+ /**
23+ * Auto-populated by `base44 types generate` with the names of your deployed handlers.
24+ * Do not edit this interface manually — use {@link RealtimeHandlerRegistry} for message types.
25+ */
26+ export interface RealtimeHandlerNameRegistry { }
27+
28+ type AllHandlerNames = keyof RealtimeHandlerRegistry | keyof RealtimeHandlerNameRegistry ;
29+
30+ type InboundFor < N extends string > = N extends keyof RealtimeHandlerRegistry
31+ ? RealtimeHandlerRegistry [ N ] extends { inbound : infer I }
32+ ? I
33+ : unknown
34+ : unknown ;
35+
36+ type OutboundFor < N extends string > = N extends keyof RealtimeHandlerRegistry
37+ ? RealtimeHandlerRegistry [ N ] extends { outbound : infer O }
38+ ? O
39+ : unknown
40+ : unknown ;
1041
1142/**
1243 * Client for a single named RealtimeHandler.
44+ * Typed automatically when the handler is registered in {@link RealtimeHandlerRegistry}.
1345 */
14- export interface RealtimeHandlerClient {
15- /**
16- * Subscribe to messages from a specific RealtimeHandler instance.
17- *
18- * @param instanceId - The instance ID of the Durable Object.
19- * @param callback - Called with each parsed message payload.
20- * @returns A subscription handle with `send` and `close` methods.
21- */
46+ export interface RealtimeHandlerClient < N extends string = string > {
47+ /** Open a WebSocket subscription. Returns a synchronous unsubscribe function. */
2248 subscribe (
2349 instanceId : string ,
24- callback : ( data : unknown ) => void ,
25- ) : Promise < RealtimeSubscription > ;
50+ callback : ( data : InboundFor < N > ) => void ,
51+ ) : ( ) => void ;
2652
27- /**
28- * Send a message to an existing active subscription.
29- *
30- * @param instanceId - The instance ID of the Durable Object.
31- * @param data - The data to send (will be JSON-serialized).
32- * @throws {Error } When no active subscription exists for this handler/instance pair.
33- */
34- send ( instanceId : string , data : unknown ) : void ;
53+ /** Send a message over the open socket. Throws if not subscribed. */
54+ send ( instanceId : string , data : OutboundFor < N > ) : void ;
3555}
3656
3757/**
@@ -41,10 +61,14 @@ export interface RealtimeHandlerClient {
4161 * Handler names are accessed as dynamic properties on this module:
4262 * ```typescript
4363 * const sub = await base44.realtime.MyHandler.subscribe("room-1", (msg) => {
44- * console.log(msg);
64+ * console.log(msg); // typed if MyHandler is in RealtimeHandlerRegistry
4565 * });
4666 * sub.send({ text: "hello" });
4767 * sub.close();
4868 * ```
4969 */
50- export type RealtimeModule = Record < string , RealtimeHandlerClient > ;
70+ export type RealtimeModule = {
71+ [ K in AllHandlerNames ] : K extends keyof RealtimeHandlerRegistry
72+ ? RealtimeHandlerClient < string & K >
73+ : RealtimeHandlerClient ;
74+ } & Record < string , RealtimeHandlerClient > ;
0 commit comments