@naylence/runtime 0.3.5-test.942 → 0.3.5-test.944
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 +380 -8
- package/dist/browser/index.mjs +380 -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/broadcast-channel-listener.js +35 -0
- package/dist/cjs/naylence/fame/connector/inpage-connector-factory.js +12 -0
- package/dist/cjs/naylence/fame/connector/inpage-connector.js +66 -1
- package/dist/cjs/naylence/fame/connector/inpage-listener.js +49 -2
- 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/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/broadcast-channel-listener.js +35 -0
- package/dist/esm/naylence/fame/connector/inpage-connector-factory.js +12 -0
- package/dist/esm/naylence/fame/connector/inpage-connector.js +66 -1
- package/dist/esm/naylence/fame/connector/inpage-listener.js +49 -2
- 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/version.js +2 -2
- package/dist/node/index.cjs +380 -8
- package/dist/node/index.mjs +380 -8
- package/dist/node/node.cjs +396 -8
- package/dist/node/node.mjs +396 -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 +4 -0
- package/dist/types/naylence/fame/connector/inpage-listener.d.ts +1 -0
- 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.mjs
CHANGED
|
@@ -13,12 +13,12 @@ import fastify from 'fastify';
|
|
|
13
13
|
import websocketPlugin from '@fastify/websocket';
|
|
14
14
|
|
|
15
15
|
// This file is auto-generated during build - do not edit manually
|
|
16
|
-
// Generated from package.json version: 0.3.5-test.
|
|
16
|
+
// Generated from package.json version: 0.3.5-test.944
|
|
17
17
|
/**
|
|
18
18
|
* The package version, injected at build time.
|
|
19
19
|
* @internal
|
|
20
20
|
*/
|
|
21
|
-
const VERSION = '0.3.5-test.
|
|
21
|
+
const VERSION = '0.3.5-test.944';
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Fame protocol specific error classes with WebSocket close codes and proper inheritance.
|
|
@@ -9733,6 +9733,85 @@ class BoundedAsyncQueue {
|
|
|
9733
9733
|
}
|
|
9734
9734
|
}
|
|
9735
9735
|
|
|
9736
|
+
/**
|
|
9737
|
+
* Transport frame layer for multiplexing logical links on physical channels.
|
|
9738
|
+
*
|
|
9739
|
+
* This lightweight framing layer wraps raw FAME payloads to enable multiple
|
|
9740
|
+
* logical connections over a single physical channel (BroadcastChannel or InPage bus).
|
|
9741
|
+
*
|
|
9742
|
+
* The transport frame does NOT modify FAME envelopes - it only wraps the raw
|
|
9743
|
+
* Uint8Array payload at the connector level.
|
|
9744
|
+
*/
|
|
9745
|
+
/**
|
|
9746
|
+
* Transport frame version for future compatibility
|
|
9747
|
+
*/
|
|
9748
|
+
const TRANSPORT_FRAME_VERSION = 1;
|
|
9749
|
+
/**
|
|
9750
|
+
* Wrap a raw payload in a transport frame
|
|
9751
|
+
*
|
|
9752
|
+
* @param payload - Raw FAME envelope bytes
|
|
9753
|
+
* @param srcNodeId - Local node ID (this connector)
|
|
9754
|
+
* @param dstNodeId - Remote node ID (target connector)
|
|
9755
|
+
* @returns Transport frame ready for transmission
|
|
9756
|
+
*/
|
|
9757
|
+
function wrapTransportFrame(payload, srcNodeId, dstNodeId) {
|
|
9758
|
+
return {
|
|
9759
|
+
v: TRANSPORT_FRAME_VERSION,
|
|
9760
|
+
src: srcNodeId,
|
|
9761
|
+
dst: dstNodeId,
|
|
9762
|
+
payload,
|
|
9763
|
+
};
|
|
9764
|
+
}
|
|
9765
|
+
/**
|
|
9766
|
+
* Serialize a transport frame for transmission over the bus
|
|
9767
|
+
*
|
|
9768
|
+
* @param frame - Transport frame to serialize
|
|
9769
|
+
* @returns Serialized frame data ready for postMessage/dispatchEvent
|
|
9770
|
+
*/
|
|
9771
|
+
function serializeTransportFrame(frame) {
|
|
9772
|
+
// Convert Uint8Array to regular array for JSON serialization
|
|
9773
|
+
const serializable = {
|
|
9774
|
+
v: frame.v,
|
|
9775
|
+
src: frame.src,
|
|
9776
|
+
dst: frame.dst,
|
|
9777
|
+
payload: Array.from(frame.payload),
|
|
9778
|
+
};
|
|
9779
|
+
return serializable;
|
|
9780
|
+
}
|
|
9781
|
+
/**
|
|
9782
|
+
* Unwrap a transport frame, validating source and destination
|
|
9783
|
+
*
|
|
9784
|
+
* @param raw - Raw data from the bus
|
|
9785
|
+
* @param localNodeId - This connector's node ID
|
|
9786
|
+
* @param remoteNodeId - Expected remote node ID
|
|
9787
|
+
* @returns Unwrapped payload if frame is valid and addressed to us, null otherwise
|
|
9788
|
+
*/
|
|
9789
|
+
function unwrapTransportFrame(raw, localNodeId, remoteNodeId) {
|
|
9790
|
+
// Validate basic structure
|
|
9791
|
+
if (!raw || typeof raw !== 'object') {
|
|
9792
|
+
return null;
|
|
9793
|
+
}
|
|
9794
|
+
const frame = raw;
|
|
9795
|
+
// Check version
|
|
9796
|
+
if (frame.v !== TRANSPORT_FRAME_VERSION) {
|
|
9797
|
+
return null;
|
|
9798
|
+
}
|
|
9799
|
+
// Check src and dst
|
|
9800
|
+
if (typeof frame.src !== 'string' || typeof frame.dst !== 'string') {
|
|
9801
|
+
return null;
|
|
9802
|
+
}
|
|
9803
|
+
// Only accept frames addressed to us from the expected remote
|
|
9804
|
+
if (frame.dst !== localNodeId || frame.src !== remoteNodeId) {
|
|
9805
|
+
return null;
|
|
9806
|
+
}
|
|
9807
|
+
// Extract payload
|
|
9808
|
+
if (!frame.payload || !Array.isArray(frame.payload)) {
|
|
9809
|
+
return null;
|
|
9810
|
+
}
|
|
9811
|
+
// Convert array back to Uint8Array
|
|
9812
|
+
return Uint8Array.from(frame.payload);
|
|
9813
|
+
}
|
|
9814
|
+
|
|
9736
9815
|
const logger$_ = getLogger('naylence.fame.connector.broadcast_channel_connector');
|
|
9737
9816
|
const BROADCAST_CHANNEL_CONNECTOR_TYPE = 'broadcast-channel-connector';
|
|
9738
9817
|
const DEFAULT_CHANNEL$7 = 'naylence-fabric';
|
|
@@ -9798,9 +9877,20 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9798
9877
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
9799
9878
|
this.connectorId = BroadcastChannelConnector.generateConnectorId();
|
|
9800
9879
|
this.channel = new BroadcastChannel(this.channelName);
|
|
9880
|
+
// Set local and remote node IDs (defaults to connector ID for backwards compatibility)
|
|
9881
|
+
this.localNodeId =
|
|
9882
|
+
typeof config.localNodeId === 'string' && config.localNodeId.trim().length > 0
|
|
9883
|
+
? config.localNodeId.trim()
|
|
9884
|
+
: this.connectorId;
|
|
9885
|
+
this.remoteNodeId =
|
|
9886
|
+
typeof config.remoteNodeId === 'string' && config.remoteNodeId.trim().length > 0
|
|
9887
|
+
? config.remoteNodeId.trim()
|
|
9888
|
+
: '*'; // Accept from any remote if not specified
|
|
9801
9889
|
logger$_.debug('broadcast_channel_connector_created', {
|
|
9802
9890
|
channel: this.channelName,
|
|
9803
9891
|
connector_id: this.connectorId,
|
|
9892
|
+
local_node_id: this.localNodeId,
|
|
9893
|
+
remote_node_id: this.remoteNodeId,
|
|
9804
9894
|
inbox_capacity: preferredCapacity,
|
|
9805
9895
|
timestamp: new Date().toISOString(),
|
|
9806
9896
|
});
|
|
@@ -9833,6 +9923,46 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9833
9923
|
if (busMessage.senderId === this.connectorId) {
|
|
9834
9924
|
return;
|
|
9835
9925
|
}
|
|
9926
|
+
// Try to unwrap as transport frame
|
|
9927
|
+
const unwrapped = unwrapTransportFrame(busMessage.payload, this.localNodeId, this.remoteNodeId === '*' ? busMessage.senderId : this.remoteNodeId);
|
|
9928
|
+
if (unwrapped) {
|
|
9929
|
+
// Successfully unwrapped transport frame
|
|
9930
|
+
logger$_.debug('broadcast_channel_transport_frame_received', {
|
|
9931
|
+
channel: this.channelName,
|
|
9932
|
+
sender_id: busMessage.senderId,
|
|
9933
|
+
connector_id: this.connectorId,
|
|
9934
|
+
local_node_id: this.localNodeId,
|
|
9935
|
+
remote_node_id: this.remoteNodeId,
|
|
9936
|
+
payload_length: unwrapped.byteLength,
|
|
9937
|
+
});
|
|
9938
|
+
if (this._shouldSkipDuplicateAck(busMessage.senderId, unwrapped)) {
|
|
9939
|
+
return;
|
|
9940
|
+
}
|
|
9941
|
+
try {
|
|
9942
|
+
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
9943
|
+
const accepted = this.inbox.tryEnqueue(unwrapped);
|
|
9944
|
+
if (accepted) {
|
|
9945
|
+
return;
|
|
9946
|
+
}
|
|
9947
|
+
}
|
|
9948
|
+
this.inbox.enqueue(unwrapped);
|
|
9949
|
+
}
|
|
9950
|
+
catch (error) {
|
|
9951
|
+
if (error instanceof QueueFullError) {
|
|
9952
|
+
logger$_.warning('broadcast_channel_receive_queue_full', {
|
|
9953
|
+
channel: this.channelName,
|
|
9954
|
+
});
|
|
9955
|
+
}
|
|
9956
|
+
else {
|
|
9957
|
+
logger$_.error('broadcast_channel_receive_error', {
|
|
9958
|
+
channel: this.channelName,
|
|
9959
|
+
error: error instanceof Error ? error.message : String(error),
|
|
9960
|
+
});
|
|
9961
|
+
}
|
|
9962
|
+
}
|
|
9963
|
+
return;
|
|
9964
|
+
}
|
|
9965
|
+
// Fall back to legacy format (no transport frame)
|
|
9836
9966
|
const payload = BroadcastChannelConnector.coercePayload(busMessage.payload);
|
|
9837
9967
|
if (!payload) {
|
|
9838
9968
|
logger$_.debug('broadcast_channel_payload_rejected', {
|
|
@@ -9971,10 +10101,26 @@ let BroadcastChannelConnector$2 = class BroadcastChannelConnector extends BaseAs
|
|
|
9971
10101
|
logger$_.debug('broadcast_channel_message_sending', {
|
|
9972
10102
|
channel: this.channelName,
|
|
9973
10103
|
sender_id: this.connectorId,
|
|
9974
|
-
|
|
10104
|
+
local_node_id: this.localNodeId,
|
|
10105
|
+
remote_node_id: this.remoteNodeId,
|
|
10106
|
+
});
|
|
10107
|
+
// Only use transport framing if both localNodeId and remoteNodeId are explicitly set
|
|
10108
|
+
// (not using default values). This ensures backwards compatibility.
|
|
10109
|
+
const useTransportFrame = this.localNodeId !== this.connectorId ||
|
|
10110
|
+
this.remoteNodeId !== '*';
|
|
10111
|
+
let payload;
|
|
10112
|
+
if (useTransportFrame) {
|
|
10113
|
+
// Wrap payload in transport frame
|
|
10114
|
+
const frame = wrapTransportFrame(data, this.localNodeId, this.remoteNodeId);
|
|
10115
|
+
payload = serializeTransportFrame(frame);
|
|
10116
|
+
}
|
|
10117
|
+
else {
|
|
10118
|
+
// Legacy format: send raw payload
|
|
10119
|
+
payload = data;
|
|
10120
|
+
}
|
|
9975
10121
|
this.channel.postMessage({
|
|
9976
10122
|
senderId: this.connectorId,
|
|
9977
|
-
payload
|
|
10123
|
+
payload,
|
|
9978
10124
|
});
|
|
9979
10125
|
}
|
|
9980
10126
|
async _transportReceive() {
|
|
@@ -10267,6 +10413,14 @@ function isBroadcastChannelConnectionGrant(candidate) {
|
|
|
10267
10413
|
record.inboxCapacity <= 0)) {
|
|
10268
10414
|
return false;
|
|
10269
10415
|
}
|
|
10416
|
+
if (record.localNodeId !== undefined &&
|
|
10417
|
+
(typeof record.localNodeId !== 'string' || record.localNodeId.length === 0)) {
|
|
10418
|
+
return false;
|
|
10419
|
+
}
|
|
10420
|
+
if (record.remoteNodeId !== undefined &&
|
|
10421
|
+
(typeof record.remoteNodeId !== 'string' || record.remoteNodeId.length === 0)) {
|
|
10422
|
+
return false;
|
|
10423
|
+
}
|
|
10270
10424
|
return true;
|
|
10271
10425
|
}
|
|
10272
10426
|
function normalizeBroadcastChannelConnectionGrant(candidate) {
|
|
@@ -10300,6 +10454,20 @@ function normalizeBroadcastChannelConnectionGrant(candidate) {
|
|
|
10300
10454
|
}
|
|
10301
10455
|
result.inboxCapacity = Math.floor(inboxValue);
|
|
10302
10456
|
}
|
|
10457
|
+
const localNodeIdValue = candidate.localNodeId ?? candidate['local_node_id'];
|
|
10458
|
+
if (localNodeIdValue !== undefined) {
|
|
10459
|
+
if (typeof localNodeIdValue !== 'string' || localNodeIdValue.trim().length === 0) {
|
|
10460
|
+
throw new TypeError('BroadcastChannelConnectionGrant "localNodeId" must be a non-empty string when provided');
|
|
10461
|
+
}
|
|
10462
|
+
result.localNodeId = localNodeIdValue.trim();
|
|
10463
|
+
}
|
|
10464
|
+
const remoteNodeIdValue = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
10465
|
+
if (remoteNodeIdValue !== undefined) {
|
|
10466
|
+
if (typeof remoteNodeIdValue !== 'string' || remoteNodeIdValue.trim().length === 0) {
|
|
10467
|
+
throw new TypeError('BroadcastChannelConnectionGrant "remoteNodeId" must be a non-empty string when provided');
|
|
10468
|
+
}
|
|
10469
|
+
result.remoteNodeId = remoteNodeIdValue.trim();
|
|
10470
|
+
}
|
|
10303
10471
|
return result;
|
|
10304
10472
|
}
|
|
10305
10473
|
function broadcastChannelGrantToConnectorConfig(grant) {
|
|
@@ -10313,6 +10481,12 @@ function broadcastChannelGrantToConnectorConfig(grant) {
|
|
|
10313
10481
|
if (normalized.inboxCapacity !== undefined) {
|
|
10314
10482
|
config.inboxCapacity = normalized.inboxCapacity;
|
|
10315
10483
|
}
|
|
10484
|
+
if (normalized.localNodeId) {
|
|
10485
|
+
config.localNodeId = normalized.localNodeId;
|
|
10486
|
+
}
|
|
10487
|
+
if (normalized.remoteNodeId) {
|
|
10488
|
+
config.remoteNodeId = normalized.remoteNodeId;
|
|
10489
|
+
}
|
|
10316
10490
|
return config;
|
|
10317
10491
|
}
|
|
10318
10492
|
|
|
@@ -20259,9 +20433,20 @@ class InPageConnector extends BaseAsyncConnector {
|
|
|
20259
20433
|
: DEFAULT_INBOX_CAPACITY$6;
|
|
20260
20434
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
20261
20435
|
this.connectorId = InPageConnector.generateConnectorId();
|
|
20436
|
+
// Set local and remote node IDs (defaults to connector ID for backwards compatibility)
|
|
20437
|
+
this.localNodeId =
|
|
20438
|
+
typeof config.localNodeId === 'string' && config.localNodeId.trim().length > 0
|
|
20439
|
+
? config.localNodeId.trim()
|
|
20440
|
+
: this.connectorId;
|
|
20441
|
+
this.remoteNodeId =
|
|
20442
|
+
typeof config.remoteNodeId === 'string' && config.remoteNodeId.trim().length > 0
|
|
20443
|
+
? config.remoteNodeId.trim()
|
|
20444
|
+
: '*'; // Accept from any remote if not specified
|
|
20262
20445
|
logger$G.debug('inpage_connector_initialized', {
|
|
20263
20446
|
channel: this.channelName,
|
|
20264
20447
|
connector_id: this.connectorId,
|
|
20448
|
+
local_node_id: this.localNodeId,
|
|
20449
|
+
remote_node_id: this.remoteNodeId,
|
|
20265
20450
|
});
|
|
20266
20451
|
this.onMsg = (event) => {
|
|
20267
20452
|
const messageEvent = event;
|
|
@@ -20295,6 +20480,43 @@ class InPageConnector extends BaseAsyncConnector {
|
|
|
20295
20480
|
if (busMessage.senderId === this.connectorId) {
|
|
20296
20481
|
return;
|
|
20297
20482
|
}
|
|
20483
|
+
// Try to unwrap as transport frame
|
|
20484
|
+
const unwrapped = unwrapTransportFrame(busMessage.payload, this.localNodeId, this.remoteNodeId === '*' ? busMessage.senderId : this.remoteNodeId);
|
|
20485
|
+
if (unwrapped) {
|
|
20486
|
+
// Successfully unwrapped transport frame
|
|
20487
|
+
logger$G.debug('inpage_transport_frame_received', {
|
|
20488
|
+
channel: this.channelName,
|
|
20489
|
+
sender_id: busMessage.senderId,
|
|
20490
|
+
connector_id: this.connectorId,
|
|
20491
|
+
local_node_id: this.localNodeId,
|
|
20492
|
+
remote_node_id: this.remoteNodeId,
|
|
20493
|
+
payload_length: unwrapped.byteLength,
|
|
20494
|
+
});
|
|
20495
|
+
try {
|
|
20496
|
+
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
20497
|
+
const accepted = this.inbox.tryEnqueue(unwrapped);
|
|
20498
|
+
if (accepted) {
|
|
20499
|
+
return;
|
|
20500
|
+
}
|
|
20501
|
+
}
|
|
20502
|
+
this.inbox.enqueue(unwrapped);
|
|
20503
|
+
}
|
|
20504
|
+
catch (error) {
|
|
20505
|
+
if (error instanceof QueueFullError) {
|
|
20506
|
+
logger$G.warning('inpage_receive_queue_full', {
|
|
20507
|
+
channel: this.channelName,
|
|
20508
|
+
});
|
|
20509
|
+
}
|
|
20510
|
+
else {
|
|
20511
|
+
logger$G.error('inpage_receive_error', {
|
|
20512
|
+
channel: this.channelName,
|
|
20513
|
+
error: error instanceof Error ? error.message : String(error),
|
|
20514
|
+
});
|
|
20515
|
+
}
|
|
20516
|
+
}
|
|
20517
|
+
return;
|
|
20518
|
+
}
|
|
20519
|
+
// Fall back to legacy format (no transport frame)
|
|
20298
20520
|
const payload = InPageConnector.coercePayload(busMessage.payload);
|
|
20299
20521
|
if (!payload) {
|
|
20300
20522
|
logger$G.debug('inpage_payload_rejected', {
|
|
@@ -20453,11 +20675,27 @@ class InPageConnector extends BaseAsyncConnector {
|
|
|
20453
20675
|
logger$G.debug('inpage_message_sending', {
|
|
20454
20676
|
channel: this.channelName,
|
|
20455
20677
|
sender_id: this.connectorId,
|
|
20456
|
-
|
|
20678
|
+
local_node_id: this.localNodeId,
|
|
20679
|
+
remote_node_id: this.remoteNodeId,
|
|
20680
|
+
});
|
|
20681
|
+
// Only use transport framing if both localNodeId and remoteNodeId are explicitly set
|
|
20682
|
+
// (not using default values). This ensures backwards compatibility.
|
|
20683
|
+
const useTransportFrame = this.localNodeId !== this.connectorId ||
|
|
20684
|
+
this.remoteNodeId !== '*';
|
|
20685
|
+
let payload;
|
|
20686
|
+
if (useTransportFrame) {
|
|
20687
|
+
// Wrap payload in transport frame
|
|
20688
|
+
const frame = wrapTransportFrame(data, this.localNodeId, this.remoteNodeId);
|
|
20689
|
+
payload = serializeTransportFrame(frame);
|
|
20690
|
+
}
|
|
20691
|
+
else {
|
|
20692
|
+
// Legacy format: send raw payload
|
|
20693
|
+
payload = data;
|
|
20694
|
+
}
|
|
20457
20695
|
const event = new MessageEvent(this.channelName, {
|
|
20458
20696
|
data: {
|
|
20459
20697
|
senderId: this.connectorId,
|
|
20460
|
-
payload
|
|
20698
|
+
payload,
|
|
20461
20699
|
},
|
|
20462
20700
|
});
|
|
20463
20701
|
getSharedBus$1().dispatchEvent(event);
|
|
@@ -27822,6 +28060,14 @@ function isInPageConnectionGrant(candidate) {
|
|
|
27822
28060
|
record.inboxCapacity <= 0)) {
|
|
27823
28061
|
return false;
|
|
27824
28062
|
}
|
|
28063
|
+
if (record.localNodeId !== undefined &&
|
|
28064
|
+
(typeof record.localNodeId !== 'string' || record.localNodeId.length === 0)) {
|
|
28065
|
+
return false;
|
|
28066
|
+
}
|
|
28067
|
+
if (record.remoteNodeId !== undefined &&
|
|
28068
|
+
(typeof record.remoteNodeId !== 'string' || record.remoteNodeId.length === 0)) {
|
|
28069
|
+
return false;
|
|
28070
|
+
}
|
|
27825
28071
|
return true;
|
|
27826
28072
|
}
|
|
27827
28073
|
function normalizeInPageConnectionGrant(candidate) {
|
|
@@ -27855,6 +28101,20 @@ function normalizeInPageConnectionGrant(candidate) {
|
|
|
27855
28101
|
}
|
|
27856
28102
|
result.inboxCapacity = Math.floor(inboxValue);
|
|
27857
28103
|
}
|
|
28104
|
+
const localNodeIdValue = candidate.localNodeId ?? candidate['local_node_id'];
|
|
28105
|
+
if (localNodeIdValue !== undefined) {
|
|
28106
|
+
if (typeof localNodeIdValue !== 'string' || localNodeIdValue.trim().length === 0) {
|
|
28107
|
+
throw new TypeError('InPageConnectionGrant "localNodeId" must be a non-empty string when provided');
|
|
28108
|
+
}
|
|
28109
|
+
result.localNodeId = localNodeIdValue.trim();
|
|
28110
|
+
}
|
|
28111
|
+
const remoteNodeIdValue = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
28112
|
+
if (remoteNodeIdValue !== undefined) {
|
|
28113
|
+
if (typeof remoteNodeIdValue !== 'string' || remoteNodeIdValue.trim().length === 0) {
|
|
28114
|
+
throw new TypeError('InPageConnectionGrant "remoteNodeId" must be a non-empty string when provided');
|
|
28115
|
+
}
|
|
28116
|
+
result.remoteNodeId = remoteNodeIdValue.trim();
|
|
28117
|
+
}
|
|
27858
28118
|
return result;
|
|
27859
28119
|
}
|
|
27860
28120
|
function inPageGrantToConnectorConfig(grant) {
|
|
@@ -27868,6 +28128,12 @@ function inPageGrantToConnectorConfig(grant) {
|
|
|
27868
28128
|
if (normalized.inboxCapacity !== undefined) {
|
|
27869
28129
|
config.inboxCapacity = normalized.inboxCapacity;
|
|
27870
28130
|
}
|
|
28131
|
+
if (normalized.localNodeId) {
|
|
28132
|
+
config.localNodeId = normalized.localNodeId;
|
|
28133
|
+
}
|
|
28134
|
+
if (normalized.remoteNodeId) {
|
|
28135
|
+
config.remoteNodeId = normalized.remoteNodeId;
|
|
28136
|
+
}
|
|
27871
28137
|
return config;
|
|
27872
28138
|
}
|
|
27873
28139
|
|
|
@@ -28494,6 +28760,8 @@ class BroadcastChannelConnectorFactory extends ConnectorFactory {
|
|
|
28494
28760
|
type: BROADCAST_CHANNEL_CONNECTOR_TYPE,
|
|
28495
28761
|
channelName,
|
|
28496
28762
|
inboxCapacity,
|
|
28763
|
+
localNodeId: normalized.localNodeId,
|
|
28764
|
+
remoteNodeId: normalized.remoteNodeId,
|
|
28497
28765
|
};
|
|
28498
28766
|
const connector = new BroadcastChannelConnector(connectorConfig, baseConfig);
|
|
28499
28767
|
if (options.authorization) {
|
|
@@ -28555,6 +28823,16 @@ class BroadcastChannelConnectorFactory extends ConnectorFactory {
|
|
|
28555
28823
|
if (candidate.authorizationContext !== undefined) {
|
|
28556
28824
|
normalized.authorizationContext = candidate.authorizationContext;
|
|
28557
28825
|
}
|
|
28826
|
+
// Handle localNodeId
|
|
28827
|
+
const localNodeId = candidate.localNodeId ?? candidate['local_node_id'];
|
|
28828
|
+
if (typeof localNodeId === 'string' && localNodeId.trim().length > 0) {
|
|
28829
|
+
normalized.localNodeId = localNodeId.trim();
|
|
28830
|
+
}
|
|
28831
|
+
// Handle remoteNodeId
|
|
28832
|
+
const remoteNodeId = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
28833
|
+
if (typeof remoteNodeId === 'string' && remoteNodeId.trim().length > 0) {
|
|
28834
|
+
normalized.remoteNodeId = remoteNodeId.trim();
|
|
28835
|
+
}
|
|
28558
28836
|
normalized.channelName = normalized.channelName ?? DEFAULT_CHANNEL$5;
|
|
28559
28837
|
normalized.inboxCapacity =
|
|
28560
28838
|
normalized.inboxCapacity ?? DEFAULT_INBOX_CAPACITY$5;
|
|
@@ -29118,6 +29396,8 @@ class InPageConnectorFactory extends ConnectorFactory {
|
|
|
29118
29396
|
type: INPAGE_CONNECTOR_TYPE,
|
|
29119
29397
|
channelName,
|
|
29120
29398
|
inboxCapacity,
|
|
29399
|
+
localNodeId: normalized.localNodeId,
|
|
29400
|
+
remoteNodeId: normalized.remoteNodeId,
|
|
29121
29401
|
};
|
|
29122
29402
|
const connector = new InPageConnector(connectorConfig, baseConfig);
|
|
29123
29403
|
if (options.authorization) {
|
|
@@ -29186,6 +29466,16 @@ class InPageConnectorFactory extends ConnectorFactory {
|
|
|
29186
29466
|
if (candidate.authorizationContext !== undefined) {
|
|
29187
29467
|
normalized.authorizationContext = candidate.authorizationContext;
|
|
29188
29468
|
}
|
|
29469
|
+
// Handle localNodeId
|
|
29470
|
+
const localNodeId = candidate.localNodeId ?? candidate['local_node_id'];
|
|
29471
|
+
if (typeof localNodeId === 'string' && localNodeId.trim().length > 0) {
|
|
29472
|
+
normalized.localNodeId = localNodeId.trim();
|
|
29473
|
+
}
|
|
29474
|
+
// Handle remoteNodeId
|
|
29475
|
+
const remoteNodeId = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
29476
|
+
if (typeof remoteNodeId === 'string' && remoteNodeId.trim().length > 0) {
|
|
29477
|
+
normalized.remoteNodeId = remoteNodeId.trim();
|
|
29478
|
+
}
|
|
29189
29479
|
normalized.channelName = normalized.channelName ?? DEFAULT_CHANNEL$3;
|
|
29190
29480
|
normalized.inboxCapacity =
|
|
29191
29481
|
normalized.inboxCapacity ?? DEFAULT_INBOX_CAPACITY$3;
|
|
@@ -36153,6 +36443,26 @@ class BroadcastChannelListener extends TransportListener {
|
|
|
36153
36443
|
inboxCapacity: this._inboxCapacity,
|
|
36154
36444
|
};
|
|
36155
36445
|
}
|
|
36446
|
+
// Automatically configure transport frame multiplexing:
|
|
36447
|
+
// Set remoteNodeId to the incoming senderId to target responses back to the specific client/agent
|
|
36448
|
+
const broadcastConfig = connectorConfig;
|
|
36449
|
+
if (!broadcastConfig.remoteNodeId) {
|
|
36450
|
+
broadcastConfig.remoteNodeId = params.senderId;
|
|
36451
|
+
logger$a.debug('broadcast_channel_listener_auto_configured_remote_node_id', {
|
|
36452
|
+
sender_id: params.senderId,
|
|
36453
|
+
system_id: systemId,
|
|
36454
|
+
remote_node_id: params.senderId,
|
|
36455
|
+
local_node_id: broadcastConfig.localNodeId ?? '<not set>',
|
|
36456
|
+
});
|
|
36457
|
+
}
|
|
36458
|
+
else {
|
|
36459
|
+
logger$a.debug('broadcast_channel_listener_using_provided_remote_node_id', {
|
|
36460
|
+
sender_id: params.senderId,
|
|
36461
|
+
system_id: systemId,
|
|
36462
|
+
remote_node_id: broadcastConfig.remoteNodeId,
|
|
36463
|
+
local_node_id: broadcastConfig.localNodeId ?? '<not set>',
|
|
36464
|
+
});
|
|
36465
|
+
}
|
|
36156
36466
|
try {
|
|
36157
36467
|
const connector = await routingNode.createOriginConnector({
|
|
36158
36468
|
originType,
|
|
@@ -36222,6 +36532,21 @@ class BroadcastChannelListener extends TransportListener {
|
|
|
36222
36532
|
inboxCandidate > 0) {
|
|
36223
36533
|
config.inboxCapacity = Math.floor(inboxCandidate);
|
|
36224
36534
|
}
|
|
36535
|
+
// Extract transport frame multiplexing node IDs
|
|
36536
|
+
const localNodeIdCandidate = candidate.localNodeId ?? candidate['local_node_id'];
|
|
36537
|
+
if (typeof localNodeIdCandidate === 'string' && localNodeIdCandidate.trim().length > 0) {
|
|
36538
|
+
config.localNodeId = localNodeIdCandidate.trim();
|
|
36539
|
+
logger$a.debug('broadcast_channel_listener_extracted_local_node_id', {
|
|
36540
|
+
local_node_id: config.localNodeId,
|
|
36541
|
+
});
|
|
36542
|
+
}
|
|
36543
|
+
const remoteNodeIdCandidate = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
36544
|
+
if (typeof remoteNodeIdCandidate === 'string' && remoteNodeIdCandidate.trim().length > 0) {
|
|
36545
|
+
config.remoteNodeId = remoteNodeIdCandidate.trim();
|
|
36546
|
+
logger$a.debug('broadcast_channel_listener_extracted_remote_node_id', {
|
|
36547
|
+
remote_node_id: config.remoteNodeId,
|
|
36548
|
+
});
|
|
36549
|
+
}
|
|
36225
36550
|
return config;
|
|
36226
36551
|
}
|
|
36227
36552
|
_monitorConnectorLifecycle(senderId, systemId, connector) {
|
|
@@ -36944,6 +37269,7 @@ class InPageListener extends TransportListener {
|
|
|
36944
37269
|
this._busHandler = null;
|
|
36945
37270
|
this._senderRegistry = new Map();
|
|
36946
37271
|
this._systemToSender = new Map();
|
|
37272
|
+
this._flowIdToSender = new Map();
|
|
36947
37273
|
this._pendingAttachments = new Map();
|
|
36948
37274
|
ensureBrowserEnvironment();
|
|
36949
37275
|
const channelCandidate = options?.channelName;
|
|
@@ -37010,6 +37336,7 @@ class InPageListener extends TransportListener {
|
|
|
37010
37336
|
this._unregisterBusListener();
|
|
37011
37337
|
this._senderRegistry.clear();
|
|
37012
37338
|
this._systemToSender.clear();
|
|
37339
|
+
this._flowIdToSender.clear();
|
|
37013
37340
|
this._pendingAttachments.clear();
|
|
37014
37341
|
logger$7.debug('inpage_listener_stopped', {
|
|
37015
37342
|
channel: this._channelName,
|
|
@@ -37063,10 +37390,25 @@ class InPageListener extends TransportListener {
|
|
|
37063
37390
|
await this._handleAttachFrame(senderId, envelope);
|
|
37064
37391
|
return;
|
|
37065
37392
|
}
|
|
37066
|
-
|
|
37393
|
+
// Try to find connector by sender ID first
|
|
37394
|
+
let entry = this._senderRegistry.get(senderId);
|
|
37395
|
+
// If not found and we have a flowId, try to route based on flow
|
|
37396
|
+
if (!entry && envelope.flowId) {
|
|
37397
|
+
const originalSenderId = this._flowIdToSender.get(envelope.flowId);
|
|
37398
|
+
if (originalSenderId) {
|
|
37399
|
+
entry = this._senderRegistry.get(originalSenderId);
|
|
37400
|
+
logger$7.debug('inpage_listener_routed_by_flow_id', {
|
|
37401
|
+
sender_id: senderId,
|
|
37402
|
+
original_sender_id: originalSenderId,
|
|
37403
|
+
flow_id: envelope.flowId,
|
|
37404
|
+
frame_type: envelope.frame?.type ?? 'unknown',
|
|
37405
|
+
});
|
|
37406
|
+
}
|
|
37407
|
+
}
|
|
37067
37408
|
if (!entry) {
|
|
37068
37409
|
logger$7.debug('inpage_listener_no_connector_for_sender', {
|
|
37069
37410
|
sender_id: senderId,
|
|
37411
|
+
flow_id: envelope.flowId,
|
|
37070
37412
|
frame_type: envelope.frame?.type ?? 'unknown',
|
|
37071
37413
|
});
|
|
37072
37414
|
return;
|
|
@@ -37143,6 +37485,15 @@ class InPageListener extends TransportListener {
|
|
|
37143
37485
|
}
|
|
37144
37486
|
this._senderRegistry.set(senderId, entry);
|
|
37145
37487
|
this._systemToSender.set(entry.systemId, senderId);
|
|
37488
|
+
// Track the flowId if present so we can route responses back
|
|
37489
|
+
if (envelope.flowId) {
|
|
37490
|
+
this._flowIdToSender.set(envelope.flowId, senderId);
|
|
37491
|
+
logger$7.debug('inpage_listener_registered_flow_id', {
|
|
37492
|
+
sender_id: senderId,
|
|
37493
|
+
system_id: entry.systemId,
|
|
37494
|
+
flow_id: envelope.flowId,
|
|
37495
|
+
});
|
|
37496
|
+
}
|
|
37146
37497
|
await this._deliverEnvelope(entry, envelope);
|
|
37147
37498
|
}
|
|
37148
37499
|
async _createConnectorForAttach(params) {
|
|
@@ -37190,7 +37541,7 @@ class InPageListener extends TransportListener {
|
|
|
37190
37541
|
origin_type: originType,
|
|
37191
37542
|
connector_type: connector.constructor?.name ?? 'unknown',
|
|
37192
37543
|
});
|
|
37193
|
-
return { connector, systemId, originType };
|
|
37544
|
+
return { connector, systemId, originType, senderId: params.senderId };
|
|
37194
37545
|
}
|
|
37195
37546
|
catch (error) {
|
|
37196
37547
|
logger$7.error('inpage_listener_connector_creation_failed', {
|
|
@@ -37244,6 +37595,12 @@ class InPageListener extends TransportListener {
|
|
|
37244
37595
|
if (this._systemToSender.get(systemId) === senderId) {
|
|
37245
37596
|
this._systemToSender.delete(systemId);
|
|
37246
37597
|
}
|
|
37598
|
+
// Clean up flowId mappings for this sender
|
|
37599
|
+
for (const [flowId, sid] of this._flowIdToSender.entries()) {
|
|
37600
|
+
if (sid === senderId) {
|
|
37601
|
+
this._flowIdToSender.delete(flowId);
|
|
37602
|
+
}
|
|
37603
|
+
}
|
|
37247
37604
|
})
|
|
37248
37605
|
.catch((error) => {
|
|
37249
37606
|
logger$7.debug('inpage_listener_wait_until_closed_failed', {
|
|
@@ -37255,9 +37612,24 @@ class InPageListener extends TransportListener {
|
|
|
37255
37612
|
if (this._systemToSender.get(systemId) === senderId) {
|
|
37256
37613
|
this._systemToSender.delete(systemId);
|
|
37257
37614
|
}
|
|
37615
|
+
// Clean up flowId mappings for this sender
|
|
37616
|
+
for (const [flowId, sid] of this._flowIdToSender.entries()) {
|
|
37617
|
+
if (sid === senderId) {
|
|
37618
|
+
this._flowIdToSender.delete(flowId);
|
|
37619
|
+
}
|
|
37620
|
+
}
|
|
37258
37621
|
});
|
|
37259
37622
|
}
|
|
37260
37623
|
async _deliverEnvelope(entry, envelope) {
|
|
37624
|
+
// Track flowId for routing responses back
|
|
37625
|
+
if (envelope.flowId && !this._flowIdToSender.has(envelope.flowId)) {
|
|
37626
|
+
this._flowIdToSender.set(envelope.flowId, entry.senderId);
|
|
37627
|
+
logger$7.debug('inpage_listener_registered_flow_id_on_delivery', {
|
|
37628
|
+
sender_id: entry.senderId,
|
|
37629
|
+
system_id: entry.systemId,
|
|
37630
|
+
flow_id: envelope.flowId,
|
|
37631
|
+
});
|
|
37632
|
+
}
|
|
37261
37633
|
const message = this._buildChannelMessage({
|
|
37262
37634
|
envelope,
|
|
37263
37635
|
connector: entry.connector,
|