@naylence/runtime 0.3.5-test.953 → 0.3.5-test.954
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 +32 -514
- package/dist/browser/index.mjs +32 -514
- package/dist/cjs/naylence/fame/connector/broadcast-channel-connector-factory.js +2 -14
- package/dist/cjs/naylence/fame/connector/broadcast-channel-connector.browser.js +1 -108
- package/dist/cjs/naylence/fame/connector/broadcast-channel-listener.js +10 -76
- package/dist/cjs/naylence/fame/connector/inpage-connector-factory.js +0 -12
- package/dist/cjs/naylence/fame/connector/inpage-connector.js +1 -105
- package/dist/cjs/naylence/fame/connector/inpage-listener.js +2 -49
- package/dist/cjs/naylence/fame/grants/broadcast-channel-connection-grant.js +12 -23
- package/dist/cjs/naylence/fame/grants/inpage-connection-grant.js +0 -28
- package/dist/cjs/naylence/fame/node/admission/default-node-attach-client.js +0 -14
- package/dist/cjs/naylence/fame/node/upstream-session-manager.js +0 -6
- package/dist/cjs/version.js +2 -2
- package/dist/esm/naylence/fame/connector/broadcast-channel-connector-factory.js +2 -14
- package/dist/esm/naylence/fame/connector/broadcast-channel-connector.browser.js +1 -108
- package/dist/esm/naylence/fame/connector/broadcast-channel-listener.js +10 -76
- package/dist/esm/naylence/fame/connector/inpage-connector-factory.js +0 -12
- package/dist/esm/naylence/fame/connector/inpage-connector.js +1 -105
- package/dist/esm/naylence/fame/connector/inpage-listener.js +2 -49
- package/dist/esm/naylence/fame/grants/broadcast-channel-connection-grant.js +12 -23
- package/dist/esm/naylence/fame/grants/inpage-connection-grant.js +0 -28
- package/dist/esm/naylence/fame/node/admission/default-node-attach-client.js +0 -14
- package/dist/esm/naylence/fame/node/upstream-session-manager.js +0 -6
- package/dist/esm/version.js +2 -2
- package/dist/node/index.cjs +32 -514
- package/dist/node/index.mjs +32 -514
- package/dist/node/node.cjs +32 -530
- package/dist/node/node.mjs +32 -530
- package/dist/types/naylence/fame/connector/broadcast-channel-connector-factory.d.ts +0 -2
- package/dist/types/naylence/fame/connector/broadcast-channel-connector.browser.d.ts +1 -9
- package/dist/types/naylence/fame/connector/inpage-connector-factory.d.ts +0 -2
- package/dist/types/naylence/fame/connector/inpage-connector.d.ts +0 -9
- package/dist/types/naylence/fame/connector/inpage-listener.d.ts +0 -1
- package/dist/types/naylence/fame/grants/broadcast-channel-connection-grant.d.ts +3 -6
- package/dist/types/naylence/fame/grants/inpage-connection-grant.d.ts +0 -8
- package/dist/types/version.d.ts +1 -1
- package/package.json +1 -1
- package/dist/cjs/naylence/fame/connector/transport-frame.js +0 -100
- package/dist/esm/naylence/fame/connector/transport-frame.js +0 -93
- package/dist/types/naylence/fame/connector/transport-frame.d.ts +0 -56
|
@@ -25,14 +25,6 @@ function isInPageConnectionGrant(candidate) {
|
|
|
25
25
|
record.inboxCapacity <= 0)) {
|
|
26
26
|
return false;
|
|
27
27
|
}
|
|
28
|
-
if (record.localNodeId !== undefined &&
|
|
29
|
-
(typeof record.localNodeId !== 'string' || record.localNodeId.length === 0)) {
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
if (record.remoteNodeId !== undefined &&
|
|
33
|
-
(typeof record.remoteNodeId !== 'string' || record.remoteNodeId.length === 0)) {
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
28
|
return true;
|
|
37
29
|
}
|
|
38
30
|
function normalizeInPageConnectionGrant(candidate) {
|
|
@@ -66,20 +58,6 @@ function normalizeInPageConnectionGrant(candidate) {
|
|
|
66
58
|
}
|
|
67
59
|
result.inboxCapacity = Math.floor(inboxValue);
|
|
68
60
|
}
|
|
69
|
-
const localNodeIdValue = candidate.localNodeId ?? candidate['local_node_id'];
|
|
70
|
-
if (localNodeIdValue !== undefined) {
|
|
71
|
-
if (typeof localNodeIdValue !== 'string' || localNodeIdValue.trim().length === 0) {
|
|
72
|
-
throw new TypeError('InPageConnectionGrant "localNodeId" must be a non-empty string when provided');
|
|
73
|
-
}
|
|
74
|
-
result.localNodeId = localNodeIdValue.trim();
|
|
75
|
-
}
|
|
76
|
-
const remoteNodeIdValue = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
77
|
-
if (remoteNodeIdValue !== undefined) {
|
|
78
|
-
if (typeof remoteNodeIdValue !== 'string' || remoteNodeIdValue.trim().length === 0) {
|
|
79
|
-
throw new TypeError('InPageConnectionGrant "remoteNodeId" must be a non-empty string when provided');
|
|
80
|
-
}
|
|
81
|
-
result.remoteNodeId = remoteNodeIdValue.trim();
|
|
82
|
-
}
|
|
83
61
|
return result;
|
|
84
62
|
}
|
|
85
63
|
function inPageGrantToConnectorConfig(grant) {
|
|
@@ -93,11 +71,5 @@ function inPageGrantToConnectorConfig(grant) {
|
|
|
93
71
|
if (normalized.inboxCapacity !== undefined) {
|
|
94
72
|
config.inboxCapacity = normalized.inboxCapacity;
|
|
95
73
|
}
|
|
96
|
-
if (normalized.localNodeId) {
|
|
97
|
-
config.localNodeId = normalized.localNodeId;
|
|
98
|
-
}
|
|
99
|
-
if (normalized.remoteNodeId) {
|
|
100
|
-
config.remoteNodeId = normalized.remoteNodeId;
|
|
101
|
-
}
|
|
102
74
|
return config;
|
|
103
75
|
}
|
|
@@ -166,20 +166,6 @@ class DefaultNodeAttachClient {
|
|
|
166
166
|
if (!targetSystemId) {
|
|
167
167
|
throw new Error('Target system ID must be set in NodeAttachAckFrame on success');
|
|
168
168
|
}
|
|
169
|
-
// Update connector's remote node ID if it supports it (e.g., BroadcastChannelConnector, InPageConnector)
|
|
170
|
-
// This allows upstream connectors to switch from wildcard '*' to specific node addressing
|
|
171
|
-
const updatableConnector = connector;
|
|
172
|
-
if (typeof updatableConnector.updateRemoteNodeId === 'function') {
|
|
173
|
-
try {
|
|
174
|
-
updatableConnector.updateRemoteNodeId(targetSystemId);
|
|
175
|
-
}
|
|
176
|
-
catch (error) {
|
|
177
|
-
logger.debug('connector_remote_node_id_update_failed', {
|
|
178
|
-
target_system_id: targetSystemId,
|
|
179
|
-
error: error instanceof Error ? error.message : String(error),
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
169
|
try {
|
|
184
170
|
if (this.replicaStickinessManager) {
|
|
185
171
|
this.replicaStickinessManager.accept(ackFrame.stickiness ?? null);
|
|
@@ -299,12 +299,6 @@ class UpstreamSessionManager extends task_spawner_js_1.TaskSpawner {
|
|
|
299
299
|
cryptoProvider.prepareForAttach(welcome.frame.systemId, welcome.frame.assignedPath, welcome.frame.acceptedLogicals ?? []);
|
|
300
300
|
}
|
|
301
301
|
await this.onWelcome(welcome.frame);
|
|
302
|
-
// Inject node ID into grant for transport frame multiplexing
|
|
303
|
-
// This ensures localNodeId matches the node's systemId for proper frame filtering
|
|
304
|
-
grant.localNodeId = welcome.frame.systemId;
|
|
305
|
-
if (welcome.frame.targetSystemId) {
|
|
306
|
-
grant.remoteNodeId = welcome.frame.targetSystemId;
|
|
307
|
-
}
|
|
308
302
|
const connector = await connector_factory_js_1.ConnectorFactory.createConnector(grant, {
|
|
309
303
|
systemId: welcome.frame.systemId,
|
|
310
304
|
});
|
package/dist/cjs/version.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// This file is auto-generated during build - do not edit manually
|
|
3
|
-
// Generated from package.json version: 0.3.5-test.
|
|
3
|
+
// Generated from package.json version: 0.3.5-test.954
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.VERSION = void 0;
|
|
6
6
|
/**
|
|
7
7
|
* The package version, injected at build time.
|
|
8
8
|
* @internal
|
|
9
9
|
*/
|
|
10
|
-
exports.VERSION = '0.3.5-test.
|
|
10
|
+
exports.VERSION = '0.3.5-test.954';
|
|
@@ -37,8 +37,7 @@ export class BroadcastChannelConnectorFactory extends ConnectorFactory {
|
|
|
37
37
|
type: BROADCAST_CHANNEL_CONNECTOR_TYPE,
|
|
38
38
|
channelName: connectorConfig.channelName,
|
|
39
39
|
inboxCapacity: connectorConfig.inboxCapacity,
|
|
40
|
-
|
|
41
|
-
remoteNodeId: connectorConfig.remoteNodeId,
|
|
40
|
+
initialWindow: connectorConfig.initialWindow,
|
|
42
41
|
};
|
|
43
42
|
}
|
|
44
43
|
const config = {
|
|
@@ -63,6 +62,7 @@ export class BroadcastChannelConnectorFactory extends ConnectorFactory {
|
|
|
63
62
|
purpose: 'connection',
|
|
64
63
|
channelName: normalizedConfig.channelName,
|
|
65
64
|
inboxCapacity: normalizedConfig.inboxCapacity,
|
|
65
|
+
initialWindow: normalizedConfig.initialWindow,
|
|
66
66
|
});
|
|
67
67
|
return grant;
|
|
68
68
|
}
|
|
@@ -88,8 +88,6 @@ export class BroadcastChannelConnectorFactory extends ConnectorFactory {
|
|
|
88
88
|
type: BROADCAST_CHANNEL_CONNECTOR_TYPE,
|
|
89
89
|
channelName,
|
|
90
90
|
inboxCapacity,
|
|
91
|
-
localNodeId: normalized.localNodeId,
|
|
92
|
-
remoteNodeId: normalized.remoteNodeId,
|
|
93
91
|
};
|
|
94
92
|
const connector = new BroadcastChannelConnector(connectorConfig, baseConfig);
|
|
95
93
|
if (options.authorization) {
|
|
@@ -151,16 +149,6 @@ export class BroadcastChannelConnectorFactory extends ConnectorFactory {
|
|
|
151
149
|
if (candidate.authorizationContext !== undefined) {
|
|
152
150
|
normalized.authorizationContext = candidate.authorizationContext;
|
|
153
151
|
}
|
|
154
|
-
// Handle localNodeId
|
|
155
|
-
const localNodeId = candidate.localNodeId ?? candidate['local_node_id'];
|
|
156
|
-
if (typeof localNodeId === 'string' && localNodeId.trim().length > 0) {
|
|
157
|
-
normalized.localNodeId = localNodeId.trim();
|
|
158
|
-
}
|
|
159
|
-
// Handle remoteNodeId
|
|
160
|
-
const remoteNodeId = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
161
|
-
if (typeof remoteNodeId === 'string' && remoteNodeId.trim().length > 0) {
|
|
162
|
-
normalized.remoteNodeId = remoteNodeId.trim();
|
|
163
|
-
}
|
|
164
152
|
normalized.channelName = normalized.channelName ?? DEFAULT_CHANNEL;
|
|
165
153
|
normalized.inboxCapacity =
|
|
166
154
|
normalized.inboxCapacity ?? DEFAULT_INBOX_CAPACITY;
|
|
@@ -3,7 +3,6 @@ import { FameTransportClose } from '../errors/errors.js';
|
|
|
3
3
|
import { getLogger } from '../util/logging.js';
|
|
4
4
|
import { BoundedAsyncQueue, QueueFullError, } from '../util/bounded-async-queue.js';
|
|
5
5
|
import { ConnectorState } from '@naylence/core';
|
|
6
|
-
import { wrapTransportFrame, unwrapTransportFrame, serializeTransportFrame, } from './transport-frame.js';
|
|
7
6
|
const logger = getLogger('naylence.fame.connector.broadcast_channel_connector');
|
|
8
7
|
export const BROADCAST_CHANNEL_CONNECTOR_TYPE = 'broadcast-channel-connector';
|
|
9
8
|
const DEFAULT_CHANNEL = 'naylence-fabric';
|
|
@@ -69,20 +68,9 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
69
68
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
70
69
|
this.connectorId = BroadcastChannelConnector.generateConnectorId();
|
|
71
70
|
this.channel = new BroadcastChannel(this.channelName);
|
|
72
|
-
// Set local and remote node IDs (defaults to connector ID for backwards compatibility)
|
|
73
|
-
this.localNodeId =
|
|
74
|
-
typeof config.localNodeId === 'string' && config.localNodeId.trim().length > 0
|
|
75
|
-
? config.localNodeId.trim()
|
|
76
|
-
: this.connectorId;
|
|
77
|
-
this.remoteNodeId =
|
|
78
|
-
typeof config.remoteNodeId === 'string' && config.remoteNodeId.trim().length > 0
|
|
79
|
-
? config.remoteNodeId.trim()
|
|
80
|
-
: '*'; // Accept from any remote if not specified
|
|
81
71
|
logger.debug('broadcast_channel_connector_created', {
|
|
82
72
|
channel: this.channelName,
|
|
83
73
|
connector_id: this.connectorId,
|
|
84
|
-
local_node_id: this.localNodeId,
|
|
85
|
-
remote_node_id: this.remoteNodeId,
|
|
86
74
|
inbox_capacity: preferredCapacity,
|
|
87
75
|
timestamp: new Date().toISOString(),
|
|
88
76
|
});
|
|
@@ -115,67 +103,6 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
115
103
|
if (busMessage.senderId === this.connectorId) {
|
|
116
104
|
return;
|
|
117
105
|
}
|
|
118
|
-
// Try to unwrap as transport frame
|
|
119
|
-
const frame = unwrapTransportFrame(busMessage.payload);
|
|
120
|
-
if (frame) {
|
|
121
|
-
// Apply connector's filtering policy: strict dst check, src accepts wildcard
|
|
122
|
-
const srcMatches = this.remoteNodeId === '*' || frame.src === this.remoteNodeId;
|
|
123
|
-
const dstMatches = frame.dst === this.localNodeId;
|
|
124
|
-
if (dstMatches && srcMatches) {
|
|
125
|
-
// Successfully received and filtered transport frame
|
|
126
|
-
logger.debug('broadcast_channel_transport_frame_received', {
|
|
127
|
-
channel: this.channelName,
|
|
128
|
-
sender_id: busMessage.senderId,
|
|
129
|
-
connector_id: this.connectorId,
|
|
130
|
-
local_node_id: this.localNodeId,
|
|
131
|
-
remote_node_id: this.remoteNodeId,
|
|
132
|
-
frame_src: frame.src,
|
|
133
|
-
frame_dst: frame.dst,
|
|
134
|
-
payload_length: frame.payload.byteLength,
|
|
135
|
-
});
|
|
136
|
-
const unwrapped = frame.payload;
|
|
137
|
-
if (this._shouldSkipDuplicateAck(busMessage.senderId, unwrapped)) {
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
try {
|
|
141
|
-
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
142
|
-
const accepted = this.inbox.tryEnqueue(unwrapped);
|
|
143
|
-
if (accepted) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
this.inbox.enqueue(unwrapped);
|
|
148
|
-
}
|
|
149
|
-
catch (error) {
|
|
150
|
-
if (error instanceof QueueFullError) {
|
|
151
|
-
logger.warning('broadcast_channel_receive_queue_full', {
|
|
152
|
-
channel: this.channelName,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
logger.error('broadcast_channel_receive_error', {
|
|
157
|
-
channel: this.channelName,
|
|
158
|
-
error: error instanceof Error ? error.message : String(error),
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
// Frame filtered out by addressing rules
|
|
166
|
-
logger.debug('broadcast_channel_transport_frame_filtered', {
|
|
167
|
-
channel: this.channelName,
|
|
168
|
-
connector_id: this.connectorId,
|
|
169
|
-
local_node_id: this.localNodeId,
|
|
170
|
-
remote_node_id: this.remoteNodeId,
|
|
171
|
-
frame_src: frame.src,
|
|
172
|
-
frame_dst: frame.dst,
|
|
173
|
-
reason: !dstMatches ? 'wrong_destination' : 'wrong_source',
|
|
174
|
-
});
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
// Fall back to legacy format (no transport frame)
|
|
179
106
|
const payload = BroadcastChannelConnector.coercePayload(busMessage.payload);
|
|
180
107
|
if (!payload) {
|
|
181
108
|
logger.debug('broadcast_channel_payload_rejected', {
|
|
@@ -314,26 +241,10 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
314
241
|
logger.debug('broadcast_channel_message_sending', {
|
|
315
242
|
channel: this.channelName,
|
|
316
243
|
sender_id: this.connectorId,
|
|
317
|
-
local_node_id: this.localNodeId,
|
|
318
|
-
remote_node_id: this.remoteNodeId,
|
|
319
244
|
});
|
|
320
|
-
// Only use transport framing if both localNodeId and remoteNodeId are explicitly set
|
|
321
|
-
// (not using default values). This ensures backwards compatibility.
|
|
322
|
-
const useTransportFrame = this.localNodeId !== this.connectorId ||
|
|
323
|
-
this.remoteNodeId !== '*';
|
|
324
|
-
let payload;
|
|
325
|
-
if (useTransportFrame) {
|
|
326
|
-
// Wrap payload in transport frame
|
|
327
|
-
const frame = wrapTransportFrame(data, this.localNodeId, this.remoteNodeId);
|
|
328
|
-
payload = serializeTransportFrame(frame);
|
|
329
|
-
}
|
|
330
|
-
else {
|
|
331
|
-
// Legacy format: send raw payload
|
|
332
|
-
payload = data;
|
|
333
|
-
}
|
|
334
245
|
this.channel.postMessage({
|
|
335
246
|
senderId: this.connectorId,
|
|
336
|
-
payload,
|
|
247
|
+
payload: data,
|
|
337
248
|
});
|
|
338
249
|
}
|
|
339
250
|
async _transportReceive() {
|
|
@@ -489,24 +400,6 @@ export class BroadcastChannelConnector extends BaseAsyncConnector {
|
|
|
489
400
|
});
|
|
490
401
|
}
|
|
491
402
|
}
|
|
492
|
-
/**
|
|
493
|
-
* Update the remote node ID after learning it from NodeAttachAck
|
|
494
|
-
* This allows upstream connectors to switch from wildcard to specific addressing
|
|
495
|
-
*/
|
|
496
|
-
updateRemoteNodeId(newRemoteNodeId) {
|
|
497
|
-
if (typeof newRemoteNodeId !== 'string' || newRemoteNodeId.trim().length === 0) {
|
|
498
|
-
throw new Error('Invalid remote node ID');
|
|
499
|
-
}
|
|
500
|
-
const oldValue = this.remoteNodeId;
|
|
501
|
-
this.remoteNodeId = newRemoteNodeId.trim();
|
|
502
|
-
logger.debug('broadcast_channel_connector_remote_node_id_updated', {
|
|
503
|
-
channel: this.channelName,
|
|
504
|
-
connector_id: this.connectorId,
|
|
505
|
-
local_node_id: this.localNodeId,
|
|
506
|
-
old_remote_node_id: oldValue,
|
|
507
|
-
new_remote_node_id: this.remoteNodeId,
|
|
508
|
-
});
|
|
509
|
-
}
|
|
510
403
|
_trimSeenAcks(now) {
|
|
511
404
|
while (this.seenAckOrder.length > 0) {
|
|
512
405
|
const candidate = this.seenAckOrder[0];
|
|
@@ -7,7 +7,6 @@ import { BROADCAST_CHANNEL_CONNECTOR_TYPE, } from './broadcast-channel-connector
|
|
|
7
7
|
import { GrantSelectionContext, defaultGrantSelectionPolicy, } from './grant-selection-policy.js';
|
|
8
8
|
import { QueueFullError } from '../util/bounded-async-queue.js';
|
|
9
9
|
import { BROADCAST_CHANNEL_CONNECTION_GRANT_TYPE, broadcastChannelGrantToConnectorConfig, } from '../grants/broadcast-channel-connection-grant.js';
|
|
10
|
-
import { unwrapTransportFrame, } from './transport-frame.js';
|
|
11
10
|
const logger = getLogger('naylence.fame.connector.broadcast_channel_listener');
|
|
12
11
|
const DEFAULT_CHANNEL = 'naylence-fabric';
|
|
13
12
|
const DEFAULT_INBOX_CAPACITY = 2048;
|
|
@@ -139,18 +138,13 @@ export class BroadcastChannelListener extends TransportListener {
|
|
|
139
138
|
});
|
|
140
139
|
}
|
|
141
140
|
asCallbackGrant() {
|
|
142
|
-
|
|
141
|
+
return this.withLegacySnakeCaseKeys({
|
|
143
142
|
type: BROADCAST_CHANNEL_CONNECTOR_TYPE,
|
|
144
143
|
connectorType: BROADCAST_CHANNEL_CONNECTOR_TYPE,
|
|
145
144
|
connectionGrantType: BROADCAST_CHANNEL_CONNECTION_GRANT_TYPE,
|
|
146
145
|
channelName: this._channelName,
|
|
147
146
|
inboxCapacity: this._inboxCapacity,
|
|
148
|
-
};
|
|
149
|
-
// Include localNodeId for transport frame multiplexing if node is available
|
|
150
|
-
if (this._routingNode) {
|
|
151
|
-
grant.localNodeId = this._routingNode.id;
|
|
152
|
-
}
|
|
153
|
-
return this.withLegacySnakeCaseKeys(grant);
|
|
147
|
+
});
|
|
154
148
|
}
|
|
155
149
|
_registerChannelListener() {
|
|
156
150
|
if (this._channelHandler) {
|
|
@@ -210,54 +204,23 @@ export class BroadcastChannelListener extends TransportListener {
|
|
|
210
204
|
if (typeof senderId !== 'string' || senderId.length === 0) {
|
|
211
205
|
return null;
|
|
212
206
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
// Apply listener's filtering policy: accept frames addressed to us OR with wildcard destination
|
|
220
|
-
// Wildcard is needed because downstream nodes don't know the sentinel's ID during initial attach
|
|
221
|
-
const isAddressedToUs = frame.dst === this._routingNode.id || frame.dst === '*';
|
|
222
|
-
if (isAddressedToUs) {
|
|
223
|
-
envelopePayload = frame.payload;
|
|
224
|
-
logger.debug('broadcast_channel_listener_unwrapped_transport_frame', {
|
|
225
|
-
sender_id: senderId,
|
|
226
|
-
src: frame.src,
|
|
227
|
-
dst: frame.dst,
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
else {
|
|
231
|
-
// Frame addressed to a different node, ignore it
|
|
232
|
-
logger.debug('broadcast_channel_listener_ignored_frame_wrong_destination', {
|
|
233
|
-
sender_id: senderId,
|
|
234
|
-
dst: frame.dst,
|
|
235
|
-
expected: this._routingNode.id,
|
|
236
|
-
});
|
|
237
|
-
return null;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
// If not a transport frame, try to coerce as legacy format
|
|
242
|
-
if (!envelopePayload) {
|
|
243
|
-
envelopePayload = coercePayload(record.payload);
|
|
244
|
-
if (!envelopePayload) {
|
|
245
|
-
logger.debug('broadcast_channel_listener_ignored_event_without_payload', {
|
|
246
|
-
sender_id: senderId,
|
|
247
|
-
});
|
|
248
|
-
return null;
|
|
249
|
-
}
|
|
207
|
+
const payload = coercePayload(record.payload);
|
|
208
|
+
if (!payload) {
|
|
209
|
+
logger.debug('broadcast_channel_listener_ignored_event_without_payload', {
|
|
210
|
+
sender_id: senderId,
|
|
211
|
+
});
|
|
212
|
+
return null;
|
|
250
213
|
}
|
|
251
214
|
let envelope;
|
|
252
215
|
try {
|
|
253
|
-
const decoded = new TextDecoder().decode(
|
|
216
|
+
const decoded = new TextDecoder().decode(payload);
|
|
254
217
|
const parsed = JSON.parse(decoded);
|
|
255
218
|
envelope = deserializeEnvelope(parsed);
|
|
256
219
|
}
|
|
257
220
|
catch (error) {
|
|
258
221
|
const decoded = (() => {
|
|
259
222
|
try {
|
|
260
|
-
return new TextDecoder().decode(
|
|
223
|
+
return new TextDecoder().decode(payload);
|
|
261
224
|
}
|
|
262
225
|
catch {
|
|
263
226
|
return null;
|
|
@@ -377,20 +340,6 @@ export class BroadcastChannelListener extends TransportListener {
|
|
|
377
340
|
inboxCapacity: this._inboxCapacity,
|
|
378
341
|
};
|
|
379
342
|
}
|
|
380
|
-
// Automatically configure transport frame multiplexing:
|
|
381
|
-
// Use node IDs (not connector IDs) for node-to-node targeting
|
|
382
|
-
const broadcastConfig = connectorConfig;
|
|
383
|
-
// Always force localNodeId to be this listener's node ID
|
|
384
|
-
// This ensures the sentinel sets localNodeId=sentinel, not the child's ID
|
|
385
|
-
broadcastConfig.localNodeId = routingNode.id;
|
|
386
|
-
// Always force remoteNodeId to be the attaching child's system ID
|
|
387
|
-
broadcastConfig.remoteNodeId = systemId;
|
|
388
|
-
logger.debug('broadcast_channel_listener_configured_node_ids', {
|
|
389
|
-
sender_id: params.senderId,
|
|
390
|
-
system_id: systemId,
|
|
391
|
-
local_node_id: broadcastConfig.localNodeId,
|
|
392
|
-
remote_node_id: broadcastConfig.remoteNodeId,
|
|
393
|
-
});
|
|
394
343
|
try {
|
|
395
344
|
const connector = await routingNode.createOriginConnector({
|
|
396
345
|
originType,
|
|
@@ -460,21 +409,6 @@ export class BroadcastChannelListener extends TransportListener {
|
|
|
460
409
|
inboxCandidate > 0) {
|
|
461
410
|
config.inboxCapacity = Math.floor(inboxCandidate);
|
|
462
411
|
}
|
|
463
|
-
// Extract transport frame multiplexing node IDs
|
|
464
|
-
const localNodeIdCandidate = candidate.localNodeId ?? candidate['local_node_id'];
|
|
465
|
-
if (typeof localNodeIdCandidate === 'string' && localNodeIdCandidate.trim().length > 0) {
|
|
466
|
-
config.localNodeId = localNodeIdCandidate.trim();
|
|
467
|
-
logger.debug('broadcast_channel_listener_extracted_local_node_id', {
|
|
468
|
-
local_node_id: config.localNodeId,
|
|
469
|
-
});
|
|
470
|
-
}
|
|
471
|
-
const remoteNodeIdCandidate = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
472
|
-
if (typeof remoteNodeIdCandidate === 'string' && remoteNodeIdCandidate.trim().length > 0) {
|
|
473
|
-
config.remoteNodeId = remoteNodeIdCandidate.trim();
|
|
474
|
-
logger.debug('broadcast_channel_listener_extracted_remote_node_id', {
|
|
475
|
-
remote_node_id: config.remoteNodeId,
|
|
476
|
-
});
|
|
477
|
-
}
|
|
478
412
|
return config;
|
|
479
413
|
}
|
|
480
414
|
_monitorConnectorLifecycle(senderId, systemId, connector) {
|
|
@@ -81,8 +81,6 @@ export class InPageConnectorFactory extends ConnectorFactory {
|
|
|
81
81
|
type: INPAGE_CONNECTOR_TYPE,
|
|
82
82
|
channelName,
|
|
83
83
|
inboxCapacity,
|
|
84
|
-
localNodeId: normalized.localNodeId,
|
|
85
|
-
remoteNodeId: normalized.remoteNodeId,
|
|
86
84
|
};
|
|
87
85
|
const connector = new InPageConnector(connectorConfig, baseConfig);
|
|
88
86
|
if (options.authorization) {
|
|
@@ -151,16 +149,6 @@ export class InPageConnectorFactory extends ConnectorFactory {
|
|
|
151
149
|
if (candidate.authorizationContext !== undefined) {
|
|
152
150
|
normalized.authorizationContext = candidate.authorizationContext;
|
|
153
151
|
}
|
|
154
|
-
// Handle localNodeId
|
|
155
|
-
const localNodeId = candidate.localNodeId ?? candidate['local_node_id'];
|
|
156
|
-
if (typeof localNodeId === 'string' && localNodeId.trim().length > 0) {
|
|
157
|
-
normalized.localNodeId = localNodeId.trim();
|
|
158
|
-
}
|
|
159
|
-
// Handle remoteNodeId
|
|
160
|
-
const remoteNodeId = candidate.remoteNodeId ?? candidate['remote_node_id'];
|
|
161
|
-
if (typeof remoteNodeId === 'string' && remoteNodeId.trim().length > 0) {
|
|
162
|
-
normalized.remoteNodeId = remoteNodeId.trim();
|
|
163
|
-
}
|
|
164
152
|
normalized.channelName = normalized.channelName ?? DEFAULT_CHANNEL;
|
|
165
153
|
normalized.inboxCapacity =
|
|
166
154
|
normalized.inboxCapacity ?? DEFAULT_INBOX_CAPACITY;
|
|
@@ -7,7 +7,6 @@ import { FameTransportClose } from '../errors/errors.js';
|
|
|
7
7
|
import { getLogger } from '../util/logging.js';
|
|
8
8
|
import { BoundedAsyncQueue, QueueFullError, } from '../util/bounded-async-queue.js';
|
|
9
9
|
import { ConnectorState } from '@naylence/core';
|
|
10
|
-
import { wrapTransportFrame, unwrapTransportFrame, serializeTransportFrame, } from './transport-frame.js';
|
|
11
10
|
const logger = getLogger('naylence.fame.connector.inpage_connector');
|
|
12
11
|
export const INPAGE_CONNECTOR_TYPE = 'inpage-connector';
|
|
13
12
|
const DEFAULT_CHANNEL = 'naylence-fabric';
|
|
@@ -78,20 +77,9 @@ export class InPageConnector extends BaseAsyncConnector {
|
|
|
78
77
|
: DEFAULT_INBOX_CAPACITY;
|
|
79
78
|
this.inbox = new BoundedAsyncQueue(preferredCapacity);
|
|
80
79
|
this.connectorId = InPageConnector.generateConnectorId();
|
|
81
|
-
// Set local and remote node IDs (defaults to connector ID for backwards compatibility)
|
|
82
|
-
this.localNodeId =
|
|
83
|
-
typeof config.localNodeId === 'string' && config.localNodeId.trim().length > 0
|
|
84
|
-
? config.localNodeId.trim()
|
|
85
|
-
: this.connectorId;
|
|
86
|
-
this.remoteNodeId =
|
|
87
|
-
typeof config.remoteNodeId === 'string' && config.remoteNodeId.trim().length > 0
|
|
88
|
-
? config.remoteNodeId.trim()
|
|
89
|
-
: '*'; // Accept from any remote if not specified
|
|
90
80
|
logger.debug('inpage_connector_initialized', {
|
|
91
81
|
channel: this.channelName,
|
|
92
82
|
connector_id: this.connectorId,
|
|
93
|
-
local_node_id: this.localNodeId,
|
|
94
|
-
remote_node_id: this.remoteNodeId,
|
|
95
83
|
});
|
|
96
84
|
this.onMsg = (event) => {
|
|
97
85
|
const messageEvent = event;
|
|
@@ -125,64 +113,6 @@ export class InPageConnector extends BaseAsyncConnector {
|
|
|
125
113
|
if (busMessage.senderId === this.connectorId) {
|
|
126
114
|
return;
|
|
127
115
|
}
|
|
128
|
-
// Try to unwrap as transport frame
|
|
129
|
-
const frame = unwrapTransportFrame(busMessage.payload);
|
|
130
|
-
if (frame) {
|
|
131
|
-
// Apply connector's filtering policy: strict dst check, src accepts wildcard
|
|
132
|
-
const srcMatches = this.remoteNodeId === '*' || frame.src === this.remoteNodeId;
|
|
133
|
-
const dstMatches = frame.dst === this.localNodeId;
|
|
134
|
-
if (dstMatches && srcMatches) {
|
|
135
|
-
// Successfully received and filtered transport frame
|
|
136
|
-
logger.debug('inpage_transport_frame_received', {
|
|
137
|
-
channel: this.channelName,
|
|
138
|
-
sender_id: busMessage.senderId,
|
|
139
|
-
connector_id: this.connectorId,
|
|
140
|
-
local_node_id: this.localNodeId,
|
|
141
|
-
remote_node_id: this.remoteNodeId,
|
|
142
|
-
frame_src: frame.src,
|
|
143
|
-
frame_dst: frame.dst,
|
|
144
|
-
payload_length: frame.payload.byteLength,
|
|
145
|
-
});
|
|
146
|
-
const unwrapped = frame.payload;
|
|
147
|
-
try {
|
|
148
|
-
if (typeof this.inbox.tryEnqueue === 'function') {
|
|
149
|
-
const accepted = this.inbox.tryEnqueue(unwrapped);
|
|
150
|
-
if (accepted) {
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
this.inbox.enqueue(unwrapped);
|
|
155
|
-
}
|
|
156
|
-
catch (error) {
|
|
157
|
-
if (error instanceof QueueFullError) {
|
|
158
|
-
logger.warning('inpage_receive_queue_full', {
|
|
159
|
-
channel: this.channelName,
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
logger.error('inpage_receive_error', {
|
|
164
|
-
channel: this.channelName,
|
|
165
|
-
error: error instanceof Error ? error.message : String(error),
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
// Frame filtered out by addressing rules
|
|
173
|
-
logger.debug('inpage_transport_frame_filtered', {
|
|
174
|
-
channel: this.channelName,
|
|
175
|
-
connector_id: this.connectorId,
|
|
176
|
-
local_node_id: this.localNodeId,
|
|
177
|
-
remote_node_id: this.remoteNodeId,
|
|
178
|
-
frame_src: frame.src,
|
|
179
|
-
frame_dst: frame.dst,
|
|
180
|
-
reason: !dstMatches ? 'wrong_destination' : 'wrong_source',
|
|
181
|
-
});
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
// Fall back to legacy format (no transport frame)
|
|
186
116
|
const payload = InPageConnector.coercePayload(busMessage.payload);
|
|
187
117
|
if (!payload) {
|
|
188
118
|
logger.debug('inpage_payload_rejected', {
|
|
@@ -341,27 +271,11 @@ export class InPageConnector extends BaseAsyncConnector {
|
|
|
341
271
|
logger.debug('inpage_message_sending', {
|
|
342
272
|
channel: this.channelName,
|
|
343
273
|
sender_id: this.connectorId,
|
|
344
|
-
local_node_id: this.localNodeId,
|
|
345
|
-
remote_node_id: this.remoteNodeId,
|
|
346
274
|
});
|
|
347
|
-
// Only use transport framing if both localNodeId and remoteNodeId are explicitly set
|
|
348
|
-
// (not using default values). This ensures backwards compatibility.
|
|
349
|
-
const useTransportFrame = this.localNodeId !== this.connectorId ||
|
|
350
|
-
this.remoteNodeId !== '*';
|
|
351
|
-
let payload;
|
|
352
|
-
if (useTransportFrame) {
|
|
353
|
-
// Wrap payload in transport frame
|
|
354
|
-
const frame = wrapTransportFrame(data, this.localNodeId, this.remoteNodeId);
|
|
355
|
-
payload = serializeTransportFrame(frame);
|
|
356
|
-
}
|
|
357
|
-
else {
|
|
358
|
-
// Legacy format: send raw payload
|
|
359
|
-
payload = data;
|
|
360
|
-
}
|
|
361
275
|
const event = new MessageEvent(this.channelName, {
|
|
362
276
|
data: {
|
|
363
277
|
senderId: this.connectorId,
|
|
364
|
-
payload,
|
|
278
|
+
payload: data,
|
|
365
279
|
},
|
|
366
280
|
});
|
|
367
281
|
getSharedBus().dispatchEvent(event);
|
|
@@ -390,22 +304,4 @@ export class InPageConnector extends BaseAsyncConnector {
|
|
|
390
304
|
}
|
|
391
305
|
return rawOrEnvelope;
|
|
392
306
|
}
|
|
393
|
-
/**
|
|
394
|
-
* Update the remote node ID after learning it from NodeAttachAck
|
|
395
|
-
* This allows upstream connectors to switch from wildcard to specific addressing
|
|
396
|
-
*/
|
|
397
|
-
updateRemoteNodeId(newRemoteNodeId) {
|
|
398
|
-
if (typeof newRemoteNodeId !== 'string' || newRemoteNodeId.trim().length === 0) {
|
|
399
|
-
throw new Error('Invalid remote node ID');
|
|
400
|
-
}
|
|
401
|
-
const oldValue = this.remoteNodeId;
|
|
402
|
-
this.remoteNodeId = newRemoteNodeId.trim();
|
|
403
|
-
logger.debug('inpage_connector_remote_node_id_updated', {
|
|
404
|
-
channel: this.channelName,
|
|
405
|
-
connector_id: this.connectorId,
|
|
406
|
-
local_node_id: this.localNodeId,
|
|
407
|
-
old_remote_node_id: oldValue,
|
|
408
|
-
new_remote_node_id: this.remoteNodeId,
|
|
409
|
-
});
|
|
410
|
-
}
|
|
411
307
|
}
|