signal-bridge 1.0.3 → 1.0.5

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 ADDED
@@ -0,0 +1,249 @@
1
+ # 🚀 Signal Bridge
2
+
3
+ Lightweight communication bridge berbasis `window.postMessage` untuk komunikasi **Host ↔ Iframe (Remote App)** dengan fitur:
4
+
5
+ * 🔐 Optional encryption (AES)
6
+ * 🛡️ Origin validation (security)
7
+ * 🔁 Listener & emitter sederhana
8
+ * ♻️ Singleton instance (init hanya sekali)
9
+ * 🌐 Support UMD (browser global) + npm package
10
+
11
+ ---
12
+
13
+ ## 📦 Installation
14
+
15
+ ```bash
16
+ npm install signal-bridge
17
+ ```
18
+
19
+ atau via CDN (UMD):
20
+
21
+ ```html
22
+ <script src="signal-bridge.umd.js"></script>
23
+ ```
24
+
25
+ ---
26
+
27
+ ## ⚙️ Konsep Dasar
28
+
29
+ Bridge ini digunakan untuk komunikasi antara:
30
+
31
+ * **Host App** (parent window)
32
+ * **Remote App** (iframe)
33
+
34
+ ⚠️ Library ini **hanya berjalan di dalam iframe (remote)**.
35
+
36
+ ---
37
+
38
+ ## 🧠 API Overview
39
+
40
+ ### 1. Create Bridge (Singleton)
41
+
42
+ ```ts
43
+ import { createBridge } from "signal-bridge";
44
+
45
+ const bridge = createBridge("my-app-id", {
46
+ allowedHostOrigins: ["https://host.com"],
47
+ cryptoKey: "SECRET_KEY", // optional
48
+ debug: true
49
+ });
50
+ ```
51
+
52
+ > Hanya akan dibuat **1x (singleton)**. Jika dipanggil ulang, akan reuse instance lama.
53
+
54
+ ---
55
+
56
+ ### 2. Init Bridge
57
+
58
+ ```ts
59
+ bridge.init();
60
+ ```
61
+
62
+ Mengirim sinyal `"ready"` ke host.
63
+
64
+ ---
65
+
66
+ ### 3. Emit Event ke Host
67
+
68
+ ```ts
69
+ bridge.emit("login", {
70
+ userId: 123,
71
+ token: "abc"
72
+ });
73
+ ```
74
+
75
+ ---
76
+
77
+ ### 4. Listen Event dari Host
78
+
79
+ ```ts
80
+ bridge.listen((message) => {
81
+ console.log("Received:", message);
82
+
83
+ if (message.type === "logout") {
84
+ // handle logout
85
+ }
86
+ });
87
+ ```
88
+
89
+ ---
90
+
91
+ ### 5. Akses Global Instance
92
+
93
+ Jika ingin akses dari mana saja:
94
+
95
+ ```ts
96
+ import { signalBridge } from "signal-bridge";
97
+
98
+ signalBridge().emit("ping", {});
99
+ ```
100
+
101
+ ⚠️ Pastikan sudah `createBridge().init()` sebelumnya.
102
+
103
+ ---
104
+
105
+ ### 6. Reset Bridge
106
+
107
+ ```ts
108
+ import { resetBridge } from "signal-bridge";
109
+
110
+ resetBridge();
111
+ ```
112
+
113
+ ---
114
+
115
+ ## 🔐 Security Features
116
+
117
+ ### ✅ Origin Validation
118
+
119
+ ```ts
120
+ allowedHostOrigins: ["https://host.com"]
121
+ ```
122
+
123
+ Hanya origin ini yang bisa kirim message ke iframe.
124
+
125
+ ---
126
+
127
+ ### ✅ Encryption (Optional)
128
+
129
+ ```ts
130
+ cryptoKey: "SECRET_KEY"
131
+ ```
132
+
133
+ Payload akan otomatis:
134
+
135
+ * Encrypt saat `emit`
136
+ * Decrypt saat `receive`
137
+
138
+ ---
139
+
140
+ ## 📡 Message Format
141
+
142
+ ```ts
143
+ type BridgeMessage = {
144
+ type: string;
145
+ payload: any;
146
+ txn: string;
147
+ __source: "host" | "remote";
148
+ __origin?: string;
149
+ };
150
+ ```
151
+
152
+ ---
153
+
154
+ ## 🌍 Browser (UMD) Usage
155
+
156
+ ```html
157
+ <script>
158
+ const bridge = window.SignalBridge.createBridge("app-id", {
159
+ allowedHostOrigins: ["https://host.com"]
160
+ });
161
+
162
+ bridge.init();
163
+
164
+ bridge.listen((msg) => {
165
+ console.log(msg);
166
+ });
167
+
168
+ bridge.emit("hello", { foo: "bar" });
169
+ </script>
170
+ ```
171
+
172
+ ---
173
+
174
+ ## 🧪 Example Flow
175
+
176
+ ### Remote (Iframe)
177
+
178
+ ```ts
179
+ const bridge = createBridge("child-app", {
180
+ allowedHostOrigins: ["https://parent.com"]
181
+ });
182
+
183
+ bridge.init();
184
+
185
+ bridge.listen((msg) => {
186
+ if (msg.type === "user-data") {
187
+ console.log("User:", msg.payload);
188
+ }
189
+ });
190
+
191
+ bridge.emit("ready", { status: "ok" });
192
+ ```
193
+
194
+ ---
195
+
196
+ ## ⚠️ Important Notes
197
+
198
+ * ❗ Harus dijalankan di dalam iframe
199
+ * ❗ `init()` hanya akan trigger sekali (anti duplicate)
200
+ * ❗ Pastikan origin host sesuai (tidak akan menerima jika tidak match)
201
+ * ❗ Encryption hanya aktif jika `cryptoKey` di-set
202
+
203
+ ---
204
+
205
+ ## 🛠️ Available Exports
206
+
207
+ ```ts
208
+ createBridge
209
+ signalBridge
210
+ resetBridge
211
+ encrypt
212
+ decrypt
213
+ generateKey
214
+ ```
215
+
216
+ ---
217
+
218
+ ## 🧩 Internal Behavior
219
+
220
+ * Singleton global instance (`globalBridge`)
221
+ * Anti loop message (`__source` check)
222
+ * Auto ignore invalid message
223
+ * Optional debug logger
224
+
225
+ ---
226
+
227
+ ## 📄 Source
228
+
229
+ Implementasi utama bisa dilihat di file:
230
+
231
+
232
+
233
+ ---
234
+
235
+ ## 🧑‍💻 Author Notes
236
+
237
+ Dirancang untuk kebutuhan komunikasi microfrontend / iframe integration dengan fokus:
238
+
239
+ * Simple API
240
+ * Secure by default
241
+ * Minimal dependency
242
+
243
+ ---
244
+
245
+ ## 📜 License
246
+
247
+ MIT License © 2026 - EkaHersada
248
+
249
+ ---
package/dist/index.d.mts CHANGED
@@ -18,11 +18,24 @@ interface BridgeOptions {
18
18
  debug?: boolean;
19
19
  enableNavigationSync?: boolean;
20
20
  }
21
- declare function signalBridge(appId: string, options: BridgeOptions): {
21
+ declare function createBridge(appId: string, options: BridgeOptions): {
22
+ init(): void;
23
+ listen(handler: Listener): void;
24
+ emit(type: string, payload: any): void;
25
+ destroy(): void;
26
+ };
27
+ declare function resetBridge(): void;
28
+ declare function signalBridge(): {
29
+ init(): void;
30
+ listen(handler: Listener): void;
31
+ emit(type: string, payload: any): void;
32
+ destroy(): void;
33
+ };
34
+ declare function setupBridge(appId: string, options: BridgeOptions): {
22
35
  init(): void;
23
36
  listen(handler: Listener): void;
24
37
  emit(type: string, payload: any): void;
25
38
  destroy(): void;
26
39
  };
27
40
 
28
- export { base64UrlDecode, base64UrlEncode, decrypt, encrypt, generateKey, signalBridge };
41
+ export { base64UrlDecode, base64UrlEncode, createBridge, decrypt, encrypt, generateKey, resetBridge, setupBridge, signalBridge };
package/dist/index.d.ts CHANGED
@@ -18,11 +18,24 @@ interface BridgeOptions {
18
18
  debug?: boolean;
19
19
  enableNavigationSync?: boolean;
20
20
  }
21
- declare function signalBridge(appId: string, options: BridgeOptions): {
21
+ declare function createBridge(appId: string, options: BridgeOptions): {
22
+ init(): void;
23
+ listen(handler: Listener): void;
24
+ emit(type: string, payload: any): void;
25
+ destroy(): void;
26
+ };
27
+ declare function resetBridge(): void;
28
+ declare function signalBridge(): {
29
+ init(): void;
30
+ listen(handler: Listener): void;
31
+ emit(type: string, payload: any): void;
32
+ destroy(): void;
33
+ };
34
+ declare function setupBridge(appId: string, options: BridgeOptions): {
22
35
  init(): void;
23
36
  listen(handler: Listener): void;
24
37
  emit(type: string, payload: any): void;
25
38
  destroy(): void;
26
39
  };
27
40
 
28
- export { base64UrlDecode, base64UrlEncode, decrypt, encrypt, generateKey, signalBridge };
41
+ export { base64UrlDecode, base64UrlEncode, createBridge, decrypt, encrypt, generateKey, resetBridge, setupBridge, signalBridge };
@@ -6629,9 +6629,12 @@ var signalBridge = (() => {
6629
6629
  __export(index_exports, {
6630
6630
  base64UrlDecode: () => base64UrlDecode,
6631
6631
  base64UrlEncode: () => base64UrlEncode,
6632
+ createBridge: () => createBridge,
6632
6633
  decrypt: () => decrypt,
6633
6634
  encrypt: () => encrypt,
6634
6635
  generateKey: () => generateKey,
6636
+ resetBridge: () => resetBridge,
6637
+ setupBridge: () => setupBridge,
6635
6638
  signalBridge: () => signalBridge
6636
6639
  });
6637
6640
 
@@ -6675,7 +6678,33 @@ var signalBridge = (() => {
6675
6678
 
6676
6679
  // src/index.ts
6677
6680
  var isInitialized = false;
6678
- function signalBridge(appId, options) {
6681
+ var globalConfig = null;
6682
+ var globalBridge = null;
6683
+ function createBridge(appId, options) {
6684
+ if (globalBridge) {
6685
+ if ((globalConfig == null ? void 0 : globalConfig.appId) !== appId || JSON.stringify(globalConfig == null ? void 0 : globalConfig.origins) !== JSON.stringify(options.allowedHostOrigins)) {
6686
+ console.warn("\u26A0\uFE0F Bridge already initialized with different config");
6687
+ }
6688
+ return globalBridge;
6689
+ }
6690
+ globalConfig = {
6691
+ appId,
6692
+ origins: options.allowedHostOrigins
6693
+ };
6694
+ globalBridge = setupBridge(appId, options);
6695
+ return globalBridge;
6696
+ }
6697
+ function resetBridge() {
6698
+ globalBridge == null ? void 0 : globalBridge.destroy();
6699
+ globalBridge = null;
6700
+ }
6701
+ function signalBridge() {
6702
+ if (!globalBridge) {
6703
+ throw new Error("\u274C Bridge belum di-init. Panggil createBridge().init() dulu");
6704
+ }
6705
+ return globalBridge;
6706
+ }
6707
+ function setupBridge(appId, options) {
6679
6708
  const { allowedHostOrigins, cryptoKey, debug } = options;
6680
6709
  const isRemote = window.parent && window.parent !== window;
6681
6710
  if (!isRemote) {
@@ -6699,14 +6728,14 @@ var signalBridge = (() => {
6699
6728
  const remoteMessage = {
6700
6729
  type: data.type,
6701
6730
  payload,
6702
- txn: data.txn,
6731
+ txn: data.txn || "",
6703
6732
  __source: "host",
6704
6733
  __origin: origin
6705
6734
  };
6706
6735
  listeners.forEach((fn) => fn(remoteMessage));
6707
6736
  };
6708
6737
  window.addEventListener("message", messageHandler);
6709
- function emitToHost(type, payload) {
6738
+ function emitToHost(type, payload, txn) {
6710
6739
  let finalPayload = payload;
6711
6740
  if (cryptoKey) {
6712
6741
  finalPayload = encrypt(payload, cryptoKey);
@@ -6715,7 +6744,7 @@ var signalBridge = (() => {
6715
6744
  app_id: appId,
6716
6745
  type,
6717
6746
  payload: finalPayload,
6718
- txn: generateKey(),
6747
+ txn: txn || "",
6719
6748
  __origin: window.location.origin,
6720
6749
  __source: "remote"
6721
6750
  };
@@ -6752,7 +6781,10 @@ var signalBridge = (() => {
6752
6781
  }
6753
6782
  if (typeof window !== "undefined") {
6754
6783
  window.SignalBridge = {
6784
+ createBridge,
6785
+ // 👈 NEW
6755
6786
  signalBridge,
6787
+ // 👈 NEW
6756
6788
  encrypt,
6757
6789
  decrypt,
6758
6790
  generateKey