iframe.io 1.0.6 → 1.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 CHANGED
@@ -1,18 +1,19 @@
1
1
  # iframe.io
2
2
 
3
- Easy and friendly API to connect and interact between content window and its containing iframe with enhanced features like heartbeat monitoring, automatic reconnection, message queuing, and rate limiting.
3
+ Easy and friendly API to connect and interact between content window and its containing iframe with enhanced security, reliability, and modern async/await support.
4
4
 
5
- ## Features
5
+ ## New Features & Improvements
6
6
 
7
- - 🔄 **Bi-directional Communication** - Seamless messaging between parent window and iframe
8
- - 💓 **Heartbeat Monitoring** - Automatic connection health checking
9
- - 🔌 **Auto Reconnection** - Automatic reconnection with exponential backoff
10
- - 📦 **Message Queuing** - Queue messages when connection is lost
11
- - 🛡️ **Security** - Origin validation and message sanitization
12
- - **Rate Limiting** - Prevent message flooding
13
- - 🎯 **Event System** - Robust event-driven architecture
14
- - **Promise Support** - Async/await compatible methods
15
- - 📊 **Connection Stats** - Real-time connection statistics
7
+ ### 🆕 Version 1.1.0 Updates
8
+
9
+ - **🔒 Enhanced Security**: Origin validation, message sanitization, and payload size limits
10
+ - **🔄 Auto-Reconnection**: Automatic reconnection with exponential backoff strategy
11
+ - **💓 Heartbeat Monitoring**: Connection health monitoring with configurable intervals
12
+ - **📦 Message Queuing**: Queue messages when disconnected and replay on reconnection
13
+ - **⚡ Rate Limiting**: Configurable message rate limiting to prevent spam
14
+ - **🎯 Promise Support**: Modern async/await APIs with timeout handling
15
+ - **📊 Connection Statistics**: Real-time connection and performance metrics
16
+ - **🛡️ Comprehensive Error Handling**: Detailed error types and handling mechanisms
16
17
 
17
18
  ## Installation
18
19
 
@@ -20,429 +21,391 @@ Easy and friendly API to connect and interact between content window and its con
20
21
  npm install iframe.io
21
22
  ```
22
23
 
23
- ## Quick Start
24
+ ## Basic Usage
24
25
 
25
- ### Parent Window (WINDOW type)
26
+ ### Parent Window (WINDOW peer)
26
27
 
27
28
  ```javascript
28
29
  import IOF from 'iframe.io'
29
30
 
30
- // Create iframe and get reference
31
- const iframe = document.createElement('iframe')
32
- iframe.src = 'https://example.com/iframe-content'
33
- document.body.appendChild(iframe)
34
-
35
- // Initialize connection
36
- const iof = new IOF({ type: 'WINDOW', debug: true })
37
-
38
- iframe.onload = () => {
39
- // Initiate connection with iframe
40
- iof.initiate(iframe.contentWindow, 'https://example.com')
41
-
42
- // Listen for connection
43
- iof.on('connect', () => {
44
- console.log('Connected to iframe!')
45
-
46
- // Send message
47
- iof.emit('hello', { message: 'Hello from parent!' })
48
- })
49
-
50
- // Listen for messages
51
- iof.on('response', (data) => {
52
- console.log('Received:', data)
53
- })
54
- }
31
+ const iframe = document.getElementById('myIframe')
32
+ const iframeIO = new IOF({
33
+ type: 'WINDOW',
34
+ debug: true
35
+ })
36
+
37
+ // Establish connection
38
+ iframeIO.initiate(iframe.contentWindow, 'https://child-domain.com')
39
+
40
+ // Listen for connection
41
+ iframeIO.on('connect', () => {
42
+ console.log('Connected to iframe!')
43
+
44
+ // Send a message
45
+ iframeIO.emit('hello', { message: 'Hello from parent!' })
46
+ })
47
+
48
+ // Listen for messages
49
+ iframeIO.on('response', (data) => {
50
+ console.log('Received:', data)
51
+ })
55
52
  ```
56
53
 
57
- ### Iframe Content (IFRAME type)
54
+ ### Child Window (IFRAME peer)
58
55
 
59
56
  ```javascript
60
57
  import IOF from 'iframe.io'
61
58
 
62
- // Create connection listener
63
- const iof = new IOF({ type: 'IFRAME', debug: true })
59
+ const iframeIO = new IOF({
60
+ type: 'IFRAME',
61
+ debug: true
62
+ })
64
63
 
65
64
  // Listen for parent connection
66
- iof.listen('https://parent-domain.com')
65
+ iframeIO.listen('https://parent-domain.com')
67
66
 
68
67
  // Handle connection
69
- iof.on('connect', () => {
68
+ iframeIO.on('connect', () => {
70
69
  console.log('Connected to parent!')
71
70
  })
72
71
 
73
72
  // Listen for messages
74
- iof.on('hello', (data, ack) => {
75
- console.log('Received from parent:', data)
76
-
73
+ iframeIO.on('hello', (data) => {
74
+ console.log('Received:', data)
75
+
77
76
  // Send response
78
- iof.emit('response', { message: 'Hello from iframe!' })
79
-
80
- // Acknowledge receipt (optional)
81
- if (ack) ack(false, 'Message received')
77
+ iframeIO.emit('response', { received: true })
82
78
  })
83
79
  ```
84
80
 
85
- ## API Reference
86
-
87
- ### Constructor
81
+ ## Enhanced Configuration Options
88
82
 
89
83
  ```javascript
90
- new IOF(options?)
84
+ const iframeIO = new IOF({
85
+ type: 'WINDOW', // 'WINDOW' or 'IFRAME'
86
+ debug: false, // Enable debug logging
87
+ heartbeatInterval: 30000, // Heartbeat interval in ms (30s)
88
+ connectionTimeout: 10000, // Connection timeout in ms (10s)
89
+ maxMessageSize: 1024 * 1024, // Max message size in bytes (1MB)
90
+ maxMessagesPerSecond: 100, // Rate limit (100 messages/second)
91
+ autoReconnect: true, // Enable automatic reconnection
92
+ messageQueueSize: 50, // Max queued messages when disconnected
93
+ allowedIncomingEvents: ['hello', 'response'], // Optional incoming event allowlist (non-reserved events)
94
+ validateIncoming: (event, payload, origin) => true // Optional custom incoming validator
95
+ })
91
96
  ```
92
97
 
93
- #### Options
98
+ ## New Async/Await Support
94
99
 
95
- | Option | Type | Default | Description |
96
- |--------|------|---------|-------------|
97
- | `type` | `'WINDOW' \| 'IFRAME'` | `'IFRAME'` | Connection type |
98
- | `debug` | `boolean` | `false` | Enable debug logging |
99
- | `heartbeatInterval` | `number` | `30000` | Heartbeat interval in ms |
100
- | `connectionTimeout` | `number` | `10000` | Connection timeout in ms |
101
- | `maxMessageSize` | `number` | `1048576` | Max message size (1MB) |
102
- | `maxMessagesPerSecond` | `number` | `100` | Rate limit for messages |
103
- | `autoReconnect` | `boolean` | `true` | Enable auto reconnection |
104
- | `messageQueueSize` | `number` | `50` | Max queued messages |
100
+ ### Send Messages with Acknowledgments
105
101
 
106
- ### Connection Methods
102
+ ```javascript
103
+ // Send message and wait for acknowledgment with timeout
104
+ try {
105
+ const response = await iframeIO.emitAsync('getData', { id: 123 }, 10000) // 10s timeout
106
+ console.log('Response:', response)
107
+ } catch (error) {
108
+ console.error('Request failed:', error.message)
109
+ }
107
110
 
108
- #### `initiate(contentWindow, iframeOrigin)`
111
+ // Listen and acknowledge
112
+ iframeIO.on('getData', async (data, ack) => {
113
+ try {
114
+ const result = await fetchData(data.id)
115
+ ack(false, result) // Success: ack(error, ...response)
116
+ } catch (error) {
117
+ ack(error.message) // Error: ack(errorMessage)
118
+ }
119
+ })
120
+ ```
109
121
 
110
- Establish connection with an iframe (WINDOW type only).
122
+ ### Wait for Connection
111
123
 
112
124
  ```javascript
113
- iof.initiate(iframe.contentWindow, 'https://iframe-origin.com')
114
- ```
125
+ // Wait for connection with timeout
126
+ try {
127
+ await iframeIO.connectAsync(5000) // 5 second timeout
128
+ console.log('Connection established!')
129
+ } catch (error) {
130
+ console.error('Connection failed:', error.message)
131
+ }
115
132
 
116
- **Parameters:**
117
- - `contentWindow` - The iframe's contentWindow
118
- - `iframeOrigin` - The iframe's origin URL
133
+ // Wait for single event
134
+ const userData = await iframeIO.onceAsync('userProfile')
135
+ console.log('User data received:', userData)
136
+ ```
119
137
 
120
- #### `listen(hostOrigin?)`
138
+ ## Enhanced Connection Management
121
139
 
122
- Listen for connection from parent window (IFRAME type).
140
+ ### Auto-Reconnection
123
141
 
124
142
  ```javascript
125
- iof.listen('https://parent-origin.com') // Optional origin restriction
126
- ```
143
+ // Handle connection events
144
+ iframeIO.on('disconnect', (data) => {
145
+ console.log('Disconnected:', data.reason)
146
+ })
127
147
 
128
- **Parameters:**
129
- - `hostOrigin` (optional) - Restrict connections to specific origin
148
+ iframeIO.on('reconnecting', (data) => {
149
+ console.log(`Reconnection attempt ${data.attempt}, delay: ${data.delay}ms`)
150
+ })
130
151
 
131
- #### `disconnect(callback?)`
152
+ iframeIO.on('reconnection_failed', (data) => {
153
+ console.error(`Failed to reconnect after ${data.attempts} attempts`)
154
+ })
155
+ ```
132
156
 
133
- Disconnect and clean up all resources.
157
+ ### Connection Statistics
134
158
 
135
159
  ```javascript
136
- iof.disconnect(() => {
137
- console.log('Disconnected!')
138
- })
160
+ const stats = iframeIO.getStats()
161
+ console.log(stats)
162
+ // {
163
+ // connected: true,
164
+ // peerType: 'WINDOW',
165
+ // origin: 'https://example.com',
166
+ // lastHeartbeat: 1609459200000,
167
+ // queuedMessages: 0,
168
+ // reconnectAttempts: 0,
169
+ // activeListeners: 5,
170
+ // messageRate: 2
171
+ // }
139
172
  ```
140
173
 
141
- ### Messaging Methods
174
+ ## Security Features
142
175
 
143
- #### `emit(event, payload?, callback?)`
144
-
145
- Send a message to the peer.
176
+ ### Origin Validation
146
177
 
147
178
  ```javascript
148
- // Simple message
149
- iof.emit('myEvent', { data: 'hello' })
179
+ // Strict origin checking
180
+ iframeIO.listen('https://trusted-domain.com') // Only accept from this origin
150
181
 
151
- // With acknowledgment
152
- iof.emit('myEvent', { data: 'hello' }, (error, response) => {
153
- if (error) {
154
- console.error('Error:', error)
155
- } else {
156
- console.log('Response:', response)
182
+ // Error handling for invalid origins
183
+ iframeIO.on('error', (error) => {
184
+ if (error.type === 'INVALID_ORIGIN') {
185
+ console.log(`Rejected message from ${error.received}`)
157
186
  }
158
187
  })
159
-
160
- // Callback as second parameter
161
- iof.emit('myEvent', (error, response) => {
162
- console.log('Response:', response)
163
- })
164
188
  ```
165
189
 
166
- #### `on(event, listener)`
167
-
168
- Add event listener.
190
+ ### Message Sanitization
169
191
 
170
192
  ```javascript
171
- iof.on('myEvent', (data, ack) => {
172
- console.log('Received:', data)
173
-
174
- // Send acknowledgment (optional)
175
- if (ack) ack(false, 'Success response')
193
+ // Automatic payload sanitization removes functions and undefined values
194
+ iframeIO.emit('data', {
195
+ text: 'Hello',
196
+ func: () => {}, // Functions are automatically removed
197
+ undef: undefined // Undefined values are automatically removed
176
198
  })
177
199
  ```
178
200
 
179
- #### `once(event, listener)`
180
-
181
- Add one-time event listener.
201
+ ### Rate Limiting
182
202
 
183
203
  ```javascript
184
- iof.once('myEvent', (data) => {
185
- console.log('This will only fire once:', data)
204
+ const iframeIO = new IOF({
205
+ maxMessagesPerSecond: 10 // Limit to 10 messages per second
186
206
  })
187
- ```
188
-
189
- #### `off(event, listener?)`
190
-
191
- Remove event listener(s).
192
-
193
- ```javascript
194
- // Remove specific listener
195
- iof.off('myEvent', myListener)
196
207
 
197
- // Remove all listeners for event
198
- iof.off('myEvent')
208
+ iframeIO.on('error', (error) => {
209
+ if (error.type === 'RATE_LIMIT_EXCEEDED') {
210
+ console.log(`Rate limited: ${error.current}/${error.limit}`)
211
+ }
212
+ })
199
213
  ```
200
214
 
201
- #### `removeListeners(callback?)`
215
+ ### Incoming Event Allowlist & Validation
202
216
 
203
- Remove all event listeners.
217
+ For defense-in-depth, you can restrict which **application-level** events are accepted and/or validate incoming payloads. Reserved internal events (`ping`, `pong`, `__heartbeat`, `__heartbeat_response`) are always allowed.
204
218
 
205
219
  ```javascript
206
- iof.removeListeners(() => {
207
- console.log('All listeners removed')
220
+ const iframeIO = new IOF({
221
+ type: 'IFRAME',
222
+ debug: true,
223
+ allowedIncomingEvents: ['getData', 'hello'],
224
+ validateIncoming: (event, payload, origin) => {
225
+ // Example: basic shape checks
226
+ if (event === 'getData') return payload && typeof payload.id === 'number'
227
+ return true
228
+ }
208
229
  })
209
- ```
210
230
 
211
- ### Async Methods
212
-
213
- #### `emitAsync(event, payload?)`
214
-
215
- Send message and return Promise.
216
-
217
- ```javascript
218
- try {
219
- const response = await iof.emitAsync('getData', { id: 123 })
220
- console.log('Response:', response)
221
- } catch (error) {
222
- console.error('Error:', error)
223
- }
231
+ iframeIO.on('error', (error) => {
232
+ if (error.type === 'DISALLOWED_EVENT' || error.type === 'INVALID_MESSAGE') {
233
+ console.warn('Dropped incoming message:', error)
234
+ }
235
+ })
224
236
  ```
225
237
 
226
- #### `onceAsync(event)`
227
-
228
- Wait for single event occurrence.
238
+ ## Comprehensive Error Handling
229
239
 
230
240
  ```javascript
231
- const data = await iof.onceAsync('dataReady')
232
- console.log('Data received:', data)
241
+ iframeIO.on('error', (error) => {
242
+ switch (error.type) {
243
+ case 'INVALID_ORIGIN':
244
+ console.error(`Invalid origin: expected ${error.expected}, got ${error.received}`)
245
+ break
246
+ case 'ORIGIN_MISMATCH':
247
+ console.error(`Origin mismatch: expected ${error.expected}, got ${error.received}`)
248
+ break
249
+ case 'RATE_LIMIT_EXCEEDED':
250
+ console.warn(`Rate limit exceeded: ${error.current}/${error.limit} messages/second`)
251
+ break
252
+ case 'MESSAGE_HANDLING_ERROR':
253
+ console.error(`Error handling event ${error.event}: ${error.error}`)
254
+ break
255
+ case 'EMIT_ERROR':
256
+ console.error(`Error sending event ${error.event}: ${error.error}`)
257
+ break
258
+ case 'LISTENER_ERROR':
259
+ console.error(`Error in listener for ${error.event}: ${error.error}`)
260
+ break
261
+ case 'NO_CONNECTION':
262
+ console.error(`Attempted to send ${error.event} without connection`)
263
+ break
264
+ default:
265
+ console.error('Unknown error:', error)
266
+ }
267
+ })
233
268
  ```
234
269
 
235
- #### `connectAsync(timeout?)`
236
-
237
- Wait for connection to be established.
270
+ ## Message Queuing
238
271
 
239
272
  ```javascript
240
- try {
241
- await iof.connectAsync(5000) // 5 second timeout
242
- console.log('Connected!')
243
- } catch (error) {
244
- console.error('Connection timeout')
245
- }
246
- ```
247
-
248
- ### Utility Methods
273
+ // Messages are automatically queued when disconnected
274
+ iframeIO.emit('important-data', { data: 'This will be queued if disconnected' })
249
275
 
250
- #### `isConnected()`
276
+ // Clear queue manually if needed
277
+ iframeIO.clearQueue()
251
278
 
252
- Check if connection is active.
253
-
254
- ```javascript
255
- if (iof.isConnected()) {
256
- console.log('Connection is active')
257
- }
279
+ // Check queue status
280
+ const stats = iframeIO.getStats()
281
+ console.log(`${stats.queuedMessages} messages queued`)
258
282
  ```
259
283
 
260
- #### `getStats()`
261
-
262
- Get connection statistics.
284
+ ## API Reference
263
285
 
264
- ```javascript
265
- const stats = iof.getStats()
266
- console.log('Stats:', stats)
267
- /*
268
- {
269
- connected: true,
270
- peerType: 'WINDOW',
271
- origin: 'https://example.com',
272
- lastHeartbeat: 1640995200000,
273
- queuedMessages: 0,
274
- reconnectAttempts: 0,
275
- activeListeners: 5,
276
- messageRate: 10
277
- }
278
- */
279
- ```
286
+ ### New Methods
280
287
 
281
- #### `clearQueue()`
288
+ #### Async Methods
289
+ - **`emitAsync(event, payload?, timeout?)`** - Send message and wait for response (Promise)
290
+ - **`connectAsync(timeout?)`** - Wait for connection with timeout (Promise)
291
+ - **`onceAsync(event)`** - Wait for single event (Promise)
282
292
 
283
- Clear queued messages.
293
+ #### Utility Methods
294
+ - **`getStats()`** - Get connection statistics
295
+ - **`clearQueue()`** - Clear queued messages
284
296
 
285
- ```javascript
286
- iof.clearQueue()
287
- ```
297
+ ### Connection Methods
288
298
 
289
- ## Events
299
+ - **`initiate(contentWindow, iframeOrigin)`** - Establish connection (WINDOW peer only)
300
+ - **`listen(hostOrigin?)`** - Listen for connection (IFRAME peer only)
301
+ - **`disconnect(callback?)`** - Disconnect and cleanup
302
+ - **`isConnected()`** - Check connection status
290
303
 
291
- ### Built-in Events
304
+ ### Messaging Methods
292
305
 
293
- | Event | Description | Data |
294
- |-------|-------------|------|
295
- | `connect` | Connection established | - |
296
- | `disconnect` | Connection lost | `{ reason: string }` |
297
- | `reconnecting` | Reconnection attempt | `{ attempt: number, delay: number }` |
298
- | `reconnection_failed` | All reconnection attempts failed | `{ attempts: number }` |
299
- | `error` | Error occurred | `{ type: string, ...details }` |
306
+ - **`emit(event, payload?, callback?)`** - Send message
307
+ - **`on(event, listener)`** - Add event listener
308
+ - **`once(event, listener)`** - Add one-time event listener
309
+ - **`off(event, listener?)`** - Remove event listener(s)
310
+ - **`removeListeners(callback?)`** - Remove all listeners
300
311
 
301
- ### Error Types
312
+ ### Events
302
313
 
303
- - `RATE_LIMIT_EXCEEDED` - Message rate limit exceeded
304
- - `MESSAGE_HANDLING_ERROR` - Error processing received message
305
- - `EMIT_ERROR` - Error sending message
306
- - `LISTENER_ERROR` - Error in event listener
307
- - `INVALID_ORIGIN` - Message from unauthorized origin
308
- - `ORIGIN_MISMATCH` - Origin doesn't match established connection
309
- - `NO_CONNECTION` - Attempted to send without connection
314
+ #### Connection Events
315
+ - **`connect`** - Connection established
316
+ - **`disconnect`** - Connection lost with reason
317
+ - **`reconnecting`** - Reconnection attempt started
318
+ - **`reconnection_failed`** - All reconnection attempts failed
310
319
 
311
- ## Advanced Usage
320
+ #### Error Events
321
+ - **`error`** - Various error conditions with detailed error objects
312
322
 
313
- ### Message Acknowledgments
323
+ ## TypeScript Support
314
324
 
315
- ```javascript
316
- // Sender
317
- iof.emit('processData', { data: [...] }, (error, result) => {
318
- if (error) {
319
- console.error('Processing failed:', error)
320
- } else {
321
- console.log('Processing result:', result)
322
- }
323
- })
325
+ Full TypeScript support with comprehensive type definitions:
324
326
 
325
- // Receiver
326
- iof.on('processData', async (data, ack) => {
327
- try {
328
- const result = await processData(data.data)
329
- ack(false, result) // Success: ack(error, ...args)
330
- } catch (error) {
331
- ack(error.message) // Error: ack(errorMessage)
332
- }
333
- })
334
- ```
327
+ ```typescript
328
+ import IOF, { Options, Listener, AckFunction } from 'iframe.io'
335
329
 
336
- ### Connection Monitoring
330
+ const options: Options = {
331
+ type: 'WINDOW',
332
+ debug: true,
333
+ heartbeatInterval: 30000,
334
+ maxMessageSize: 512 * 1024
335
+ }
337
336
 
338
- ```javascript
339
- const iof = new IOF({
340
- heartbeatInterval: 10000, // 10 seconds
341
- connectionTimeout: 5000, // 5 seconds
342
- autoReconnect: true
343
- })
337
+ const iframeIO = new IOF(options)
344
338
 
345
- iof.on('disconnect', ({ reason }) => {
346
- console.log('Connection lost:', reason)
339
+ // Typed event listeners
340
+ iframeIO.on('userAction', (data: { action: string; userId: number }) => {
341
+ console.log(`User ${data.userId} performed ${data.action}`)
347
342
  })
348
343
 
349
- iof.on('reconnecting', ({ attempt, delay }) => {
350
- console.log(`Reconnecting (${attempt}/5) in ${delay}ms`)
351
- })
344
+ // Typed async responses
345
+ interface ApiResponse {
346
+ success: boolean
347
+ data: any[]
348
+ }
352
349
 
353
- iof.on('reconnection_failed', ({ attempts }) => {
354
- console.log(`Failed to reconnect after ${attempts} attempts`)
355
- })
350
+ const response = await iframeIO.emitAsync<{ query: string }, ApiResponse>(
351
+ 'search',
352
+ { query: 'hello' },
353
+ 5000 // 5 second timeout
354
+ )
356
355
  ```
357
356
 
358
- ### Message Queuing
357
+ ## Error Types Reference
359
358
 
360
- ```javascript
361
- const iof = new IOF({
362
- messageQueueSize: 100,
363
- autoReconnect: true
364
- })
359
+ | Error Type | Description |
360
+ |------------|-------------|
361
+ | `INVALID_ORIGIN` | Message from unexpected origin |
362
+ | `ORIGIN_MISMATCH` | Origin changed during session |
363
+ | `MESSAGE_HANDLING_ERROR` | Error processing incoming message |
364
+ | `EMIT_ERROR` | Error sending message |
365
+ | `LISTENER_ERROR` | Error in event listener |
366
+ | `DISALLOWED_EVENT` | Incoming event rejected by `allowedIncomingEvents` |
367
+ | `INVALID_MESSAGE` | Incoming message rejected by `validateIncoming` |
368
+ | `RATE_LIMIT_EXCEEDED` | Too many messages sent |
369
+ | `NO_CONNECTION` | Attempted to send without connection |
365
370
 
366
- // Messages sent while disconnected are automatically queued
367
- iof.emit('queuedMessage', { data: 'This will be queued if disconnected' })
371
+ ## Browser Compatibility
368
372
 
369
- // Check queue status
370
- const stats = iof.getStats()
371
- console.log(`Queued messages: ${stats.queuedMessages}`)
372
- ```
373
+ - Chrome 60+
374
+ - Firefox 55+
375
+ - Safari 12+
376
+ - Edge 79+
373
377
 
374
- ### Rate Limiting
378
+ ## Migration Guide
375
379
 
376
- ```javascript
377
- const iof = new IOF({
378
- maxMessagesPerSecond: 50,
379
- maxMessageSize: 512 * 1024 // 512KB
380
- })
380
+ ### From v1.0.x to v1.1.0
381
381
 
382
- iof.on('error', ({ type, limit, current }) => {
383
- if (type === 'RATE_LIMIT_EXCEEDED') {
384
- console.log(`Rate limit exceeded: ${current}/${limit} messages per second`)
385
- }
386
- })
387
- ```
388
-
389
- ### Security Best Practices
382
+ All existing code continues to work without changes. New features are additive:
390
383
 
391
384
  ```javascript
392
- // Always specify allowed origins
393
- iof.listen('https://trusted-parent.com')
394
-
395
- // Handle security errors
396
- iof.on('error', ({ type, expected, received }) => {
397
- if (type === 'INVALID_ORIGIN') {
398
- console.warn(`Rejected message from ${received}, expected ${expected}`)
399
- }
400
- })
401
-
402
- // Validate message content
403
- iof.on('userData', (data, ack) => {
404
- if (!isValidUserData(data)) {
405
- return ack('Invalid data format')
385
+ // Old way (still works)
386
+ iframeIO.emit('getData', { id: 123 }, (error, result) => {
387
+ if (error) {
388
+ console.error('Error:', error)
389
+ } else {
390
+ console.log('Result:', result)
406
391
  }
407
- // Process valid data...
408
392
  })
409
- ```
410
-
411
- ## Browser Support
412
-
413
- - Modern browsers with postMessage API support
414
- - Chrome 2+
415
- - Firefox 3+
416
- - Safari 4+
417
- - IE 8+
418
- - Edge (all versions)
419
-
420
- ## TypeScript Support
421
-
422
- The library is written in TypeScript and includes full type definitions:
423
393
 
424
- ```typescript
425
- import IOF, { Options, PeerType, AckFunction, Listener } from 'iframe.io'
426
-
427
- const options: Options = {
428
- type: 'WINDOW',
429
- debug: true,
430
- heartbeatInterval: 15000
394
+ // New async way
395
+ try {
396
+ const result = await iframeIO.emitAsync('getData', { id: 123 })
397
+ console.log('Result:', result)
398
+ } catch (error) {
399
+ console.error('Error:', error.message)
431
400
  }
401
+ ```
432
402
 
433
- const iof = new IOF(options)
434
-
435
- // Type-safe event handling
436
- iof.on('myEvent', (data: { message: string }, ack?: AckFunction) => {
437
- console.log(data.message)
438
- ack?.(false, 'success')
439
- })
403
+ ## Performance Considerations
440
404
 
441
- // Type-safe async emissions
442
- const response = await iof.emitAsync<{ query: string }, { result: any }>('search', {
443
- query: 'typescript'
444
- })
445
- ```
405
+ - **Message Size**: Keep messages under the configured `maxMessageSize` (default 1MB)
406
+ - **Rate Limiting**: Respect the `maxMessagesPerSecond` limit (default 100/sec)
407
+ - **Queue Size**: Monitor queued messages to avoid memory issues
408
+ - **Heartbeat**: Adjust `heartbeatInterval` based on your reliability needs
446
409
 
447
410
  ## License
448
411
 
@@ -456,4 +419,4 @@ Contributions are welcome! Please read our contributing guidelines and submit pu
456
419
 
457
420
  - Create an issue on GitHub for bug reports
458
421
  - Check existing issues for common problems
459
- - Review the documentation for usage examples
422
+ - Review the documentation for usage examples