tab-bridge 0.1.0 → 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.
- package/README.md +6 -101
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,16 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
<br />
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
graph LR
|
|
27
|
-
A["<b>Tab A</b><br/>👑 Leader"] <-->|"realtime sync"| B["<b>Tab B</b><br/>Follower"]
|
|
28
|
-
B <-->|"realtime sync"| C["<b>Tab C</b><br/>Follower"]
|
|
29
|
-
A <-->|"realtime sync"| C
|
|
30
|
-
|
|
31
|
-
style A fill:#4f46e5,stroke:#4338ca,color:#fff,stroke-width:2px
|
|
32
|
-
style B fill:#6366f1,stroke:#4f46e5,color:#fff,stroke-width:2px
|
|
33
|
-
style C fill:#6366f1,stroke:#4f46e5,color:#fff,stroke-width:2px
|
|
34
|
-
```
|
|
25
|
+
<img src="https://mermaid.ink/img/Z3JhcGggTFIKICAgIEFbIlRhYiBBXG7wn5GRIExlYWRlciJdIDwtLT58InJlYWx0aW1lIHN5bmMifCBCWyJUYWIgQlxuRm9sbG93ZXIiXQogICAgQiA8LS0-fCJyZWFsdGltZSBzeW5jInwgQ1siVGFiIENcbkZvbGxvd2VyIl0KICAgIEEgPC0tPnwicmVhbHRpbWUgc3luYyJ8IEMKICAgIHN0eWxlIEEgZmlsbDojNGY0NmU1LHN0cm9rZTojNDMzOGNhLGNvbG9yOiNmZmYsc3Ryb2tlLXdpZHRoOjJweAogICAgc3R5bGUgQiBmaWxsOiM2MzY2ZjEsc3Ryb2tlOiM0ZjQ2ZTUsY29sb3I6I2ZmZixzdHJva2Utd2lkdGg6MnB4CiAgICBzdHlsZSBDIGZpbGw6IzYzNjZmMSxzdHJva2U6IzRmNDZlNSxjb2xvcjojZmZmLHN0cm9rZS13aWR0aDoycHg?theme=dark&bgColor=0d1117" alt="tab-bridge sync diagram" />
|
|
35
26
|
|
|
36
27
|
<br />
|
|
37
28
|
|
|
@@ -328,19 +319,7 @@ const sync = createTabSync({
|
|
|
328
319
|
});
|
|
329
320
|
```
|
|
330
321
|
|
|
331
|
-
|
|
332
|
-
graph LR
|
|
333
|
-
A["set('age', -5)"] --> B{Middleware<br/>Pipeline}
|
|
334
|
-
B -->|"age < 0 → reject"| C["❌ Blocked"]
|
|
335
|
-
D["set('name', ' Alice ')"] --> B
|
|
336
|
-
B -->|"trim()"| E["✅ 'Alice'"]
|
|
337
|
-
|
|
338
|
-
style A fill:#f59e0b,stroke:#d97706,color:#fff
|
|
339
|
-
style D fill:#f59e0b,stroke:#d97706,color:#fff
|
|
340
|
-
style B fill:#6366f1,stroke:#4f46e5,color:#fff
|
|
341
|
-
style C fill:#ef4444,stroke:#dc2626,color:#fff
|
|
342
|
-
style E fill:#22c55e,stroke:#16a34a,color:#fff
|
|
343
|
-
```
|
|
322
|
+
<img src="https://mermaid.ink/img/Z3JhcGggTFIKICAgIEFbInNldChhZ2UsIC01KSJdIC0tPiBCe01pZGRsZXdhcmUgUGlwZWxpbmV9CiAgICBCIC0tPnwiYWdlIDwgMCByZWplY3QifCBDWyJCbG9ja2VkIl0KICAgIERbInNldChuYW1lLCBBbGljZSkiXSAtLT4gQgogICAgQiAtLT58InRyaW0ifCBFWyJBbGljZSJdCiAgICBzdHlsZSBBIGZpbGw6I2Y1OWUwYixzdHJva2U6I2Q5NzcwNixjb2xvcjojZmZmCiAgICBzdHlsZSBEIGZpbGw6I2Y1OWUwYixzdHJva2U6I2Q5NzcwNixjb2xvcjojZmZmCiAgICBzdHlsZSBCIGZpbGw6IzYzNjZmMSxzdHJva2U6IzRmNDZlNSxjb2xvcjojZmZmCiAgICBzdHlsZSBDIGZpbGw6I2VmNDQ0NCxzdHJva2U6I2RjMjYyNixjb2xvcjojZmZmCiAgICBzdHlsZSBFIGZpbGw6IzIyYzU1ZSxzdHJva2U6IzE2YTM0YSxjb2xvcjojZmZm?theme=dark&bgColor=0d1117" alt="middleware pipeline diagram" />
|
|
344
323
|
|
|
345
324
|
<br />
|
|
346
325
|
|
|
@@ -505,42 +484,7 @@ createTabSync({ onError: (err) => Sentry.captureException(err) });
|
|
|
505
484
|
|
|
506
485
|
<div align="center">
|
|
507
486
|
|
|
508
|
-
|
|
509
|
-
graph TB
|
|
510
|
-
subgraph API["🔌 Public API — createTabSync()"]
|
|
511
|
-
SM["📊 State Manager<br/><i>get / set / patch / subscribe</i>"]
|
|
512
|
-
LE["👑 Leader Election<br/><i>heartbeat / failover / resign</i>"]
|
|
513
|
-
RPC["📡 RPC Handler<br/><i>call / handle / timeout</i>"]
|
|
514
|
-
end
|
|
515
|
-
|
|
516
|
-
subgraph CORE["⚙️ Core Layer"]
|
|
517
|
-
TR["📋 Tab Registry<br/><i>tracks all active tabs</i>"]
|
|
518
|
-
MW["🛡️ Middleware Pipeline<br/><i>intercept → validate → transform → apply</i>"]
|
|
519
|
-
end
|
|
520
|
-
|
|
521
|
-
subgraph TRANSPORT["📡 Transport Layer — auto-detect"]
|
|
522
|
-
BC["⚡ BroadcastChannel<br/><i>primary, fast</i>"]
|
|
523
|
-
LS["💾 localStorage<br/><i>fallback</i>"]
|
|
524
|
-
end
|
|
525
|
-
|
|
526
|
-
SM --> TR
|
|
527
|
-
LE --> TR
|
|
528
|
-
RPC --> TR
|
|
529
|
-
TR --> MW
|
|
530
|
-
MW --> BC
|
|
531
|
-
MW --> LS
|
|
532
|
-
|
|
533
|
-
style API fill:#4f46e5,stroke:#4338ca,color:#fff,stroke-width:2px
|
|
534
|
-
style CORE fill:#7c3aed,stroke:#6d28d9,color:#fff,stroke-width:2px
|
|
535
|
-
style TRANSPORT fill:#2563eb,stroke:#1d4ed8,color:#fff,stroke-width:2px
|
|
536
|
-
style SM fill:#6366f1,stroke:#4f46e5,color:#fff
|
|
537
|
-
style LE fill:#6366f1,stroke:#4f46e5,color:#fff
|
|
538
|
-
style RPC fill:#6366f1,stroke:#4f46e5,color:#fff
|
|
539
|
-
style TR fill:#8b5cf6,stroke:#7c3aed,color:#fff
|
|
540
|
-
style MW fill:#8b5cf6,stroke:#7c3aed,color:#fff
|
|
541
|
-
style BC fill:#3b82f6,stroke:#2563eb,color:#fff
|
|
542
|
-
style LS fill:#3b82f6,stroke:#2563eb,color:#fff
|
|
543
|
-
```
|
|
487
|
+
<img src="https://mermaid.ink/img/Z3JhcGggVEIKICAgIHN1YmdyYXBoIEFQSVsiUHVibGljIEFQSSAtIGNyZWF0ZVRhYlN5bmMiXQogICAgICAgIFNNWyJTdGF0ZSBNYW5hZ2VyIl0KICAgICAgICBMRVsiTGVhZGVyIEVsZWN0aW9uIl0KICAgICAgICBSUENbIlJQQyBIYW5kbGVyIl0KICAgIGVuZAogICAgc3ViZ3JhcGggQ09SRVsiQ29yZSBMYXllciJdCiAgICAgICAgVFJbIlRhYiBSZWdpc3RyeSJdCiAgICAgICAgTVdbIk1pZGRsZXdhcmUgUGlwZWxpbmUiXQogICAgZW5kCiAgICBzdWJncmFwaCBUUkFOU1BPUlRbIlRyYW5zcG9ydCBMYXllciJdCiAgICAgICAgQkNbIkJyb2FkY2FzdENoYW5uZWwiXQogICAgICAgIExTWyJsb2NhbFN0b3JhZ2UiXQogICAgZW5kCiAgICBTTSAtLT4gVFIKICAgIExFIC0tPiBUUgogICAgUlBDIC0tPiBUUgogICAgVFIgLS0-IE1XCiAgICBNVyAtLT4gQkMKICAgIE1XIC0tPiBMUwogICAgc3R5bGUgQVBJIGZpbGw6IzRmNDZlNSxzdHJva2U6IzQzMzhjYSxjb2xvcjojZmZmLHN0cm9rZS13aWR0aDoycHgKICAgIHN0eWxlIENPUkUgZmlsbDojN2MzYWVkLHN0cm9rZTojNmQyOGQ5LGNvbG9yOiNmZmYsc3Ryb2tlLXdpZHRoOjJweAogICAgc3R5bGUgVFJBTlNQT1JUIGZpbGw6IzI1NjNlYixzdHJva2U6IzFkNGVkOCxjb2xvcjojZmZmLHN0cm9rZS13aWR0aDoycHg?theme=dark&bgColor=0d1117" alt="architecture diagram" />
|
|
544
488
|
|
|
545
489
|
</div>
|
|
546
490
|
|
|
@@ -548,40 +492,11 @@ graph TB
|
|
|
548
492
|
|
|
549
493
|
### How State Sync Works
|
|
550
494
|
|
|
551
|
-
|
|
552
|
-
sequenceDiagram
|
|
553
|
-
participant A as Tab A (Leader 👑)
|
|
554
|
-
participant BC as BroadcastChannel
|
|
555
|
-
participant B as Tab B
|
|
556
|
-
participant C as Tab C
|
|
557
|
-
|
|
558
|
-
A->>A: set('theme', 'dark')
|
|
559
|
-
Note over A: Local state updated instantly
|
|
560
|
-
A->>BC: STATE_UPDATE { theme: 'dark' }
|
|
561
|
-
BC-->>B:
|
|
562
|
-
BC-->>C:
|
|
563
|
-
B->>B: Apply state + notify subscribers
|
|
564
|
-
C->>C: Apply state + notify subscribers
|
|
565
|
-
```
|
|
495
|
+
<img src="https://mermaid.ink/img/c2VxdWVuY2VEaWFncmFtCiAgICBwYXJ0aWNpcGFudCBBIGFzIFRhYiBBIExlYWRlcgogICAgcGFydGljaXBhbnQgQkMgYXMgQnJvYWRjYXN0Q2hhbm5lbAogICAgcGFydGljaXBhbnQgQiBhcyBUYWIgQgogICAgcGFydGljaXBhbnQgQyBhcyBUYWIgQwogICAgQS0-PkE6IHNldCB0aGVtZSBkYXJrCiAgICBOb3RlIG92ZXIgQTogTG9jYWwgc3RhdGUgdXBkYXRlZAogICAgQS0-PkJDOiBTVEFURV9VUERBVEUKICAgIEJDLS0-PkI6IG1lc3NhZ2UKICAgIEJDLS0-PkM6IG1lc3NhZ2UKICAgIEItPj5COiBBcHBseSArIG5vdGlmeQogICAgQy0-PkM6IEFwcGx5ICsgbm90aWZ5?theme=dark&bgColor=0d1117" alt="state sync sequence diagram" />
|
|
566
496
|
|
|
567
497
|
### How Leader Election Works
|
|
568
498
|
|
|
569
|
-
|
|
570
|
-
sequenceDiagram
|
|
571
|
-
participant A as Tab A (oldest)
|
|
572
|
-
participant B as Tab B
|
|
573
|
-
participant C as Tab C (newest)
|
|
574
|
-
|
|
575
|
-
Note over A,C: Leader (Tab A) closes...
|
|
576
|
-
A--xB: ❌ Heartbeat stops
|
|
577
|
-
B->>B: 3 missed heartbeats → leader dead
|
|
578
|
-
B->>C: LEADER_CLAIM
|
|
579
|
-
C->>C: Tab B is older → yield
|
|
580
|
-
Note over B: Waits 300ms for higher-priority claims
|
|
581
|
-
B->>C: LEADER_ACK
|
|
582
|
-
Note over B: 👑 Tab B is now leader
|
|
583
|
-
B->>C: LEADER_HEARTBEAT (every 2s)
|
|
584
|
-
```
|
|
499
|
+
<img src="https://mermaid.ink/img/c2VxdWVuY2VEaWFncmFtCiAgICBwYXJ0aWNpcGFudCBBIGFzIFRhYiBBIG9sZGVzdAogICAgcGFydGljaXBhbnQgQiBhcyBUYWIgQgogICAgcGFydGljaXBhbnQgQyBhcyBUYWIgQyBuZXdlc3QKICAgIE5vdGUgb3ZlciBBLEM6IExlYWRlciBUYWIgQSBjbG9zZXMKICAgIEItPj5COiAzIG1pc3NlZCBoZWFydGJlYXRzCiAgICBCLT4-QzogTEVBREVSX0NMQUlNCiAgICBDLT4-QzogVGFiIEIgaXMgb2xkZXIgeWllbGQKICAgIE5vdGUgb3ZlciBCOiBXYWl0IDMwMG1zCiAgICBCLT4-QzogTEVBREVSX0FDSwogICAgTm90ZSBvdmVyIEI6IFRhYiBCIGlzIG5vdyBsZWFkZXIKICAgIEItPj5DOiBMRUFERVJfSEVBUlRCRUFU?theme=dark&bgColor=0d1117" alt="leader election sequence diagram" />
|
|
585
500
|
|
|
586
501
|
<br />
|
|
587
502
|
|
|
@@ -692,17 +607,7 @@ function logout() {
|
|
|
692
607
|
|
|
693
608
|
<br />
|
|
694
609
|
|
|
695
|
-
|
|
696
|
-
graph LR
|
|
697
|
-
Server["🖥️ Server"] <-->|WebSocket| A["Tab A<br/>👑 Leader"]
|
|
698
|
-
A -->|"state sync"| B["Tab B"]
|
|
699
|
-
A -->|"state sync"| C["Tab C"]
|
|
700
|
-
|
|
701
|
-
style Server fill:#059669,stroke:#047857,color:#fff
|
|
702
|
-
style A fill:#4f46e5,stroke:#4338ca,color:#fff
|
|
703
|
-
style B fill:#6366f1,stroke:#4f46e5,color:#fff
|
|
704
|
-
style C fill:#6366f1,stroke:#4f46e5,color:#fff
|
|
705
|
-
```
|
|
610
|
+
<img src="https://mermaid.ink/img/Z3JhcGggTFIKICAgIFNlcnZlclsiU2VydmVyIl0gPC0tPnxXZWJTb2NrZXR8IEFbIlRhYiBBIExlYWRlciJdCiAgICBBIC0tPnxzdGF0ZSBzeW5jfCBCWyJUYWIgQiJdCiAgICBBIC0tPnxzdGF0ZSBzeW5jfCBDWyJUYWIgQyJdCiAgICBzdHlsZSBTZXJ2ZXIgZmlsbDojMDU5NjY5LHN0cm9rZTojMDQ3ODU3LGNvbG9yOiNmZmYKICAgIHN0eWxlIEEgZmlsbDojNGY0NmU1LHN0cm9rZTojNDMzOGNhLGNvbG9yOiNmZmYKICAgIHN0eWxlIEIgZmlsbDojNjM2NmYxLHN0cm9rZTojNGY0NmU1LGNvbG9yOiNmZmYKICAgIHN0eWxlIEMgZmlsbDojNjM2NmYxLHN0cm9rZTojNGY0NmU1LGNvbG9yOiNmZmY?theme=dark&bgColor=0d1117" alt="websocket leader pattern diagram" />
|
|
706
611
|
|
|
707
612
|
```ts
|
|
708
613
|
const sync = createTabSync({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tab-bridge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Zero-dependency TypeScript library for real-time state synchronization across browser tabs, with leader election and cross-tab RPC",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|