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