@xemahq/realtime-client 0.1.1

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.
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RealtimeLeader = void 0;
4
+ class RealtimeLeader {
5
+ hooks;
6
+ tabId;
7
+ channelName;
8
+ channel = null;
9
+ isLeader = false;
10
+ knownPeers = new Map();
11
+ heartbeatTimer = null;
12
+ peerCheckTimer = null;
13
+ constructor(orgId, hooks) {
14
+ this.hooks = hooks;
15
+ this.tabId =
16
+ typeof crypto !== 'undefined' && crypto.randomUUID
17
+ ? crypto.randomUUID()
18
+ : `${Date.now()}-${Math.random().toString(16).slice(2)}`;
19
+ this.channelName = `xema_realtime_${orgId}`;
20
+ }
21
+ start() {
22
+ this.channel = new BroadcastChannel(this.channelName);
23
+ this.channel.addEventListener('message', (e) => this.handle(e.data));
24
+ this.broadcast({ kind: 'HELLO', tabId: this.tabId });
25
+ this.knownPeers.set(this.tabId, Date.now());
26
+ setTimeout(() => this.elect(), 100);
27
+ this.heartbeatTimer = setInterval(() => {
28
+ if (this.isLeader) {
29
+ this.broadcast({ kind: 'HEARTBEAT', tabId: this.tabId });
30
+ }
31
+ }, 3_000);
32
+ this.peerCheckTimer = setInterval(() => this.purgeStalePeers(), 5_000);
33
+ if (typeof window !== 'undefined') {
34
+ window.addEventListener('beforeunload', () => {
35
+ this.broadcast({ kind: 'BYE', tabId: this.tabId });
36
+ });
37
+ }
38
+ }
39
+ stop() {
40
+ if (this.heartbeatTimer)
41
+ clearInterval(this.heartbeatTimer);
42
+ if (this.peerCheckTimer)
43
+ clearInterval(this.peerCheckTimer);
44
+ if (this.channel) {
45
+ this.broadcast({ kind: 'BYE', tabId: this.tabId });
46
+ this.channel.close();
47
+ this.channel = null;
48
+ }
49
+ this.heartbeatTimer = null;
50
+ this.peerCheckTimer = null;
51
+ }
52
+ fanoutFrame(envelope) {
53
+ if (!this.isLeader)
54
+ return;
55
+ this.broadcast({ kind: 'FRAME', tabId: this.tabId, payload: envelope });
56
+ }
57
+ fanoutControl(frameType, data) {
58
+ if (!this.isLeader)
59
+ return;
60
+ this.broadcast({
61
+ kind: 'CONTROL',
62
+ tabId: this.tabId,
63
+ controlType: frameType,
64
+ payload: data,
65
+ });
66
+ }
67
+ handle(msg) {
68
+ if (msg.tabId === this.tabId)
69
+ return;
70
+ switch (msg.kind) {
71
+ case 'HELLO':
72
+ this.knownPeers.set(msg.tabId, Date.now());
73
+ if (this.isLeader) {
74
+ this.broadcast({ kind: 'HEARTBEAT', tabId: this.tabId });
75
+ }
76
+ this.elect();
77
+ break;
78
+ case 'HEARTBEAT':
79
+ this.knownPeers.set(msg.tabId, Date.now());
80
+ break;
81
+ case 'BYE':
82
+ this.knownPeers.delete(msg.tabId);
83
+ this.elect();
84
+ break;
85
+ case 'FRAME':
86
+ if (!this.isLeader) {
87
+ this.hooks.onFrame(msg.payload);
88
+ }
89
+ break;
90
+ case 'CONTROL':
91
+ if (!this.isLeader) {
92
+ this.hooks.onControl(msg.controlType ?? '', msg.payload);
93
+ }
94
+ break;
95
+ }
96
+ }
97
+ elect() {
98
+ const sorted = [...this.knownPeers.keys()].sort();
99
+ const leader = sorted[0];
100
+ const wasLeader = this.isLeader;
101
+ this.isLeader = leader === this.tabId;
102
+ if (this.isLeader && !wasLeader)
103
+ this.hooks.onPromoted();
104
+ else if (!this.isLeader && wasLeader)
105
+ this.hooks.onDemoted();
106
+ }
107
+ purgeStalePeers() {
108
+ const cutoff = Date.now() - 10_000;
109
+ let changed = false;
110
+ for (const [id, ts] of this.knownPeers) {
111
+ if (ts < cutoff && id !== this.tabId) {
112
+ this.knownPeers.delete(id);
113
+ changed = true;
114
+ }
115
+ }
116
+ if (changed)
117
+ this.elect();
118
+ }
119
+ broadcast(msg) {
120
+ if (!this.channel)
121
+ return;
122
+ try {
123
+ this.channel.postMessage(msg);
124
+ }
125
+ catch {
126
+ }
127
+ }
128
+ isCurrentLeader() {
129
+ return this.isLeader;
130
+ }
131
+ }
132
+ exports.RealtimeLeader = RealtimeLeader;
133
+ //# sourceMappingURL=leader-election.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"leader-election.js","sourceRoot":"","sources":["../../src/lib/leader-election.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type DeliveredEvent } from './invalidation-registry';
3
+ import { type SseClientOptions } from './sse-client';
4
+ export interface RealtimeProviderProps {
5
+ orgId: string;
6
+ tokenProvider: SseClientOptions['tokenProvider'];
7
+ url?: string;
8
+ watchdogMs?: number;
9
+ reconnectBaseMs?: number;
10
+ reconnectMaxMs?: number;
11
+ onResync?: () => void;
12
+ children: ReactNode;
13
+ }
14
+ export type RealtimeConnectionStatus = 'idle' | 'connecting' | 'connected' | 'reconnecting' | 'closed';
15
+ export interface RealtimeConnectionState {
16
+ status: RealtimeConnectionStatus;
17
+ connectionId?: string;
18
+ }
19
+ interface RealtimeContextValue {
20
+ isLeader: boolean;
21
+ state: RealtimeConnectionState;
22
+ subscribe(eventType: string, handler: (event: DeliveredEvent) => void): () => void;
23
+ subscribeToScope(connectionId: string, scope: {
24
+ kind: 'project' | 'session';
25
+ id: string;
26
+ }): Promise<void>;
27
+ unsubscribeFromScope(scope: {
28
+ kind: 'project' | 'session';
29
+ id: string;
30
+ }): void;
31
+ }
32
+ export declare function RealtimeProvider(props: RealtimeProviderProps): ReactNode;
33
+ export declare function useCloudEvent(eventType: string, handler: (event: DeliveredEvent) => void): void;
34
+ export declare function useRealtimeContext(): RealtimeContextValue;
35
+ export declare function useRealtimeStatus(): RealtimeConnectionState;
36
+ export declare function useRealtimeIsLeader(): boolean;
37
+ export {};
38
+ //# sourceMappingURL=realtime-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-context.d.ts","sourceRoot":"","sources":["../../src/lib/realtime-context.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAEL,KAAK,gBAAgB,EAEtB,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,gBAAgB,CAAC,eAAe,CAAC,CAAC;IACjD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IAKxB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAQD,MAAM,MAAM,wBAAwB,GAChC,MAAM,GACN,YAAY,GACZ,WAAW,GACX,cAAc,GACd,QAAQ,CAAC;AAEb,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,wBAAwB,CAAC;IAEjC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,oBAAoB;IAE5B,QAAQ,EAAE,OAAO,CAAC;IAElB,KAAK,EAAE,uBAAuB,CAAC;IAE/B,SAAS,CACP,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GACvC,MAAM,IAAI,CAAC;IAOd,gBAAgB,CACd,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE;QAAE,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GACjD,OAAO,CAAC,IAAI,CAAC,CAAC;IASjB,oBAAoB,CAAC,KAAK,EAAE;QAC1B,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;QAC5B,EAAE,EAAE,MAAM,CAAC;KACZ,GAAG,IAAI,CAAC;CACV;AAyED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,SAAS,CAqNxE;AAGD,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GACvC,IAAI,CAMN;AAED,wBAAgB,kBAAkB,IAAI,oBAAoB,CAQzD;AAQD,wBAAgB,iBAAiB,IAAI,uBAAuB,CAG3D;AAGD,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C"}
@@ -0,0 +1,251 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RealtimeProvider = RealtimeProvider;
4
+ exports.useCloudEvent = useCloudEvent;
5
+ exports.useRealtimeContext = useRealtimeContext;
6
+ exports.useRealtimeStatus = useRealtimeStatus;
7
+ exports.useRealtimeIsLeader = useRealtimeIsLeader;
8
+ const jsx_runtime_1 = require("react/jsx-runtime");
9
+ const react_1 = require("react");
10
+ const react_query_1 = require("@tanstack/react-query");
11
+ const invalidation_registry_1 = require("./invalidation-registry");
12
+ const leader_election_1 = require("./leader-election");
13
+ const sse_client_1 = require("./sse-client");
14
+ const RealtimeContext = (0, react_1.createContext)(null);
15
+ function eventDebugCategory(type) {
16
+ if (type.startsWith('design-system-builder.'))
17
+ return 'design-system-builder';
18
+ if (type.startsWith('session.'))
19
+ return 'session';
20
+ if (type.startsWith('workflow.run.'))
21
+ return 'workflow-run';
22
+ if (type.startsWith('workflow.job.'))
23
+ return 'workflow-job';
24
+ if (type.startsWith('workflow.activity.'))
25
+ return 'workflow-activity';
26
+ return undefined;
27
+ }
28
+ function parseProducerSource(source) {
29
+ if (!source || typeof source !== 'string') {
30
+ return { sourceKind: 'unknown', sourceId: 'unknown' };
31
+ }
32
+ const sourceMatch = source.match(/\/(services|biomes)\/([^/?#]+)/i);
33
+ const segment = sourceMatch?.[1];
34
+ const id = sourceMatch?.[2];
35
+ if (!sourceMatch || segment === undefined || id === undefined) {
36
+ return { sourceKind: 'unknown', sourceId: source };
37
+ }
38
+ return {
39
+ sourceKind: segment.toLowerCase() === 'services' ? 'service' : 'biome',
40
+ sourceId: id,
41
+ };
42
+ }
43
+ function debugGlobalRealtimeEvent(event, invalidationKeys) {
44
+ const category = eventDebugCategory(event.type) ?? 'other';
45
+ const { sourceKind, sourceId } = parseProducerSource(event.source);
46
+ console.log('[GlobalRealtime]', {
47
+ category,
48
+ type: event.type,
49
+ id: event.id ?? null,
50
+ source: event.source ?? null,
51
+ sourceKind,
52
+ sourceId,
53
+ orgId: event.ehorgid,
54
+ projectId: event.ehprojectid ?? null,
55
+ userId: event.ehuserid ?? null,
56
+ sessionSeq: event.ehsessionseq ?? null,
57
+ hint: event.__hint ?? null,
58
+ invalidationKeys,
59
+ data: event.data ?? null,
60
+ });
61
+ }
62
+ function debugGlobalRealtimeControl(frameType, data) {
63
+ console.log('[GlobalRealtime:control]', {
64
+ frameType,
65
+ data,
66
+ });
67
+ }
68
+ function RealtimeProvider(props) {
69
+ const queryClient = (0, react_query_1.useQueryClient)();
70
+ const sseRef = (0, react_1.useRef)(null);
71
+ const subscribersRef = (0, react_1.useRef)(new Map());
72
+ const [isLeader, setIsLeader] = (0, react_1.useState)(false);
73
+ const [state, setState] = (0, react_1.useState)({
74
+ status: 'idle',
75
+ });
76
+ const scopeRefcountsRef = (0, react_1.useRef)(new Map());
77
+ const scopeBoundConnectionIdRef = (0, react_1.useRef)(null);
78
+ (0, react_1.useEffect)(() => {
79
+ const cid = state.connectionId ?? null;
80
+ if (cid !== scopeBoundConnectionIdRef.current) {
81
+ scopeRefcountsRef.current.clear();
82
+ scopeBoundConnectionIdRef.current = cid;
83
+ }
84
+ }, [state.connectionId]);
85
+ const dispatchEnvelope = (0, react_1.useCallback)((envelope) => {
86
+ const event = envelope;
87
+ const keys = invalidation_registry_1.globalInvalidationRegistry.resolveQueryKeys(event);
88
+ debugGlobalRealtimeEvent(event, keys);
89
+ for (const key of keys) {
90
+ void queryClient.invalidateQueries({
91
+ queryKey: key,
92
+ });
93
+ }
94
+ const subs = subscribersRef.current.get(event.type);
95
+ if (subs) {
96
+ for (const fn of subs) {
97
+ try {
98
+ fn(event);
99
+ }
100
+ catch {
101
+ }
102
+ }
103
+ }
104
+ }, [queryClient]);
105
+ const dispatchControl = (0, react_1.useCallback)((frameType, data) => {
106
+ debugGlobalRealtimeControl(frameType, data);
107
+ if (frameType === 'connected' && data && typeof data === 'object') {
108
+ const cid = data.connectionId;
109
+ setState({
110
+ status: 'connected',
111
+ ...(typeof cid === 'string' ? { connectionId: cid } : {}),
112
+ });
113
+ }
114
+ else if (frameType === 'goodbye') {
115
+ setState({ status: 'reconnecting' });
116
+ }
117
+ }, []);
118
+ const dispatchTransportStatus = (0, react_1.useCallback)((transport) => {
119
+ setState((prev) => {
120
+ if (transport === 'closed')
121
+ return { status: 'closed' };
122
+ if (transport === 'reconnecting')
123
+ return { status: 'reconnecting' };
124
+ if (transport === 'connecting') {
125
+ return prev.status === 'connected'
126
+ ? { status: 'reconnecting' }
127
+ : { status: 'connecting' };
128
+ }
129
+ return prev;
130
+ });
131
+ }, []);
132
+ const leader = (0, react_1.useMemo)(() => new leader_election_1.RealtimeLeader(props.orgId, {
133
+ onPromoted: () => {
134
+ setIsLeader(true);
135
+ setState({ status: 'connecting' });
136
+ const sse = new sse_client_1.SseClient({
137
+ orgId: props.orgId,
138
+ tokenProvider: props.tokenProvider,
139
+ ...(props.url !== undefined ? { url: props.url } : {}),
140
+ ...(props.watchdogMs !== undefined
141
+ ? { watchdogMs: props.watchdogMs }
142
+ : {}),
143
+ ...(props.reconnectBaseMs !== undefined
144
+ ? { reconnectBaseMs: props.reconnectBaseMs }
145
+ : {}),
146
+ ...(props.reconnectMaxMs !== undefined
147
+ ? { reconnectMaxMs: props.reconnectMaxMs }
148
+ : {}),
149
+ }, (envelope) => {
150
+ dispatchEnvelope(envelope);
151
+ leader.fanoutFrame(envelope);
152
+ }, (frameType, data) => {
153
+ dispatchControl(frameType, data);
154
+ leader.fanoutControl(frameType, data);
155
+ }, () => {
156
+ if (props.onResync)
157
+ props.onResync();
158
+ void queryClient.invalidateQueries();
159
+ }, undefined, dispatchTransportStatus);
160
+ sseRef.current = sse;
161
+ sse.start();
162
+ },
163
+ onDemoted: () => {
164
+ setIsLeader(false);
165
+ setState({ status: 'idle' });
166
+ if (sseRef.current) {
167
+ sseRef.current.stop();
168
+ sseRef.current = null;
169
+ }
170
+ },
171
+ onFrame: dispatchEnvelope,
172
+ onControl: dispatchControl,
173
+ }), [props.orgId]);
174
+ (0, react_1.useEffect)(() => {
175
+ leader.start();
176
+ return () => {
177
+ leader.stop();
178
+ if (sseRef.current) {
179
+ sseRef.current.stop();
180
+ sseRef.current = null;
181
+ }
182
+ setState({ status: 'closed' });
183
+ };
184
+ }, [leader]);
185
+ const value = (0, react_1.useMemo)(() => ({
186
+ isLeader,
187
+ state,
188
+ subscribe(eventType, handler) {
189
+ const subs = subscribersRef.current.get(eventType) ?? new Set();
190
+ subs.add(handler);
191
+ subscribersRef.current.set(eventType, subs);
192
+ return () => {
193
+ subs.delete(handler);
194
+ };
195
+ },
196
+ async subscribeToScope(connectionId, scope) {
197
+ const key = `${scope.kind}:${scope.id}`;
198
+ const current = scopeRefcountsRef.current.get(key) ?? 0;
199
+ scopeRefcountsRef.current.set(key, current + 1);
200
+ if (current > 0) {
201
+ return;
202
+ }
203
+ const token = await Promise.resolve(props.tokenProvider());
204
+ const sseUrl = props.url ?? '/realtime/stream';
205
+ const subscriptionsUrl = sseUrl.replace(/\/stream\/?$/, `/streams/${encodeURIComponent(connectionId)}/subscriptions`);
206
+ await fetch(subscriptionsUrl, {
207
+ method: 'POST',
208
+ headers: {
209
+ Authorization: `Bearer ${token}`,
210
+ 'Content-Type': 'application/json',
211
+ 'X-Org-Id': props.orgId,
212
+ },
213
+ body: JSON.stringify({ scope: scope.kind, id: scope.id }),
214
+ });
215
+ },
216
+ unsubscribeFromScope(scope) {
217
+ const key = `${scope.kind}:${scope.id}`;
218
+ const current = scopeRefcountsRef.current.get(key) ?? 0;
219
+ if (current <= 1) {
220
+ scopeRefcountsRef.current.delete(key);
221
+ }
222
+ else {
223
+ scopeRefcountsRef.current.set(key, current - 1);
224
+ }
225
+ },
226
+ }), [isLeader, state, props.orgId, props.tokenProvider]);
227
+ return ((0, jsx_runtime_1.jsx)(RealtimeContext.Provider, { value: value, children: props.children }));
228
+ }
229
+ function useCloudEvent(eventType, handler) {
230
+ const ctx = (0, react_1.useContext)(RealtimeContext);
231
+ (0, react_1.useEffect)(() => {
232
+ if (!ctx)
233
+ return;
234
+ return ctx.subscribe(eventType, handler);
235
+ }, [ctx, eventType, handler]);
236
+ }
237
+ function useRealtimeContext() {
238
+ const ctx = (0, react_1.useContext)(RealtimeContext);
239
+ if (!ctx) {
240
+ throw new Error('useRealtimeContext must be used inside a RealtimeProvider.');
241
+ }
242
+ return ctx;
243
+ }
244
+ function useRealtimeStatus() {
245
+ const ctx = (0, react_1.useContext)(RealtimeContext);
246
+ return ctx?.state ?? { status: 'idle' };
247
+ }
248
+ function useRealtimeIsLeader() {
249
+ return useRealtimeContext().isLeader;
250
+ }
251
+ //# sourceMappingURL=realtime-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-context.js","sourceRoot":"","sources":["../../src/lib/realtime-context.tsx"],"names":[],"mappings":";;AAmKA,4CAqNC;AAGD,sCASC;AAED,gDAQC;AAQD,8CAGC;AAGD,kDAEC;;AA9ZD,iCASe;AAEf,uDAAuD;AACvD,mEAIiC;AACjC,uDAAmD;AACnD,6CAIsB;AAsEtB,MAAM,eAAe,GAAG,IAAA,qBAAa,EAA8B,IAAI,CAAC,CAAC;AAEzE,SAAS,kBAAkB,CAAC,IAAY;IACtC,IAAI,IAAI,CAAC,UAAU,CAAC,wBAAwB,CAAC;QAAE,OAAO,uBAAuB,CAAC;IAC9E,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,SAAS,CAAC;IAClD,IAAI,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC;QAAE,OAAO,cAAc,CAAC;IAC5D,IAAI,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC;QAAE,OAAO,cAAc,CAAC;IAC5D,IAAI,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC;QAAE,OAAO,mBAAmB,CAAC;IACtE,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,mBAAmB,CAAC,MAA0B;IAIrD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC1C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IACxD,CAAC;IACD,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACpE,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC;IACjC,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5B,IAAI,CAAC,WAAW,IAAI,OAAO,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;QAC9D,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACrD,CAAC;IACD,OAAO;QACL,UAAU,EAAE,OAAO,CAAC,WAAW,EAAE,KAAK,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO;QACtE,QAAQ,EAAE,EAAE;KACb,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAC/B,KAAqB,EACrB,gBAA4B;IAE5B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC;IAC3D,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,mBAAmB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAGnE,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE;QAC9B,QAAQ;QACR,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,EAAE,EAAE,KAAK,CAAC,EAAE,IAAI,IAAI;QACpB,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI;QAC5B,UAAU;QACV,QAAQ;QACR,KAAK,EAAE,KAAK,CAAC,OAAO;QACpB,SAAS,EAAE,KAAK,CAAC,WAAW,IAAI,IAAI;QACpC,MAAM,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAI;QAC9B,UAAU,EAAE,KAAK,CAAC,YAAY,IAAI,IAAI;QACtC,IAAI,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI;QAC1B,gBAAgB;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI;KACzB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,0BAA0B,CAAC,SAAiB,EAAE,IAAa;IAGlE,OAAO,CAAC,GAAG,CAAC,0BAA0B,EAAE;QACtC,SAAS;QACT,IAAI;KACL,CAAC,CAAC;AACL,CAAC;AASD,SAAgB,gBAAgB,CAAC,KAA4B;IAC3D,MAAM,WAAW,GAAG,IAAA,4BAAc,GAAE,CAAC;IACrC,MAAM,MAAM,GAAG,IAAA,cAAM,EAAmB,IAAI,CAAC,CAAC;IAC9C,MAAM,cAAc,GAAG,IAAA,cAAM,EAC3B,IAAI,GAAG,EAAgD,CACxD,CAAC;IAEF,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAChD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAA0B;QAC1D,MAAM,EAAE,MAAM;KACf,CAAC,CAAC;IAKH,MAAM,iBAAiB,GAAG,IAAA,cAAM,EAAC,IAAI,GAAG,EAAkB,CAAC,CAAC;IAC5D,MAAM,yBAAyB,GAAG,IAAA,cAAM,EAAgB,IAAI,CAAC,CAAC;IAC9D,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,MAAM,GAAG,GAAG,KAAK,CAAC,YAAY,IAAI,IAAI,CAAC;QACvC,IAAI,GAAG,KAAK,yBAAyB,CAAC,OAAO,EAAE,CAAC;YAC9C,iBAAiB,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAClC,yBAAyB,CAAC,OAAO,GAAG,GAAG,CAAC;QAC1C,CAAC;IACH,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;IAEzB,MAAM,gBAAgB,GAAG,IAAA,mBAAW,EAClC,CAAC,QAAiC,EAAQ,EAAE;QAC1C,MAAM,KAAK,GAAG,QAAqC,CAAC;QACpD,MAAM,IAAI,GAAG,kDAA0B,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAChE,wBAAwB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACtC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,KAAK,WAAW,CAAC,iBAAiB,CAAC;gBACjC,QAAQ,EAAE,GAAyB;aACpC,CAAC,CAAC;QACL,CAAC;QACD,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACpD,IAAI,IAAI,EAAE,CAAC;YACT,KAAK,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;gBACtB,IAAI,CAAC;oBACH,EAAE,CAAC,KAAK,CAAC,CAAC;gBACZ,CAAC;gBAAC,MAAM,CAAC;gBAET,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC,EACD,CAAC,WAAW,CAAC,CACd,CAAC;IAEF,MAAM,eAAe,GAAG,IAAA,mBAAW,EACjC,CAAC,SAAiB,EAAE,IAAa,EAAQ,EAAE;QACzC,0BAA0B,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC5C,IAAI,SAAS,KAAK,WAAW,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAClE,MAAM,GAAG,GAAI,IAAmC,CAAC,YAAY,CAAC;YAC9D,QAAQ,CAAC;gBACP,MAAM,EAAE,WAAW;gBACnB,GAAG,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC1D,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YACnC,QAAQ,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;QACvC,CAAC;IACH,CAAC,EACD,EAAE,CACH,CAAC;IAQF,MAAM,uBAAuB,GAAG,IAAA,mBAAW,EACzC,CAAC,SAA6B,EAAQ,EAAE;QACtC,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE;YAChB,IAAI,SAAS,KAAK,QAAQ;gBAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;YACxD,IAAI,SAAS,KAAK,cAAc;gBAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;YACpE,IAAI,SAAS,KAAK,YAAY,EAAE,CAAC;gBAC/B,OAAO,IAAI,CAAC,MAAM,KAAK,WAAW;oBAChC,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE;oBAC5B,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;YAC/B,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,EACD,EAAE,CACH,CAAC;IAEF,MAAM,MAAM,GAAG,IAAA,eAAO,EACpB,GAAG,EAAE,CACH,IAAI,gCAAc,CAAC,KAAK,CAAC,KAAK,EAAE;QAC9B,UAAU,EAAE,GAAG,EAAE;YACf,WAAW,CAAC,IAAI,CAAC,CAAC;YAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;YACnC,MAAM,GAAG,GAAG,IAAI,sBAAS,CACvB;gBACE,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,aAAa,EAAE,KAAK,CAAC,aAAa;gBAClC,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtD,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS;oBAChC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE;oBAClC,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CAAC,KAAK,CAAC,eAAe,KAAK,SAAS;oBACrC,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE;oBAC5C,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CAAC,KAAK,CAAC,cAAc,KAAK,SAAS;oBACpC,CAAC,CAAC,EAAE,cAAc,EAAE,KAAK,CAAC,cAAc,EAAE;oBAC1C,CAAC,CAAC,EAAE,CAAC;aACR,EACD,CAAC,QAAQ,EAAE,EAAE;gBACX,gBAAgB,CAAC,QAAQ,CAAC,CAAC;gBAC3B,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC/B,CAAC,EACD,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE;gBAClB,eAAe,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;gBACjC,MAAM,CAAC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YACxC,CAAC,EACD,GAAG,EAAE;gBACH,IAAI,KAAK,CAAC,QAAQ;oBAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACrC,KAAK,WAAW,CAAC,iBAAiB,EAAE,CAAC;YACvC,CAAC,EACD,SAAS,EACT,uBAAuB,CACxB,CAAC;YACF,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,KAAK,EAAE,CAAC;QACd,CAAC;QACD,SAAS,EAAE,GAAG,EAAE;YACd,WAAW,CAAC,KAAK,CAAC,CAAC;YACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YAC7B,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBACtB,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;YACxB,CAAC;QACH,CAAC;QACD,OAAO,EAAE,gBAAgB;QACzB,SAAS,EAAE,eAAe;KAC3B,CAAC,EAGJ,CAAC,KAAK,CAAC,KAAK,CAAC,CACd,CAAC;IAEF,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,OAAO,GAAG,EAAE;YACV,MAAM,CAAC,IAAI,EAAE,CAAC;YACd,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBACtB,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;YACxB,CAAC;YACD,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QACjC,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,MAAM,KAAK,GAAG,IAAA,eAAO,EACnB,GAAG,EAAE,CAAC,CAAC;QACL,QAAQ;QACR,KAAK;QACL,SAAS,CAAC,SAAS,EAAE,OAAO;YAC1B,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC;YAChE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAClB,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YAC5C,OAAO,GAAG,EAAE;gBACV,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,gBAAgB,CAAC,YAAY,EAAE,KAAK;YACxC,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACxD,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;YAChD,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;gBAEhB,OAAO;YACT,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC;YAC3D,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,IAAI,kBAAkB,CAAC;YAC/C,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,CACrC,cAAc,EACd,YAAY,kBAAkB,CAAC,YAAY,CAAC,gBAAgB,CAC7D,CAAC;YACF,MAAM,KAAK,CAAC,gBAAgB,EAAE;gBAC5B,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,KAAK,EAAE;oBAChC,cAAc,EAAE,kBAAkB;oBAClC,UAAU,EAAE,KAAK,CAAC,KAAK;iBACxB;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC;aAC1D,CAAC,CAAC;QACL,CAAC;QACD,oBAAoB,CAAC,KAAK;YACxB,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACxD,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;gBACjB,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACxC,CAAC;iBAAM,CAAC;gBACN,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;YAClD,CAAC;QAKH,CAAC;KACF,CAAC,EAEF,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,CACpD,CAAC;IAEF,OAAO,CACL,uBAAC,eAAe,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YACnC,KAAK,CAAC,QAAQ,GACU,CAC5B,CAAC;AACJ,CAAC;AAGD,SAAgB,aAAa,CAC3B,SAAiB,EACjB,OAAwC;IAExC,MAAM,GAAG,GAAG,IAAA,kBAAU,EAAC,eAAe,CAAC,CAAC;IACxC,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,OAAO,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,SAAgB,kBAAkB;IAChC,MAAM,GAAG,GAAG,IAAA,kBAAU,EAAC,eAAe,CAAC,CAAC;IACxC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CACb,4DAA4D,CAC7D,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAQD,SAAgB,iBAAiB;IAC/B,MAAM,GAAG,GAAG,IAAA,kBAAU,EAAC,eAAe,CAAC,CAAC;IACxC,OAAO,GAAG,EAAE,KAAK,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC1C,CAAC;AAGD,SAAgB,mBAAmB;IACjC,OAAO,kBAAkB,EAAE,CAAC,QAAQ,CAAC;AACvC,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { CursorStore, type ClientCursorMap } from './cursor-store';
2
+ export interface SseClientOptions {
3
+ url?: string;
4
+ tokenProvider: () => Promise<string> | string;
5
+ orgId: string;
6
+ watchdogMs?: number;
7
+ reconnectBaseMs?: number;
8
+ reconnectMaxMs?: number;
9
+ }
10
+ export type SseEventHandler = (envelope: Record<string, unknown>) => void;
11
+ export type SseControlHandler = (frameType: string, data: unknown) => void;
12
+ export type SseResyncHandler = () => void;
13
+ export type SseTransportStatus = 'connecting' | 'open' | 'reconnecting' | 'closed';
14
+ export type SseStatusHandler = (status: SseTransportStatus) => void;
15
+ export declare class SseClient {
16
+ private readonly options;
17
+ private readonly onEnvelope;
18
+ private readonly onControl;
19
+ private readonly onResync;
20
+ private readonly onStatus?;
21
+ private readonly cursorStore;
22
+ private readonly url;
23
+ private readonly watchdogMs;
24
+ private readonly baseMs;
25
+ private readonly maxMs;
26
+ private abortController;
27
+ private watchdogTimer;
28
+ private reconnectAttempt;
29
+ private stopped;
30
+ constructor(options: SseClientOptions, onEnvelope: SseEventHandler, onControl: SseControlHandler, onResync: SseResyncHandler, cursorStore?: CursorStore, onStatus?: SseStatusHandler | undefined);
31
+ private emitStatus;
32
+ start(): void;
33
+ stop(): void;
34
+ cursors(): ClientCursorMap;
35
+ private connect;
36
+ private handleParsed;
37
+ private captureCursors;
38
+ private captureControlCursors;
39
+ private armWatchdog;
40
+ private clearWatchdog;
41
+ private scheduleReconnect;
42
+ }
43
+ //# sourceMappingURL=sse-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse-client.d.ts","sourceRoot":"","sources":["../../src/lib/sse-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEnE,MAAM,WAAW,gBAAgB;IAE/B,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,aAAa,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IAE9C,KAAK,EAAE,MAAM,CAAC;IAEd,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;AAC1E,MAAM,MAAM,iBAAiB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;AAC3E,MAAM,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC;AAgB1C,MAAM,MAAM,kBAAkB,GAC1B,YAAY,GACZ,MAAM,GACN,cAAc,GACd,QAAQ,CAAC;AAEb,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAapE,qBAAa,SAAS;IAYlB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAEzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAhB5B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,aAAa,CAA8C;IACnE,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,OAAO,CAAS;gBAGL,OAAO,EAAE,gBAAgB,EACzB,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,iBAAiB,EAC5B,QAAQ,EAAE,gBAAgB,EAC3C,WAAW,CAAC,EAAE,WAAW,EACR,QAAQ,CAAC,EAAE,gBAAgB,YAAA;IAS9C,OAAO,CAAC,UAAU;IAKlB,KAAK,IAAI,IAAI;IAMb,IAAI,IAAI,IAAI;IAWZ,OAAO,IAAI,eAAe;YAMZ,OAAO;IA4ErB,OAAO,CAAC,YAAY;IA2DpB,OAAO,CAAC,cAAc;IAoBtB,OAAO,CAAC,qBAAqB;IAc7B,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,iBAAiB;CAS1B"}