tiny-essentials 1.25.2 โ†’ 1.25.3

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.
@@ -1,18 +1,20 @@
1
1
  # ๐Ÿงฉ TinyIframeEvents
2
2
 
3
- A flexible event routing system for structured communication between a **parent window** and its **iframe** using postMessage.
3
+ A flexible event routing system for structured communication between a **parent window** and its **iframe** using `MessageChannel`.
4
4
 
5
- This module abstracts the complexity of origin validation, window detection, and message direction. It allows **modular, bidirectional, and secure communication** across frames.
5
+ This module abstracts the complexity of cross-origin communication by establishing a direct, un-interceptable port connection after a secure initial handshake. It allows **modular, bidirectional, and secure communication** across frames, completely bypassing the broadcast vulnerabilities of standard `postMessage`.
6
6
 
7
7
  ---
8
8
 
9
9
  ## โœจ Features
10
10
 
11
- - ๐Ÿ” Bidirectional communication (`iframe` โ‡„ `parent`)
12
- - ๐ŸŽฏ Named event routes with custom payloads
13
- - ๐Ÿ” Target window and origin validation
14
- - ๐Ÿง  Smart context detection (no config required inside iframe)
15
- - ๐Ÿงน Clean-up support with `.destroy()`
11
+ - ๐Ÿ” **Bidirectional communication** (`iframe` โ‡„ `parent`) via a private `MessagePort`.
12
+ - ๐ŸŽฏ **Named event routes** with custom payloads.
13
+ - ๐Ÿง  **Smart context detection** (no config required inside the iframe).
14
+ - โš™๏ธ **Customizable internals:** Avoid naming collisions by customizing the secret handshake and ready event names.
15
+ - โณ **Queue management:** Safely emit events before the connection is ready; they will be flushed automatically once established.
16
+ - ๐Ÿ”„ **Auto-reconnect:** Automatically handles port resets if the target iframe is reloaded.
17
+ - ๐Ÿงน **Clean-up support** with `.destroy()`.
16
18
 
17
19
  ---
18
20
 
@@ -27,11 +29,20 @@ const iframe = document.querySelector('iframe');
27
29
 
28
30
  const parentEvents = new TinyIframeEvents({
29
31
  targetIframe: iframe, // Will use iframe.contentWindow
30
- targetOrigin: window.location.origin
32
+ targetOrigin: window.location.origin,
33
+ // Optional: customize internal events to prevent collisions
34
+ secretEventName: '__myCustomSecret__',
31
35
  });
32
36
 
37
+ // You can safely emit before the iframe is ready.
38
+ // It will be queued and sent automatically!
33
39
  parentEvents.emit('hello:iframe', { text: '๐Ÿ‘‹ From parent!' });
34
40
 
41
+ // Wait for the secure channel to be fully established
42
+ parentEvents.onReady(() => {
43
+ console.log('โœ… Secure connection established with iframe!');
44
+ });
45
+
35
46
  parentEvents.on('reply:fromIframe', (data, event) => {
36
47
  console.log('๐Ÿ“จ Received from iframe:', data, event);
37
48
  });
@@ -44,13 +55,19 @@ parentEvents.on('reply:fromIframe', (data, event) => {
44
55
  ```js
45
56
  import TinyIframeEvents from './TinyIframeEvents.mjs';
46
57
 
47
- const iframeEvents = new TinyIframeEvents();
58
+ const iframeEvents = new TinyIframeEvents({
59
+ // Make sure these match the parent's config if you changed them!
60
+ secretEventName: '__myCustomSecret__',
61
+ });
48
62
 
49
- iframeEvents.on('hello:iframe', (data, event) => {
50
- console.log('๐Ÿ“ฅ Message from parent:', event);
63
+ iframeEvents.onReady(() => {
64
+ console.log('โœ… Secure connection established with parent!');
65
+ iframeEvents.emit('reply:fromIframe', { text: '๐Ÿ™‹โ€โ™€๏ธ Hi parent!' });
51
66
  });
52
67
 
53
- iframeEvents.emit('reply:fromIframe', { text: '๐Ÿ™‹โ€โ™€๏ธ Hi parent!' });
68
+ iframeEvents.on('hello:iframe', (data, event) => {
69
+ console.log('๐Ÿ“ฅ Message from parent:', data);
70
+ });
54
71
  ```
55
72
 
56
73
  ---
@@ -59,29 +76,44 @@ iframeEvents.emit('reply:fromIframe', { text: '๐Ÿ™‹โ€โ™€๏ธ Hi parent!' });
59
76
 
60
77
  ### `new TinyIframeEvents(config?)`
61
78
 
62
- Creates a new instance for communication.
79
+ Creates a new instance for communication and automatically begins the handshake process.
63
80
 
64
81
  #### Parameters:
65
82
 
66
- | Name | Type | Description |
67
- | -------------- | -------------------- | --------------------------------------------------------------------- |
68
- | `targetIframe` | `HTMLIFrameElement?` | The iframe element to communicate with (used in the parent only). |
69
- | `targetOrigin` | `string?` | Expected origin (for security). Defaults to `window.location.origin`. |
83
+ | Name | Type | Description |
84
+ | :--- | :--- | :--- |
85
+ | `targetIframe` | `HTMLIFrameElement?` | The iframe element to communicate with (required in the parent only). |
86
+ | `targetOrigin` | `string?` | Expected origin for the initial handshake. Defaults to `window.location.origin`. |
87
+ | `secretEventName` | `string?` | Internal key used to validate standard routing messages. |
88
+ | `handshakeEventName`| `string?` | Internal event name used for the initial `MessageChannel` port transfer. |
89
+ | `readyEventName` | `string?` | Internal event name used to trigger `.onReady()` listeners. |
90
+
91
+ ---
92
+
93
+ ### `onReady(handler)`
94
+
95
+ Executes a callback when the secure `MessageChannel` connection is fully established. If the connection is already ready, it executes immediately.
96
+
97
+ ```js
98
+ iframeEvents.onReady(() => {
99
+ // Safe to assume the secure pipeline is open
100
+ });
101
+ ```
70
102
 
71
103
  ---
72
104
 
73
105
  ### `emit(eventName, payload)`
74
106
 
75
- Sends a message to the target frame.
107
+ Sends a message to the target frame through the secure port. If the port is not ready yet, the message is queued.
76
108
 
77
- | Param | Type | Description |
78
- | ----------- | -------- | ------------------------------------------ |
79
- | `eventName` | `string` | Unique identifier of the event. |
80
- | `payload` | `any` | The data to send (any serializable value). |
109
+ | Param | Type | Description |
110
+ | :--- | :--- | :--- |
111
+ | `eventName` | `string` | Unique identifier of the event. |
112
+ | `payload` | `any` | The data to send (must be a serializable value; DOM nodes and functions cannot be cloned). |
81
113
 
82
114
  #### Throws:
83
-
84
115
  * `TypeError` if `eventName` is not a string.
116
+ * `Error` if the instance has been destroyed.
85
117
 
86
118
  ---
87
119
 
@@ -91,7 +123,7 @@ Registers a listener for a specific event.
91
123
 
92
124
  ```js
93
125
  iframeEvents.on('my:event', (payload, event) => {
94
- // event = { origin, source }
126
+ // Access data via `payload`
95
127
  });
96
128
  ```
97
129
 
@@ -99,8 +131,7 @@ iframeEvents.on('my:event', (payload, event) => {
99
131
 
100
132
  ### `destroy()`
101
133
 
102
- Removes all listeners and message event binding.
103
- Call this when the instance is no longer needed.
134
+ Removes all listeners, closes the `MessagePort`, and cleans up DOM event bindings to prevent memory leaks. Call this when the instance is no longer needed.
104
135
 
105
136
  ```js
106
137
  iframeEvents.destroy();
@@ -122,18 +153,16 @@ if (events.isDestroyed()) {
122
153
 
123
154
  ## ๐Ÿ”’ Security Notes
124
155
 
125
- * Only messages with the flag `__tinyEvent: true` are accepted.
126
- * The source window is checked strictly (`source === targetWindow`).
127
- * Messages are ignored unless their `direction` matches the current side (`iframe` or `parent`).
156
+ * **Direct Pipeline:** Once the initial handshake passes the `MessagePort`, all communication happens directly between the two contexts. It does not broadcast to `window.addEventListener('message')`, making it immune to interception by other scripts or browser extensions.
157
+ * **Internal Validation:** Messages are strictly validated using the `secretEventName` flag and direction checks (`iframe` vs `parent`).
128
158
 
129
159
  ---
130
160
 
131
161
  ## ๐Ÿ“š Internals (for advanced users)
132
162
 
133
163
  This class internally wraps:
134
-
135
- * postMessage
136
- * A minimal event router: `TinyEvents`
164
+ * `MessageChannel` and `MessagePort` for isolated communication.
165
+ * A minimal event router: `TinyEvents`.
137
166
 
138
167
  ---
139
168
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiny-essentials",
3
- "version": "1.25.2",
3
+ "version": "1.25.3",
4
4
  "description": "Collection of small, essential scripts designed to be used across various projects. These simple utilities are crafted for speed, ease of use, and versatility.",
5
5
  "scripts": {
6
6
  "test": "npm run test:mjs && npm run test:cjs && npm run test:js",