iframe.io 1.0.6 → 1.1.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,364 @@ 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
+ })
91
94
  ```
92
95
 
93
- #### Options
94
-
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 |
96
+ ## New Async/Await Support
105
97
 
106
- ### Connection Methods
107
-
108
- #### `initiate(contentWindow, iframeOrigin)`
109
-
110
- Establish connection with an iframe (WINDOW type only).
98
+ ### Send Messages with Acknowledgments
111
99
 
112
100
  ```javascript
113
- iof.initiate(iframe.contentWindow, 'https://iframe-origin.com')
114
- ```
115
-
116
- **Parameters:**
117
- - `contentWindow` - The iframe's contentWindow
118
- - `iframeOrigin` - The iframe's origin URL
119
-
120
- #### `listen(hostOrigin?)`
121
-
122
- Listen for connection from parent window (IFRAME type).
101
+ // Send message and wait for acknowledgment with timeout
102
+ try {
103
+ const response = await iframeIO.emitAsync('getData', { id: 123 }, 10000) // 10s timeout
104
+ console.log('Response:', response)
105
+ } catch (error) {
106
+ console.error('Request failed:', error.message)
107
+ }
123
108
 
124
- ```javascript
125
- iof.listen('https://parent-origin.com') // Optional origin restriction
109
+ // Listen and acknowledge
110
+ iframeIO.on('getData', async (data, ack) => {
111
+ try {
112
+ const result = await fetchData(data.id)
113
+ ack(false, result) // Success: ack(error, ...response)
114
+ } catch (error) {
115
+ ack(error.message) // Error: ack(errorMessage)
116
+ }
117
+ })
126
118
  ```
127
119
 
128
- **Parameters:**
129
- - `hostOrigin` (optional) - Restrict connections to specific origin
130
-
131
- #### `disconnect(callback?)`
132
-
133
- Disconnect and clean up all resources.
120
+ ### Wait for Connection
134
121
 
135
122
  ```javascript
136
- iof.disconnect(() => {
137
- console.log('Disconnected!')
138
- })
139
- ```
123
+ // Wait for connection with timeout
124
+ try {
125
+ await iframeIO.connectAsync(5000) // 5 second timeout
126
+ console.log('Connection established!')
127
+ } catch (error) {
128
+ console.error('Connection failed:', error.message)
129
+ }
140
130
 
141
- ### Messaging Methods
131
+ // Wait for single event
132
+ const userData = await iframeIO.onceAsync('userProfile')
133
+ console.log('User data received:', userData)
134
+ ```
142
135
 
143
- #### `emit(event, payload?, callback?)`
136
+ ## Enhanced Connection Management
144
137
 
145
- Send a message to the peer.
138
+ ### Auto-Reconnection
146
139
 
147
140
  ```javascript
148
- // Simple message
149
- iof.emit('myEvent', { data: 'hello' })
150
-
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)
157
- }
141
+ // Handle connection events
142
+ iframeIO.on('disconnect', (data) => {
143
+ console.log('Disconnected:', data.reason)
158
144
  })
159
145
 
160
- // Callback as second parameter
161
- iof.emit('myEvent', (error, response) => {
162
- console.log('Response:', response)
146
+ iframeIO.on('reconnecting', (data) => {
147
+ console.log(`Reconnection attempt ${data.attempt}, delay: ${data.delay}ms`)
163
148
  })
164
- ```
165
-
166
- #### `on(event, listener)`
167
149
 
168
- Add event listener.
169
-
170
- ```javascript
171
- iof.on('myEvent', (data, ack) => {
172
- console.log('Received:', data)
173
-
174
- // Send acknowledgment (optional)
175
- if (ack) ack(false, 'Success response')
150
+ iframeIO.on('reconnection_failed', (data) => {
151
+ console.error(`Failed to reconnect after ${data.attempts} attempts`)
176
152
  })
177
153
  ```
178
154
 
179
- #### `once(event, listener)`
180
-
181
- Add one-time event listener.
155
+ ### Connection Statistics
182
156
 
183
157
  ```javascript
184
- iof.once('myEvent', (data) => {
185
- console.log('This will only fire once:', data)
186
- })
158
+ const stats = iframeIO.getStats()
159
+ console.log(stats)
160
+ // {
161
+ // connected: true,
162
+ // peerType: 'WINDOW',
163
+ // origin: 'https://example.com',
164
+ // lastHeartbeat: 1609459200000,
165
+ // queuedMessages: 0,
166
+ // reconnectAttempts: 0,
167
+ // activeListeners: 5,
168
+ // messageRate: 2
169
+ // }
187
170
  ```
188
171
 
189
- #### `off(event, listener?)`
172
+ ## Security Features
190
173
 
191
- Remove event listener(s).
174
+ ### Origin Validation
192
175
 
193
176
  ```javascript
194
- // Remove specific listener
195
- iof.off('myEvent', myListener)
177
+ // Strict origin checking
178
+ iframeIO.listen('https://trusted-domain.com') // Only accept from this origin
196
179
 
197
- // Remove all listeners for event
198
- iof.off('myEvent')
180
+ // Error handling for invalid origins
181
+ iframeIO.on('error', (error) => {
182
+ if (error.type === 'INVALID_ORIGIN') {
183
+ console.log(`Rejected message from ${error.received}`)
184
+ }
185
+ })
199
186
  ```
200
187
 
201
- #### `removeListeners(callback?)`
202
-
203
- Remove all event listeners.
188
+ ### Message Sanitization
204
189
 
205
190
  ```javascript
206
- iof.removeListeners(() => {
207
- console.log('All listeners removed')
191
+ // Automatic payload sanitization removes functions and undefined values
192
+ iframeIO.emit('data', {
193
+ text: 'Hello',
194
+ func: () => {}, // Functions are automatically removed
195
+ undef: undefined // Undefined values are automatically removed
208
196
  })
209
197
  ```
210
198
 
211
- ### Async Methods
212
-
213
- #### `emitAsync(event, payload?)`
214
-
215
- Send message and return Promise.
199
+ ### Rate Limiting
216
200
 
217
201
  ```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
- }
224
- ```
225
-
226
- #### `onceAsync(event)`
227
-
228
- Wait for single event occurrence.
202
+ const iframeIO = new IOF({
203
+ maxMessagesPerSecond: 10 // Limit to 10 messages per second
204
+ })
229
205
 
230
- ```javascript
231
- const data = await iof.onceAsync('dataReady')
232
- console.log('Data received:', data)
206
+ iframeIO.on('error', (error) => {
207
+ if (error.type === 'RATE_LIMIT_EXCEEDED') {
208
+ console.log(`Rate limited: ${error.current}/${error.limit}`)
209
+ }
210
+ })
233
211
  ```
234
212
 
235
- #### `connectAsync(timeout?)`
236
-
237
- Wait for connection to be established.
213
+ ## Comprehensive Error Handling
238
214
 
239
215
  ```javascript
240
- try {
241
- await iof.connectAsync(5000) // 5 second timeout
242
- console.log('Connected!')
243
- } catch (error) {
244
- console.error('Connection timeout')
245
- }
216
+ iframeIO.on('error', (error) => {
217
+ switch (error.type) {
218
+ case 'INVALID_ORIGIN':
219
+ console.error(`Invalid origin: expected ${error.expected}, got ${error.received}`)
220
+ break
221
+ case 'ORIGIN_MISMATCH':
222
+ console.error(`Origin mismatch: expected ${error.expected}, got ${error.received}`)
223
+ break
224
+ case 'RATE_LIMIT_EXCEEDED':
225
+ console.warn(`Rate limit exceeded: ${error.current}/${error.limit} messages/second`)
226
+ break
227
+ case 'MESSAGE_HANDLING_ERROR':
228
+ console.error(`Error handling event ${error.event}: ${error.error}`)
229
+ break
230
+ case 'EMIT_ERROR':
231
+ console.error(`Error sending event ${error.event}: ${error.error}`)
232
+ break
233
+ case 'LISTENER_ERROR':
234
+ console.error(`Error in listener for ${error.event}: ${error.error}`)
235
+ break
236
+ case 'NO_CONNECTION':
237
+ console.error(`Attempted to send ${error.event} without connection`)
238
+ break
239
+ default:
240
+ console.error('Unknown error:', error)
241
+ }
242
+ })
246
243
  ```
247
244
 
248
- ### Utility Methods
245
+ ## Message Queuing
249
246
 
250
- #### `isConnected()`
247
+ ```javascript
248
+ // Messages are automatically queued when disconnected
249
+ iframeIO.emit('important-data', { data: 'This will be queued if disconnected' })
251
250
 
252
- Check if connection is active.
251
+ // Clear queue manually if needed
252
+ iframeIO.clearQueue()
253
253
 
254
- ```javascript
255
- if (iof.isConnected()) {
256
- console.log('Connection is active')
257
- }
254
+ // Check queue status
255
+ const stats = iframeIO.getStats()
256
+ console.log(`${stats.queuedMessages} messages queued`)
258
257
  ```
259
258
 
260
- #### `getStats()`
261
-
262
- Get connection statistics.
259
+ ## API Reference
263
260
 
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
- ```
261
+ ### New Methods
280
262
 
281
- #### `clearQueue()`
263
+ #### Async Methods
264
+ - **`emitAsync(event, payload?, timeout?)`** - Send message and wait for response (Promise)
265
+ - **`connectAsync(timeout?)`** - Wait for connection with timeout (Promise)
266
+ - **`onceAsync(event)`** - Wait for single event (Promise)
282
267
 
283
- Clear queued messages.
268
+ #### Utility Methods
269
+ - **`getStats()`** - Get connection statistics
270
+ - **`clearQueue()`** - Clear queued messages
284
271
 
285
- ```javascript
286
- iof.clearQueue()
287
- ```
272
+ ### Connection Methods
288
273
 
289
- ## Events
274
+ - **`initiate(contentWindow, iframeOrigin)`** - Establish connection (WINDOW peer only)
275
+ - **`listen(hostOrigin?)`** - Listen for connection (IFRAME peer only)
276
+ - **`disconnect(callback?)`** - Disconnect and cleanup
277
+ - **`isConnected()`** - Check connection status
290
278
 
291
- ### Built-in Events
279
+ ### Messaging Methods
292
280
 
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 }` |
281
+ - **`emit(event, payload?, callback?)`** - Send message
282
+ - **`on(event, listener)`** - Add event listener
283
+ - **`once(event, listener)`** - Add one-time event listener
284
+ - **`off(event, listener?)`** - Remove event listener(s)
285
+ - **`removeListeners(callback?)`** - Remove all listeners
300
286
 
301
- ### Error Types
287
+ ### Events
302
288
 
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
289
+ #### Connection Events
290
+ - **`connect`** - Connection established
291
+ - **`disconnect`** - Connection lost with reason
292
+ - **`reconnecting`** - Reconnection attempt started
293
+ - **`reconnection_failed`** - All reconnection attempts failed
310
294
 
311
- ## Advanced Usage
295
+ #### Error Events
296
+ - **`error`** - Various error conditions with detailed error objects
312
297
 
313
- ### Message Acknowledgments
298
+ ## TypeScript Support
314
299
 
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
- })
300
+ Full TypeScript support with comprehensive type definitions:
324
301
 
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
- ```
302
+ ```typescript
303
+ import IOF, { Options, Listener, AckFunction } from 'iframe.io'
335
304
 
336
- ### Connection Monitoring
305
+ const options: Options = {
306
+ type: 'WINDOW',
307
+ debug: true,
308
+ heartbeatInterval: 30000,
309
+ maxMessageSize: 512 * 1024
310
+ }
337
311
 
338
- ```javascript
339
- const iof = new IOF({
340
- heartbeatInterval: 10000, // 10 seconds
341
- connectionTimeout: 5000, // 5 seconds
342
- autoReconnect: true
343
- })
312
+ const iframeIO = new IOF(options)
344
313
 
345
- iof.on('disconnect', ({ reason }) => {
346
- console.log('Connection lost:', reason)
314
+ // Typed event listeners
315
+ iframeIO.on('userAction', (data: { action: string; userId: number }) => {
316
+ console.log(`User ${data.userId} performed ${data.action}`)
347
317
  })
348
318
 
349
- iof.on('reconnecting', ({ attempt, delay }) => {
350
- console.log(`Reconnecting (${attempt}/5) in ${delay}ms`)
351
- })
319
+ // Typed async responses
320
+ interface ApiResponse {
321
+ success: boolean
322
+ data: any[]
323
+ }
352
324
 
353
- iof.on('reconnection_failed', ({ attempts }) => {
354
- console.log(`Failed to reconnect after ${attempts} attempts`)
355
- })
325
+ const response = await iframeIO.emitAsync<{ query: string }, ApiResponse>(
326
+ 'search',
327
+ { query: 'hello' },
328
+ 5000 // 5 second timeout
329
+ )
356
330
  ```
357
331
 
358
- ### Message Queuing
332
+ ## Error Types Reference
359
333
 
360
- ```javascript
361
- const iof = new IOF({
362
- messageQueueSize: 100,
363
- autoReconnect: true
364
- })
334
+ | Error Type | Description |
335
+ |------------|-------------|
336
+ | `INVALID_ORIGIN` | Message from unexpected origin |
337
+ | `ORIGIN_MISMATCH` | Origin changed during session |
338
+ | `MESSAGE_HANDLING_ERROR` | Error processing incoming message |
339
+ | `EMIT_ERROR` | Error sending message |
340
+ | `LISTENER_ERROR` | Error in event listener |
341
+ | `RATE_LIMIT_EXCEEDED` | Too many messages sent |
342
+ | `NO_CONNECTION` | Attempted to send without connection |
365
343
 
366
- // Messages sent while disconnected are automatically queued
367
- iof.emit('queuedMessage', { data: 'This will be queued if disconnected' })
344
+ ## Browser Compatibility
368
345
 
369
- // Check queue status
370
- const stats = iof.getStats()
371
- console.log(`Queued messages: ${stats.queuedMessages}`)
372
- ```
346
+ - Chrome 60+
347
+ - Firefox 55+
348
+ - Safari 12+
349
+ - Edge 79+
373
350
 
374
- ### Rate Limiting
351
+ ## Migration Guide
375
352
 
376
- ```javascript
377
- const iof = new IOF({
378
- maxMessagesPerSecond: 50,
379
- maxMessageSize: 512 * 1024 // 512KB
380
- })
353
+ ### From v1.0.x to v1.1.0
381
354
 
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
355
+ All existing code continues to work without changes. New features are additive:
390
356
 
391
357
  ```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')
358
+ // Old way (still works)
359
+ iframeIO.emit('getData', { id: 123 }, (error, result) => {
360
+ if (error) {
361
+ console.error('Error:', error)
362
+ } else {
363
+ console.log('Result:', result)
406
364
  }
407
- // Process valid data...
408
365
  })
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
366
 
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
367
+ // New async way
368
+ try {
369
+ const result = await iframeIO.emitAsync('getData', { id: 123 })
370
+ console.log('Result:', result)
371
+ } catch (error) {
372
+ console.error('Error:', error.message)
431
373
  }
374
+ ```
432
375
 
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
- })
376
+ ## Performance Considerations
440
377
 
441
- // Type-safe async emissions
442
- const response = await iof.emitAsync<{ query: string }, { result: any }>('search', {
443
- query: 'typescript'
444
- })
445
- ```
378
+ - **Message Size**: Keep messages under the configured `maxMessageSize` (default 1MB)
379
+ - **Rate Limiting**: Respect the `maxMessagesPerSecond` limit (default 100/sec)
380
+ - **Queue Size**: Monitor queued messages to avoid memory issues
381
+ - **Heartbeat**: Adjust `heartbeatInterval` based on your reliability needs
446
382
 
447
383
  ## License
448
384
 
@@ -456,4 +392,4 @@ Contributions are welcome! Please read our contributing guidelines and submit pu
456
392
 
457
393
  - Create an issue on GitHub for bug reports
458
394
  - Check existing issues for common problems
459
- - Review the documentation for usage examples
395
+ - Review the documentation for usage examples
package/dist/index.js CHANGED
@@ -242,7 +242,8 @@ var IOF = /** @class */ (function () {
242
242
  _this.startHeartbeat();
243
243
  _this.fire('connect');
244
244
  _this.processMessageQueue();
245
- return _this.debug("[".concat(_this.peer.type, "] connected"));
245
+ _this.debug("[".concat(_this.peer.type, "] connected"));
246
+ return;
246
247
  }
247
248
  // Fire available event listeners
248
249
  _this.fire(_event, payload, cid);
@@ -326,7 +327,8 @@ var IOF = /** @class */ (function () {
326
327
  _this.startHeartbeat();
327
328
  _this.fire('connect');
328
329
  _this.processMessageQueue();
329
- return _this.debug("[".concat(_this.peer.type, "] connected"));
330
+ _this.debug("[".concat(_this.peer.type, "] connected"));
331
+ return;
330
332
  }
331
333
  // Fire available event listeners
332
334
  _this.fire(_event, payload, cid);
@@ -346,8 +348,10 @@ var IOF = /** @class */ (function () {
346
348
  IOF.prototype.fire = function (_event, payload, cid) {
347
349
  var _this = this;
348
350
  // Volatile event - check if any listeners exist
349
- if (!this.Events[_event] && !this.Events[_event + '--@once'])
350
- return this.debug("[".concat(this.peer.type, "] No <").concat(_event, "> listener defined"));
351
+ if (!this.Events[_event] && !this.Events[_event + '--@once']) {
352
+ this.debug("[".concat(this.peer.type, "] No <").concat(_event, "> listener defined"));
353
+ return;
354
+ }
351
355
  var ackFn = cid
352
356
  ? function (error) {
353
357
  var args = [];
@@ -541,7 +545,7 @@ var IOF = /** @class */ (function () {
541
545
  }
542
546
  };
543
547
  IOF.prototype.disconnect = function (fn) {
544
- // Clean disconnect method
548
+ // Cleanup on disconnect
545
549
  this.cleanup();
546
550
  this.peer.connected = false;
547
551
  this.peer.source = undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iframe.io",
3
- "version": "1.0.6",
3
+ "version": "1.1.0",
4
4
  "description": "Easy and friendly API to connect and interact between content window and its containing iframe",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
package/src/index.ts CHANGED
@@ -312,11 +312,13 @@ export default class IOF {
312
312
  this.peer.connected = true
313
313
  this.reconnectAttempts = 0
314
314
  this.peer.lastHeartbeat = Date.now()
315
+
315
316
  this.startHeartbeat()
316
317
  this.fire('connect')
317
318
  this.processMessageQueue()
319
+ this.debug(`[${this.peer.type}] connected`)
318
320
 
319
- return this.debug(`[${this.peer.type}] connected`)
321
+ return
320
322
  }
321
323
 
322
324
  // Fire available event listeners
@@ -347,6 +349,7 @@ export default class IOF {
347
349
  this.peer.type = 'IFRAME' // iframe.io connection listener is automatically set as IFRAME
348
350
  this.peer.connected = false
349
351
  this.reconnectAttempts = 0
352
+
350
353
  this.debug(`[${this.peer.type}] Listening to connect${hostOrigin ? `: Host <${hostOrigin}>` : ''}`)
351
354
 
352
355
  // Clean up existing listener if any
@@ -414,7 +417,8 @@ export default class IOF {
414
417
  this.fire('connect')
415
418
  this.processMessageQueue()
416
419
 
417
- return this.debug(`[${this.peer.type}] connected`)
420
+ this.debug(`[${this.peer.type}] connected`)
421
+ return
418
422
  }
419
423
 
420
424
  // Fire available event listeners
@@ -437,8 +441,10 @@ export default class IOF {
437
441
 
438
442
  fire( _event: string, payload?: MessageData['payload'], cid?: string ){
439
443
  // Volatile event - check if any listeners exist
440
- if( !this.Events[_event] && !this.Events[_event + '--@once'] )
441
- return this.debug(`[${this.peer.type}] No <${_event}> listener defined`)
444
+ if( !this.Events[_event] && !this.Events[_event + '--@once'] ){
445
+ this.debug(`[${this.peer.type}] No <${_event}> listener defined`)
446
+ return
447
+ }
442
448
 
443
449
  const ackFn = cid
444
450
  ? ( error: boolean | string, ...args: any[] ): void => {
@@ -590,7 +596,7 @@ export default class IOF {
590
596
  return new Promise(( resolve, reject ) => {
591
597
  const timeoutId = setTimeout(() => {
592
598
  reject( new Error(`Event '${_event}' acknowledgment timeout after ${timeout}ms`) )
593
- }, timeout)
599
+ }, timeout )
594
600
 
595
601
  try {
596
602
  this.emit( _event, payload, ( error, ...args ) => {
@@ -646,7 +652,7 @@ export default class IOF {
646
652
  }
647
653
 
648
654
  disconnect( fn?: () => void ){
649
- // Clean disconnect method
655
+ // Cleanup on disconnect
650
656
  this.cleanup()
651
657
 
652
658
  this.peer.connected = false
@@ -656,6 +662,7 @@ export default class IOF {
656
662
  this.messageQueue = []
657
663
  this.messageRateTracker = []
658
664
  this.reconnectAttempts = 0
665
+
659
666
  this.removeListeners()
660
667
 
661
668
  typeof fn == 'function' && fn()