@naylence/runtime 0.3.5-test.941 → 0.3.5-test.943

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.
Files changed (33) hide show
  1. package/dist/browser/index.cjs +390 -8
  2. package/dist/browser/index.mjs +390 -8
  3. package/dist/cjs/naylence/fame/connector/broadcast-channel-connector-factory.js +12 -0
  4. package/dist/cjs/naylence/fame/connector/broadcast-channel-connector.browser.js +69 -1
  5. package/dist/cjs/naylence/fame/connector/inpage-connector-factory.js +12 -0
  6. package/dist/cjs/naylence/fame/connector/inpage-connector.js +159 -1
  7. package/dist/cjs/naylence/fame/connector/transport-frame.js +101 -0
  8. package/dist/cjs/naylence/fame/grants/broadcast-channel-connection-grant.js +28 -0
  9. package/dist/cjs/naylence/fame/grants/inpage-connection-grant.js +28 -0
  10. package/dist/cjs/naylence/fame/node/upstream-session-manager.js +2 -2
  11. package/dist/cjs/version.js +2 -2
  12. package/dist/esm/naylence/fame/connector/broadcast-channel-connector-factory.js +12 -0
  13. package/dist/esm/naylence/fame/connector/broadcast-channel-connector.browser.js +69 -1
  14. package/dist/esm/naylence/fame/connector/inpage-connector-factory.js +12 -0
  15. package/dist/esm/naylence/fame/connector/inpage-connector.js +159 -1
  16. package/dist/esm/naylence/fame/connector/transport-frame.js +94 -0
  17. package/dist/esm/naylence/fame/grants/broadcast-channel-connection-grant.js +28 -0
  18. package/dist/esm/naylence/fame/grants/inpage-connection-grant.js +28 -0
  19. package/dist/esm/naylence/fame/node/upstream-session-manager.js +2 -2
  20. package/dist/esm/version.js +2 -2
  21. package/dist/node/index.cjs +390 -8
  22. package/dist/node/index.mjs +390 -8
  23. package/dist/node/node.cjs +406 -8
  24. package/dist/node/node.mjs +406 -8
  25. package/dist/types/naylence/fame/connector/broadcast-channel-connector-factory.d.ts +2 -0
  26. package/dist/types/naylence/fame/connector/broadcast-channel-connector.browser.d.ts +4 -0
  27. package/dist/types/naylence/fame/connector/inpage-connector-factory.d.ts +2 -0
  28. package/dist/types/naylence/fame/connector/inpage-connector.d.ts +11 -1
  29. package/dist/types/naylence/fame/connector/transport-frame.d.ts +58 -0
  30. package/dist/types/naylence/fame/grants/broadcast-channel-connection-grant.d.ts +6 -0
  31. package/dist/types/naylence/fame/grants/inpage-connection-grant.d.ts +8 -0
  32. package/dist/types/version.d.ts +1 -1
  33. package/package.json +1 -1
@@ -96,12 +96,12 @@ installProcessEnvShim();
96
96
  // --- END ENV SHIM ---
97
97
 
98
98
  // This file is auto-generated during build - do not edit manually
99
- // Generated from package.json version: 0.3.5-test.941
99
+ // Generated from package.json version: 0.3.5-test.943
100
100
  /**
101
101
  * The package version, injected at build time.
102
102
  * @internal
103
103
  */
104
- const VERSION = '0.3.5-test.941';
104
+ const VERSION = '0.3.5-test.943';
105
105
 
106
106
  /**
107
107
  * Fame protocol specific error classes with WebSocket close codes and proper inheritance.
@@ -9816,6 +9816,85 @@ class BoundedAsyncQueue {
9816
9816
  }
9817
9817
  }
9818
9818
 
9819
+ /**
9820
+ * Transport frame layer for multiplexing logical links on physical channels.
9821
+ *
9822
+ * This lightweight framing layer wraps raw FAME payloads to enable multiple
9823
+ * logical connections over a single physical channel (BroadcastChannel or InPage bus).
9824
+ *
9825
+ * The transport frame does NOT modify FAME envelopes - it only wraps the raw
9826
+ * Uint8Array payload at the connector level.
9827
+ */
9828
+ /**
9829
+ * Transport frame version for future compatibility
9830
+ */
9831
+ const TRANSPORT_FRAME_VERSION = 1;
9832
+ /**
9833
+ * Wrap a raw payload in a transport frame
9834
+ *
9835
+ * @param payload - Raw FAME envelope bytes
9836
+ * @param srcNodeId - Local node ID (this connector)
9837
+ * @param dstNodeId - Remote node ID (target connector)
9838
+ * @returns Transport frame ready for transmission
9839
+ */
9840
+ function wrapTransportFrame(payload, srcNodeId, dstNodeId) {
9841
+ return {
9842
+ v: TRANSPORT_FRAME_VERSION,
9843
+ src: srcNodeId,
9844
+ dst: dstNodeId,
9845
+ payload,
9846
+ };
9847
+ }
9848
+ /**
9849
+ * Serialize a transport frame for transmission over the bus
9850
+ *
9851
+ * @param frame - Transport frame to serialize
9852
+ * @returns Serialized frame data ready for postMessage/dispatchEvent
9853
+ */
9854
+ function serializeTransportFrame(frame) {
9855
+ // Convert Uint8Array to regular array for JSON serialization
9856
+ const serializable = {
9857
+ v: frame.v,
9858
+ src: frame.src,
9859
+ dst: frame.dst,
9860
+ payload: Array.from(frame.payload),
9861
+ };
9862
+ return serializable;
9863
+ }
9864
+ /**
9865
+ * Unwrap a transport frame, validating source and destination
9866
+ *
9867
+ * @param raw - Raw data from the bus
9868
+ * @param localNodeId - This connector's node ID
9869
+ * @param remoteNodeId - Expected remote node ID
9870
+ * @returns Unwrapped payload if frame is valid and addressed to us, null otherwise
9871
+ */
9872
+ function unwrapTransportFrame(raw, localNodeId, remoteNodeId) {
9873
+ // Validate basic structure
9874
+ if (!raw || typeof raw !== 'object') {
9875
+ return null;
9876
+ }
9877
+ const frame = raw;
9878
+ // Check version
9879
+ if (frame.v !== TRANSPORT_FRAME_VERSION) {
9880
+ return null;
9881
+ }
9882
+ // Check src and dst
9883
+ if (typeof frame.src !== 'string' || typeof frame.dst !== 'string') {
9884
+ return null;
9885
+ }
9886
+ // Only accept frames addressed to us from the expected remote
9887
+ if (frame.dst !== localNodeId || frame.src !== remoteNodeId) {
9888
+ return null;
9889
+ }
9890
+ // Extract payload
9891
+ if (!frame.payload || !Array.isArray(frame.payload)) {
9892
+ return null;
9893
+ }
9894
+ // Convert array back to Uint8Array
9895
+ return Uint8Array.from(frame.payload);
9896
+ }
9897
+
9819
9898
  const logger$_ = getLogger('naylence.fame.connector.broadcast_channel_connector');
9820
9899
  const BROADCAST_CHANNEL_CONNECTOR_TYPE = 'broadcast-channel-connector';
9821
9900
  const DEFAULT_CHANNEL$7 = 'naylence-fabric';
@@ -9881,9 +9960,20 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
9881
9960
  this.inbox = new BoundedAsyncQueue(preferredCapacity);
9882
9961
  this.connectorId = BroadcastChannelConnector.generateConnectorId();
9883
9962
  this.channel = new BroadcastChannel(this.channelName);
9963
+ // Set local and remote node IDs (defaults to connector ID for backwards compatibility)
9964
+ this.localNodeId =
9965
+ typeof config.localNodeId === 'string' && config.localNodeId.trim().length > 0
9966
+ ? config.localNodeId.trim()
9967
+ : this.connectorId;
9968
+ this.remoteNodeId =
9969
+ typeof config.remoteNodeId === 'string' && config.remoteNodeId.trim().length > 0
9970
+ ? config.remoteNodeId.trim()
9971
+ : '*'; // Accept from any remote if not specified
9884
9972
  logger$_.debug('broadcast_channel_connector_created', {
9885
9973
  channel: this.channelName,
9886
9974
  connector_id: this.connectorId,
9975
+ local_node_id: this.localNodeId,
9976
+ remote_node_id: this.remoteNodeId,
9887
9977
  inbox_capacity: preferredCapacity,
9888
9978
  timestamp: new Date().toISOString(),
9889
9979
  });
@@ -9916,6 +10006,46 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
9916
10006
  if (busMessage.senderId === this.connectorId) {
9917
10007
  return;
9918
10008
  }
10009
+ // Try to unwrap as transport frame
10010
+ const unwrapped = unwrapTransportFrame(busMessage.payload, this.localNodeId, this.remoteNodeId === '*' ? busMessage.senderId : this.remoteNodeId);
10011
+ if (unwrapped) {
10012
+ // Successfully unwrapped transport frame
10013
+ logger$_.debug('broadcast_channel_transport_frame_received', {
10014
+ channel: this.channelName,
10015
+ sender_id: busMessage.senderId,
10016
+ connector_id: this.connectorId,
10017
+ local_node_id: this.localNodeId,
10018
+ remote_node_id: this.remoteNodeId,
10019
+ payload_length: unwrapped.byteLength,
10020
+ });
10021
+ if (this._shouldSkipDuplicateAck(busMessage.senderId, unwrapped)) {
10022
+ return;
10023
+ }
10024
+ try {
10025
+ if (typeof this.inbox.tryEnqueue === 'function') {
10026
+ const accepted = this.inbox.tryEnqueue(unwrapped);
10027
+ if (accepted) {
10028
+ return;
10029
+ }
10030
+ }
10031
+ this.inbox.enqueue(unwrapped);
10032
+ }
10033
+ catch (error) {
10034
+ if (error instanceof QueueFullError) {
10035
+ logger$_.warning('broadcast_channel_receive_queue_full', {
10036
+ channel: this.channelName,
10037
+ });
10038
+ }
10039
+ else {
10040
+ logger$_.error('broadcast_channel_receive_error', {
10041
+ channel: this.channelName,
10042
+ error: error instanceof Error ? error.message : String(error),
10043
+ });
10044
+ }
10045
+ }
10046
+ return;
10047
+ }
10048
+ // Fall back to legacy format (no transport frame)
9919
10049
  const payload = BroadcastChannelConnector.coercePayload(busMessage.payload);
9920
10050
  if (!payload) {
9921
10051
  logger$_.debug('broadcast_channel_payload_rejected', {
@@ -10054,10 +10184,26 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
10054
10184
  logger$_.debug('broadcast_channel_message_sending', {
10055
10185
  channel: this.channelName,
10056
10186
  sender_id: this.connectorId,
10057
- });
10187
+ local_node_id: this.localNodeId,
10188
+ remote_node_id: this.remoteNodeId,
10189
+ });
10190
+ // Only use transport framing if both localNodeId and remoteNodeId are explicitly set
10191
+ // (not using default values). This ensures backwards compatibility.
10192
+ const useTransportFrame = this.localNodeId !== this.connectorId ||
10193
+ this.remoteNodeId !== '*';
10194
+ let payload;
10195
+ if (useTransportFrame) {
10196
+ // Wrap payload in transport frame
10197
+ const frame = wrapTransportFrame(data, this.localNodeId, this.remoteNodeId);
10198
+ payload = serializeTransportFrame(frame);
10199
+ }
10200
+ else {
10201
+ // Legacy format: send raw payload
10202
+ payload = data;
10203
+ }
10058
10204
  this.channel.postMessage({
10059
10205
  senderId: this.connectorId,
10060
- payload: data,
10206
+ payload,
10061
10207
  });
10062
10208
  }
10063
10209
  async _transportReceive() {
@@ -10350,6 +10496,14 @@ function isBroadcastChannelConnectionGrant(candidate) {
10350
10496
  record.inboxCapacity <= 0)) {
10351
10497
  return false;
10352
10498
  }
10499
+ if (record.localNodeId !== undefined &&
10500
+ (typeof record.localNodeId !== 'string' || record.localNodeId.length === 0)) {
10501
+ return false;
10502
+ }
10503
+ if (record.remoteNodeId !== undefined &&
10504
+ (typeof record.remoteNodeId !== 'string' || record.remoteNodeId.length === 0)) {
10505
+ return false;
10506
+ }
10353
10507
  return true;
10354
10508
  }
10355
10509
  function normalizeBroadcastChannelConnectionGrant(candidate) {
@@ -10383,6 +10537,20 @@ function normalizeBroadcastChannelConnectionGrant(candidate) {
10383
10537
  }
10384
10538
  result.inboxCapacity = Math.floor(inboxValue);
10385
10539
  }
10540
+ const localNodeIdValue = candidate.localNodeId ?? candidate['local_node_id'];
10541
+ if (localNodeIdValue !== undefined) {
10542
+ if (typeof localNodeIdValue !== 'string' || localNodeIdValue.trim().length === 0) {
10543
+ throw new TypeError('BroadcastChannelConnectionGrant "localNodeId" must be a non-empty string when provided');
10544
+ }
10545
+ result.localNodeId = localNodeIdValue.trim();
10546
+ }
10547
+ const remoteNodeIdValue = candidate.remoteNodeId ?? candidate['remote_node_id'];
10548
+ if (remoteNodeIdValue !== undefined) {
10549
+ if (typeof remoteNodeIdValue !== 'string' || remoteNodeIdValue.trim().length === 0) {
10550
+ throw new TypeError('BroadcastChannelConnectionGrant "remoteNodeId" must be a non-empty string when provided');
10551
+ }
10552
+ result.remoteNodeId = remoteNodeIdValue.trim();
10553
+ }
10386
10554
  return result;
10387
10555
  }
10388
10556
  function broadcastChannelGrantToConnectorConfig(grant) {
@@ -10396,6 +10564,12 @@ function broadcastChannelGrantToConnectorConfig(grant) {
10396
10564
  if (normalized.inboxCapacity !== undefined) {
10397
10565
  config.inboxCapacity = normalized.inboxCapacity;
10398
10566
  }
10567
+ if (normalized.localNodeId) {
10568
+ config.localNodeId = normalized.localNodeId;
10569
+ }
10570
+ if (normalized.remoteNodeId) {
10571
+ config.remoteNodeId = normalized.remoteNodeId;
10572
+ }
10399
10573
  return config;
10400
10574
  }
10401
10575
 
@@ -10775,7 +10949,7 @@ class UpstreamSessionManager extends TaskSpawner {
10775
10949
  this.currentStopSubtasks = null;
10776
10950
  await Promise.allSettled(tasks.map((task) => task.promise));
10777
10951
  if (this.connector) {
10778
- logger$Z.info('upstream_stopping_old_connector', {
10952
+ logger$Z.debug('upstream_stopping_old_connector', {
10779
10953
  connect_epoch: this.connectEpoch,
10780
10954
  target_system_id: this.targetSystemId,
10781
10955
  timestamp: new Date().toISOString(),
@@ -10786,7 +10960,7 @@ class UpstreamSessionManager extends TaskSpawner {
10786
10960
  error: err instanceof Error ? err.message : String(err),
10787
10961
  });
10788
10962
  });
10789
- logger$Z.info('upstream_old_connector_stopped', {
10963
+ logger$Z.debug('upstream_old_connector_stopped', {
10790
10964
  connect_epoch: this.connectEpoch,
10791
10965
  target_system_id: this.targetSystemId,
10792
10966
  timestamp: new Date().toISOString(),
@@ -20330,6 +20504,7 @@ class InPageConnector extends BaseAsyncConnector {
20330
20504
  ensureBrowserEnvironment$2();
20331
20505
  super(baseConfig);
20332
20506
  this.listenerRegistered = false;
20507
+ this.visibilityChangeListenerRegistered = false;
20333
20508
  this.channelName =
20334
20509
  typeof config.channelName === 'string' && config.channelName.trim().length > 0
20335
20510
  ? config.channelName.trim()
@@ -20341,9 +20516,20 @@ class InPageConnector extends BaseAsyncConnector {
20341
20516
  : DEFAULT_INBOX_CAPACITY$6;
20342
20517
  this.inbox = new BoundedAsyncQueue(preferredCapacity);
20343
20518
  this.connectorId = InPageConnector.generateConnectorId();
20519
+ // Set local and remote node IDs (defaults to connector ID for backwards compatibility)
20520
+ this.localNodeId =
20521
+ typeof config.localNodeId === 'string' && config.localNodeId.trim().length > 0
20522
+ ? config.localNodeId.trim()
20523
+ : this.connectorId;
20524
+ this.remoteNodeId =
20525
+ typeof config.remoteNodeId === 'string' && config.remoteNodeId.trim().length > 0
20526
+ ? config.remoteNodeId.trim()
20527
+ : '*'; // Accept from any remote if not specified
20344
20528
  logger$G.debug('inpage_connector_initialized', {
20345
20529
  channel: this.channelName,
20346
20530
  connector_id: this.connectorId,
20531
+ local_node_id: this.localNodeId,
20532
+ remote_node_id: this.remoteNodeId,
20347
20533
  });
20348
20534
  this.onMsg = (event) => {
20349
20535
  const messageEvent = event;
@@ -20377,6 +20563,43 @@ class InPageConnector extends BaseAsyncConnector {
20377
20563
  if (busMessage.senderId === this.connectorId) {
20378
20564
  return;
20379
20565
  }
20566
+ // Try to unwrap as transport frame
20567
+ const unwrapped = unwrapTransportFrame(busMessage.payload, this.localNodeId, this.remoteNodeId === '*' ? busMessage.senderId : this.remoteNodeId);
20568
+ if (unwrapped) {
20569
+ // Successfully unwrapped transport frame
20570
+ logger$G.debug('inpage_transport_frame_received', {
20571
+ channel: this.channelName,
20572
+ sender_id: busMessage.senderId,
20573
+ connector_id: this.connectorId,
20574
+ local_node_id: this.localNodeId,
20575
+ remote_node_id: this.remoteNodeId,
20576
+ payload_length: unwrapped.byteLength,
20577
+ });
20578
+ try {
20579
+ if (typeof this.inbox.tryEnqueue === 'function') {
20580
+ const accepted = this.inbox.tryEnqueue(unwrapped);
20581
+ if (accepted) {
20582
+ return;
20583
+ }
20584
+ }
20585
+ this.inbox.enqueue(unwrapped);
20586
+ }
20587
+ catch (error) {
20588
+ if (error instanceof QueueFullError) {
20589
+ logger$G.warning('inpage_receive_queue_full', {
20590
+ channel: this.channelName,
20591
+ });
20592
+ }
20593
+ else {
20594
+ logger$G.error('inpage_receive_error', {
20595
+ channel: this.channelName,
20596
+ error: error instanceof Error ? error.message : String(error),
20597
+ });
20598
+ }
20599
+ }
20600
+ return;
20601
+ }
20602
+ // Fall back to legacy format (no transport frame)
20380
20603
  const payload = InPageConnector.coercePayload(busMessage.payload);
20381
20604
  if (!payload) {
20382
20605
  logger$G.debug('inpage_payload_rejected', {
@@ -20417,6 +20640,92 @@ class InPageConnector extends BaseAsyncConnector {
20417
20640
  };
20418
20641
  getSharedBus$1().addEventListener(this.channelName, this.onMsg);
20419
20642
  this.listenerRegistered = true;
20643
+ // Setup visibility change monitoring
20644
+ this.visibilityChangeHandler = () => {
20645
+ const isHidden = document.hidden;
20646
+ logger$G.debug('inpage_visibility_changed', {
20647
+ channel: this.channelName,
20648
+ connector_id: this.connectorId,
20649
+ visibility: isHidden ? 'hidden' : 'visible',
20650
+ timestamp: new Date().toISOString(),
20651
+ });
20652
+ // Pause/resume connector based on visibility
20653
+ if (isHidden && this.state === ConnectorState.STARTED) {
20654
+ this.pause().catch((err) => {
20655
+ logger$G.warning('inpage_pause_failed', {
20656
+ channel: this.channelName,
20657
+ connector_id: this.connectorId,
20658
+ error: err instanceof Error ? err.message : String(err),
20659
+ });
20660
+ });
20661
+ }
20662
+ else if (!isHidden && this.state === ConnectorState.PAUSED) {
20663
+ this.resume().catch((err) => {
20664
+ logger$G.warning('inpage_resume_failed', {
20665
+ channel: this.channelName,
20666
+ connector_id: this.connectorId,
20667
+ error: err instanceof Error ? err.message : String(err),
20668
+ });
20669
+ });
20670
+ }
20671
+ };
20672
+ if (typeof document !== 'undefined') {
20673
+ document.addEventListener('visibilitychange', this.visibilityChangeHandler);
20674
+ this.visibilityChangeListenerRegistered = true;
20675
+ // Track page lifecycle events to detect browser unload/discard
20676
+ if (typeof window !== 'undefined') {
20677
+ const lifecycleLogger = (event) => {
20678
+ logger$G.info('inpage_page_lifecycle', {
20679
+ channel: this.channelName,
20680
+ connector_id: this.connectorId,
20681
+ event_type: event.type,
20682
+ visibility_state: document.visibilityState,
20683
+ timestamp: new Date().toISOString(),
20684
+ });
20685
+ };
20686
+ window.addEventListener('beforeunload', lifecycleLogger);
20687
+ window.addEventListener('unload', lifecycleLogger);
20688
+ window.addEventListener('pagehide', lifecycleLogger);
20689
+ window.addEventListener('pageshow', lifecycleLogger);
20690
+ document.addEventListener('freeze', lifecycleLogger);
20691
+ document.addEventListener('resume', lifecycleLogger);
20692
+ }
20693
+ // Log initial state with detailed visibility info
20694
+ logger$G.debug('inpage_initial_visibility', {
20695
+ channel: this.channelName,
20696
+ connector_id: this.connectorId,
20697
+ visibility: document.hidden ? 'hidden' : 'visible',
20698
+ document_hidden: document.hidden,
20699
+ visibility_state: document.visibilityState,
20700
+ has_focus: document.hasFocus(),
20701
+ timestamp: new Date().toISOString(),
20702
+ });
20703
+ }
20704
+ }
20705
+ /**
20706
+ * Override start() to check initial visibility state
20707
+ */
20708
+ async start(inboundHandler) {
20709
+ await super.start(inboundHandler);
20710
+ // After transitioning to STARTED, check if tab is already hidden
20711
+ if (typeof document !== 'undefined' && document.hidden) {
20712
+ logger$G.debug('inpage_start_in_hidden_tab', {
20713
+ channel: this.channelName,
20714
+ connector_id: this.connectorId,
20715
+ document_hidden: document.hidden,
20716
+ visibility_state: document.visibilityState,
20717
+ has_focus: document.hasFocus(),
20718
+ timestamp: new Date().toISOString(),
20719
+ });
20720
+ // Immediately pause if tab is hidden at start time
20721
+ await this.pause().catch((err) => {
20722
+ logger$G.warning('inpage_initial_pause_failed', {
20723
+ channel: this.channelName,
20724
+ connector_id: this.connectorId,
20725
+ error: err instanceof Error ? err.message : String(err),
20726
+ });
20727
+ });
20728
+ }
20420
20729
  }
20421
20730
  // Allow listeners to feed envelopes directly into the in-page receive queue.
20422
20731
  async pushToReceive(rawOrEnvelope) {
@@ -20449,11 +20758,27 @@ class InPageConnector extends BaseAsyncConnector {
20449
20758
  logger$G.debug('inpage_message_sending', {
20450
20759
  channel: this.channelName,
20451
20760
  sender_id: this.connectorId,
20452
- });
20761
+ local_node_id: this.localNodeId,
20762
+ remote_node_id: this.remoteNodeId,
20763
+ });
20764
+ // Only use transport framing if both localNodeId and remoteNodeId are explicitly set
20765
+ // (not using default values). This ensures backwards compatibility.
20766
+ const useTransportFrame = this.localNodeId !== this.connectorId ||
20767
+ this.remoteNodeId !== '*';
20768
+ let payload;
20769
+ if (useTransportFrame) {
20770
+ // Wrap payload in transport frame
20771
+ const frame = wrapTransportFrame(data, this.localNodeId, this.remoteNodeId);
20772
+ payload = serializeTransportFrame(frame);
20773
+ }
20774
+ else {
20775
+ // Legacy format: send raw payload
20776
+ payload = data;
20777
+ }
20453
20778
  const event = new MessageEvent(this.channelName, {
20454
20779
  data: {
20455
20780
  senderId: this.connectorId,
20456
- payload: data,
20781
+ payload,
20457
20782
  },
20458
20783
  });
20459
20784
  getSharedBus$1().dispatchEvent(event);
@@ -20466,6 +20791,11 @@ class InPageConnector extends BaseAsyncConnector {
20466
20791
  getSharedBus$1().removeEventListener(this.channelName, this.onMsg);
20467
20792
  this.listenerRegistered = false;
20468
20793
  }
20794
+ if (this.visibilityChangeListenerRegistered && this.visibilityChangeHandler && typeof document !== 'undefined') {
20795
+ document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
20796
+ this.visibilityChangeListenerRegistered = false;
20797
+ this.visibilityChangeHandler = undefined;
20798
+ }
20469
20799
  const closeCode = typeof code === 'number' ? code : 1000;
20470
20800
  const closeReason = typeof reason === 'string' && reason.length > 0 ? reason : 'closed';
20471
20801
  const shutdownError = new FameTransportClose(closeReason, closeCode);
@@ -27813,6 +28143,14 @@ function isInPageConnectionGrant(candidate) {
27813
28143
  record.inboxCapacity <= 0)) {
27814
28144
  return false;
27815
28145
  }
28146
+ if (record.localNodeId !== undefined &&
28147
+ (typeof record.localNodeId !== 'string' || record.localNodeId.length === 0)) {
28148
+ return false;
28149
+ }
28150
+ if (record.remoteNodeId !== undefined &&
28151
+ (typeof record.remoteNodeId !== 'string' || record.remoteNodeId.length === 0)) {
28152
+ return false;
28153
+ }
27816
28154
  return true;
27817
28155
  }
27818
28156
  function normalizeInPageConnectionGrant(candidate) {
@@ -27846,6 +28184,20 @@ function normalizeInPageConnectionGrant(candidate) {
27846
28184
  }
27847
28185
  result.inboxCapacity = Math.floor(inboxValue);
27848
28186
  }
28187
+ const localNodeIdValue = candidate.localNodeId ?? candidate['local_node_id'];
28188
+ if (localNodeIdValue !== undefined) {
28189
+ if (typeof localNodeIdValue !== 'string' || localNodeIdValue.trim().length === 0) {
28190
+ throw new TypeError('InPageConnectionGrant "localNodeId" must be a non-empty string when provided');
28191
+ }
28192
+ result.localNodeId = localNodeIdValue.trim();
28193
+ }
28194
+ const remoteNodeIdValue = candidate.remoteNodeId ?? candidate['remote_node_id'];
28195
+ if (remoteNodeIdValue !== undefined) {
28196
+ if (typeof remoteNodeIdValue !== 'string' || remoteNodeIdValue.trim().length === 0) {
28197
+ throw new TypeError('InPageConnectionGrant "remoteNodeId" must be a non-empty string when provided');
28198
+ }
28199
+ result.remoteNodeId = remoteNodeIdValue.trim();
28200
+ }
27849
28201
  return result;
27850
28202
  }
27851
28203
  function inPageGrantToConnectorConfig(grant) {
@@ -27859,6 +28211,12 @@ function inPageGrantToConnectorConfig(grant) {
27859
28211
  if (normalized.inboxCapacity !== undefined) {
27860
28212
  config.inboxCapacity = normalized.inboxCapacity;
27861
28213
  }
28214
+ if (normalized.localNodeId) {
28215
+ config.localNodeId = normalized.localNodeId;
28216
+ }
28217
+ if (normalized.remoteNodeId) {
28218
+ config.remoteNodeId = normalized.remoteNodeId;
28219
+ }
27862
28220
  return config;
27863
28221
  }
27864
28222
 
@@ -28480,6 +28838,8 @@ class InPageConnectorFactory extends ConnectorFactory {
28480
28838
  type: INPAGE_CONNECTOR_TYPE,
28481
28839
  channelName,
28482
28840
  inboxCapacity,
28841
+ localNodeId: normalized.localNodeId,
28842
+ remoteNodeId: normalized.remoteNodeId,
28483
28843
  };
28484
28844
  const connector = new InPageConnector(connectorConfig, baseConfig);
28485
28845
  if (options.authorization) {
@@ -28548,6 +28908,16 @@ class InPageConnectorFactory extends ConnectorFactory {
28548
28908
  if (candidate.authorizationContext !== undefined) {
28549
28909
  normalized.authorizationContext = candidate.authorizationContext;
28550
28910
  }
28911
+ // Handle localNodeId
28912
+ const localNodeId = candidate.localNodeId ?? candidate['local_node_id'];
28913
+ if (typeof localNodeId === 'string' && localNodeId.trim().length > 0) {
28914
+ normalized.localNodeId = localNodeId.trim();
28915
+ }
28916
+ // Handle remoteNodeId
28917
+ const remoteNodeId = candidate.remoteNodeId ?? candidate['remote_node_id'];
28918
+ if (typeof remoteNodeId === 'string' && remoteNodeId.trim().length > 0) {
28919
+ normalized.remoteNodeId = remoteNodeId.trim();
28920
+ }
28551
28921
  normalized.channelName = normalized.channelName ?? DEFAULT_CHANNEL$5;
28552
28922
  normalized.inboxCapacity =
28553
28923
  normalized.inboxCapacity ?? DEFAULT_INBOX_CAPACITY$5;
@@ -28647,6 +29017,8 @@ class BroadcastChannelConnectorFactory extends ConnectorFactory {
28647
29017
  type: BROADCAST_CHANNEL_CONNECTOR_TYPE,
28648
29018
  channelName,
28649
29019
  inboxCapacity,
29020
+ localNodeId: normalized.localNodeId,
29021
+ remoteNodeId: normalized.remoteNodeId,
28650
29022
  };
28651
29023
  const connector = new BroadcastChannelConnector(connectorConfig, baseConfig);
28652
29024
  if (options.authorization) {
@@ -28708,6 +29080,16 @@ class BroadcastChannelConnectorFactory extends ConnectorFactory {
28708
29080
  if (candidate.authorizationContext !== undefined) {
28709
29081
  normalized.authorizationContext = candidate.authorizationContext;
28710
29082
  }
29083
+ // Handle localNodeId
29084
+ const localNodeId = candidate.localNodeId ?? candidate['local_node_id'];
29085
+ if (typeof localNodeId === 'string' && localNodeId.trim().length > 0) {
29086
+ normalized.localNodeId = localNodeId.trim();
29087
+ }
29088
+ // Handle remoteNodeId
29089
+ const remoteNodeId = candidate.remoteNodeId ?? candidate['remote_node_id'];
29090
+ if (typeof remoteNodeId === 'string' && remoteNodeId.trim().length > 0) {
29091
+ normalized.remoteNodeId = remoteNodeId.trim();
29092
+ }
28711
29093
  normalized.channelName = normalized.channelName ?? DEFAULT_CHANNEL$4;
28712
29094
  normalized.inboxCapacity =
28713
29095
  normalized.inboxCapacity ?? DEFAULT_INBOX_CAPACITY$4;
@@ -89,6 +89,8 @@ class BroadcastChannelConnectorFactory extends connector_factory_js_1.ConnectorF
89
89
  type: broadcast_channel_connector_js_1.BROADCAST_CHANNEL_CONNECTOR_TYPE,
90
90
  channelName,
91
91
  inboxCapacity,
92
+ localNodeId: normalized.localNodeId,
93
+ remoteNodeId: normalized.remoteNodeId,
92
94
  };
93
95
  const connector = new broadcast_channel_connector_js_1.BroadcastChannelConnector(connectorConfig, baseConfig);
94
96
  if (options.authorization) {
@@ -150,6 +152,16 @@ class BroadcastChannelConnectorFactory extends connector_factory_js_1.ConnectorF
150
152
  if (candidate.authorizationContext !== undefined) {
151
153
  normalized.authorizationContext = candidate.authorizationContext;
152
154
  }
155
+ // Handle localNodeId
156
+ const localNodeId = candidate.localNodeId ?? candidate['local_node_id'];
157
+ if (typeof localNodeId === 'string' && localNodeId.trim().length > 0) {
158
+ normalized.localNodeId = localNodeId.trim();
159
+ }
160
+ // Handle remoteNodeId
161
+ const remoteNodeId = candidate.remoteNodeId ?? candidate['remote_node_id'];
162
+ if (typeof remoteNodeId === 'string' && remoteNodeId.trim().length > 0) {
163
+ normalized.remoteNodeId = remoteNodeId.trim();
164
+ }
153
165
  normalized.channelName = normalized.channelName ?? DEFAULT_CHANNEL;
154
166
  normalized.inboxCapacity =
155
167
  normalized.inboxCapacity ?? DEFAULT_INBOX_CAPACITY;