webview.io 1.0.4 → 1.0.6

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/dist/index.d.ts CHANGED
@@ -78,6 +78,9 @@ export default class WIO {
78
78
  initiate(webViewRef: RefObject<WebView>, origin: string): this;
79
79
  /**
80
80
  * Listening to connection from the WebView host
81
+ *
82
+ * NOTE: This is called manually from page code,
83
+ * not auto-initialized
81
84
  */
82
85
  listen(hostOrigin?: string): this;
83
86
  /**
@@ -115,6 +118,7 @@ export default class WIO {
115
118
  /**
116
119
  * Get injected JavaScript for WebView
117
120
  * Sets up the EMBEDDED side of the bridge
121
+ * NOTE: Does not auto-initialize - page must call window._wio.listen()
118
122
  */
119
123
  getInjectedJavaScript(): string;
120
124
  }
package/dist/index.js CHANGED
@@ -143,13 +143,9 @@ var WIO = /** @class */ (function () {
143
143
  _this.connectionAttempts = 0;
144
144
  _this.connectionToken = generateToken();
145
145
  // Re-initiate connection for WEBVIEW type
146
- if (_this.peer.type === 'WEBVIEW') {
147
- _this.startConnectionAttempt();
148
- }
146
+ _this.peer.type === 'WEBVIEW' && _this.startConnectionAttempt();
149
147
  // For EMBEDDED type, announce readiness
150
- if (_this.peer.type === 'EMBEDDED') {
151
- _this.announceEmbeddedReady();
152
- }
148
+ _this.peer.type === 'EMBEDDED' && _this.announceEmbeddedReady();
153
149
  // Set timeout for this reconnection attempt
154
150
  setTimeout(function () {
155
151
  if (_this.peer.connected)
@@ -181,9 +177,8 @@ var WIO = /** @class */ (function () {
181
177
  _this.debug("[".concat(_this.peer.type, "] Connection attempt ").concat(_this.connectionAttempts, "/").concat(_this.options.maxConnectionAttempts));
182
178
  _this.emit('ping', { token: _this.connectionToken });
183
179
  }
184
- else {
180
+ else
185
181
  _this.stopConnectionAttempt();
186
- }
187
182
  }, this.options.connectionPingInterval);
188
183
  // Set overall timeout
189
184
  this.connectionAttemptTimer = setTimeout(function () {
@@ -225,16 +220,15 @@ var WIO = /** @class */ (function () {
225
220
  _this.debug("[".concat(_this.peer.type, "] Ready announcement attempt ").concat(attempts, "/").concat(maxAttempts));
226
221
  _this.emit('__embedded_ready');
227
222
  }
228
- else {
223
+ else
229
224
  _this.stopEmbeddedReadyAnnouncement();
230
- }
231
225
  }, this.options.connectionPingInterval);
232
226
  };
233
227
  WIO.prototype.stopEmbeddedReadyAnnouncement = function () {
234
- if (this.embeddedReadyCheckInterval) {
235
- clearInterval(this.embeddedReadyCheckInterval);
236
- this.embeddedReadyCheckInterval = undefined;
237
- }
228
+ if (!this.embeddedReadyCheckInterval)
229
+ return;
230
+ clearInterval(this.embeddedReadyCheckInterval);
231
+ this.embeddedReadyCheckInterval = undefined;
238
232
  };
239
233
  // Message rate limiting
240
234
  WIO.prototype.checkRateLimit = function () {
@@ -257,8 +251,8 @@ var WIO = /** @class */ (function () {
257
251
  };
258
252
  // Queue messages when not connected
259
253
  WIO.prototype.queueMessage = function (_event, payload, fn) {
254
+ // Remove oldest message
260
255
  if (this.messageQueue.length >= this.options.messageQueueSize) {
261
- // Remove oldest message
262
256
  var removed = this.messageQueue.shift();
263
257
  this.debug("[".concat(this.peer.type, "] Message queue full, removed oldest message:"), removed === null || removed === void 0 ? void 0 : removed._event);
264
258
  }
@@ -311,6 +305,9 @@ var WIO = /** @class */ (function () {
311
305
  };
312
306
  /**
313
307
  * Listening to connection from the WebView host
308
+ *
309
+ * NOTE: This is called manually from page code,
310
+ * not auto-initialized
314
311
  */
315
312
  WIO.prototype.listen = function (hostOrigin) {
316
313
  var _this = this;
@@ -320,9 +317,7 @@ var WIO = /** @class */ (function () {
320
317
  this.reconnectAttempts = 0;
321
318
  this.debug("[".concat(this.peer.type, "] Listening to connect").concat(hostOrigin ? ": Host <".concat(hostOrigin, ">") : ''));
322
319
  // Start announcing readiness
323
- setTimeout(function () {
324
- _this.announceEmbeddedReady();
325
- }, 100);
320
+ setTimeout(function () { return _this.announceEmbeddedReady(); }, 100);
326
321
  return this;
327
322
  };
328
323
  /**
@@ -359,9 +354,9 @@ var WIO = /** @class */ (function () {
359
354
  this.peer.embeddedReady = true;
360
355
  this.debug("[".concat(this.peer.type, "] Embedded peer ready"));
361
356
  // If we're WEBVIEW and not connected, send ping
362
- if (this.peer.type === 'WEBVIEW' && !this.peer.connected) {
363
- this.emit('ping', { token: this.connectionToken });
364
- }
357
+ this.peer.type === 'WEBVIEW'
358
+ && !this.peer.connected
359
+ && this.emit('ping', { token: this.connectionToken });
365
360
  return;
366
361
  }
367
362
  // Handle webview ready signal
@@ -583,9 +578,7 @@ var WIO = /** @class */ (function () {
583
578
  var _this = this;
584
579
  if (timeout === void 0) { timeout = 5000; }
585
580
  return new Promise(function (resolve, reject) {
586
- var timeoutId = setTimeout(function () {
587
- reject(new Error("Event '".concat(_event, "' acknowledgment timeout after ").concat(timeout, "ms")));
588
- }, timeout);
581
+ var timeoutId = setTimeout(function () { return reject(new Error("Event '".concat(_event, "' acknowledgment timeout after ").concat(timeout, "ms"))); }, timeout);
589
582
  try {
590
583
  _this.emit(_event, payload, function (error) {
591
584
  var args = [];
@@ -677,9 +670,10 @@ var WIO = /** @class */ (function () {
677
670
  /**
678
671
  * Get injected JavaScript for WebView
679
672
  * Sets up the EMBEDDED side of the bridge
673
+ * NOTE: Does not auto-initialize - page must call window._wio.listen()
680
674
  */
681
675
  WIO.prototype.getInjectedJavaScript = function () {
682
- return "\n (function() {\n try {\n console.log('[EMBEDDED] Initializing WIO bridge...')\n \n const RESERVED_EVENTS = [\n 'ping',\n 'pong',\n '__heartbeat',\n '__heartbeat_response',\n '__embedded_ready',\n '__connection_ack',\n '__webview_ready'\n ]\n \n // Use closure variable to avoid 'this' binding issues\n window._wio = {\n type: 'EMBEDDED',\n connected: false,\n Events: {},\n messageQueue: [],\n connectionToken: null,\n setupComplete: false,\n\n listen: function(){\n console.log('[EMBEDDED] Setting up message listeners...')\n\n // Listen to messages from React Native\n window.addEventListener('message', function( event ){\n try {\n const message = typeof event.data === 'string' ? JSON.parse( event.data ) : event.data\n window._wio.handleMessage( message ) // Use window._wio instead of this\n }\n catch( error ){ console.error('[EMBEDDED] Parse error:', error ) }\n })\n \n // Android support\n if( typeof document !== 'undefined' ){\n document.addEventListener('message', function( event ){\n try {\n const message = typeof event.data === 'string' ? JSON.parse( event.data ) : event.data\n window._wio.handleMessage( message ) // Use window._wio instead of this\n }\n catch( error ){ console.error('[EMBEDDED] Parse error:', error ) }\n })\n }\n\n window._wio.setupComplete = true // Use window._wio instead of this\n console.log('[EMBEDDED] Setup complete')\n\n return window._wio\n },\n \n ackId: function(){\n const\n rmin = 100000,\n rmax = 999999,\n timestamp = Date.now(),\n random = Math.floor( Math.random() * ( rmax - rmin + 1 ) + rmin )\n\n return timestamp + '_' + random\n },\n \n fire: function( _event, payload, cid ){\n if( !window._wio.Events[_event] && !window._wio.Events[_event + '--@once'] ){\n console.log('[EMBEDDED] No listener for:', _event)\n return\n }\n \n const ackFn = cid\n ? ( error, ...args ) => window._wio.emit( _event + '--' + cid + '--@ack', { error: error || false, args } )\n : undefined\n \n let listeners = []\n if( window._wio.Events[_event + '--@once'] ){\n _event += '--@once'\n listeners = window._wio.Events[_event]\n\n delete window._wio.Events[_event]\n }\n else listeners = window._wio.Events[_event] || []\n \n listeners.forEach( fn => {\n try { payload !== undefined ? fn( payload, ackFn ) : fn( ackFn ) }\n catch( error ){ console.error('[EMBEDDED] Listener error:', error ) }\n })\n },\n \n emit: function( _event, payload, fn ){\n if( typeof payload === 'function' ){\n fn = payload\n payload = undefined\n }\n \n if( !window._wio.connected && !RESERVED_EVENTS.includes(_event) ){\n window._wio.messageQueue.push({ _event, payload, fn, timestamp: Date.now() })\n console.log('[EMBEDDED] Queued message:', _event)\n return\n }\n \n try {\n let cid\n if( typeof fn === 'function' ){\n cid = window._wio.ackId()\n window._wio.once( _event + '--' + cid + '--@ack', ({ error, args }) => fn( error, ...args ) )\n }\n \n const messageData = {\n _event,\n payload,\n cid,\n timestamp: Date.now(),\n token: RESERVED_EVENTS.includes(_event) ? window._wio.connectionToken : undefined\n }\n \n if( typeof window.ReactNativeWebView !== 'undefined' )\n window.ReactNativeWebView.postMessage( JSON.stringify( messageData ) )\n else console.error('[EMBEDDED] ReactNativeWebView not available')\n }\n catch( error ){\n console.error('[EMBEDDED] Emit error:', error )\n typeof fn === 'function' && fn( String(error) )\n }\n },\n \n on: function( _event, fn ){\n if( !window._wio.Events[_event] ) window._wio.Events[_event] = []\n window._wio.Events[_event].push( fn )\n\n return window._wio\n },\n \n once: function( _event, fn ){\n _event += '--@once'\n if( !window._wio.Events[_event] ) window._wio.Events[_event] = []\n\n window._wio.Events[_event].push( fn )\n\n return window._wio\n },\n \n off: function( _event, fn ){\n if( fn && window._wio.Events[_event] ){\n const index = window._wio.Events[_event].indexOf( fn )\n if( index > -1 ){\n window._wio.Events[_event].splice( index, 1 )\n if( window._wio.Events[_event].length === 0 ) delete window._wio.Events[_event]\n }\n }\n else delete window._wio.Events[_event]\n\n return window._wio\n },\n \n processMessageQueue: function(){\n if( !window._wio.connected || window._wio.messageQueue.length === 0 ) return\n \n console.log('[EMBEDDED] Processing', window._wio.messageQueue.length, 'queued messages')\n const queue = [ ...window._wio.messageQueue ]\n window._wio.messageQueue = []\n \n queue.forEach( msg => {\n try { window._wio.emit( msg._event, msg.payload, msg.fn ) }\n catch( error ){ console.error('[EMBEDDED] Queue process error:', error ) }\n })\n },\n \n handleMessage: function( data ){\n if( !data || !data._event ) return\n \n const { _event, payload, cid, token } = data\n \n console.log('[EMBEDDED] Received:', _event )\n \n // Handle heartbeat response\n if( _event === '__heartbeat_response' )\n return\n \n // Handle heartbeat request\n if( _event === '__heartbeat' ){\n window._wio.emit('__heartbeat_response', { timestamp: Date.now() })\n return\n }\n \n // Handle webview ready signal\n if( _event === '__webview_ready' ){\n console.log('[EMBEDDED] WebView ready signal received')\n return\n }\n \n // Handle ping from WEBVIEW\n if( _event === 'ping' ){\n console.log('[EMBEDDED] Received ping, sending pong')\n window._wio.connectionToken = token\n\n window._wio.emit('pong', { token: window._wio.connectionToken })\n return\n }\n \n // Handle connection acknowledgment\n if( _event === '__connection_ack' ){\n if( token && token !== window._wio.connectionToken ){\n console.error('[EMBEDDED] Invalid connection token in ack')\n return\n }\n \n console.log('[EMBEDDED] Connection established (received ack)')\n\n window._wio.connected = true\n window._wio.processMessageQueue()\n window._wio.fire('connect')\n\n return\n }\n \n // Fire event listeners\n window._wio.fire( _event, payload, cid )\n },\n \n announceReady: function(){\n let attempts = 0\n const maxAttempts = 5\n const interval = 2000\n \n console.log('[EMBEDDED] Starting ready announcements')\n \n const announce = () => {\n if( window._wio.connected ){\n console.log('[EMBEDDED] Connected, stopping announcements')\n return\n }\n \n attempts++\n if( attempts > maxAttempts ){\n console.log('[EMBEDDED] Max announcement attempts reached')\n return\n }\n \n console.log('[EMBEDDED] Announcing ready (attempt', attempts + '/' + maxAttempts + ')')\n window._wio.emit('__embedded_ready')\n \n setTimeout( announce, interval )\n }\n \n announce()\n }\n }\n\n // Initialize\n wio.listen()\n // Start announcing readiness after a short delay\n setTimeout(() => wio.announceReady(), 100)\n \n console.log('[EMBEDDED] WIO bridge initialized successfully')\n }\n catch( error ){\n console.error('[EMBEDDED] Setup failed:', error )\n \n // Create minimal fallback\n window._wio = {\n error: error.toString(),\n emit: function(){ console.error('[EMBEDDED] WIO failed to initialize') },\n on: function(){},\n once: function(){},\n off: function(){}\n }\n }\n\n true\n })()\n ";
676
+ return "\n (function() {\n try {\n console.log('[EMBEDDED] Initializing WIO bridge...')\n \n const RESERVED_EVENTS = [\n 'ping',\n 'pong',\n '__heartbeat',\n '__heartbeat_response',\n '__embedded_ready',\n '__connection_ack',\n '__webview_ready'\n ]\n \n // Use closure variable to avoid 'this' binding issues\n window._wio = {\n type: 'EMBEDDED',\n connected: false,\n Events: {},\n messageQueue: [],\n connectionToken: null,\n setupComplete: false,\n\n listen: function(){\n if( this.setupComplete ){\n console.warn('[EMBEDDED] Already listening')\n return this\n }\n\n console.log('[EMBEDDED] Setting up message listeners...')\n\n // Listen to messages from React Native\n window.addEventListener('message', function( event ){\n try {\n const message = typeof event.data === 'string' ? JSON.parse( event.data ) : event.data\n window._wio.handleMessage( message )\n }\n catch( error ){ console.error('[EMBEDDED] Parse error:', error ) }\n })\n \n // Android support\n if( typeof document !== 'undefined' ){\n document.addEventListener('message', function( event ){\n try {\n const message = typeof event.data === 'string' ? JSON.parse( event.data ) : event.data\n window._wio.handleMessage( message )\n }\n catch( error ){ console.error('[EMBEDDED] Parse error:', error ) }\n })\n }\n\n this.setupComplete = true\n console.log('[EMBEDDED] Setup complete, starting ready announcements')\n\n // Start announcing readiness\n this.announceReady()\n\n return this\n },\n \n ackId: function(){\n const\n rmin = 100000,\n rmax = 999999,\n timestamp = Date.now(),\n random = Math.floor( Math.random() * ( rmax - rmin + 1 ) + rmin )\n\n return timestamp + '_' + random\n },\n \n fire: function( _event, payload, cid ){\n if( !window._wio.Events[_event] && !window._wio.Events[_event + '--@once'] ){\n console.log('[EMBEDDED] No listener for:', _event)\n return\n }\n \n const ackFn = cid\n ? ( error, ...args ) => window._wio.emit( _event + '--' + cid + '--@ack', { error: error || false, args } )\n : undefined\n \n let listeners = []\n if( window._wio.Events[_event + '--@once'] ){\n _event += '--@once'\n listeners = window._wio.Events[_event]\n\n delete window._wio.Events[_event]\n }\n else listeners = window._wio.Events[_event] || []\n \n listeners.forEach( fn => {\n try { payload !== undefined ? fn( payload, ackFn ) : fn( ackFn ) }\n catch( error ){ console.error('[EMBEDDED] Listener error:', error ) }\n })\n },\n \n emit: function( _event, payload, fn ){\n if( typeof payload === 'function' ){\n fn = payload\n payload = undefined\n }\n \n if( !window._wio.connected && !RESERVED_EVENTS.includes(_event) ){\n window._wio.messageQueue.push({ _event, payload, fn, timestamp: Date.now() })\n console.log('[EMBEDDED] Queued message:', _event)\n return\n }\n \n try {\n let cid\n if( typeof fn === 'function' ){\n cid = window._wio.ackId()\n window._wio.once( _event + '--' + cid + '--@ack', ({ error, args }) => fn( error, ...args ) )\n }\n \n const messageData = {\n _event,\n payload,\n cid,\n timestamp: Date.now(),\n token: RESERVED_EVENTS.includes(_event) ? window._wio.connectionToken : undefined\n }\n \n if( typeof window.ReactNativeWebView !== 'undefined' )\n window.ReactNativeWebView.postMessage( JSON.stringify( messageData ) )\n else console.error('[EMBEDDED] ReactNativeWebView not available')\n }\n catch( error ){\n console.error('[EMBEDDED] Emit error:', error )\n typeof fn === 'function' && fn( String(error) )\n }\n },\n \n on: function( _event, fn ){\n if( !window._wio.Events[_event] ) window._wio.Events[_event] = []\n window._wio.Events[_event].push( fn )\n\n return window._wio\n },\n \n once: function( _event, fn ){\n _event += '--@once'\n if( !window._wio.Events[_event] ) window._wio.Events[_event] = []\n\n window._wio.Events[_event].push( fn )\n\n return window._wio\n },\n \n off: function( _event, fn ){\n if( fn && window._wio.Events[_event] ){\n const index = window._wio.Events[_event].indexOf( fn )\n if( index > -1 ){\n window._wio.Events[_event].splice( index, 1 )\n if( window._wio.Events[_event].length === 0 ) delete window._wio.Events[_event]\n }\n }\n else delete window._wio.Events[_event]\n\n return window._wio\n },\n \n processMessageQueue: function(){\n if( !window._wio.connected || window._wio.messageQueue.length === 0 ) return\n \n console.log('[EMBEDDED] Processing', window._wio.messageQueue.length, 'queued messages')\n const queue = [ ...window._wio.messageQueue ]\n window._wio.messageQueue = []\n \n queue.forEach( msg => {\n try { window._wio.emit( msg._event, msg.payload, msg.fn ) }\n catch( error ){ console.error('[EMBEDDED] Queue process error:', error ) }\n })\n },\n \n handleMessage: function( data ){\n if( !data || !data._event ) return\n \n const { _event, payload, cid, token } = data\n \n console.log('[EMBEDDED] Received:', _event )\n \n // Handle heartbeat response\n if( _event === '__heartbeat_response' )\n return\n \n // Handle heartbeat request\n if( _event === '__heartbeat' ){\n window._wio.emit('__heartbeat_response', { timestamp: Date.now() })\n return\n }\n \n // Handle webview ready signal\n if( _event === '__webview_ready' ){\n console.log('[EMBEDDED] WebView ready signal received')\n return\n }\n \n // Handle ping from WEBVIEW\n if( _event === 'ping' ){\n console.log('[EMBEDDED] Received ping, sending pong')\n window._wio.connectionToken = token\n\n window._wio.emit('pong', { token: window._wio.connectionToken })\n return\n }\n \n // Handle connection acknowledgment\n if( _event === '__connection_ack' ){\n if( token && token !== window._wio.connectionToken ){\n console.error('[EMBEDDED] Invalid connection token in ack')\n return\n }\n \n console.log('[EMBEDDED] Connection established (received ack)')\n\n window._wio.connected = true\n window._wio.processMessageQueue()\n window._wio.fire('connect')\n\n return\n }\n \n // Fire event listeners\n window._wio.fire( _event, payload, cid )\n },\n \n announceReady: function(){\n let attempts = 0\n const maxAttempts = 10\n const interval = 1000\n \n console.log('[EMBEDDED] Starting ready announcements')\n \n const announce = () => {\n if( window._wio.connected ){\n console.log('[EMBEDDED] Connected, stopping announcements')\n return\n }\n \n attempts++\n if( attempts > maxAttempts ){\n console.log('[EMBEDDED] Max announcement attempts reached')\n return\n }\n \n console.log('[EMBEDDED] Announcing ready (attempt', attempts + '/' + maxAttempts + ')')\n window._wio.emit('__embedded_ready')\n \n setTimeout( announce, interval )\n }\n \n announce()\n }\n }\n\n console.log('[EMBEDDED] WIO bridge ready. Call window._wio.listen() to connect.')\n }\n catch( error ){\n console.error('[EMBEDDED] Setup failed:', error )\n \n // Create minimal fallback\n window._wio = {\n error: error.toString(),\n listen: function(){ console.error('[EMBEDDED] WIO failed to initialize') },\n emit: function(){ console.error('[EMBEDDED] WIO failed to initialize') },\n on: function(){},\n once: function(){},\n off: function(){}\n }\n }\n\n true\n })()\n ";
683
677
  };
684
678
  return WIO;
685
679
  }());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webview.io",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "Easy and friendly API to connect and interact between React Native and WebView with enhanced security, reliability, and modern async/await support.",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
package/src/index.ts CHANGED
@@ -131,8 +131,7 @@ export default class WIO {
131
131
  this.Events = {}
132
132
  this.peer = { type: 'WEBVIEW', connected: false, embeddedReady: false }
133
133
 
134
- if( options.type )
135
- this.peer.type = options.type
134
+ if( options.type ) this.peer.type = options.type
136
135
  }
137
136
 
138
137
  debug( ...args: any[] ){
@@ -211,24 +210,19 @@ export default class WIO {
211
210
  this.connectionToken = generateToken()
212
211
 
213
212
  // Re-initiate connection for WEBVIEW type
214
- if( this.peer.type === 'WEBVIEW' ){
215
- this.startConnectionAttempt()
216
- }
217
-
213
+ this.peer.type === 'WEBVIEW' && this.startConnectionAttempt()
218
214
  // For EMBEDDED type, announce readiness
219
- if( this.peer.type === 'EMBEDDED' ){
220
- this.announceEmbeddedReady()
221
- }
215
+ this.peer.type === 'EMBEDDED' && this.announceEmbeddedReady()
222
216
 
223
217
  // Set timeout for this reconnection attempt
224
- setTimeout(() => {
218
+ setTimeout( () => {
225
219
  if( this.peer.connected ) return
226
220
 
227
221
  this.reconnectAttempts < this.maxReconnectAttempts
228
222
  ? this.attemptReconnection()
229
223
  : this.fire('reconnection_failed', { attempts: this.reconnectAttempts })
230
- }, this.options.connectionTimeout!)
231
- }, delay)
224
+ }, this.options.connectionTimeout! )
225
+ }, delay )
232
226
  }
233
227
 
234
228
  // Start connection attempt with timeout and retries
@@ -257,10 +251,8 @@ export default class WIO {
257
251
  this.debug(`[${this.peer.type}] Connection attempt ${this.connectionAttempts}/${this.options.maxConnectionAttempts}`)
258
252
  this.emit('ping', { token: this.connectionToken })
259
253
  }
260
- else {
261
- this.stopConnectionAttempt()
262
- }
263
- }, this.options.connectionPingInterval!)
254
+ else this.stopConnectionAttempt()
255
+ }, this.options.connectionPingInterval! )
264
256
 
265
257
  // Set overall timeout
266
258
  this.connectionAttemptTimer = setTimeout(() => {
@@ -310,17 +302,15 @@ export default class WIO {
310
302
  this.debug(`[${this.peer.type}] Ready announcement attempt ${attempts}/${maxAttempts}`)
311
303
  this.emit('__embedded_ready')
312
304
  }
313
- else {
314
- this.stopEmbeddedReadyAnnouncement()
315
- }
305
+ else this.stopEmbeddedReadyAnnouncement()
316
306
  }, this.options.connectionPingInterval!)
317
307
  }
318
308
 
319
309
  private stopEmbeddedReadyAnnouncement(){
320
- if( this.embeddedReadyCheckInterval ){
321
- clearInterval( this.embeddedReadyCheckInterval )
322
- this.embeddedReadyCheckInterval = undefined
323
- }
310
+ if( !this.embeddedReadyCheckInterval ) return
311
+
312
+ clearInterval( this.embeddedReadyCheckInterval )
313
+ this.embeddedReadyCheckInterval = undefined
324
314
  }
325
315
 
326
316
  // Message rate limiting
@@ -351,8 +341,8 @@ export default class WIO {
351
341
 
352
342
  // Queue messages when not connected
353
343
  private queueMessage( _event: string, payload?: any, fn?: AckFunction ){
344
+ // Remove oldest message
354
345
  if( this.messageQueue.length >= this.options.messageQueueSize! ){
355
- // Remove oldest message
356
346
  const removed = this.messageQueue.shift()
357
347
  this.debug(`[${this.peer.type}] Message queue full, removed oldest message:`, removed?._event)
358
348
  }
@@ -413,6 +403,9 @@ export default class WIO {
413
403
 
414
404
  /**
415
405
  * Listening to connection from the WebView host
406
+ *
407
+ * NOTE: This is called manually from page code,
408
+ * not auto-initialized
416
409
  */
417
410
  listen( hostOrigin?: string ){
418
411
  this.peer.type = 'EMBEDDED'
@@ -423,9 +416,7 @@ export default class WIO {
423
416
  this.debug(`[${this.peer.type}] Listening to connect${hostOrigin ? `: Host <${hostOrigin}>` : ''}`)
424
417
 
425
418
  // Start announcing readiness
426
- setTimeout(() => {
427
- this.announceEmbeddedReady()
428
- }, 100)
419
+ setTimeout( () => this.announceEmbeddedReady(), 100 )
429
420
 
430
421
  return this
431
422
  }
@@ -436,9 +427,9 @@ export default class WIO {
436
427
  handleMessage( event: { nativeEvent: { data: string } } ){
437
428
  try {
438
429
  const data = JSON.parse( event.nativeEvent.data )
439
-
440
430
  // Enhanced security: check valid message structure
441
- if( typeof data !== 'object' || !data.hasOwnProperty('_event') ) return
431
+ if( typeof data !== 'object' || !data.hasOwnProperty('_event') )
432
+ return
442
433
 
443
434
  const { _event, payload, cid, timestamp, token } = data as MessageData
444
435
 
@@ -470,9 +461,10 @@ export default class WIO {
470
461
  this.debug(`[${this.peer.type}] Embedded peer ready`)
471
462
 
472
463
  // If we're WEBVIEW and not connected, send ping
473
- if( this.peer.type === 'WEBVIEW' && !this.peer.connected ){
474
- this.emit('ping', { token: this.connectionToken })
475
- }
464
+ this.peer.type === 'WEBVIEW'
465
+ && !this.peer.connected
466
+ && this.emit('ping', { token: this.connectionToken })
467
+
476
468
  return
477
469
  }
478
470
 
@@ -494,6 +486,7 @@ export default class WIO {
494
486
  // Don't set fully connected yet - wait for ack
495
487
  this.debug(`[${this.peer.type}] Received ping, sent pong`)
496
488
  }
489
+
497
490
  return
498
491
  }
499
492
 
@@ -522,6 +515,7 @@ export default class WIO {
522
515
 
523
516
  this.debug(`[${this.peer.type}] Connected (3-way handshake complete)`)
524
517
  }
518
+
525
519
  return
526
520
  }
527
521
 
@@ -546,6 +540,7 @@ export default class WIO {
546
540
 
547
541
  this.debug(`[${this.peer.type}] Connected (received ack)`)
548
542
  }
543
+
549
544
  return
550
545
  }
551
546
 
@@ -569,11 +564,11 @@ export default class WIO {
569
564
  }
570
565
 
571
566
  const ackFn = cid
572
- ? ( error: boolean | string, ...args: any[] ): void => {
573
- this.emit(`${_event}--${cid}--@ack`, { error: error || false, args })
574
- return
575
- }
576
- : undefined
567
+ ? ( error: boolean | string, ...args: any[] ): void => {
568
+ this.emit(`${_event}--${cid}--@ack`, { error: error || false, args })
569
+ return
570
+ }
571
+ : undefined
577
572
  let listeners: Listener[] = []
578
573
 
579
574
  if( this.Events[_event + '--@once'] ){
@@ -717,9 +712,7 @@ export default class WIO {
717
712
 
718
713
  emitAsync<T = any, R = any>( _event: string, payload?: T, timeout: number = 5000 ): Promise<R> {
719
714
  return new Promise(( resolve, reject ) => {
720
- const timeoutId = setTimeout(() => {
721
- reject( new Error(`Event '${_event}' acknowledgment timeout after ${timeout}ms`) )
722
- }, timeout )
715
+ const timeoutId = setTimeout(() => reject( new Error(`Event '${_event}' acknowledgment timeout after ${timeout}ms`) ), timeout )
723
716
 
724
717
  try {
725
718
  this.emit( _event, payload, ( error, ...args ) => {
@@ -745,17 +738,17 @@ export default class WIO {
745
738
  return new Promise(( resolve, reject ) => {
746
739
  if( this.isConnected() ) return resolve()
747
740
 
748
- const timeoutId = setTimeout(() => {
749
- this.off('connect', connectHandler)
741
+ const timeoutId = setTimeout( () => {
742
+ this.off('connect', connectHandler )
750
743
  reject( new Error('Connection timeout') )
751
- }, timeout || this.options.connectionTimeout)
744
+ }, timeout || this.options.connectionTimeout )
752
745
 
753
746
  const connectHandler = () => {
754
747
  clearTimeout( timeoutId )
755
748
  resolve()
756
749
  }
757
750
 
758
- this.once('connect', connectHandler)
751
+ this.once('connect', connectHandler )
759
752
  })
760
753
  }
761
754
 
@@ -822,6 +815,7 @@ export default class WIO {
822
815
  /**
823
816
  * Get injected JavaScript for WebView
824
817
  * Sets up the EMBEDDED side of the bridge
818
+ * NOTE: Does not auto-initialize - page must call window._wio.listen()
825
819
  */
826
820
  getInjectedJavaScript(): string {
827
821
  return `
@@ -849,13 +843,18 @@ export default class WIO {
849
843
  setupComplete: false,
850
844
 
851
845
  listen: function(){
846
+ if( this.setupComplete ){
847
+ console.warn('[EMBEDDED] Already listening')
848
+ return this
849
+ }
850
+
852
851
  console.log('[EMBEDDED] Setting up message listeners...')
853
852
 
854
853
  // Listen to messages from React Native
855
854
  window.addEventListener('message', function( event ){
856
855
  try {
857
856
  const message = typeof event.data === 'string' ? JSON.parse( event.data ) : event.data
858
- window._wio.handleMessage( message ) // Use window._wio instead of this
857
+ window._wio.handleMessage( message )
859
858
  }
860
859
  catch( error ){ console.error('[EMBEDDED] Parse error:', error ) }
861
860
  })
@@ -865,16 +864,19 @@ export default class WIO {
865
864
  document.addEventListener('message', function( event ){
866
865
  try {
867
866
  const message = typeof event.data === 'string' ? JSON.parse( event.data ) : event.data
868
- window._wio.handleMessage( message ) // Use window._wio instead of this
867
+ window._wio.handleMessage( message )
869
868
  }
870
869
  catch( error ){ console.error('[EMBEDDED] Parse error:', error ) }
871
870
  })
872
871
  }
873
872
 
874
- window._wio.setupComplete = true // Use window._wio instead of this
875
- console.log('[EMBEDDED] Setup complete')
873
+ this.setupComplete = true
874
+ console.log('[EMBEDDED] Setup complete, starting ready announcements')
876
875
 
877
- return window._wio
876
+ // Start announcing readiness
877
+ this.announceReady()
878
+
879
+ return this
878
880
  },
879
881
 
880
882
  ackId: function(){
@@ -1045,8 +1047,8 @@ export default class WIO {
1045
1047
 
1046
1048
  announceReady: function(){
1047
1049
  let attempts = 0
1048
- const maxAttempts = 5
1049
- const interval = 2000
1050
+ const maxAttempts = 10
1051
+ const interval = 1000
1050
1052
 
1051
1053
  console.log('[EMBEDDED] Starting ready announcements')
1052
1054
 
@@ -1072,12 +1074,7 @@ export default class WIO {
1072
1074
  }
1073
1075
  }
1074
1076
 
1075
- // Initialize
1076
- wio.listen()
1077
- // Start announcing readiness after a short delay
1078
- setTimeout(() => wio.announceReady(), 100)
1079
-
1080
- console.log('[EMBEDDED] WIO bridge initialized successfully')
1077
+ console.log('[EMBEDDED] WIO bridge ready. Call window._wio.listen() to connect.')
1081
1078
  }
1082
1079
  catch( error ){
1083
1080
  console.error('[EMBEDDED] Setup failed:', error )
@@ -1085,6 +1082,7 @@ export default class WIO {
1085
1082
  // Create minimal fallback
1086
1083
  window._wio = {
1087
1084
  error: error.toString(),
1085
+ listen: function(){ console.error('[EMBEDDED] WIO failed to initialize') },
1088
1086
  emit: function(){ console.error('[EMBEDDED] WIO failed to initialize') },
1089
1087
  on: function(){},
1090
1088
  once: function(){},