@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.
- package/dist/browser/index.cjs +390 -8
- package/dist/browser/index.mjs +390 -8
- package/dist/cjs/naylence/fame/connector/broadcast-channel-connector-factory.js +12 -0
- package/dist/cjs/naylence/fame/connector/broadcast-channel-connector.browser.js +69 -1
- package/dist/cjs/naylence/fame/connector/inpage-connector-factory.js +12 -0
- package/dist/cjs/naylence/fame/connector/inpage-connector.js +159 -1
- package/dist/cjs/naylence/fame/connector/transport-frame.js +101 -0
- package/dist/cjs/naylence/fame/grants/broadcast-channel-connection-grant.js +28 -0
- package/dist/cjs/naylence/fame/grants/inpage-connection-grant.js +28 -0
- package/dist/cjs/naylence/fame/node/upstream-session-manager.js +2 -2
- package/dist/cjs/version.js +2 -2
- package/dist/esm/naylence/fame/connector/broadcast-channel-connector-factory.js +12 -0
- package/dist/esm/naylence/fame/connector/broadcast-channel-connector.browser.js +69 -1
- package/dist/esm/naylence/fame/connector/inpage-connector-factory.js +12 -0
- package/dist/esm/naylence/fame/connector/inpage-connector.js +159 -1
- package/dist/esm/naylence/fame/connector/transport-frame.js +94 -0
- package/dist/esm/naylence/fame/grants/broadcast-channel-connection-grant.js +28 -0
- package/dist/esm/naylence/fame/grants/inpage-connection-grant.js +28 -0
- package/dist/esm/naylence/fame/node/upstream-session-manager.js +2 -2
- package/dist/esm/version.js +2 -2
- package/dist/node/index.cjs +390 -8
- package/dist/node/index.mjs +390 -8
- package/dist/node/node.cjs +406 -8
- package/dist/node/node.mjs +406 -8
- package/dist/types/naylence/fame/connector/broadcast-channel-connector-factory.d.ts +2 -0
- package/dist/types/naylence/fame/connector/broadcast-channel-connector.browser.d.ts +4 -0
- package/dist/types/naylence/fame/connector/inpage-connector-factory.d.ts +2 -0
- package/dist/types/naylence/fame/connector/inpage-connector.d.ts +11 -1
- package/dist/types/naylence/fame/connector/transport-frame.d.ts +58 -0
- package/dist/types/naylence/fame/grants/broadcast-channel-connection-grant.d.ts +6 -0
- package/dist/types/naylence/fame/grants/inpage-connection-grant.d.ts +8 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/node/index.cjs
CHANGED
|
@@ -14,12 +14,12 @@ var fastify = require('fastify');
|
|
|
14
14
|
var websocketPlugin = require('@fastify/websocket');
|
|
15
15
|
|
|
16
16
|
// This file is auto-generated during build - do not edit manually
|
|
17
|
-
// Generated from package.json version: 0.3.5-test.
|
|
17
|
+
// Generated from package.json version: 0.3.5-test.943
|
|
18
18
|
/**
|
|
19
19
|
* The package version, injected at build time.
|
|
20
20
|
* @internal
|
|
21
21
|
*/
|
|
22
|
-
const VERSION = '0.3.5-test.
|
|
22
|
+
const VERSION = '0.3.5-test.943';
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Fame protocol specific error classes with WebSocket close codes and proper inheritance.
|
|
@@ -9734,6 +9734,85 @@ class BoundedAsyncQueue {
|
|
|
9734
9734
|
}
|
|
9735
9735
|
}
|
|
9736
9736
|
|
|
9737
|
+
/**
|
|
9738
|
+
* Transport frame layer for multiplexing logical links on physical channels.
|
|
9739
|
+
*
|
|
9740
|
+
* This lightweight framing layer wraps raw FAME payloads to enable multiple
|
|
9741
|
+
* logical connections over a single physical channel (BroadcastChannel or InPage bus).
|
|
9742
|
+
*
|
|
9743
|
+
* The transport frame does NOT modify FAME envelopes - it only wraps the raw
|
|
9744
|
+
* Uint8Array payload at the connector level.
|
|
9745
|
+
*/
|
|
9746
|
+
/**
|
|
9747
|
+
* Transport frame version for future compatibility
|
|
9748
|
+
*/
|
|
9749
|
+
const TRANSPORT_FRAME_VERSION = 1;
|
|
9750
|
+
/**
|
|
9751
|
+
* Wrap a raw payload in a transport frame
|
|
9752
|
+
*
|
|
9753
|
+
* @param payload - Raw FAME envelope bytes
|
|
9754
|
+
* @param srcNodeId - Local node ID (this connector)
|
|
9755
|
+
* @param dstNodeId - Remote node ID (target connector)
|
|
9756
|
+
* @returns Transport frame ready for transmission
|
|
9757
|
+
*/
|
|
9758
|
+
function wrapTransportFrame(payload, srcNodeId, dstNodeId) {
|
|
9759
|
+
return {
|
|
9760
|
+
v: TRANSPORT_FRAME_VERSION,
|
|
9761
|
+
src: srcNodeId,
|
|
9762
|
+
dst: dstNodeId,
|
|
9763
|
+
payload,
|
|
9764
|
+
};
|
|
9765
|
+
}
|
|
9766
|
+
/**
|
|
9767
|
+
* Serialize a transport frame for transmission over the bus
|
|
9768
|
+
*
|
|
9769
|
+
* @param frame - Transport frame to serialize
|
|
9770
|
+
* @returns Serialized frame data ready for postMessage/dispatchEvent
|
|
9771
|
+
*/
|
|
9772
|
+
function serializeTransportFrame(frame) {
|
|
9773
|
+
// Convert Uint8Array to regular array for JSON serialization
|
|
9774
|
+
const serializable = {
|
|
9775
|
+
v: frame.v,
|
|
9776
|
+
src: frame.src,
|
|
9777
|
+
dst: frame.dst,
|
|
9778
|
+
payload: Array.from(frame.payload),
|
|
9779
|
+
};
|
|
9780
|
+
return serializable;
|
|
9781
|
+
}
|
|
9782
|
+
/**
|
|
9783
|
+
* Unwrap a transport frame, validating source and destination
|
|
9784
|
+
*
|
|
9785
|
+
* @param raw - Raw data from the bus
|
|
9786
|
+
* @param localNodeId - This connector's node ID
|
|
9787
|
+
* @param remoteNodeId - Expected remote node ID
|
|
9788
|
+
* @returns Unwrapped payload if frame is valid and addressed to us, null otherwise
|
|
9789
|
+
*/
|
|
9790
|
+
function unwrapTransportFrame(raw, localNodeId, remoteNodeId) {
|
|
9791
|
+
// Validate basic structure
|
|
9792
|
+
if (!raw || typeof raw !== 'object') {
|
|
9793
|
+
return null;
|
|
9794
|
+
}
|
|
9795
|
+
const frame = raw;
|
|
9796
|
+
// Check version
|
|
9797
|
+
if (frame.v !== TRANSPORT_FRAME_VERSION) {
|
|
9798
|
+
return null;
|
|
9799
|
+
}
|
|
9800
|
+
// Check src and dst
|
|
9801
|
+
if (typeof frame.src !== 'string' || typeof frame.dst !== 'string') {
|
|
9802
|
+
return null;
|
|
9803
|
+
}
|
|
9804
|
+
// Only accept frames addressed to us from the expected remote
|
|
9805
|
+
if (frame.dst !== localNodeId || frame.src !== remoteNodeId) {
|
|
9806
|
+
return null;
|
|
9807
|
+
}
|
|
9808
|
+
// Extract payload
|
|
9809
|
+
if (!frame.payload || !Array.isArray(frame.payload)) {
|
|
9810
|
+
return null;
|
|
9811
|
+
}
|
|
9812
|
+
// Convert array back to Uint8Array
|
|
9813
|
+
return Uint8Array.from(frame.payload);
|
|
9814
|
+
}
|
|
9815
|
+
|
|
9737
9816
|
const logger$_ = getLogger('naylence.fame.connector.broadcast_channel_connector');
|
|
9738
9817
|
const BROADCAST_CHANNEL_CONNECTOR_TYPE = 'broadcast-channel-connector';
|
|
9739
9818
|
const DEFAULT_CHANNEL$7 = 'naylence-fabric';
|
|
@@ -9799,9 +9878,20 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9799
9878
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
9800
9879
|
this.connectorId = BroadcastChannelConnector.generateConnectorId();
|
|
9801
9880
|
this.channel = new BroadcastChannel(this.channelName);
|
|
9881
|
+
// Set local and remote node IDs (defaults to connector ID for backwards compatibility)
|
|
9882
|
+
this.localNodeId =
|
|
9883
|
+
typeof config.localNodeId === 'string' && config.localNodeId.trim().length > 0
|
|
9884
|
+
? config.localNodeId.trim()
|
|
9885
|
+
: this.connectorId;
|
|
9886
|
+
this.remoteNodeId =
|
|
9887
|
+
typeof config.remoteNodeId === 'string' && config.remoteNodeId.trim().length > 0
|
|
9888
|
+
? config.remoteNodeId.trim()
|
|
9889
|
+
: '*'; // Accept from any remote if not specified
|
|
9802
9890
|
logger$_.debug('broadcast_channel_connector_created', {
|
|
9803
9891
|
channel: this.channelName,
|
|
9804
9892
|
connector_id: this.connectorId,
|
|
9893
|
+
local_node_id: this.localNodeId,
|
|
9894
|
+
remote_node_id: this.remoteNodeId,
|
|
9805
9895
|
inbox_capacity: preferredCapacity,
|
|
9806
9896
|
timestamp: new Date().toISOString(),
|
|
9807
9897
|
});
|
|
@@ -9834,6 +9924,46 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9834
9924
|
if (busMessage.senderId === this.connectorId) {
|
|
9835
9925
|
return;
|
|
9836
9926
|
}
|
|
9927
|
+
// Try to unwrap as transport frame
|
|
9928
|
+
const unwrapped = unwrapTransportFrame(busMessage.payload, this.localNodeId, this.remoteNodeId === '*' ? busMessage.senderId : this.remoteNodeId);
|
|
9929
|
+
if (unwrapped) {
|
|
9930
|
+
// Successfully unwrapped transport frame
|
|
9931
|
+
logger$_.debug('broadcast_channel_transport_frame_received', {
|
|
9932
|
+
channel: this.channelName,
|
|
9933
|
+
sender_id: busMessage.senderId,
|
|
9934
|
+
connector_id: this.connectorId,
|
|
9935
|
+
local_node_id: this.localNodeId,
|
|
9936
|
+
remote_node_id: this.remoteNodeId,
|
|
9937
|
+
payload_length: unwrapped.byteLength,
|
|
9938
|
+
});
|
|
9939
|
+
if (this._shouldSkipDuplicateAck(busMessage.senderId, unwrapped)) {
|
|
9940
|
+
return;
|
|
9941
|
+
}
|
|
9942
|
+
try {
|
|
9943
|
+
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
9944
|
+
const accepted = this.inbox.tryEnqueue(unwrapped);
|
|
9945
|
+
if (accepted) {
|
|
9946
|
+
return;
|
|
9947
|
+
}
|
|
9948
|
+
}
|
|
9949
|
+
this.inbox.enqueue(unwrapped);
|
|
9950
|
+
}
|
|
9951
|
+
catch (error) {
|
|
9952
|
+
if (error instanceof QueueFullError) {
|
|
9953
|
+
logger$_.warning('broadcast_channel_receive_queue_full', {
|
|
9954
|
+
channel: this.channelName,
|
|
9955
|
+
});
|
|
9956
|
+
}
|
|
9957
|
+
else {
|
|
9958
|
+
logger$_.error('broadcast_channel_receive_error', {
|
|
9959
|
+
channel: this.channelName,
|
|
9960
|
+
error: error instanceof Error ? error.message : String(error),
|
|
9961
|
+
});
|
|
9962
|
+
}
|
|
9963
|
+
}
|
|
9964
|
+
return;
|
|
9965
|
+
}
|
|
9966
|
+
// Fall back to legacy format (no transport frame)
|
|
9837
9967
|
const payload = BroadcastChannelConnector.coercePayload(busMessage.payload);
|
|
9838
9968
|
if (!payload) {
|
|
9839
9969
|
logger$_.debug('broadcast_channel_payload_rejected', {
|
|
@@ -9972,10 +10102,26 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9972
10102
|
logger$_.debug('broadcast_channel_message_sending', {
|
|
9973
10103
|
channel: this.channelName,
|
|
9974
10104
|
sender_id: this.connectorId,
|
|
9975
|
-
|
|
10105
|
+
local_node_id: this.localNodeId,
|
|
10106
|
+
remote_node_id: this.remoteNodeId,
|
|
10107
|
+
});
|
|
10108
|
+
// Only use transport framing if both localNodeId and remoteNodeId are explicitly set
|
|
10109
|
+
// (not using default values). This ensures backwards compatibility.
|
|
10110
|
+
const useTransportFrame = this.localNodeId !== this.connectorId ||
|
|
10111
|
+
this.remoteNodeId !== '*';
|
|
10112
|
+
let payload;
|
|
10113
|
+
if (useTransportFrame) {
|
|
10114
|
+
// Wrap payload in transport frame
|
|
10115
|
+
const frame = wrapTransportFrame(data, this.localNodeId, this.remoteNodeId);
|
|
10116
|
+
payload = serializeTransportFrame(frame);
|
|
10117
|
+
}
|
|
10118
|
+
else {
|
|
10119
|
+
// Legacy format: send raw payload
|
|
10120
|
+
payload = data;
|
|
10121
|
+
}
|
|
9976
10122
|
this.channel.postMessage({
|
|
9977
10123
|
senderId: this.connectorId,
|
|
9978
|
-
payload
|
|
10124
|
+
payload,
|
|
9979
10125
|
});
|
|
9980
10126
|
}
|
|
9981
10127
|
async _transportReceive() {
|
|
@@ -10268,6 +10414,14 @@ function isBroadcastChannelConnectionGrant(candidate) {
|
|
|
10268
10414
|
record.inboxCapacity <= 0)) {
|
|
10269
10415
|
return false;
|
|
10270
10416
|
}
|
|
10417
|
+
if (record.localNodeId !== undefined &&
|
|
10418
|
+
(typeof record.localNodeId !== 'string' || record.localNodeId.length === 0)) {
|
|
10419
|
+
return false;
|
|
10420
|
+
}
|
|
10421
|
+
if (record.remoteNodeId !== undefined &&
|
|
10422
|
+
(typeof record.remoteNodeId !== 'string' || record.remoteNodeId.length === 0)) {
|
|
10423
|
+
return false;
|
|
10424
|
+
}
|
|
10271
10425
|
return true;
|
|
10272
10426
|
}
|
|
10273
10427
|
function normalizeBroadcastChannelConnectionGrant(candidate) {
|
|
@@ -10301,6 +10455,20 @@ function normalizeBroadcastChannelConnectionGrant(candidate) {
|
|
|
10301
10455
|
}
|
|
10302
10456
|
result.inboxCapacity = Math.floor(inboxValue);
|
|
10303
10457
|
}
|
|
10458
|
+
const localNodeIdValue = candidate.localNodeId ?? candidate['local_node_id'];
|
|
10459
|
+
if (localNodeIdValue !== undefined) {
|
|
10460
|
+
if (typeof localNodeIdValue !== 'string' || localNodeIdValue.trim().length === 0) {
|
|
10461
|
+
throw new TypeError('BroadcastChannelConnectionGrant "localNodeId" must be a non-empty string when provided');
|
|
10462
|
+
}
|
|
10463
|
+
result.localNodeId = localNodeIdValue.trim();
|
|
10464
|
+
}
|
|
10465
|
+
const remoteNodeIdValue = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
10466
|
+
if (remoteNodeIdValue !== undefined) {
|
|
10467
|
+
if (typeof remoteNodeIdValue !== 'string' || remoteNodeIdValue.trim().length === 0) {
|
|
10468
|
+
throw new TypeError('BroadcastChannelConnectionGrant "remoteNodeId" must be a non-empty string when provided');
|
|
10469
|
+
}
|
|
10470
|
+
result.remoteNodeId = remoteNodeIdValue.trim();
|
|
10471
|
+
}
|
|
10304
10472
|
return result;
|
|
10305
10473
|
}
|
|
10306
10474
|
function broadcastChannelGrantToConnectorConfig(grant) {
|
|
@@ -10314,6 +10482,12 @@ function broadcastChannelGrantToConnectorConfig(grant) {
|
|
|
10314
10482
|
if (normalized.inboxCapacity !== undefined) {
|
|
10315
10483
|
config.inboxCapacity = normalized.inboxCapacity;
|
|
10316
10484
|
}
|
|
10485
|
+
if (normalized.localNodeId) {
|
|
10486
|
+
config.localNodeId = normalized.localNodeId;
|
|
10487
|
+
}
|
|
10488
|
+
if (normalized.remoteNodeId) {
|
|
10489
|
+
config.remoteNodeId = normalized.remoteNodeId;
|
|
10490
|
+
}
|
|
10317
10491
|
return config;
|
|
10318
10492
|
}
|
|
10319
10493
|
|
|
@@ -10693,7 +10867,7 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10693
10867
|
this.currentStopSubtasks = null;
|
|
10694
10868
|
await Promise.allSettled(tasks.map((task) => task.promise));
|
|
10695
10869
|
if (this.connector) {
|
|
10696
|
-
logger$Z.
|
|
10870
|
+
logger$Z.debug('upstream_stopping_old_connector', {
|
|
10697
10871
|
connect_epoch: this.connectEpoch,
|
|
10698
10872
|
target_system_id: this.targetSystemId,
|
|
10699
10873
|
timestamp: new Date().toISOString(),
|
|
@@ -10704,7 +10878,7 @@ class UpstreamSessionManager extends TaskSpawner {
|
|
|
10704
10878
|
error: err instanceof Error ? err.message : String(err),
|
|
10705
10879
|
});
|
|
10706
10880
|
});
|
|
10707
|
-
logger$Z.
|
|
10881
|
+
logger$Z.debug('upstream_old_connector_stopped', {
|
|
10708
10882
|
connect_epoch: this.connectEpoch,
|
|
10709
10883
|
target_system_id: this.targetSystemId,
|
|
10710
10884
|
timestamp: new Date().toISOString(),
|
|
@@ -20248,6 +20422,7 @@ class InPageConnector extends BaseAsyncConnector {
|
|
|
20248
20422
|
ensureBrowserEnvironment$2();
|
|
20249
20423
|
super(baseConfig);
|
|
20250
20424
|
this.listenerRegistered = false;
|
|
20425
|
+
this.visibilityChangeListenerRegistered = false;
|
|
20251
20426
|
this.channelName =
|
|
20252
20427
|
typeof config.channelName === 'string' && config.channelName.trim().length > 0
|
|
20253
20428
|
? config.channelName.trim()
|
|
@@ -20259,9 +20434,20 @@ class InPageConnector extends BaseAsyncConnector {
|
|
|
20259
20434
|
: DEFAULT_INBOX_CAPACITY$6;
|
|
20260
20435
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
20261
20436
|
this.connectorId = InPageConnector.generateConnectorId();
|
|
20437
|
+
// Set local and remote node IDs (defaults to connector ID for backwards compatibility)
|
|
20438
|
+
this.localNodeId =
|
|
20439
|
+
typeof config.localNodeId === 'string' && config.localNodeId.trim().length > 0
|
|
20440
|
+
? config.localNodeId.trim()
|
|
20441
|
+
: this.connectorId;
|
|
20442
|
+
this.remoteNodeId =
|
|
20443
|
+
typeof config.remoteNodeId === 'string' && config.remoteNodeId.trim().length > 0
|
|
20444
|
+
? config.remoteNodeId.trim()
|
|
20445
|
+
: '*'; // Accept from any remote if not specified
|
|
20262
20446
|
logger$G.debug('inpage_connector_initialized', {
|
|
20263
20447
|
channel: this.channelName,
|
|
20264
20448
|
connector_id: this.connectorId,
|
|
20449
|
+
local_node_id: this.localNodeId,
|
|
20450
|
+
remote_node_id: this.remoteNodeId,
|
|
20265
20451
|
});
|
|
20266
20452
|
this.onMsg = (event) => {
|
|
20267
20453
|
const messageEvent = event;
|
|
@@ -20295,6 +20481,43 @@ class InPageConnector extends BaseAsyncConnector {
|
|
|
20295
20481
|
if (busMessage.senderId === this.connectorId) {
|
|
20296
20482
|
return;
|
|
20297
20483
|
}
|
|
20484
|
+
// Try to unwrap as transport frame
|
|
20485
|
+
const unwrapped = unwrapTransportFrame(busMessage.payload, this.localNodeId, this.remoteNodeId === '*' ? busMessage.senderId : this.remoteNodeId);
|
|
20486
|
+
if (unwrapped) {
|
|
20487
|
+
// Successfully unwrapped transport frame
|
|
20488
|
+
logger$G.debug('inpage_transport_frame_received', {
|
|
20489
|
+
channel: this.channelName,
|
|
20490
|
+
sender_id: busMessage.senderId,
|
|
20491
|
+
connector_id: this.connectorId,
|
|
20492
|
+
local_node_id: this.localNodeId,
|
|
20493
|
+
remote_node_id: this.remoteNodeId,
|
|
20494
|
+
payload_length: unwrapped.byteLength,
|
|
20495
|
+
});
|
|
20496
|
+
try {
|
|
20497
|
+
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
20498
|
+
const accepted = this.inbox.tryEnqueue(unwrapped);
|
|
20499
|
+
if (accepted) {
|
|
20500
|
+
return;
|
|
20501
|
+
}
|
|
20502
|
+
}
|
|
20503
|
+
this.inbox.enqueue(unwrapped);
|
|
20504
|
+
}
|
|
20505
|
+
catch (error) {
|
|
20506
|
+
if (error instanceof QueueFullError) {
|
|
20507
|
+
logger$G.warning('inpage_receive_queue_full', {
|
|
20508
|
+
channel: this.channelName,
|
|
20509
|
+
});
|
|
20510
|
+
}
|
|
20511
|
+
else {
|
|
20512
|
+
logger$G.error('inpage_receive_error', {
|
|
20513
|
+
channel: this.channelName,
|
|
20514
|
+
error: error instanceof Error ? error.message : String(error),
|
|
20515
|
+
});
|
|
20516
|
+
}
|
|
20517
|
+
}
|
|
20518
|
+
return;
|
|
20519
|
+
}
|
|
20520
|
+
// Fall back to legacy format (no transport frame)
|
|
20298
20521
|
const payload = InPageConnector.coercePayload(busMessage.payload);
|
|
20299
20522
|
if (!payload) {
|
|
20300
20523
|
logger$G.debug('inpage_payload_rejected', {
|
|
@@ -20335,6 +20558,92 @@ class InPageConnector extends BaseAsyncConnector {
|
|
|
20335
20558
|
};
|
|
20336
20559
|
getSharedBus$1().addEventListener(this.channelName, this.onMsg);
|
|
20337
20560
|
this.listenerRegistered = true;
|
|
20561
|
+
// Setup visibility change monitoring
|
|
20562
|
+
this.visibilityChangeHandler = () => {
|
|
20563
|
+
const isHidden = document.hidden;
|
|
20564
|
+
logger$G.debug('inpage_visibility_changed', {
|
|
20565
|
+
channel: this.channelName,
|
|
20566
|
+
connector_id: this.connectorId,
|
|
20567
|
+
visibility: isHidden ? 'hidden' : 'visible',
|
|
20568
|
+
timestamp: new Date().toISOString(),
|
|
20569
|
+
});
|
|
20570
|
+
// Pause/resume connector based on visibility
|
|
20571
|
+
if (isHidden && this.state === core.ConnectorState.STARTED) {
|
|
20572
|
+
this.pause().catch((err) => {
|
|
20573
|
+
logger$G.warning('inpage_pause_failed', {
|
|
20574
|
+
channel: this.channelName,
|
|
20575
|
+
connector_id: this.connectorId,
|
|
20576
|
+
error: err instanceof Error ? err.message : String(err),
|
|
20577
|
+
});
|
|
20578
|
+
});
|
|
20579
|
+
}
|
|
20580
|
+
else if (!isHidden && this.state === core.ConnectorState.PAUSED) {
|
|
20581
|
+
this.resume().catch((err) => {
|
|
20582
|
+
logger$G.warning('inpage_resume_failed', {
|
|
20583
|
+
channel: this.channelName,
|
|
20584
|
+
connector_id: this.connectorId,
|
|
20585
|
+
error: err instanceof Error ? err.message : String(err),
|
|
20586
|
+
});
|
|
20587
|
+
});
|
|
20588
|
+
}
|
|
20589
|
+
};
|
|
20590
|
+
if (typeof document !== 'undefined') {
|
|
20591
|
+
document.addEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
20592
|
+
this.visibilityChangeListenerRegistered = true;
|
|
20593
|
+
// Track page lifecycle events to detect browser unload/discard
|
|
20594
|
+
if (typeof window !== 'undefined') {
|
|
20595
|
+
const lifecycleLogger = (event) => {
|
|
20596
|
+
logger$G.info('inpage_page_lifecycle', {
|
|
20597
|
+
channel: this.channelName,
|
|
20598
|
+
connector_id: this.connectorId,
|
|
20599
|
+
event_type: event.type,
|
|
20600
|
+
visibility_state: document.visibilityState,
|
|
20601
|
+
timestamp: new Date().toISOString(),
|
|
20602
|
+
});
|
|
20603
|
+
};
|
|
20604
|
+
window.addEventListener('beforeunload', lifecycleLogger);
|
|
20605
|
+
window.addEventListener('unload', lifecycleLogger);
|
|
20606
|
+
window.addEventListener('pagehide', lifecycleLogger);
|
|
20607
|
+
window.addEventListener('pageshow', lifecycleLogger);
|
|
20608
|
+
document.addEventListener('freeze', lifecycleLogger);
|
|
20609
|
+
document.addEventListener('resume', lifecycleLogger);
|
|
20610
|
+
}
|
|
20611
|
+
// Log initial state with detailed visibility info
|
|
20612
|
+
logger$G.debug('inpage_initial_visibility', {
|
|
20613
|
+
channel: this.channelName,
|
|
20614
|
+
connector_id: this.connectorId,
|
|
20615
|
+
visibility: document.hidden ? 'hidden' : 'visible',
|
|
20616
|
+
document_hidden: document.hidden,
|
|
20617
|
+
visibility_state: document.visibilityState,
|
|
20618
|
+
has_focus: document.hasFocus(),
|
|
20619
|
+
timestamp: new Date().toISOString(),
|
|
20620
|
+
});
|
|
20621
|
+
}
|
|
20622
|
+
}
|
|
20623
|
+
/**
|
|
20624
|
+
* Override start() to check initial visibility state
|
|
20625
|
+
*/
|
|
20626
|
+
async start(inboundHandler) {
|
|
20627
|
+
await super.start(inboundHandler);
|
|
20628
|
+
// After transitioning to STARTED, check if tab is already hidden
|
|
20629
|
+
if (typeof document !== 'undefined' && document.hidden) {
|
|
20630
|
+
logger$G.debug('inpage_start_in_hidden_tab', {
|
|
20631
|
+
channel: this.channelName,
|
|
20632
|
+
connector_id: this.connectorId,
|
|
20633
|
+
document_hidden: document.hidden,
|
|
20634
|
+
visibility_state: document.visibilityState,
|
|
20635
|
+
has_focus: document.hasFocus(),
|
|
20636
|
+
timestamp: new Date().toISOString(),
|
|
20637
|
+
});
|
|
20638
|
+
// Immediately pause if tab is hidden at start time
|
|
20639
|
+
await this.pause().catch((err) => {
|
|
20640
|
+
logger$G.warning('inpage_initial_pause_failed', {
|
|
20641
|
+
channel: this.channelName,
|
|
20642
|
+
connector_id: this.connectorId,
|
|
20643
|
+
error: err instanceof Error ? err.message : String(err),
|
|
20644
|
+
});
|
|
20645
|
+
});
|
|
20646
|
+
}
|
|
20338
20647
|
}
|
|
20339
20648
|
// Allow listeners to feed envelopes directly into the in-page receive queue.
|
|
20340
20649
|
async pushToReceive(rawOrEnvelope) {
|
|
@@ -20367,11 +20676,27 @@ class InPageConnector extends BaseAsyncConnector {
|
|
|
20367
20676
|
logger$G.debug('inpage_message_sending', {
|
|
20368
20677
|
channel: this.channelName,
|
|
20369
20678
|
sender_id: this.connectorId,
|
|
20370
|
-
|
|
20679
|
+
local_node_id: this.localNodeId,
|
|
20680
|
+
remote_node_id: this.remoteNodeId,
|
|
20681
|
+
});
|
|
20682
|
+
// Only use transport framing if both localNodeId and remoteNodeId are explicitly set
|
|
20683
|
+
// (not using default values). This ensures backwards compatibility.
|
|
20684
|
+
const useTransportFrame = this.localNodeId !== this.connectorId ||
|
|
20685
|
+
this.remoteNodeId !== '*';
|
|
20686
|
+
let payload;
|
|
20687
|
+
if (useTransportFrame) {
|
|
20688
|
+
// Wrap payload in transport frame
|
|
20689
|
+
const frame = wrapTransportFrame(data, this.localNodeId, this.remoteNodeId);
|
|
20690
|
+
payload = serializeTransportFrame(frame);
|
|
20691
|
+
}
|
|
20692
|
+
else {
|
|
20693
|
+
// Legacy format: send raw payload
|
|
20694
|
+
payload = data;
|
|
20695
|
+
}
|
|
20371
20696
|
const event = new MessageEvent(this.channelName, {
|
|
20372
20697
|
data: {
|
|
20373
20698
|
senderId: this.connectorId,
|
|
20374
|
-
payload
|
|
20699
|
+
payload,
|
|
20375
20700
|
},
|
|
20376
20701
|
});
|
|
20377
20702
|
getSharedBus$1().dispatchEvent(event);
|
|
@@ -20384,6 +20709,11 @@ class InPageConnector extends BaseAsyncConnector {
|
|
|
20384
20709
|
getSharedBus$1().removeEventListener(this.channelName, this.onMsg);
|
|
20385
20710
|
this.listenerRegistered = false;
|
|
20386
20711
|
}
|
|
20712
|
+
if (this.visibilityChangeListenerRegistered && this.visibilityChangeHandler && typeof document !== 'undefined') {
|
|
20713
|
+
document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
20714
|
+
this.visibilityChangeListenerRegistered = false;
|
|
20715
|
+
this.visibilityChangeHandler = undefined;
|
|
20716
|
+
}
|
|
20387
20717
|
const closeCode = typeof code === 'number' ? code : 1000;
|
|
20388
20718
|
const closeReason = typeof reason === 'string' && reason.length > 0 ? reason : 'closed';
|
|
20389
20719
|
const shutdownError = new FameTransportClose(closeReason, closeCode);
|
|
@@ -27731,6 +28061,14 @@ function isInPageConnectionGrant(candidate) {
|
|
|
27731
28061
|
record.inboxCapacity <= 0)) {
|
|
27732
28062
|
return false;
|
|
27733
28063
|
}
|
|
28064
|
+
if (record.localNodeId !== undefined &&
|
|
28065
|
+
(typeof record.localNodeId !== 'string' || record.localNodeId.length === 0)) {
|
|
28066
|
+
return false;
|
|
28067
|
+
}
|
|
28068
|
+
if (record.remoteNodeId !== undefined &&
|
|
28069
|
+
(typeof record.remoteNodeId !== 'string' || record.remoteNodeId.length === 0)) {
|
|
28070
|
+
return false;
|
|
28071
|
+
}
|
|
27734
28072
|
return true;
|
|
27735
28073
|
}
|
|
27736
28074
|
function normalizeInPageConnectionGrant(candidate) {
|
|
@@ -27764,6 +28102,20 @@ function normalizeInPageConnectionGrant(candidate) {
|
|
|
27764
28102
|
}
|
|
27765
28103
|
result.inboxCapacity = Math.floor(inboxValue);
|
|
27766
28104
|
}
|
|
28105
|
+
const localNodeIdValue = candidate.localNodeId ?? candidate['local_node_id'];
|
|
28106
|
+
if (localNodeIdValue !== undefined) {
|
|
28107
|
+
if (typeof localNodeIdValue !== 'string' || localNodeIdValue.trim().length === 0) {
|
|
28108
|
+
throw new TypeError('InPageConnectionGrant "localNodeId" must be a non-empty string when provided');
|
|
28109
|
+
}
|
|
28110
|
+
result.localNodeId = localNodeIdValue.trim();
|
|
28111
|
+
}
|
|
28112
|
+
const remoteNodeIdValue = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
28113
|
+
if (remoteNodeIdValue !== undefined) {
|
|
28114
|
+
if (typeof remoteNodeIdValue !== 'string' || remoteNodeIdValue.trim().length === 0) {
|
|
28115
|
+
throw new TypeError('InPageConnectionGrant "remoteNodeId" must be a non-empty string when provided');
|
|
28116
|
+
}
|
|
28117
|
+
result.remoteNodeId = remoteNodeIdValue.trim();
|
|
28118
|
+
}
|
|
27767
28119
|
return result;
|
|
27768
28120
|
}
|
|
27769
28121
|
function inPageGrantToConnectorConfig(grant) {
|
|
@@ -27777,6 +28129,12 @@ function inPageGrantToConnectorConfig(grant) {
|
|
|
27777
28129
|
if (normalized.inboxCapacity !== undefined) {
|
|
27778
28130
|
config.inboxCapacity = normalized.inboxCapacity;
|
|
27779
28131
|
}
|
|
28132
|
+
if (normalized.localNodeId) {
|
|
28133
|
+
config.localNodeId = normalized.localNodeId;
|
|
28134
|
+
}
|
|
28135
|
+
if (normalized.remoteNodeId) {
|
|
28136
|
+
config.remoteNodeId = normalized.remoteNodeId;
|
|
28137
|
+
}
|
|
27780
28138
|
return config;
|
|
27781
28139
|
}
|
|
27782
28140
|
|
|
@@ -28403,6 +28761,8 @@ class BroadcastChannelConnectorFactory extends ConnectorFactory {
|
|
|
28403
28761
|
type: BROADCAST_CHANNEL_CONNECTOR_TYPE,
|
|
28404
28762
|
channelName,
|
|
28405
28763
|
inboxCapacity,
|
|
28764
|
+
localNodeId: normalized.localNodeId,
|
|
28765
|
+
remoteNodeId: normalized.remoteNodeId,
|
|
28406
28766
|
};
|
|
28407
28767
|
const connector = new BroadcastChannelConnector(connectorConfig, baseConfig);
|
|
28408
28768
|
if (options.authorization) {
|
|
@@ -28464,6 +28824,16 @@ class BroadcastChannelConnectorFactory extends ConnectorFactory {
|
|
|
28464
28824
|
if (candidate.authorizationContext !== undefined) {
|
|
28465
28825
|
normalized.authorizationContext = candidate.authorizationContext;
|
|
28466
28826
|
}
|
|
28827
|
+
// Handle localNodeId
|
|
28828
|
+
const localNodeId = candidate.localNodeId ?? candidate['local_node_id'];
|
|
28829
|
+
if (typeof localNodeId === 'string' && localNodeId.trim().length > 0) {
|
|
28830
|
+
normalized.localNodeId = localNodeId.trim();
|
|
28831
|
+
}
|
|
28832
|
+
// Handle remoteNodeId
|
|
28833
|
+
const remoteNodeId = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
28834
|
+
if (typeof remoteNodeId === 'string' && remoteNodeId.trim().length > 0) {
|
|
28835
|
+
normalized.remoteNodeId = remoteNodeId.trim();
|
|
28836
|
+
}
|
|
28467
28837
|
normalized.channelName = normalized.channelName ?? DEFAULT_CHANNEL$5;
|
|
28468
28838
|
normalized.inboxCapacity =
|
|
28469
28839
|
normalized.inboxCapacity ?? DEFAULT_INBOX_CAPACITY$5;
|
|
@@ -29027,6 +29397,8 @@ class InPageConnectorFactory extends ConnectorFactory {
|
|
|
29027
29397
|
type: INPAGE_CONNECTOR_TYPE,
|
|
29028
29398
|
channelName,
|
|
29029
29399
|
inboxCapacity,
|
|
29400
|
+
localNodeId: normalized.localNodeId,
|
|
29401
|
+
remoteNodeId: normalized.remoteNodeId,
|
|
29030
29402
|
};
|
|
29031
29403
|
const connector = new InPageConnector(connectorConfig, baseConfig);
|
|
29032
29404
|
if (options.authorization) {
|
|
@@ -29095,6 +29467,16 @@ class InPageConnectorFactory extends ConnectorFactory {
|
|
|
29095
29467
|
if (candidate.authorizationContext !== undefined) {
|
|
29096
29468
|
normalized.authorizationContext = candidate.authorizationContext;
|
|
29097
29469
|
}
|
|
29470
|
+
// Handle localNodeId
|
|
29471
|
+
const localNodeId = candidate.localNodeId ?? candidate['local_node_id'];
|
|
29472
|
+
if (typeof localNodeId === 'string' && localNodeId.trim().length > 0) {
|
|
29473
|
+
normalized.localNodeId = localNodeId.trim();
|
|
29474
|
+
}
|
|
29475
|
+
// Handle remoteNodeId
|
|
29476
|
+
const remoteNodeId = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
29477
|
+
if (typeof remoteNodeId === 'string' && remoteNodeId.trim().length > 0) {
|
|
29478
|
+
normalized.remoteNodeId = remoteNodeId.trim();
|
|
29479
|
+
}
|
|
29098
29480
|
normalized.channelName = normalized.channelName ?? DEFAULT_CHANNEL$3;
|
|
29099
29481
|
normalized.inboxCapacity =
|
|
29100
29482
|
normalized.inboxCapacity ?? DEFAULT_INBOX_CAPACITY$3;
|