@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.mjs
CHANGED
|
@@ -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.
|
|
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.
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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;
|