@ttt-productions/chat-react 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/index.d.ts +3 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +4 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/realtime/channel-client.d.ts +104 -0
  6. package/dist/realtime/channel-client.d.ts.map +1 -0
  7. package/dist/realtime/channel-client.js +356 -0
  8. package/dist/realtime/channel-client.js.map +1 -0
  9. package/dist/realtime/inbox-client.d.ts +55 -0
  10. package/dist/realtime/inbox-client.d.ts.map +1 -0
  11. package/dist/realtime/inbox-client.js +173 -0
  12. package/dist/realtime/inbox-client.js.map +1 -0
  13. package/dist/realtime/index.d.ts +16 -0
  14. package/dist/realtime/index.d.ts.map +1 -0
  15. package/dist/realtime/index.js +14 -0
  16. package/dist/realtime/index.js.map +1 -0
  17. package/dist/realtime/map.d.ts +31 -0
  18. package/dist/realtime/map.d.ts.map +1 -0
  19. package/dist/realtime/map.js +70 -0
  20. package/dist/realtime/map.js.map +1 -0
  21. package/dist/realtime/shared.d.ts +24 -0
  22. package/dist/realtime/shared.d.ts.map +1 -0
  23. package/dist/realtime/shared.js +19 -0
  24. package/dist/realtime/shared.js.map +1 -0
  25. package/dist/realtime/socket.d.ts +33 -0
  26. package/dist/realtime/socket.d.ts.map +1 -0
  27. package/dist/realtime/socket.js +43 -0
  28. package/dist/realtime/socket.js.map +1 -0
  29. package/dist/realtime/transport.d.ts +48 -0
  30. package/dist/realtime/transport.d.ts.map +1 -0
  31. package/dist/realtime/transport.js +47 -0
  32. package/dist/realtime/transport.js.map +1 -0
  33. package/dist/realtime/useRealtimeChatMessages.d.ts +23 -0
  34. package/dist/realtime/useRealtimeChatMessages.d.ts.map +1 -0
  35. package/dist/realtime/useRealtimeChatMessages.js +71 -0
  36. package/dist/realtime/useRealtimeChatMessages.js.map +1 -0
  37. package/dist/realtime/wire.d.ts +135 -0
  38. package/dist/realtime/wire.d.ts.map +1 -0
  39. package/dist/realtime/wire.js +71 -0
  40. package/dist/realtime/wire.js.map +1 -0
  41. package/dist/types.d.ts +38 -1
  42. package/dist/types.d.ts.map +1 -1
  43. package/dist/ui/ChatShell.d.ts +7 -1
  44. package/dist/ui/ChatShell.d.ts.map +1 -1
  45. package/dist/ui/ChatShell.js +51 -3
  46. package/dist/ui/ChatShell.js.map +1 -1
  47. package/package.json +7 -6
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type { ChatCoreConfig, ChatAttachmentConfig, ChatUploadAdapter, ChatMentionConfig, MessageRenderer, MessageRendererRegistry, RenderableMentionProvider, MentionResultRenderer, } from "./types.js";
1
+ export type { ChatCoreConfig, ChatTransportMode, ChatRealtimeTransportConfig, ChatAttachmentConfig, ChatUploadAdapter, ChatMentionConfig, MessageRenderer, MessageRendererRegistry, RenderableMentionProvider, MentionResultRenderer, } from "./types.js";
2
2
  export type { ChatAttachmentUrlResolver, ChatAttachmentUrlProviderProps, } from "./context/ChatAttachmentUrlContext.js";
3
3
  export { ChatAttachmentUrlProvider, useChatAttachmentUrlResolver, } from "./context/ChatAttachmentUrlContext.js";
4
4
  export type { ChatNameResolverProviderProps } from "./context/ChatNameResolverContext.js";
@@ -6,6 +6,8 @@ export { ChatNameResolverProvider, useChatNameResolver, useOptionalChatNameResol
6
6
  export type { UseChatMessagesResult } from "./hooks/useChatMessages.js";
7
7
  export { useChatMessages } from "./hooks/useChatMessages.js";
8
8
  export { canAccessThread } from "./hooks/useChatThreadAccess.js";
9
+ export { createRealtimeChatClient, createInboxClient, ChannelClient, InboxClient, useRealtimeChatMessages, browserSocketFactory, CHAT_SUBPROTOCOL, CHAT_CLOSE_CODES, CLIENT_FRAME, SERVER_FRAME, buildFrame, parseFrame, } from "./realtime/index.js";
10
+ export type { RealtimeChatClient, RealtimeTransportConfig, ChannelClientState, ChannelClientConfig, InboxClientState, InboxClientConfig, UseRealtimeChatMessagesResult, GrantProvider, TransportTimers, RealtimeStatus, RealtimeSocket, SocketFactory, SocketHandlers, ChannelRefTuple, WireMessageRow, WireInboxSnapshot, WireRegistryEntry, ServerFrame, } from "./realtime/index.js";
9
11
  export type { ChatShellProps } from "./ui/ChatShell.js";
10
12
  export { ChatShell } from "./ui/ChatShell.js";
11
13
  export { MessageList } from "./ui/MessageList.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,YAAY,EACV,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,uBAAuB,EACvB,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAGpB,YAAY,EACV,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,yBAAyB,EACzB,4BAA4B,GAC7B,MAAM,uCAAuC,CAAC;AAG/C,YAAY,EAAE,6BAA6B,EAAE,MAAM,sCAAsC,CAAC;AAC1F,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,2BAA2B,EAC3B,qBAAqB,GACtB,MAAM,sCAAsC,CAAC;AAE9C,YAAY,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEjE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,YAAY,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EACL,mBAAmB,EACnB,KAAK,wBAAwB,GAC9B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,sBAAsB,EACtB,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,EACjC,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,GAC7B,MAAM,wCAAwC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,2BAA2B,EAC3B,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,uBAAuB,EACvB,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAGpB,YAAY,EACV,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,yBAAyB,EACzB,4BAA4B,GAC7B,MAAM,uCAAuC,CAAC;AAG/C,YAAY,EAAE,6BAA6B,EAAE,MAAM,sCAAsC,CAAC;AAC1F,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,2BAA2B,EAC3B,qBAAqB,GACtB,MAAM,sCAAsC,CAAC;AAE9C,YAAY,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAKjE,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,UAAU,GACX,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,kBAAkB,EAClB,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,6BAA6B,EAC7B,aAAa,EACb,eAAe,EACf,cAAc,EACd,cAAc,EACd,aAAa,EACb,cAAc,EACd,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,YAAY,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EACL,mBAAmB,EACnB,KAAK,wBAAwB,GAC9B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,sBAAsB,EACtB,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,EACjC,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,GAC7B,MAAM,wCAAwC,CAAC"}
package/dist/index.js CHANGED
@@ -3,6 +3,10 @@ export { ChatAttachmentUrlProvider, useChatAttachmentUrlResolver, } from "./cont
3
3
  export { ChatNameResolverProvider, useChatNameResolver, useOptionalChatNameResolver, useResolvedSenderName, } from "./context/ChatNameResolverContext.js";
4
4
  export { useChatMessages } from "./hooks/useChatMessages.js";
5
5
  export { canAccessThread } from "./hooks/useChatThreadAccess.js";
6
+ // Realtime (Cloudflare Durable Object) transport — the client half of the chat
7
+ // worker wire protocol. Opt-in via `ChatCoreConfig.transport === 'realtime'`; the
8
+ // firestore transport stays the unchanged default. See docs/packages/chat-react.md.
9
+ export { createRealtimeChatClient, createInboxClient, ChannelClient, InboxClient, useRealtimeChatMessages, browserSocketFactory, CHAT_SUBPROTOCOL, CHAT_CLOSE_CODES, CLIENT_FRAME, SERVER_FRAME, buildFrame, parseFrame, } from "./realtime/index.js";
6
10
  export { ChatShell } from "./ui/ChatShell.js";
7
11
  export { MessageList } from "./ui/MessageList.js";
8
12
  export { Composer } from "./ui/Composer.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAyBb,OAAO,EACL,yBAAyB,EACzB,4BAA4B,GAC7B,MAAM,uCAAuC,CAAC;AAI/C,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,2BAA2B,EAC3B,qBAAqB,GACtB,MAAM,sCAAsC,CAAC;AAG9C,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAGjE,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAyB,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EACL,mBAAmB,GAEpB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,sBAAsB,GAKvB,MAAM,wCAAwC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AA2Bb,OAAO,EACL,yBAAyB,EACzB,4BAA4B,GAC7B,MAAM,uCAAuC,CAAC;AAI/C,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,2BAA2B,EAC3B,qBAAqB,GACtB,MAAM,sCAAsC,CAAC;AAG9C,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEjE,+EAA+E;AAC/E,kFAAkF;AAClF,oFAAoF;AACpF,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,UAAU,GACX,MAAM,qBAAqB,CAAC;AAuB7B,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAyB,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EACL,mBAAmB,GAEpB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,sBAAsB,GAKvB,MAAM,wCAAwC,CAAC"}
@@ -0,0 +1,104 @@
1
+ import type { ChatMessageV1 } from '@ttt-productions/chat-core';
2
+ import type { SocketFactory } from './socket.js';
3
+ import type { GrantProvider, TransportTimers, RealtimeStatus } from './shared.js';
4
+ export interface ChannelClientState {
5
+ status: RealtimeStatus;
6
+ /** Ordered ascending by seq; optimistic messages (no seq yet) sort to the tail. */
7
+ messages: ChatMessageV1[];
8
+ /** uids currently typing (cleared after ~TYPING_COALESCE_MS of silence). */
9
+ typing: string[];
10
+ /** uids the DO reports online (presence). Empty until presence-subscribe. */
11
+ presence: string[];
12
+ /** True while an older-history page request is in flight. */
13
+ isFetchingOlder: boolean;
14
+ /** False once a history page returns fewer than the requested limit (reached the head). */
15
+ hasOlder: boolean;
16
+ /** The last structured error code the DO sent (e.g. 'blocked-word', 'too-long', flood reason). */
17
+ lastErrorCode: string | null;
18
+ }
19
+ export interface ChannelClientConfig {
20
+ /** WebSocket endpoint base, e.g. `wss://chat.ttt.productions`. The client appends `/channel`. */
21
+ endpoint: string;
22
+ /** The logical thread id the UI keys on (used as ChatMessageV1.threadId). */
23
+ threadId: string;
24
+ /** The authenticated uid (sender identity for optimistic echoes + auth-switch guard). */
25
+ currentUserId: string;
26
+ /** Mints/refreshes a channel grant. Called on connect and once on a 4401 re-grant. */
27
+ grantProvider: GrantProvider;
28
+ socketFactory: SocketFactory;
29
+ timers?: TransportTimers;
30
+ /** Reconnect backoff tuning (forwarded to realtime-core). */
31
+ reconnect?: {
32
+ baseDelayMs?: number;
33
+ maxDelayMs?: number;
34
+ maxAttempts?: number | null;
35
+ random?: () => number;
36
+ };
37
+ }
38
+ export declare class ChannelClient {
39
+ private readonly config;
40
+ private readonly timers;
41
+ private readonly controller;
42
+ private socket;
43
+ private state;
44
+ private readonly listeners;
45
+ /** Resume cursor: highest seq we've durably applied. Sent on resume after reconnect. */
46
+ private resumeSeq;
47
+ /** True after a `4401` re-grant has been attempted for the CURRENT connect cycle (once-only). */
48
+ private reauthAttempted;
49
+ private presenceSubscribed;
50
+ private heartbeatTimer;
51
+ private typingTimers;
52
+ private lastTypingSentAt;
53
+ private reconnectTimer;
54
+ private closedByUs;
55
+ constructor(config: ChannelClientConfig);
56
+ getState(): ChannelClientState;
57
+ subscribe(fn: (s: ChannelClientState) => void): () => void;
58
+ private setState;
59
+ connect(): Promise<void>;
60
+ private openSocket;
61
+ private onOpen;
62
+ private onError;
63
+ private onClose;
64
+ private scheduleReconnect;
65
+ private onMessage;
66
+ private applyChannelSnapshot;
67
+ private applyMessage;
68
+ /**
69
+ * Merge a server message: reconcile an optimistic echo by clientMessageId (swap
70
+ * the `optimistic:` row for the canonical seq row), or insert/replace by seq.
71
+ * Keeps the list sorted ascending by seq with optimistic rows at the tail.
72
+ */
73
+ private mergeMessage;
74
+ private applyAck;
75
+ private applyHistoryPage;
76
+ private applyTyping;
77
+ private sendFrame;
78
+ /**
79
+ * Optimistic send: render the echo immediately keyed by clientMessageId, then
80
+ * emit the `send` frame. The server `ack`/`message` reconciles on the seq.
81
+ */
82
+ send(args: {
83
+ clientMessageId: string;
84
+ text: string;
85
+ replyTo?: {
86
+ messageSeq: number;
87
+ preview: string;
88
+ } | null;
89
+ }): void;
90
+ /** Explicit read ack (delivery != read). `focused` => the channel is open + at latest. */
91
+ readAck(readSeq: number, focused: boolean): void;
92
+ /** Coalesced typing signal: at most one frame per TYPING_COALESCE_MS. */
93
+ typing(): void;
94
+ presenceSubscribe(): void;
95
+ presenceUnsubscribe(): void;
96
+ /** Fetch the page of history older than the oldest loaded message (epoch-aware by seq). */
97
+ fetchOlder(): void;
98
+ private requestHistory;
99
+ private startHeartbeat;
100
+ private stopHeartbeat;
101
+ /** Permanently close this client (auth-user switch / unmount). Idempotent. */
102
+ close(): void;
103
+ }
104
+ //# sourceMappingURL=channel-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-client.d.ts","sourceRoot":"","sources":["../../src/realtime/channel-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,356 @@
1
+ // The Channel realtime client: ONE WebSocket to a single channel DO, driving the
2
+ // Contract C wire protocol. Framework-neutral (a plain observable store the React
3
+ // hook subscribes to) so it is unit-testable with a mock socket and no React.
4
+ //
5
+ // Responsibilities (Contract C):
6
+ // - connect via subprotocol auth (grant offered by the injected grantProvider)
7
+ // - receive versioned `message` frames; server owns `seq`
8
+ // - optimistic send keyed by clientMessageId, reconciled on the server `ack` seq
9
+ // - explicit read acks (delivery != read; focus signals "read")
10
+ // - typing (>= 2s coalesced per the V1 limit)
11
+ // - presence-subscribe/-unsubscribe + a 20s client heartbeat
12
+ // - reconnect (realtime-core controller) with a resume cursor -> snapshot then deltas
13
+ // - history pagination over the socket (page <= 50, epoch-aware via seq)
14
+ // - error codes incl. 4401 AUTH_EXPIRED -> re-mint a grant ONCE via grantProvider
15
+ //
16
+ // Timers are injected (setTimeout/clearTimeout/now) so tests run deterministically.
17
+ import { createReconnectController } from '@ttt-productions/realtime-core';
18
+ import { CLIENT_FRAME, CHAT_CLOSE_CODES, buildFrame, parseFrame, isInboxSnapshot, } from './wire.js';
19
+ import { wireRowToMessage, optimisticMessage, seqToMessageId } from './map.js';
20
+ import { defaultTimers, HEARTBEAT_MS, TYPING_COALESCE_MS, HISTORY_PAGE_MAX } from './shared.js';
21
+ const INITIAL = {
22
+ status: 'idle',
23
+ messages: [],
24
+ typing: [],
25
+ presence: [],
26
+ isFetchingOlder: false,
27
+ hasOlder: true,
28
+ lastErrorCode: null,
29
+ };
30
+ export class ChannelClient {
31
+ config;
32
+ timers;
33
+ controller;
34
+ socket = null;
35
+ state = INITIAL;
36
+ listeners = new Set();
37
+ /** Resume cursor: highest seq we've durably applied. Sent on resume after reconnect. */
38
+ resumeSeq = 0;
39
+ /** True after a `4401` re-grant has been attempted for the CURRENT connect cycle (once-only). */
40
+ reauthAttempted = false;
41
+ presenceSubscribed = false;
42
+ heartbeatTimer = null;
43
+ typingTimers = new Map();
44
+ lastTypingSentAt = Number.NEGATIVE_INFINITY;
45
+ reconnectTimer = null;
46
+ closedByUs = false;
47
+ constructor(config) {
48
+ this.config = config;
49
+ this.timers = config.timers ?? defaultTimers;
50
+ this.controller = createReconnectController(config.reconnect ?? {});
51
+ }
52
+ // ---- observable store ----
53
+ getState() {
54
+ return this.state;
55
+ }
56
+ subscribe(fn) {
57
+ this.listeners.add(fn);
58
+ return () => this.listeners.delete(fn);
59
+ }
60
+ setState(patch) {
61
+ this.state = { ...this.state, ...patch };
62
+ for (const fn of this.listeners)
63
+ fn(this.state);
64
+ }
65
+ // ---- connection lifecycle ----
66
+ async connect() {
67
+ this.closedByUs = false;
68
+ this.controller.start();
69
+ this.setState({ status: 'connecting' });
70
+ await this.openSocket();
71
+ }
72
+ async openSocket() {
73
+ let grantToken;
74
+ try {
75
+ grantToken = await this.config.grantProvider();
76
+ }
77
+ catch {
78
+ // Grant mint failed — treat as a closed attempt and back off.
79
+ return this.scheduleReconnect();
80
+ }
81
+ if (this.closedByUs)
82
+ return;
83
+ const url = `${this.config.endpoint.replace(/\/$/, '')}/channel`;
84
+ this.socket = this.config.socketFactory({
85
+ url,
86
+ grantToken,
87
+ handlers: {
88
+ onOpen: () => this.onOpen(),
89
+ onMessage: (data) => this.onMessage(data),
90
+ onClose: (code, reason) => this.onClose(code, reason),
91
+ onError: () => this.onError(),
92
+ },
93
+ });
94
+ }
95
+ onOpen() {
96
+ this.controller.onOpen();
97
+ this.reauthAttempted = false;
98
+ this.setState({ status: 'open' });
99
+ // Resume: ask the DO for the authoritative snapshot, then live deltas flow.
100
+ this.sendFrame(CLIENT_FRAME.RESUME, { ackSeq: this.resumeSeq });
101
+ // If the UI had presence open, re-subscribe after a reconnect.
102
+ if (this.presenceSubscribed)
103
+ this.sendFrame(CLIENT_FRAME.PRESENCE_SUBSCRIBE, {});
104
+ this.startHeartbeat();
105
+ }
106
+ onError() {
107
+ // The close handler does the backoff; onerror is advisory in browsers.
108
+ }
109
+ onClose(code, _reason) {
110
+ this.stopHeartbeat();
111
+ this.socket = null;
112
+ if (this.closedByUs) {
113
+ this.setState({ status: 'closed' });
114
+ return;
115
+ }
116
+ // 4401 AUTH_EXPIRED: re-mint a grant ONCE and reconnect immediately, no backoff.
117
+ if (code === CHAT_CLOSE_CODES.AUTH_EXPIRED && !this.reauthAttempted) {
118
+ this.reauthAttempted = true;
119
+ this.setState({ status: 'reconnecting' });
120
+ void this.openSocket();
121
+ return;
122
+ }
123
+ // 4403 REVOKED: access pulled. Stop — a reconnect would just re-deny at mint.
124
+ if (code === CHAT_CLOSE_CODES.REVOKED) {
125
+ this.closedByUs = true;
126
+ this.controller.close();
127
+ this.setState({ status: 'closed', lastErrorCode: 'revoked' });
128
+ return;
129
+ }
130
+ this.scheduleReconnect();
131
+ }
132
+ scheduleReconnect() {
133
+ const delay = this.controller.onClose();
134
+ if (delay == null) {
135
+ this.setState({ status: 'closed' });
136
+ return;
137
+ }
138
+ this.setState({ status: 'reconnecting' });
139
+ this.reconnectTimer = this.timers.setTimeout(() => {
140
+ this.reconnectTimer = null;
141
+ if (this.closedByUs)
142
+ return;
143
+ void this.openSocket();
144
+ }, delay);
145
+ }
146
+ // ---- inbound frames ----
147
+ onMessage(data) {
148
+ const frame = parseFrame(data);
149
+ if (!frame || !frame.type)
150
+ return;
151
+ const payload = frame.payload ?? {};
152
+ switch (frame.type) {
153
+ case 'message':
154
+ return this.applyMessage(payload.message);
155
+ case 'ack':
156
+ return this.applyAck(payload);
157
+ case 'history-page':
158
+ return this.applyHistoryPage(payload.messages ?? []);
159
+ case 'presence':
160
+ return this.setState({ presence: payload.online ?? [] });
161
+ case 'typing':
162
+ return this.applyTyping(payload.uid);
163
+ case 'snapshot':
164
+ return this.applyChannelSnapshot(payload);
165
+ case 'error':
166
+ return this.setState({ lastErrorCode: String(payload.code ?? 'error') });
167
+ default:
168
+ return; // unknown/optional types tolerated (forward compat)
169
+ }
170
+ }
171
+ applyChannelSnapshot(snap) {
172
+ // Guard: an inbox snapshot must never reach a channel client.
173
+ if (isInboxSnapshot(snap))
174
+ return;
175
+ // The snapshot tells us the authoritative tail + our read cursor. If the DO's
176
+ // tail is ahead of what we have, a missed delta is repaired by a history fetch.
177
+ if (typeof snap.lastMessageSeq === 'number' && snap.lastMessageSeq > this.resumeSeq) {
178
+ // We've reconnected and may have gaps below the tail — pull the latest page.
179
+ this.requestHistory(null);
180
+ }
181
+ }
182
+ applyMessage(row) {
183
+ if (!row || typeof row.seq !== 'number')
184
+ return;
185
+ const mapped = wireRowToMessage(row, this.config.threadId);
186
+ this.mergeMessage(mapped, row);
187
+ if (row.seq > this.resumeSeq)
188
+ this.resumeSeq = row.seq;
189
+ }
190
+ /**
191
+ * Merge a server message: reconcile an optimistic echo by clientMessageId (swap
192
+ * the `optimistic:` row for the canonical seq row), or insert/replace by seq.
193
+ * Keeps the list sorted ascending by seq with optimistic rows at the tail.
194
+ */
195
+ mergeMessage(mapped, row) {
196
+ const next = this.state.messages.filter((m) => m.messageId !== mapped.messageId &&
197
+ // drop the optimistic placeholder this server row reconciles
198
+ (m.meta?.clientMessageId !== row.clientMessageId || !m.meta?.optimistic));
199
+ next.push(mapped);
200
+ next.sort(sortBySeq);
201
+ this.setState({ messages: next });
202
+ }
203
+ applyAck(payload) {
204
+ // A read-ack echo carries readSeq only — nothing to reconcile locally.
205
+ if (payload.clientMessageId == null || typeof payload.seq !== 'number')
206
+ return;
207
+ // Reconcile the optimistic echo: stamp the server seq onto it. The canonical
208
+ // `message` broadcast (which the sender also receives) replaces it fully; this
209
+ // ack guarantees the seq even if the broadcast is dropped/reordered.
210
+ const seq = payload.seq;
211
+ const cmid = payload.clientMessageId;
212
+ const next = this.state.messages.map((m) => m.meta?.optimistic && m.meta?.clientMessageId === cmid
213
+ ? { ...m, messageId: seqToMessageId(seq), meta: { ...m.meta, optimistic: false, seq } }
214
+ : m);
215
+ next.sort(sortBySeq);
216
+ if (seq > this.resumeSeq)
217
+ this.resumeSeq = seq;
218
+ this.setState({ messages: next });
219
+ }
220
+ applyHistoryPage(rows) {
221
+ const mapped = rows.map((r) => wireRowToMessage(r, this.config.threadId));
222
+ const bySeq = new Map();
223
+ for (const m of this.state.messages)
224
+ bySeq.set(m.messageId, m);
225
+ for (const m of mapped)
226
+ bySeq.set(m.messageId, m);
227
+ const merged = [...bySeq.values()].sort(sortBySeq);
228
+ for (const r of rows)
229
+ if (r.seq > this.resumeSeq)
230
+ this.resumeSeq = r.seq;
231
+ this.setState({
232
+ messages: merged,
233
+ isFetchingOlder: false,
234
+ hasOlder: rows.length >= HISTORY_PAGE_MAX,
235
+ });
236
+ }
237
+ applyTyping(uid) {
238
+ if (!uid || uid === this.config.currentUserId)
239
+ return;
240
+ if (!this.state.typing.includes(uid))
241
+ this.setState({ typing: [...this.state.typing, uid] });
242
+ const prev = this.typingTimers.get(uid);
243
+ if (prev)
244
+ this.timers.clearTimeout(prev);
245
+ this.typingTimers.set(uid, this.timers.setTimeout(() => {
246
+ this.typingTimers.delete(uid);
247
+ this.setState({ typing: this.state.typing.filter((u) => u !== uid) });
248
+ }, TYPING_COALESCE_MS * 2));
249
+ }
250
+ // ---- outbound actions ----
251
+ sendFrame(type, payload) {
252
+ if (!this.socket || !this.socket.isOpen)
253
+ return false;
254
+ this.socket.send(buildFrame(type, payload));
255
+ return true;
256
+ }
257
+ /**
258
+ * Optimistic send: render the echo immediately keyed by clientMessageId, then
259
+ * emit the `send` frame. The server `ack`/`message` reconciles on the seq.
260
+ */
261
+ send(args) {
262
+ const now = this.timers.now();
263
+ const echo = optimisticMessage({
264
+ clientMessageId: args.clientMessageId,
265
+ threadId: this.config.threadId,
266
+ senderId: this.config.currentUserId,
267
+ text: args.text,
268
+ createdAt: now,
269
+ replyTo: args.replyTo ? { messageId: seqToMessageId(args.replyTo.messageSeq), messagePreview: args.replyTo.preview } : null,
270
+ });
271
+ const next = [...this.state.messages, echo].sort(sortBySeq);
272
+ this.setState({ messages: next, lastErrorCode: null });
273
+ this.sendFrame(CLIENT_FRAME.SEND, {
274
+ clientMessageId: args.clientMessageId,
275
+ text: args.text,
276
+ replyTo: args.replyTo ?? null,
277
+ });
278
+ }
279
+ /** Explicit read ack (delivery != read). `focused` => the channel is open + at latest. */
280
+ readAck(readSeq, focused) {
281
+ this.sendFrame(CLIENT_FRAME.READ_ACK, { readSeq, focused });
282
+ }
283
+ /** Coalesced typing signal: at most one frame per TYPING_COALESCE_MS. */
284
+ typing() {
285
+ const now = this.timers.now();
286
+ if (now - this.lastTypingSentAt < TYPING_COALESCE_MS)
287
+ return;
288
+ this.lastTypingSentAt = now;
289
+ this.sendFrame(CLIENT_FRAME.TYPING, {});
290
+ }
291
+ presenceSubscribe() {
292
+ this.presenceSubscribed = true;
293
+ this.sendFrame(CLIENT_FRAME.PRESENCE_SUBSCRIBE, {});
294
+ }
295
+ presenceUnsubscribe() {
296
+ this.presenceSubscribed = false;
297
+ this.sendFrame(CLIENT_FRAME.PRESENCE_UNSUBSCRIBE, {});
298
+ this.setState({ presence: [] });
299
+ }
300
+ /** Fetch the page of history older than the oldest loaded message (epoch-aware by seq). */
301
+ fetchOlder() {
302
+ if (this.state.isFetchingOlder || !this.state.hasOlder)
303
+ return;
304
+ const oldest = this.state.messages.find((m) => typeof m.meta?.seq === 'number');
305
+ const beforeSeq = oldest && typeof oldest.meta?.seq === 'number' ? oldest.meta.seq : null;
306
+ this.setState({ isFetchingOlder: true });
307
+ this.requestHistory(beforeSeq);
308
+ }
309
+ requestHistory(beforeSeq) {
310
+ this.sendFrame(CLIENT_FRAME.HISTORY, { beforeSeq, limit: HISTORY_PAGE_MAX });
311
+ }
312
+ // ---- heartbeat (20s) ----
313
+ startHeartbeat() {
314
+ this.stopHeartbeat();
315
+ const tick = () => {
316
+ if (!this.socket || !this.socket.isOpen)
317
+ return;
318
+ this.sendFrame(CLIENT_FRAME.HEARTBEAT, {});
319
+ this.heartbeatTimer = this.timers.setTimeout(tick, HEARTBEAT_MS);
320
+ };
321
+ this.heartbeatTimer = this.timers.setTimeout(tick, HEARTBEAT_MS);
322
+ }
323
+ stopHeartbeat() {
324
+ if (this.heartbeatTimer != null) {
325
+ this.timers.clearTimeout(this.heartbeatTimer);
326
+ this.heartbeatTimer = null;
327
+ }
328
+ }
329
+ // ---- teardown ----
330
+ /** Permanently close this client (auth-user switch / unmount). Idempotent. */
331
+ close() {
332
+ this.closedByUs = true;
333
+ this.controller.close();
334
+ this.stopHeartbeat();
335
+ for (const t of this.typingTimers.values())
336
+ this.timers.clearTimeout(t);
337
+ this.typingTimers.clear();
338
+ if (this.reconnectTimer != null) {
339
+ this.timers.clearTimeout(this.reconnectTimer);
340
+ this.reconnectTimer = null;
341
+ }
342
+ if (this.socket) {
343
+ this.socket.close(1000, 'client teardown');
344
+ this.socket = null;
345
+ }
346
+ this.setState({ status: 'closed', typing: [], presence: [] });
347
+ }
348
+ }
349
+ function sortBySeq(a, b) {
350
+ const sa = typeof a.meta?.seq === 'number' ? a.meta.seq : Number.POSITIVE_INFINITY;
351
+ const sb = typeof b.meta?.seq === 'number' ? b.meta.seq : Number.POSITIVE_INFINITY;
352
+ if (sa !== sb)
353
+ return sa - sb;
354
+ return a.createdAt - b.createdAt;
355
+ }
356
+ //# sourceMappingURL=channel-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-client.js","sourceRoot":"","sources":["../../src/realtime/channel-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import { type WireRegistryEntry } from './wire.js';
2
+ import type { SocketFactory } from './socket.js';
3
+ import type { GrantProvider, TransportTimers, RealtimeStatus } from './shared.js';
4
+ export interface InboxClientState {
5
+ status: RealtimeStatus;
6
+ /** Active (non-tombstoned) channel/invite registry entries — Chats-view visibility. */
7
+ registry: WireRegistryEntry[];
8
+ /** True if ANY active channel/invite has unread (drives the dock dot). */
9
+ hasUnread: boolean;
10
+ /** The set of channelRefs that currently carry an unread dot (per-row dots). */
11
+ unreadChannelRefs: string[];
12
+ }
13
+ export interface InboxClientConfig {
14
+ endpoint: string;
15
+ /** The authenticated uid (the inbox owner; the DO serves no one else's data). */
16
+ currentUserId: string;
17
+ /** Mints/refreshes an INBOX-scope grant (scope `{ kind:'inbox', uid }`). */
18
+ grantProvider: GrantProvider;
19
+ socketFactory: SocketFactory;
20
+ timers?: TransportTimers;
21
+ reconnect?: {
22
+ baseDelayMs?: number;
23
+ maxDelayMs?: number;
24
+ maxAttempts?: number | null;
25
+ random?: () => number;
26
+ };
27
+ }
28
+ export declare class InboxClient {
29
+ private readonly config;
30
+ private readonly timers;
31
+ private readonly controller;
32
+ private socket;
33
+ private state;
34
+ private readonly listeners;
35
+ private reauthAttempted;
36
+ private reconnectTimer;
37
+ private closedByUs;
38
+ constructor(config: InboxClientConfig);
39
+ getState(): InboxClientState;
40
+ subscribe(fn: (s: InboxClientState) => void): () => void;
41
+ private setState;
42
+ connect(): Promise<void>;
43
+ private openSocket;
44
+ private onOpen;
45
+ private onClose;
46
+ private scheduleReconnect;
47
+ private onMessage;
48
+ private applySnapshot;
49
+ private sendFrame;
50
+ /** True if a specific channel/invite currently carries an unread dot. */
51
+ channelHasUnread(channelRef: string): boolean;
52
+ /** Permanently close (auth-user switch / unmount). Idempotent. */
53
+ close(): void;
54
+ }
55
+ //# sourceMappingURL=inbox-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox-client.d.ts","sourceRoot":"","sources":["../../src/realtime/inbox-client.ts"],"names":[],"mappings":"AAWA,OAAO,EAOL,KAAK,iBAAiB,EACvB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAkB,aAAa,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,uFAAuF;IACvF,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,0EAA0E;IAC1E,SAAS,EAAE,OAAO,CAAC;IACnB,gFAAgF;IAChF,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,aAAa,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,aAAa,EAAE,aAAa,CAAC;IAC7B,aAAa,EAAE,aAAa,CAAC;IAC7B,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,SAAS,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAA;KAAE,CAAC;CAC/G;AAID,qBAAa,WAAW;IAUV,OAAO,CAAC,QAAQ,CAAC,MAAM;IATnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4C;IACtE,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,cAAc,CAA0D;IAChF,OAAO,CAAC,UAAU,CAAS;gBAEE,MAAM,EAAE,iBAAiB;IAKtD,QAAQ,IAAI,gBAAgB;IAI5B,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,IAAI,GAAG,MAAM,IAAI;IAKxD,OAAO,CAAC,QAAQ;IAKV,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAOhB,UAAU;IAqBxB,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,OAAO;IAqBf,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,SAAS;IAMjB,yEAAyE;IACzE,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAI7C,kEAAkE;IAClE,KAAK,IAAI,IAAI;CAad"}