tab-bridge 0.1.1 → 0.2.0
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.
- package/README.md +74 -11
- package/dist/{chunk-42VOZR6E.js → chunk-4JDWAUYM.js} +216 -93
- package/dist/{chunk-BQCNBNBT.cjs → chunk-TGEXRVAL.cjs} +219 -92
- package/dist/index.cjs +41 -25
- package/dist/index.d.cts +110 -5
- package/dist/index.d.ts +110 -5
- package/dist/index.js +2 -2
- package/dist/{types-BtK4ixKz.d.cts → instance-5LIItazN.d.cts} +58 -80
- package/dist/{types-BtK4ixKz.d.ts → instance-5LIItazN.d.ts} +58 -80
- package/dist/react/index.cjs +82 -9
- package/dist/react/index.d.cts +47 -2
- package/dist/react/index.d.ts +47 -2
- package/dist/react/index.js +79 -9
- package/package.json +5 -4
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkTGEXRVAL_cjs = require('./chunk-TGEXRVAL.cjs');
|
|
4
4
|
|
|
5
5
|
// src/utils/message.ts
|
|
6
6
|
function createMessage(type, senderId, payload, targetId) {
|
|
@@ -8,8 +8,8 @@ function createMessage(type, senderId, payload, targetId) {
|
|
|
8
8
|
type,
|
|
9
9
|
senderId,
|
|
10
10
|
targetId,
|
|
11
|
-
timestamp:
|
|
12
|
-
version:
|
|
11
|
+
timestamp: chunkTGEXRVAL_cjs.monotonic(),
|
|
12
|
+
version: chunkTGEXRVAL_cjs.PROTOCOL_VERSION,
|
|
13
13
|
payload
|
|
14
14
|
};
|
|
15
15
|
}
|
|
@@ -59,91 +59,107 @@ var Emitter = class {
|
|
|
59
59
|
|
|
60
60
|
Object.defineProperty(exports, "BroadcastChannelTransport", {
|
|
61
61
|
enumerable: true,
|
|
62
|
-
get: function () { return
|
|
62
|
+
get: function () { return chunkTGEXRVAL_cjs.BroadcastChannelTransport; }
|
|
63
63
|
});
|
|
64
64
|
Object.defineProperty(exports, "ErrorCode", {
|
|
65
65
|
enumerable: true,
|
|
66
|
-
get: function () { return
|
|
66
|
+
get: function () { return chunkTGEXRVAL_cjs.ErrorCode; }
|
|
67
67
|
});
|
|
68
68
|
Object.defineProperty(exports, "LeaderElection", {
|
|
69
69
|
enumerable: true,
|
|
70
|
-
get: function () { return
|
|
70
|
+
get: function () { return chunkTGEXRVAL_cjs.LeaderElection; }
|
|
71
71
|
});
|
|
72
72
|
Object.defineProperty(exports, "PROTOCOL_VERSION", {
|
|
73
73
|
enumerable: true,
|
|
74
|
-
get: function () { return
|
|
74
|
+
get: function () { return chunkTGEXRVAL_cjs.PROTOCOL_VERSION; }
|
|
75
75
|
});
|
|
76
76
|
Object.defineProperty(exports, "RPCHandler", {
|
|
77
77
|
enumerable: true,
|
|
78
|
-
get: function () { return
|
|
78
|
+
get: function () { return chunkTGEXRVAL_cjs.RPCHandler; }
|
|
79
79
|
});
|
|
80
80
|
Object.defineProperty(exports, "StateManager", {
|
|
81
81
|
enumerable: true,
|
|
82
|
-
get: function () { return
|
|
82
|
+
get: function () { return chunkTGEXRVAL_cjs.StateManager; }
|
|
83
83
|
});
|
|
84
84
|
Object.defineProperty(exports, "StorageChannel", {
|
|
85
85
|
enumerable: true,
|
|
86
|
-
get: function () { return
|
|
86
|
+
get: function () { return chunkTGEXRVAL_cjs.StorageChannel; }
|
|
87
87
|
});
|
|
88
88
|
Object.defineProperty(exports, "TabRegistry", {
|
|
89
89
|
enumerable: true,
|
|
90
|
-
get: function () { return
|
|
90
|
+
get: function () { return chunkTGEXRVAL_cjs.TabRegistry; }
|
|
91
91
|
});
|
|
92
92
|
Object.defineProperty(exports, "TabSyncError", {
|
|
93
93
|
enumerable: true,
|
|
94
|
-
get: function () { return
|
|
94
|
+
get: function () { return chunkTGEXRVAL_cjs.TabSyncError; }
|
|
95
95
|
});
|
|
96
96
|
Object.defineProperty(exports, "createBatcher", {
|
|
97
97
|
enumerable: true,
|
|
98
|
-
get: function () { return
|
|
98
|
+
get: function () { return chunkTGEXRVAL_cjs.createBatcher; }
|
|
99
99
|
});
|
|
100
100
|
Object.defineProperty(exports, "createChannel", {
|
|
101
101
|
enumerable: true,
|
|
102
|
-
get: function () { return
|
|
102
|
+
get: function () { return chunkTGEXRVAL_cjs.createChannel; }
|
|
103
|
+
});
|
|
104
|
+
Object.defineProperty(exports, "createLogger", {
|
|
105
|
+
enumerable: true,
|
|
106
|
+
get: function () { return chunkTGEXRVAL_cjs.createLogger; }
|
|
107
|
+
});
|
|
108
|
+
Object.defineProperty(exports, "createPersistSaver", {
|
|
109
|
+
enumerable: true,
|
|
110
|
+
get: function () { return chunkTGEXRVAL_cjs.createPersistSaver; }
|
|
103
111
|
});
|
|
104
112
|
Object.defineProperty(exports, "createTabSync", {
|
|
105
113
|
enumerable: true,
|
|
106
|
-
get: function () { return
|
|
114
|
+
get: function () { return chunkTGEXRVAL_cjs.createTabSync; }
|
|
107
115
|
});
|
|
108
116
|
Object.defineProperty(exports, "destroyMiddleware", {
|
|
109
117
|
enumerable: true,
|
|
110
|
-
get: function () { return
|
|
118
|
+
get: function () { return chunkTGEXRVAL_cjs.destroyMiddleware; }
|
|
111
119
|
});
|
|
112
120
|
Object.defineProperty(exports, "generateTabId", {
|
|
113
121
|
enumerable: true,
|
|
114
|
-
get: function () { return
|
|
122
|
+
get: function () { return chunkTGEXRVAL_cjs.generateTabId; }
|
|
115
123
|
});
|
|
116
124
|
Object.defineProperty(exports, "hasBroadcastChannel", {
|
|
117
125
|
enumerable: true,
|
|
118
|
-
get: function () { return
|
|
126
|
+
get: function () { return chunkTGEXRVAL_cjs.hasBroadcastChannel; }
|
|
119
127
|
});
|
|
120
128
|
Object.defineProperty(exports, "hasCrypto", {
|
|
121
129
|
enumerable: true,
|
|
122
|
-
get: function () { return
|
|
130
|
+
get: function () { return chunkTGEXRVAL_cjs.hasCrypto; }
|
|
123
131
|
});
|
|
124
132
|
Object.defineProperty(exports, "hasDocument", {
|
|
125
133
|
enumerable: true,
|
|
126
|
-
get: function () { return
|
|
134
|
+
get: function () { return chunkTGEXRVAL_cjs.hasDocument; }
|
|
127
135
|
});
|
|
128
136
|
Object.defineProperty(exports, "hasLocalStorage", {
|
|
129
137
|
enumerable: true,
|
|
130
|
-
get: function () { return
|
|
138
|
+
get: function () { return chunkTGEXRVAL_cjs.hasLocalStorage; }
|
|
131
139
|
});
|
|
132
140
|
Object.defineProperty(exports, "isBrowser", {
|
|
133
141
|
enumerable: true,
|
|
134
|
-
get: function () { return
|
|
142
|
+
get: function () { return chunkTGEXRVAL_cjs.isBrowser; }
|
|
143
|
+
});
|
|
144
|
+
Object.defineProperty(exports, "loadPersistedState", {
|
|
145
|
+
enumerable: true,
|
|
146
|
+
get: function () { return chunkTGEXRVAL_cjs.loadPersistedState; }
|
|
135
147
|
});
|
|
136
148
|
Object.defineProperty(exports, "monotonic", {
|
|
137
149
|
enumerable: true,
|
|
138
|
-
get: function () { return
|
|
150
|
+
get: function () { return chunkTGEXRVAL_cjs.monotonic; }
|
|
139
151
|
});
|
|
140
152
|
Object.defineProperty(exports, "notifyMiddleware", {
|
|
141
153
|
enumerable: true,
|
|
142
|
-
get: function () { return
|
|
154
|
+
get: function () { return chunkTGEXRVAL_cjs.notifyMiddleware; }
|
|
155
|
+
});
|
|
156
|
+
Object.defineProperty(exports, "resolvePersistOptions", {
|
|
157
|
+
enumerable: true,
|
|
158
|
+
get: function () { return chunkTGEXRVAL_cjs.resolvePersistOptions; }
|
|
143
159
|
});
|
|
144
160
|
Object.defineProperty(exports, "runMiddleware", {
|
|
145
161
|
enumerable: true,
|
|
146
|
-
get: function () { return
|
|
162
|
+
get: function () { return chunkTGEXRVAL_cjs.runMiddleware; }
|
|
147
163
|
});
|
|
148
164
|
exports.Emitter = Emitter;
|
|
149
165
|
exports.createMessage = createMessage;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,90 @@
|
|
|
1
|
-
import { R as RPCMap, T as TabSyncOptions, a as TabSyncInstance,
|
|
2
|
-
export { L as
|
|
1
|
+
import { R as RPCMap, T as TabSyncOptions, a as TabSyncInstance, C as ChangeMeta, b as TabInfo, c as RPCCallAllResult, M as Middleware, d as MiddlewareContext, P as PersistOptions } from './instance-5LIItazN.cjs';
|
|
2
|
+
export { L as LeaderOptions, e as MiddlewareResult, f as RPCArgs, g as RPCResult } from './instance-5LIItazN.cjs';
|
|
3
|
+
|
|
4
|
+
declare const PROTOCOL_VERSION = 1;
|
|
5
|
+
interface StateUpdatePayload {
|
|
6
|
+
entries: Record<string, {
|
|
7
|
+
value: unknown;
|
|
8
|
+
timestamp: number;
|
|
9
|
+
}>;
|
|
10
|
+
}
|
|
11
|
+
interface StateSyncResponsePayload {
|
|
12
|
+
state: Record<string, {
|
|
13
|
+
value: unknown;
|
|
14
|
+
timestamp: number;
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
17
|
+
interface LeaderClaimPayload {
|
|
18
|
+
createdAt: number;
|
|
19
|
+
claimId: string;
|
|
20
|
+
generation: number;
|
|
21
|
+
}
|
|
22
|
+
interface LeaderAckPayload {
|
|
23
|
+
claimId: string;
|
|
24
|
+
generation: number;
|
|
25
|
+
}
|
|
26
|
+
interface TabAnnouncePayload {
|
|
27
|
+
createdAt: number;
|
|
28
|
+
isActive: boolean;
|
|
29
|
+
url: string;
|
|
30
|
+
title?: string;
|
|
31
|
+
}
|
|
32
|
+
interface RpcRequestPayload {
|
|
33
|
+
callId: string;
|
|
34
|
+
method: string;
|
|
35
|
+
args: unknown;
|
|
36
|
+
}
|
|
37
|
+
interface RpcResponsePayload {
|
|
38
|
+
callId: string;
|
|
39
|
+
result?: unknown;
|
|
40
|
+
error?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Maps every message type to its exact payload shape.
|
|
44
|
+
* Adding a new message only requires extending this interface.
|
|
45
|
+
*/
|
|
46
|
+
interface MessagePayloadMap {
|
|
47
|
+
STATE_UPDATE: StateUpdatePayload;
|
|
48
|
+
STATE_SYNC_REQUEST: null;
|
|
49
|
+
STATE_SYNC_RESPONSE: StateSyncResponsePayload;
|
|
50
|
+
LEADER_CLAIM: LeaderClaimPayload;
|
|
51
|
+
LEADER_ACK: LeaderAckPayload;
|
|
52
|
+
LEADER_HEARTBEAT: null;
|
|
53
|
+
LEADER_RESIGN: null;
|
|
54
|
+
TAB_ANNOUNCE: TabAnnouncePayload;
|
|
55
|
+
TAB_GOODBYE: null;
|
|
56
|
+
RPC_REQUEST: RpcRequestPayload;
|
|
57
|
+
RPC_RESPONSE: RpcResponsePayload;
|
|
58
|
+
}
|
|
59
|
+
type MessageType = keyof MessagePayloadMap;
|
|
60
|
+
/**
|
|
61
|
+
* Discriminated union of all inter-tab messages.
|
|
62
|
+
*
|
|
63
|
+
* Checking `msg.type` narrows `msg.payload` to the exact payload type,
|
|
64
|
+
* eliminating the need for runtime casts:
|
|
65
|
+
*
|
|
66
|
+
* ```ts
|
|
67
|
+
* if (msg.type === 'STATE_UPDATE') {
|
|
68
|
+
* msg.payload.entries; // ← StateUpdatePayload, fully typed
|
|
69
|
+
* }
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
type TabMessage = {
|
|
73
|
+
[K in MessageType]: {
|
|
74
|
+
readonly type: K;
|
|
75
|
+
readonly senderId: string;
|
|
76
|
+
readonly targetId?: string;
|
|
77
|
+
readonly timestamp: number;
|
|
78
|
+
readonly version?: number;
|
|
79
|
+
readonly payload: MessagePayloadMap[K];
|
|
80
|
+
};
|
|
81
|
+
}[MessageType];
|
|
82
|
+
/** Extract a single message variant by its type discriminant. */
|
|
83
|
+
type MessageOf<T extends MessageType> = Extract<TabMessage, {
|
|
84
|
+
type: T;
|
|
85
|
+
}>;
|
|
86
|
+
/** Function that sends a message through the transport channel. */
|
|
87
|
+
type SendFn = (message: TabMessage) => void;
|
|
3
88
|
|
|
4
89
|
declare function createTabSync<TState extends Record<string, unknown> = Record<string, unknown>, TRPCMap extends RPCMap = RPCMap>(options?: TabSyncOptions<TState>): TabSyncInstance<TState, TRPCMap>;
|
|
5
90
|
|
|
@@ -8,7 +93,7 @@ interface Channel {
|
|
|
8
93
|
onMessage(callback: (message: TabMessage) => void): () => void;
|
|
9
94
|
close(): void;
|
|
10
95
|
}
|
|
11
|
-
declare function createChannel(channelName: string, transport?: 'broadcast-channel' | 'local-storage'): Channel;
|
|
96
|
+
declare function createChannel(channelName: string, transport?: 'broadcast-channel' | 'local-storage', onError?: (error: Error) => void): Channel;
|
|
12
97
|
|
|
13
98
|
declare class BroadcastChannelTransport implements Channel {
|
|
14
99
|
private bc;
|
|
@@ -31,9 +116,10 @@ declare class BroadcastChannelTransport implements Channel {
|
|
|
31
116
|
declare class StorageChannel implements Channel {
|
|
32
117
|
private readonly key;
|
|
33
118
|
private readonly listeners;
|
|
119
|
+
private readonly onError?;
|
|
34
120
|
private closed;
|
|
35
121
|
private seq;
|
|
36
|
-
constructor(channelName: string);
|
|
122
|
+
constructor(channelName: string, onError?: (error: Error) => void);
|
|
37
123
|
postMessage(message: TabMessage): void;
|
|
38
124
|
onMessage(callback: (message: TabMessage) => void): () => void;
|
|
39
125
|
close(): void;
|
|
@@ -158,6 +244,8 @@ declare class LeaderElection {
|
|
|
158
244
|
private leaderWatchTimer;
|
|
159
245
|
private lastLeaderHeartbeat;
|
|
160
246
|
private electing;
|
|
247
|
+
private generation;
|
|
248
|
+
private currentClaimId;
|
|
161
249
|
private readonly leaderCallbacks;
|
|
162
250
|
private readonly leaderCleanups;
|
|
163
251
|
constructor(options: LeaderElectionOptions);
|
|
@@ -191,17 +279,20 @@ interface RPCHandlerOptions {
|
|
|
191
279
|
send: SendFn;
|
|
192
280
|
tabId: string;
|
|
193
281
|
resolveLeaderId?: () => string | null;
|
|
282
|
+
resolveTabIds?: () => string[];
|
|
194
283
|
onError?: (error: Error) => void;
|
|
195
284
|
}
|
|
196
285
|
declare class RPCHandler {
|
|
197
286
|
private readonly send;
|
|
198
287
|
private readonly tabId;
|
|
199
288
|
private readonly resolveLeaderId;
|
|
289
|
+
private readonly resolveTabIds;
|
|
200
290
|
private readonly onError;
|
|
201
291
|
private readonly handlers;
|
|
202
292
|
private readonly pending;
|
|
203
293
|
constructor(options: RPCHandlerOptions);
|
|
204
294
|
call<TResult>(targetTabId: string | 'leader', method: string, args?: unknown, timeout?: number): Promise<TResult>;
|
|
295
|
+
callAll<TResult>(method: string, args?: unknown, timeout?: number): Promise<RPCCallAllResult<TResult>[]>;
|
|
205
296
|
handle<TArgs = unknown, TResult = unknown>(method: string, handler: (args: TArgs, callerTabId: string) => TResult | Promise<TResult>): () => void;
|
|
206
297
|
handleMessage(message: TabMessage): void;
|
|
207
298
|
destroy(): void;
|
|
@@ -223,6 +314,15 @@ declare function notifyMiddleware<TState extends Record<string, unknown>>(middle
|
|
|
223
314
|
/** Destroy all middlewares. */
|
|
224
315
|
declare function destroyMiddleware<TState extends Record<string, unknown>>(middlewares: readonly Middleware<TState>[]): void;
|
|
225
316
|
|
|
317
|
+
declare function resolvePersistOptions<TState extends Record<string, unknown>>(opt: PersistOptions<TState> | boolean | undefined): PersistOptions<TState> | null;
|
|
318
|
+
declare function loadPersistedState<TState extends Record<string, unknown>>(opts: PersistOptions<TState>): Partial<TState>;
|
|
319
|
+
interface PersistSaver<TState extends Record<string, unknown>> {
|
|
320
|
+
save: (state: Readonly<TState>) => void;
|
|
321
|
+
flush: () => void;
|
|
322
|
+
destroy: () => void;
|
|
323
|
+
}
|
|
324
|
+
declare function createPersistSaver<TState extends Record<string, unknown>>(opts: PersistOptions<TState>, onError: (e: Error) => void): PersistSaver<TState>;
|
|
325
|
+
|
|
226
326
|
declare function generateTabId(): string;
|
|
227
327
|
|
|
228
328
|
declare function monotonic(): number;
|
|
@@ -301,4 +401,9 @@ declare const hasLocalStorage: boolean;
|
|
|
301
401
|
declare const hasBroadcastChannel: boolean;
|
|
302
402
|
declare const hasCrypto: boolean;
|
|
303
403
|
|
|
304
|
-
|
|
404
|
+
interface Logger {
|
|
405
|
+
log: (label: string, ...args: unknown[]) => void;
|
|
406
|
+
}
|
|
407
|
+
declare function createLogger(enabled: boolean, tabId: string): Logger;
|
|
408
|
+
|
|
409
|
+
export { type Batcher, BroadcastChannelTransport, ChangeMeta, type Channel, Emitter, ErrorCode, type LeaderAckPayload, type LeaderClaimPayload, LeaderElection, type LeaderElectionOptions, type Logger, type MessageOf, type MessagePayloadMap, type MessageType, Middleware, MiddlewareContext, PROTOCOL_VERSION, PersistOptions, type PersistSaver, RPCCallAllResult, RPCHandler, type RPCHandlerOptions, RPCMap, type RpcRequestPayload, type RpcResponsePayload, type SendFn, StateManager, type StateManagerOptions, type StateSyncResponsePayload, type StateUpdatePayload, StorageChannel, type TabAnnouncePayload, TabInfo, type TabMessage, TabRegistry, type TabRegistryOptions, TabSyncError, TabSyncInstance, TabSyncOptions, createBatcher, createChannel, createLogger, createMessage, createPersistSaver, createTabSync, destroyMiddleware, generateTabId, hasBroadcastChannel, hasCrypto, hasDocument, hasLocalStorage, isBrowser, loadPersistedState, monotonic, notifyMiddleware, resolvePersistOptions, runMiddleware };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,90 @@
|
|
|
1
|
-
import { R as RPCMap, T as TabSyncOptions, a as TabSyncInstance,
|
|
2
|
-
export { L as
|
|
1
|
+
import { R as RPCMap, T as TabSyncOptions, a as TabSyncInstance, C as ChangeMeta, b as TabInfo, c as RPCCallAllResult, M as Middleware, d as MiddlewareContext, P as PersistOptions } from './instance-5LIItazN.js';
|
|
2
|
+
export { L as LeaderOptions, e as MiddlewareResult, f as RPCArgs, g as RPCResult } from './instance-5LIItazN.js';
|
|
3
|
+
|
|
4
|
+
declare const PROTOCOL_VERSION = 1;
|
|
5
|
+
interface StateUpdatePayload {
|
|
6
|
+
entries: Record<string, {
|
|
7
|
+
value: unknown;
|
|
8
|
+
timestamp: number;
|
|
9
|
+
}>;
|
|
10
|
+
}
|
|
11
|
+
interface StateSyncResponsePayload {
|
|
12
|
+
state: Record<string, {
|
|
13
|
+
value: unknown;
|
|
14
|
+
timestamp: number;
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
17
|
+
interface LeaderClaimPayload {
|
|
18
|
+
createdAt: number;
|
|
19
|
+
claimId: string;
|
|
20
|
+
generation: number;
|
|
21
|
+
}
|
|
22
|
+
interface LeaderAckPayload {
|
|
23
|
+
claimId: string;
|
|
24
|
+
generation: number;
|
|
25
|
+
}
|
|
26
|
+
interface TabAnnouncePayload {
|
|
27
|
+
createdAt: number;
|
|
28
|
+
isActive: boolean;
|
|
29
|
+
url: string;
|
|
30
|
+
title?: string;
|
|
31
|
+
}
|
|
32
|
+
interface RpcRequestPayload {
|
|
33
|
+
callId: string;
|
|
34
|
+
method: string;
|
|
35
|
+
args: unknown;
|
|
36
|
+
}
|
|
37
|
+
interface RpcResponsePayload {
|
|
38
|
+
callId: string;
|
|
39
|
+
result?: unknown;
|
|
40
|
+
error?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Maps every message type to its exact payload shape.
|
|
44
|
+
* Adding a new message only requires extending this interface.
|
|
45
|
+
*/
|
|
46
|
+
interface MessagePayloadMap {
|
|
47
|
+
STATE_UPDATE: StateUpdatePayload;
|
|
48
|
+
STATE_SYNC_REQUEST: null;
|
|
49
|
+
STATE_SYNC_RESPONSE: StateSyncResponsePayload;
|
|
50
|
+
LEADER_CLAIM: LeaderClaimPayload;
|
|
51
|
+
LEADER_ACK: LeaderAckPayload;
|
|
52
|
+
LEADER_HEARTBEAT: null;
|
|
53
|
+
LEADER_RESIGN: null;
|
|
54
|
+
TAB_ANNOUNCE: TabAnnouncePayload;
|
|
55
|
+
TAB_GOODBYE: null;
|
|
56
|
+
RPC_REQUEST: RpcRequestPayload;
|
|
57
|
+
RPC_RESPONSE: RpcResponsePayload;
|
|
58
|
+
}
|
|
59
|
+
type MessageType = keyof MessagePayloadMap;
|
|
60
|
+
/**
|
|
61
|
+
* Discriminated union of all inter-tab messages.
|
|
62
|
+
*
|
|
63
|
+
* Checking `msg.type` narrows `msg.payload` to the exact payload type,
|
|
64
|
+
* eliminating the need for runtime casts:
|
|
65
|
+
*
|
|
66
|
+
* ```ts
|
|
67
|
+
* if (msg.type === 'STATE_UPDATE') {
|
|
68
|
+
* msg.payload.entries; // ← StateUpdatePayload, fully typed
|
|
69
|
+
* }
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
type TabMessage = {
|
|
73
|
+
[K in MessageType]: {
|
|
74
|
+
readonly type: K;
|
|
75
|
+
readonly senderId: string;
|
|
76
|
+
readonly targetId?: string;
|
|
77
|
+
readonly timestamp: number;
|
|
78
|
+
readonly version?: number;
|
|
79
|
+
readonly payload: MessagePayloadMap[K];
|
|
80
|
+
};
|
|
81
|
+
}[MessageType];
|
|
82
|
+
/** Extract a single message variant by its type discriminant. */
|
|
83
|
+
type MessageOf<T extends MessageType> = Extract<TabMessage, {
|
|
84
|
+
type: T;
|
|
85
|
+
}>;
|
|
86
|
+
/** Function that sends a message through the transport channel. */
|
|
87
|
+
type SendFn = (message: TabMessage) => void;
|
|
3
88
|
|
|
4
89
|
declare function createTabSync<TState extends Record<string, unknown> = Record<string, unknown>, TRPCMap extends RPCMap = RPCMap>(options?: TabSyncOptions<TState>): TabSyncInstance<TState, TRPCMap>;
|
|
5
90
|
|
|
@@ -8,7 +93,7 @@ interface Channel {
|
|
|
8
93
|
onMessage(callback: (message: TabMessage) => void): () => void;
|
|
9
94
|
close(): void;
|
|
10
95
|
}
|
|
11
|
-
declare function createChannel(channelName: string, transport?: 'broadcast-channel' | 'local-storage'): Channel;
|
|
96
|
+
declare function createChannel(channelName: string, transport?: 'broadcast-channel' | 'local-storage', onError?: (error: Error) => void): Channel;
|
|
12
97
|
|
|
13
98
|
declare class BroadcastChannelTransport implements Channel {
|
|
14
99
|
private bc;
|
|
@@ -31,9 +116,10 @@ declare class BroadcastChannelTransport implements Channel {
|
|
|
31
116
|
declare class StorageChannel implements Channel {
|
|
32
117
|
private readonly key;
|
|
33
118
|
private readonly listeners;
|
|
119
|
+
private readonly onError?;
|
|
34
120
|
private closed;
|
|
35
121
|
private seq;
|
|
36
|
-
constructor(channelName: string);
|
|
122
|
+
constructor(channelName: string, onError?: (error: Error) => void);
|
|
37
123
|
postMessage(message: TabMessage): void;
|
|
38
124
|
onMessage(callback: (message: TabMessage) => void): () => void;
|
|
39
125
|
close(): void;
|
|
@@ -158,6 +244,8 @@ declare class LeaderElection {
|
|
|
158
244
|
private leaderWatchTimer;
|
|
159
245
|
private lastLeaderHeartbeat;
|
|
160
246
|
private electing;
|
|
247
|
+
private generation;
|
|
248
|
+
private currentClaimId;
|
|
161
249
|
private readonly leaderCallbacks;
|
|
162
250
|
private readonly leaderCleanups;
|
|
163
251
|
constructor(options: LeaderElectionOptions);
|
|
@@ -191,17 +279,20 @@ interface RPCHandlerOptions {
|
|
|
191
279
|
send: SendFn;
|
|
192
280
|
tabId: string;
|
|
193
281
|
resolveLeaderId?: () => string | null;
|
|
282
|
+
resolveTabIds?: () => string[];
|
|
194
283
|
onError?: (error: Error) => void;
|
|
195
284
|
}
|
|
196
285
|
declare class RPCHandler {
|
|
197
286
|
private readonly send;
|
|
198
287
|
private readonly tabId;
|
|
199
288
|
private readonly resolveLeaderId;
|
|
289
|
+
private readonly resolveTabIds;
|
|
200
290
|
private readonly onError;
|
|
201
291
|
private readonly handlers;
|
|
202
292
|
private readonly pending;
|
|
203
293
|
constructor(options: RPCHandlerOptions);
|
|
204
294
|
call<TResult>(targetTabId: string | 'leader', method: string, args?: unknown, timeout?: number): Promise<TResult>;
|
|
295
|
+
callAll<TResult>(method: string, args?: unknown, timeout?: number): Promise<RPCCallAllResult<TResult>[]>;
|
|
205
296
|
handle<TArgs = unknown, TResult = unknown>(method: string, handler: (args: TArgs, callerTabId: string) => TResult | Promise<TResult>): () => void;
|
|
206
297
|
handleMessage(message: TabMessage): void;
|
|
207
298
|
destroy(): void;
|
|
@@ -223,6 +314,15 @@ declare function notifyMiddleware<TState extends Record<string, unknown>>(middle
|
|
|
223
314
|
/** Destroy all middlewares. */
|
|
224
315
|
declare function destroyMiddleware<TState extends Record<string, unknown>>(middlewares: readonly Middleware<TState>[]): void;
|
|
225
316
|
|
|
317
|
+
declare function resolvePersistOptions<TState extends Record<string, unknown>>(opt: PersistOptions<TState> | boolean | undefined): PersistOptions<TState> | null;
|
|
318
|
+
declare function loadPersistedState<TState extends Record<string, unknown>>(opts: PersistOptions<TState>): Partial<TState>;
|
|
319
|
+
interface PersistSaver<TState extends Record<string, unknown>> {
|
|
320
|
+
save: (state: Readonly<TState>) => void;
|
|
321
|
+
flush: () => void;
|
|
322
|
+
destroy: () => void;
|
|
323
|
+
}
|
|
324
|
+
declare function createPersistSaver<TState extends Record<string, unknown>>(opts: PersistOptions<TState>, onError: (e: Error) => void): PersistSaver<TState>;
|
|
325
|
+
|
|
226
326
|
declare function generateTabId(): string;
|
|
227
327
|
|
|
228
328
|
declare function monotonic(): number;
|
|
@@ -301,4 +401,9 @@ declare const hasLocalStorage: boolean;
|
|
|
301
401
|
declare const hasBroadcastChannel: boolean;
|
|
302
402
|
declare const hasCrypto: boolean;
|
|
303
403
|
|
|
304
|
-
|
|
404
|
+
interface Logger {
|
|
405
|
+
log: (label: string, ...args: unknown[]) => void;
|
|
406
|
+
}
|
|
407
|
+
declare function createLogger(enabled: boolean, tabId: string): Logger;
|
|
408
|
+
|
|
409
|
+
export { type Batcher, BroadcastChannelTransport, ChangeMeta, type Channel, Emitter, ErrorCode, type LeaderAckPayload, type LeaderClaimPayload, LeaderElection, type LeaderElectionOptions, type Logger, type MessageOf, type MessagePayloadMap, type MessageType, Middleware, MiddlewareContext, PROTOCOL_VERSION, PersistOptions, type PersistSaver, RPCCallAllResult, RPCHandler, type RPCHandlerOptions, RPCMap, type RpcRequestPayload, type RpcResponsePayload, type SendFn, StateManager, type StateManagerOptions, type StateSyncResponsePayload, type StateUpdatePayload, StorageChannel, type TabAnnouncePayload, TabInfo, type TabMessage, TabRegistry, type TabRegistryOptions, TabSyncError, TabSyncInstance, TabSyncOptions, createBatcher, createChannel, createLogger, createMessage, createPersistSaver, createTabSync, destroyMiddleware, generateTabId, hasBroadcastChannel, hasCrypto, hasDocument, hasLocalStorage, isBrowser, loadPersistedState, monotonic, notifyMiddleware, resolvePersistOptions, runMiddleware };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PROTOCOL_VERSION, monotonic } from './chunk-
|
|
2
|
-
export { BroadcastChannelTransport, ErrorCode, LeaderElection, PROTOCOL_VERSION, RPCHandler, StateManager, StorageChannel, TabRegistry, TabSyncError, createBatcher, createChannel, createTabSync, destroyMiddleware, generateTabId, hasBroadcastChannel, hasCrypto, hasDocument, hasLocalStorage, isBrowser, monotonic, notifyMiddleware, runMiddleware } from './chunk-
|
|
1
|
+
import { PROTOCOL_VERSION, monotonic } from './chunk-4JDWAUYM.js';
|
|
2
|
+
export { BroadcastChannelTransport, ErrorCode, LeaderElection, PROTOCOL_VERSION, RPCHandler, StateManager, StorageChannel, TabRegistry, TabSyncError, createBatcher, createChannel, createLogger, createPersistSaver, createTabSync, destroyMiddleware, generateTabId, hasBroadcastChannel, hasCrypto, hasDocument, hasLocalStorage, isBrowser, loadPersistedState, monotonic, notifyMiddleware, resolvePersistOptions, runMiddleware } from './chunk-4JDWAUYM.js';
|
|
3
3
|
|
|
4
4
|
// src/utils/message.ts
|
|
5
5
|
function createMessage(type, senderId, payload, targetId) {
|