@naylence/runtime 0.3.6 → 0.3.7
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 +220 -172
- package/dist/browser/index.mjs +220 -173
- package/dist/cjs/_env-shim.js +2 -1
- package/dist/cjs/naylence/fame/config/extended-fame-config.js +2 -1
- package/dist/cjs/naylence/fame/connector/broadcast-channel-connector-factory.js +12 -4
- package/dist/cjs/naylence/fame/connector/broadcast-channel-connector.browser.js +14 -6
- package/dist/cjs/naylence/fame/connector/broadcast-channel-listener-factory.js +3 -1
- package/dist/cjs/naylence/fame/connector/broadcast-channel-listener.js +11 -7
- package/dist/cjs/naylence/fame/connector/index.js +2 -1
- package/dist/cjs/naylence/fame/connector/inpage-connector-factory.js +2 -1
- package/dist/cjs/naylence/fame/connector/inpage-connector.js +13 -6
- package/dist/cjs/naylence/fame/connector/inpage-listener-factory.js +4 -4
- package/dist/cjs/naylence/fame/connector/inpage-listener.js +5 -2
- package/dist/cjs/naylence/fame/delivery/default-delivery-tracker.js +4 -62
- package/dist/cjs/naylence/fame/grants/broadcast-channel-connection-grant.js +6 -3
- package/dist/cjs/naylence/fame/grants/inpage-connection-grant.js +4 -2
- package/dist/cjs/naylence/fame/http/oauth2-token-router.js +9 -9
- package/dist/cjs/naylence/fame/node/admission/default-node-attach-client.js +34 -5
- package/dist/cjs/naylence/fame/node/upstream-session-manager.js +40 -8
- package/dist/cjs/naylence/fame/security/auth/oauth2-pkce-token-provider-factory.js +10 -6
- package/dist/cjs/naylence/fame/security/auth/oauth2-pkce-token-provider.js +1 -2
- package/dist/cjs/naylence/fame/security/default-security-manager.js +2 -1
- package/dist/cjs/naylence/fame/security/trust-store/noop-trust-store-provider-factory.js +2 -2
- package/dist/cjs/naylence/fame/security/trust-store/trust-store-provider-factory.js +2 -2
- package/dist/cjs/naylence/fame/util/index.js +3 -1
- package/dist/cjs/node.js +4 -1
- package/dist/cjs/version.js +2 -2
- package/dist/esm/_env-shim.js +2 -1
- package/dist/esm/browser.js +2 -2
- package/dist/esm/naylence/fame/config/extended-fame-config.js +2 -1
- package/dist/esm/naylence/fame/connector/broadcast-channel-connector-factory.js +12 -4
- package/dist/esm/naylence/fame/connector/broadcast-channel-connector.browser.js +14 -6
- package/dist/esm/naylence/fame/connector/broadcast-channel-listener-factory.js +3 -1
- package/dist/esm/naylence/fame/connector/broadcast-channel-listener.js +11 -7
- package/dist/esm/naylence/fame/connector/index.js +2 -2
- package/dist/esm/naylence/fame/connector/inpage-connector-factory.js +2 -1
- package/dist/esm/naylence/fame/connector/inpage-connector.js +13 -6
- package/dist/esm/naylence/fame/connector/inpage-listener-factory.js +4 -4
- package/dist/esm/naylence/fame/connector/inpage-listener.js +5 -2
- package/dist/esm/naylence/fame/delivery/default-delivery-tracker.js +4 -62
- package/dist/esm/naylence/fame/grants/broadcast-channel-connection-grant.js +6 -3
- package/dist/esm/naylence/fame/grants/inpage-connection-grant.js +4 -2
- package/dist/esm/naylence/fame/http/oauth2-token-router.js +9 -9
- package/dist/esm/naylence/fame/node/admission/default-node-attach-client.js +34 -5
- package/dist/esm/naylence/fame/node/upstream-session-manager.js +40 -8
- package/dist/esm/naylence/fame/security/auth/oauth2-pkce-token-provider-factory.js +10 -6
- package/dist/esm/naylence/fame/security/auth/oauth2-pkce-token-provider.js +1 -2
- package/dist/esm/naylence/fame/security/default-security-manager.js +2 -1
- package/dist/esm/naylence/fame/security/index.js +1 -1
- package/dist/esm/naylence/fame/security/trust-store/noop-trust-store-provider-factory.js +3 -3
- package/dist/esm/naylence/fame/security/trust-store/trust-store-provider-factory.js +3 -3
- package/dist/esm/naylence/fame/util/index.js +1 -0
- package/dist/esm/node.js +2 -1
- package/dist/esm/version.js +2 -2
- package/dist/node/index.cjs +218 -171
- package/dist/node/index.mjs +218 -172
- package/dist/node/node.cjs +184 -136
- package/dist/node/node.mjs +183 -137
- package/dist/types/browser.d.ts +2 -2
- package/dist/types/naylence/fame/connector/broadcast-channel-connector-factory.d.ts +1 -0
- package/dist/types/naylence/fame/connector/index.d.ts +3 -3
- package/dist/types/naylence/fame/delivery/default-delivery-tracker.d.ts +0 -6
- package/dist/types/naylence/fame/node/admission/default-node-attach-client.d.ts +1 -0
- package/dist/types/naylence/fame/security/index.d.ts +1 -1
- package/dist/types/naylence/fame/security/trust-store/noop-trust-store-provider-factory.d.ts +3 -3
- package/dist/types/naylence/fame/security/trust-store/trust-store-provider-factory.d.ts +4 -4
- package/dist/types/naylence/fame/security/trust-store/trust-store-provider.d.ts +5 -5
- package/dist/types/naylence/fame/util/index.d.ts +1 -0
- package/dist/types/node.d.ts +2 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/cjs/_env-shim.js
CHANGED
|
@@ -17,7 +17,8 @@ function installProcessEnvShim() {
|
|
|
17
17
|
if (g.__ENV__ && typeof g.__ENV__ === 'object')
|
|
18
18
|
Object.assign(out, g.__ENV__);
|
|
19
19
|
try {
|
|
20
|
-
//
|
|
20
|
+
// import.meta is only available in ESM builds
|
|
21
|
+
// @ts-ignore
|
|
21
22
|
const ie = (typeof import.meta !== 'undefined' && import.meta.env) || undefined;
|
|
22
23
|
if (ie && typeof ie === 'object')
|
|
23
24
|
Object.assign(out, ie);
|
|
@@ -93,7 +93,8 @@ function createFsShim() {
|
|
|
93
93
|
else if (options &&
|
|
94
94
|
typeof options === 'object' &&
|
|
95
95
|
'encoding' in options &&
|
|
96
|
-
typeof options.encoding ===
|
|
96
|
+
typeof options.encoding ===
|
|
97
|
+
'string') {
|
|
97
98
|
encoding = options.encoding;
|
|
98
99
|
}
|
|
99
100
|
const data = fsBinding.readFileUtf8(pathOrDescriptor, 0);
|
|
@@ -47,10 +47,12 @@ class BroadcastChannelConnectorFactory extends connector_factory_js_1.ConnectorF
|
|
|
47
47
|
type: broadcast_channel_connector_js_1.BROADCAST_CHANNEL_CONNECTOR_TYPE,
|
|
48
48
|
};
|
|
49
49
|
const channelCandidate = record.channelName ?? record['channel_name'];
|
|
50
|
-
if (typeof channelCandidate === 'string' &&
|
|
50
|
+
if (typeof channelCandidate === 'string' &&
|
|
51
|
+
channelCandidate.trim().length > 0) {
|
|
51
52
|
config.channelName = channelCandidate.trim();
|
|
52
53
|
}
|
|
53
|
-
const inboxCandidate = record.inboxCapacity ??
|
|
54
|
+
const inboxCandidate = record.inboxCapacity ??
|
|
55
|
+
record['inbox_capacity'];
|
|
54
56
|
if (typeof inboxCandidate === 'number' &&
|
|
55
57
|
Number.isFinite(inboxCandidate) &&
|
|
56
58
|
inboxCandidate > 0) {
|
|
@@ -74,9 +76,11 @@ class BroadcastChannelConnectorFactory extends connector_factory_js_1.ConnectorF
|
|
|
74
76
|
throw new Error('BroadcastChannelConnectorFactory requires a configuration');
|
|
75
77
|
}
|
|
76
78
|
const normalized = this._normalizeConfig(config);
|
|
77
|
-
const options = (factoryArgs[0] ??
|
|
79
|
+
const options = (factoryArgs[0] ??
|
|
80
|
+
{});
|
|
78
81
|
const normalizedLocalNodeFromConfig = this._normalizeNodeId(normalized.localNodeId);
|
|
79
|
-
const localNodeId = this._normalizeNodeId(options.localNodeId) ??
|
|
82
|
+
const localNodeId = this._normalizeNodeId(options.localNodeId) ??
|
|
83
|
+
normalizedLocalNodeFromConfig;
|
|
80
84
|
if (!localNodeId) {
|
|
81
85
|
throw new Error('BroadcastChannelConnectorFactory requires a localNodeId from config or create() options');
|
|
82
86
|
}
|
|
@@ -101,6 +105,7 @@ class BroadcastChannelConnectorFactory extends connector_factory_js_1.ConnectorF
|
|
|
101
105
|
inboxCapacity,
|
|
102
106
|
localNodeId,
|
|
103
107
|
initialTargetNodeId: resolvedTarget,
|
|
108
|
+
passive: normalized.passive,
|
|
104
109
|
};
|
|
105
110
|
const connector = new broadcast_channel_connector_js_1.BroadcastChannelConnector(connectorConfig, baseConfig);
|
|
106
111
|
if (options.authorization) {
|
|
@@ -139,6 +144,9 @@ class BroadcastChannelConnectorFactory extends connector_factory_js_1.ConnectorF
|
|
|
139
144
|
if (normalizedLocalNodeId) {
|
|
140
145
|
normalized.localNodeId = normalizedLocalNodeId;
|
|
141
146
|
}
|
|
147
|
+
if (typeof candidate.passive === 'boolean') {
|
|
148
|
+
normalized.passive = candidate.passive;
|
|
149
|
+
}
|
|
142
150
|
if (typeof candidate.flowControl === 'boolean') {
|
|
143
151
|
normalized.flowControl = candidate.flowControl;
|
|
144
152
|
}
|
|
@@ -20,7 +20,8 @@ const ensureBroadcastEnvironment = () => {
|
|
|
20
20
|
};
|
|
21
21
|
class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConnector {
|
|
22
22
|
static generateConnectorId() {
|
|
23
|
-
const globalCrypto = globalThis
|
|
23
|
+
const globalCrypto = globalThis
|
|
24
|
+
.crypto;
|
|
24
25
|
if (globalCrypto?.randomUUID) {
|
|
25
26
|
return globalCrypto.randomUUID();
|
|
26
27
|
}
|
|
@@ -75,7 +76,8 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
|
|
|
75
76
|
this.listenerRegistered = false;
|
|
76
77
|
this.visibilityChangeListenerRegistered = false;
|
|
77
78
|
this.channelName =
|
|
78
|
-
typeof config.channelName === 'string' &&
|
|
79
|
+
typeof config.channelName === 'string' &&
|
|
80
|
+
config.channelName.trim().length > 0
|
|
79
81
|
? config.channelName.trim()
|
|
80
82
|
: DEFAULT_CHANNEL;
|
|
81
83
|
const preferredCapacity = typeof config.inboxCapacity === 'number' &&
|
|
@@ -99,6 +101,7 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
|
|
|
99
101
|
local_node_id: this.localNodeId,
|
|
100
102
|
target_node_id: this.targetNodeId ?? null,
|
|
101
103
|
inbox_capacity: preferredCapacity,
|
|
104
|
+
passive: config.passive ?? false,
|
|
102
105
|
timestamp: new Date().toISOString(),
|
|
103
106
|
});
|
|
104
107
|
this.onMsg = (event) => {
|
|
@@ -116,7 +119,8 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
|
|
|
116
119
|
channel: this.channelName,
|
|
117
120
|
connector_id: this.connectorId,
|
|
118
121
|
message_type: message && typeof message === 'object'
|
|
119
|
-
? message.constructor
|
|
122
|
+
? (message.constructor
|
|
123
|
+
?.name ?? typeof message)
|
|
120
124
|
: typeof message,
|
|
121
125
|
has_sender_id: Boolean(message?.senderId),
|
|
122
126
|
has_sender_node_id: Boolean(message?.senderNodeId),
|
|
@@ -346,7 +350,9 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
|
|
|
346
350
|
timestamp: new Date().toISOString(),
|
|
347
351
|
});
|
|
348
352
|
}
|
|
349
|
-
if (this.visibilityChangeListenerRegistered &&
|
|
353
|
+
if (this.visibilityChangeListenerRegistered &&
|
|
354
|
+
this.visibilityChangeHandler &&
|
|
355
|
+
typeof document !== 'undefined') {
|
|
350
356
|
document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
351
357
|
this.visibilityChangeListenerRegistered = false;
|
|
352
358
|
this.visibilityChangeHandler = undefined;
|
|
@@ -374,7 +380,7 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
|
|
|
374
380
|
return rawOrEnvelope;
|
|
375
381
|
}
|
|
376
382
|
_isWildcardTarget() {
|
|
377
|
-
return this.targetNodeId === '*' || typeof this.targetNodeId === 'undefined';
|
|
383
|
+
return (this.targetNodeId === '*' || typeof this.targetNodeId === 'undefined');
|
|
378
384
|
}
|
|
379
385
|
_shouldAcceptMessageFromBus(senderNodeId, targetNodeId) {
|
|
380
386
|
if (this._isWildcardTarget()) {
|
|
@@ -394,7 +400,9 @@ class BroadcastChannelConnector extends base_async_connector_js_1.BaseAsyncConne
|
|
|
394
400
|
return true;
|
|
395
401
|
}
|
|
396
402
|
const expectedSender = this.targetNodeId;
|
|
397
|
-
if (expectedSender &&
|
|
403
|
+
if (expectedSender &&
|
|
404
|
+
expectedSender !== '*' &&
|
|
405
|
+
senderNodeId !== expectedSender) {
|
|
398
406
|
logger.debug('broadcast_channel_message_rejected', {
|
|
399
407
|
channel: this.channelName,
|
|
400
408
|
connector_id: this.connectorId,
|
|
@@ -53,7 +53,9 @@ function normalizeConfig(config) {
|
|
|
53
53
|
: DEFAULT_CHANNEL;
|
|
54
54
|
const rawInbox = record.inboxCapacity ?? record['inbox_capacity'];
|
|
55
55
|
let inboxCapacity = DEFAULT_INBOX_CAPACITY;
|
|
56
|
-
if (typeof rawInbox === 'number' &&
|
|
56
|
+
if (typeof rawInbox === 'number' &&
|
|
57
|
+
Number.isFinite(rawInbox) &&
|
|
58
|
+
rawInbox > 0) {
|
|
57
59
|
inboxCapacity = Math.floor(rawInbox);
|
|
58
60
|
}
|
|
59
61
|
else if (typeof rawInbox === 'string') {
|
|
@@ -14,9 +14,7 @@ const broadcast_channel_connection_grant_js_1 = require("../grants/broadcast-cha
|
|
|
14
14
|
const logger = (0, logging_js_1.getLogger)('naylence.fame.connector.broadcast_channel_listener');
|
|
15
15
|
const DEFAULT_CHANNEL = 'naylence-fabric';
|
|
16
16
|
const DEFAULT_INBOX_CAPACITY = 2048;
|
|
17
|
-
const RESPONSE_TYPE_MASK = core_1.FameResponseType.ACK |
|
|
18
|
-
core_1.FameResponseType.REPLY |
|
|
19
|
-
core_1.FameResponseType.STREAM;
|
|
17
|
+
const RESPONSE_TYPE_MASK = core_1.FameResponseType.ACK | core_1.FameResponseType.REPLY | core_1.FameResponseType.STREAM;
|
|
20
18
|
const isBrowserEnvironment = () => typeof window !== 'undefined' &&
|
|
21
19
|
typeof BroadcastChannel !== 'undefined' &&
|
|
22
20
|
typeof MessageEvent !== 'undefined';
|
|
@@ -230,9 +228,7 @@ class BroadcastChannelListener extends transport_listener_js_1.TransportListener
|
|
|
230
228
|
return null;
|
|
231
229
|
}
|
|
232
230
|
})();
|
|
233
|
-
if (error instanceof zod_1.ZodError &&
|
|
234
|
-
decoded &&
|
|
235
|
-
decoded.length > 0) {
|
|
231
|
+
if (error instanceof zod_1.ZodError && decoded && decoded.length > 0) {
|
|
236
232
|
try {
|
|
237
233
|
const reparsed = JSON.parse(decoded);
|
|
238
234
|
const candidate = reparsed.rtype;
|
|
@@ -455,11 +451,19 @@ class BroadcastChannelListener extends transport_listener_js_1.TransportListener
|
|
|
455
451
|
? Math.floor(initialWindowCandidate)
|
|
456
452
|
: undefined;
|
|
457
453
|
const initialTargetNodeId = this._normalizeNodeId(targetCandidate) ?? targetSystemId;
|
|
454
|
+
const passive = typeof passiveCandidate === 'boolean' ? passiveCandidate : true;
|
|
455
|
+
logger.debug('broadcast_channel_listener_building_connector_config', {
|
|
456
|
+
system_id: systemId,
|
|
457
|
+
channel_name: channelName,
|
|
458
|
+
passive,
|
|
459
|
+
has_base_config: !!baseConfig,
|
|
460
|
+
passive_candidate: passiveCandidate,
|
|
461
|
+
});
|
|
458
462
|
return {
|
|
459
463
|
type: broadcast_channel_connector_js_1.BROADCAST_CHANNEL_CONNECTOR_TYPE,
|
|
460
464
|
channelName,
|
|
461
465
|
inboxCapacity,
|
|
462
|
-
passive
|
|
466
|
+
passive,
|
|
463
467
|
initialWindow,
|
|
464
468
|
localNodeId,
|
|
465
469
|
initialTargetNodeId,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getBroadcastChannelListenerInstance = exports.BroadcastChannelListener = exports.getInPageListenerInstance = exports.InPageListener = exports.getHttpListenerInstance = exports.HttpListener = exports.getWebsocketListenerInstance = exports.WebSocketListener = exports.DefaultHttpServer = exports.TRANSPORT_LISTENER_FACTORY_BASE_TYPE = exports.TransportListener = exports._NoopFlowController = exports.BROADCAST_CHANNEL_CONNECTOR_TYPE = exports.BroadcastChannelConnector = exports.INPAGE_CONNECTOR_TYPE = exports.InPageConnector = exports.BoundedAsyncQueue = exports.QueueFullError = exports.HttpStatelessConnector = exports.WebSocketState = exports.WebSocketConnector = exports.createResource = exports.ConnectorFactory = exports.createConnectorConfig = exports.isConnectorConfig = exports.ConnectorConfigDefaults = exports.BaseAsyncConnector = void 0;
|
|
3
|
+
exports.getBroadcastChannelListenerInstance = exports.BroadcastChannelListener = exports.getInPageListenerInstance = exports.InPageListener = exports.getHttpListenerInstance = exports.HttpListener = exports.getWebsocketListenerInstance = exports.WebSocketListener = exports.DefaultHttpServer = exports.TRANSPORT_LISTENER_FACTORY_BASE_TYPE = exports.TransportListenerFactory = exports.TransportListener = exports._NoopFlowController = exports.BROADCAST_CHANNEL_CONNECTOR_TYPE = exports.BroadcastChannelConnector = exports.INPAGE_CONNECTOR_TYPE = exports.InPageConnector = exports.BoundedAsyncQueue = exports.QueueFullError = exports.HttpStatelessConnector = exports.WebSocketState = exports.WebSocketConnector = exports.createResource = exports.ConnectorFactory = exports.createConnectorConfig = exports.isConnectorConfig = exports.ConnectorConfigDefaults = exports.BaseAsyncConnector = void 0;
|
|
4
4
|
require("./http-listener-factory.js");
|
|
5
5
|
require("./websocket-listener-factory.js");
|
|
6
6
|
require("./inpage-listener-factory.js");
|
|
@@ -45,6 +45,7 @@ Object.defineProperty(exports, "_NoopFlowController", { enumerable: true, get: f
|
|
|
45
45
|
var transport_listener_js_1 = require("./transport-listener.js");
|
|
46
46
|
Object.defineProperty(exports, "TransportListener", { enumerable: true, get: function () { return transport_listener_js_1.TransportListener; } });
|
|
47
47
|
var transport_listener_factory_js_1 = require("./transport-listener-factory.js");
|
|
48
|
+
Object.defineProperty(exports, "TransportListenerFactory", { enumerable: true, get: function () { return transport_listener_factory_js_1.TransportListenerFactory; } });
|
|
48
49
|
Object.defineProperty(exports, "TRANSPORT_LISTENER_FACTORY_BASE_TYPE", { enumerable: true, get: function () { return transport_listener_factory_js_1.TRANSPORT_LISTENER_FACTORY_BASE_TYPE; } });
|
|
49
50
|
var default_http_server_js_1 = require("./default-http-server.js");
|
|
50
51
|
Object.defineProperty(exports, "DefaultHttpServer", { enumerable: true, get: function () { return default_http_server_js_1.DefaultHttpServer; } });
|
|
@@ -69,7 +69,8 @@ class InPageConnectorFactory extends connector_factory_js_1.ConnectorFactory {
|
|
|
69
69
|
const normalized = this._normalizeConfig(config);
|
|
70
70
|
const options = (factoryArgs[0] ?? {});
|
|
71
71
|
const normalizedLocalNodeFromConfig = this._normalizeNodeId(normalized.localNodeId);
|
|
72
|
-
const localNodeId = this._normalizeNodeId(options.localNodeId) ??
|
|
72
|
+
const localNodeId = this._normalizeNodeId(options.localNodeId) ??
|
|
73
|
+
normalizedLocalNodeFromConfig;
|
|
73
74
|
if (!localNodeId) {
|
|
74
75
|
throw new Error('InPageConnectorFactory requires a localNodeId from config or create() options');
|
|
75
76
|
}
|
|
@@ -90,7 +90,8 @@ class InPageConnector extends base_async_connector_js_1.BaseAsyncConnector {
|
|
|
90
90
|
this.listenerRegistered = false;
|
|
91
91
|
this.visibilityChangeListenerRegistered = false;
|
|
92
92
|
this.channelName =
|
|
93
|
-
typeof config.channelName === 'string' &&
|
|
93
|
+
typeof config.channelName === 'string' &&
|
|
94
|
+
config.channelName.trim().length > 0
|
|
94
95
|
? config.channelName.trim()
|
|
95
96
|
: DEFAULT_CHANNEL;
|
|
96
97
|
const preferredCapacity = typeof config.inboxCapacity === 'number' &&
|
|
@@ -129,7 +130,8 @@ class InPageConnector extends base_async_connector_js_1.BaseAsyncConnector {
|
|
|
129
130
|
channel: this.channelName,
|
|
130
131
|
connector_id: this.connectorId,
|
|
131
132
|
message_type: message && typeof message === 'object'
|
|
132
|
-
? message.constructor
|
|
133
|
+
? (message.constructor
|
|
134
|
+
?.name ?? typeof message)
|
|
133
135
|
: typeof message,
|
|
134
136
|
has_sender_id: Boolean(message?.senderId),
|
|
135
137
|
has_sender_node_id: Boolean(message?.senderNodeId),
|
|
@@ -138,7 +140,8 @@ class InPageConnector extends base_async_connector_js_1.BaseAsyncConnector {
|
|
|
138
140
|
return;
|
|
139
141
|
}
|
|
140
142
|
const busMessage = message;
|
|
141
|
-
const senderId = typeof busMessage.senderId === 'string' &&
|
|
143
|
+
const senderId = typeof busMessage.senderId === 'string' &&
|
|
144
|
+
busMessage.senderId.length > 0
|
|
142
145
|
? busMessage.senderId
|
|
143
146
|
: null;
|
|
144
147
|
const senderNodeId = InPageConnector.normalizeNodeId(busMessage.senderNodeId);
|
|
@@ -389,7 +392,9 @@ class InPageConnector extends base_async_connector_js_1.BaseAsyncConnector {
|
|
|
389
392
|
timestamp: new Date().toISOString(),
|
|
390
393
|
});
|
|
391
394
|
}
|
|
392
|
-
if (this.visibilityChangeListenerRegistered &&
|
|
395
|
+
if (this.visibilityChangeListenerRegistered &&
|
|
396
|
+
this.visibilityChangeHandler &&
|
|
397
|
+
typeof document !== 'undefined') {
|
|
393
398
|
document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
394
399
|
this.visibilityChangeListenerRegistered = false;
|
|
395
400
|
this.visibilityChangeHandler = undefined;
|
|
@@ -406,7 +411,7 @@ class InPageConnector extends base_async_connector_js_1.BaseAsyncConnector {
|
|
|
406
411
|
return rawOrEnvelope;
|
|
407
412
|
}
|
|
408
413
|
_isWildcardTarget() {
|
|
409
|
-
return this.targetNodeId === '*' || typeof this.targetNodeId === 'undefined';
|
|
414
|
+
return (this.targetNodeId === '*' || typeof this.targetNodeId === 'undefined');
|
|
410
415
|
}
|
|
411
416
|
_shouldAcceptMessageFromBus(senderNodeId, targetNodeId) {
|
|
412
417
|
if (this._isWildcardTarget()) {
|
|
@@ -426,7 +431,9 @@ class InPageConnector extends base_async_connector_js_1.BaseAsyncConnector {
|
|
|
426
431
|
return true;
|
|
427
432
|
}
|
|
428
433
|
const expectedSender = this.targetNodeId;
|
|
429
|
-
if (expectedSender &&
|
|
434
|
+
if (expectedSender &&
|
|
435
|
+
expectedSender !== '*' &&
|
|
436
|
+
senderNodeId !== expectedSender) {
|
|
430
437
|
logger.debug('inpage_message_rejected', {
|
|
431
438
|
channel: this.channelName,
|
|
432
439
|
connector_id: this.connectorId,
|
|
@@ -53,7 +53,9 @@ function normalizeConfig(config) {
|
|
|
53
53
|
: DEFAULT_CHANNEL;
|
|
54
54
|
const rawInbox = record.inboxCapacity ?? record['inbox_capacity'];
|
|
55
55
|
let inboxCapacity = DEFAULT_INBOX_CAPACITY;
|
|
56
|
-
if (typeof rawInbox === 'number' &&
|
|
56
|
+
if (typeof rawInbox === 'number' &&
|
|
57
|
+
Number.isFinite(rawInbox) &&
|
|
58
|
+
rawInbox > 0) {
|
|
57
59
|
inboxCapacity = Math.floor(rawInbox);
|
|
58
60
|
}
|
|
59
61
|
else if (typeof rawInbox === 'string') {
|
|
@@ -81,9 +83,7 @@ class InPageListenerFactory extends transport_listener_factory_js_1.TransportLis
|
|
|
81
83
|
}
|
|
82
84
|
async create(config, ...factoryArgs) {
|
|
83
85
|
const normalized = normalizeConfig(config);
|
|
84
|
-
const [{ InPageListener }] = await Promise.all([
|
|
85
|
-
getInPageListenerModule(),
|
|
86
|
-
]);
|
|
86
|
+
const [{ InPageListener }] = await Promise.all([getInPageListenerModule()]);
|
|
87
87
|
void factoryArgs;
|
|
88
88
|
return new InPageListener({
|
|
89
89
|
channelName: normalized.channelName,
|
|
@@ -73,7 +73,9 @@ class InPageListener extends transport_listener_js_1.TransportListener {
|
|
|
73
73
|
typeof channelCandidate === 'string' && channelCandidate.trim().length > 0
|
|
74
74
|
? channelCandidate.trim()
|
|
75
75
|
: DEFAULT_CHANNEL;
|
|
76
|
-
const normalizedCapacity = typeof inboxCandidate === 'number' &&
|
|
76
|
+
const normalizedCapacity = typeof inboxCandidate === 'number' &&
|
|
77
|
+
Number.isFinite(inboxCandidate) &&
|
|
78
|
+
inboxCandidate > 0
|
|
77
79
|
? Math.floor(inboxCandidate)
|
|
78
80
|
: DEFAULT_INBOX_CAPACITY;
|
|
79
81
|
this._inboxCapacity = normalizedCapacity;
|
|
@@ -348,7 +350,8 @@ class InPageListener extends transport_listener_js_1.TransportListener {
|
|
|
348
350
|
if (grant.type === inpage_connection_grant_js_1.INPAGE_CONNECTION_GRANT_TYPE) {
|
|
349
351
|
return (0, inpage_connection_grant_js_1.inPageGrantToConnectorConfig)(grant);
|
|
350
352
|
}
|
|
351
|
-
if (typeof grant
|
|
353
|
+
if (typeof grant
|
|
354
|
+
?.toConnectorConfig === 'function') {
|
|
352
355
|
return grant.toConnectorConfig();
|
|
353
356
|
}
|
|
354
357
|
throw new Error(`Unsupported grant type: ${grant.type}`);
|
|
@@ -149,9 +149,6 @@ class DefaultDeliveryTracker extends task_spawner_js_1.TaskSpawner {
|
|
|
149
149
|
this.ackDoneSince = new Map();
|
|
150
150
|
this.replyDoneSince = new Map();
|
|
151
151
|
this.pendingAckDispatches = new Set();
|
|
152
|
-
this.recentlyHandled = new Map();
|
|
153
|
-
this.recentlyHandledOrder = [];
|
|
154
|
-
this.recentlyHandledTtlMs = 60000;
|
|
155
152
|
this.isPreparingToStop = false;
|
|
156
153
|
this.shutdownRequestedAtMs = null;
|
|
157
154
|
this.shutdownRetryGraceMs = 1000;
|
|
@@ -387,22 +384,6 @@ class DefaultDeliveryTracker extends task_spawner_js_1.TaskSpawner {
|
|
|
387
384
|
}
|
|
388
385
|
}
|
|
389
386
|
else {
|
|
390
|
-
const wasRecentlyHandled = await this.lock.runExclusive(async () => this.wasRecentlyHandled(envelope.id));
|
|
391
|
-
if (wasRecentlyHandled) {
|
|
392
|
-
logger.debug('tracker_duplicate_envelope_recently_handled', {
|
|
393
|
-
envp_id: envelope.id,
|
|
394
|
-
});
|
|
395
|
-
return new tracked_envelope_js_1.TrackedEnvelope({
|
|
396
|
-
timeoutAtMs: 0,
|
|
397
|
-
overallTimeoutAtMs: 0,
|
|
398
|
-
expectedResponseType: envelope.rtype ?? core_1.FameResponseType.NONE,
|
|
399
|
-
createdAtMs: Date.now(),
|
|
400
|
-
status: tracked_envelope_js_1.EnvelopeStatus.HANDLED,
|
|
401
|
-
mailboxType: tracked_envelope_js_1.MailboxType.INBOX,
|
|
402
|
-
originalEnvelope: envelope,
|
|
403
|
-
serviceName: inboxName,
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
387
|
tracked = new tracked_envelope_js_1.TrackedEnvelope({
|
|
407
388
|
timeoutAtMs: 0,
|
|
408
389
|
overallTimeoutAtMs: 0,
|
|
@@ -424,12 +405,8 @@ class DefaultDeliveryTracker extends task_spawner_js_1.TaskSpawner {
|
|
|
424
405
|
async onEnvelopeHandled(envelope) {
|
|
425
406
|
const inbox = this.ensureInbox();
|
|
426
407
|
envelope.status = tracked_envelope_js_1.EnvelopeStatus.HANDLED;
|
|
408
|
+
// Delete the envelope from inbox to prevent growth
|
|
427
409
|
await inbox.delete(envelope.originalEnvelope.id);
|
|
428
|
-
await this.lock.runExclusive(async () => {
|
|
429
|
-
this.markRecentlyHandled(envelope.originalEnvelope.id);
|
|
430
|
-
});
|
|
431
|
-
// Preserve handled envelope to prevent duplicate redelivery during shutdown drains.
|
|
432
|
-
// await inbox.set(envelope.originalEnvelope.id, envelope);
|
|
433
410
|
}
|
|
434
411
|
async onEnvelopeHandleFailed(inboxName, envelope, context, error, isFinalFailure = false) {
|
|
435
412
|
void context;
|
|
@@ -648,9 +625,9 @@ class DefaultDeliveryTracker extends task_spawner_js_1.TaskSpawner {
|
|
|
648
625
|
});
|
|
649
626
|
await this.markDoneSince(this.replyFutures, trackedEnvelope.originalEnvelope.id, this.replyDoneSince);
|
|
650
627
|
await this.markDoneSince(this.ackFutures, trackedEnvelope.originalEnvelope.id, this.ackDoneSince);
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
628
|
+
// Note: ACK is already sent in onCorrelatedMessage (lines 655-657)
|
|
629
|
+
// when the reply envelope is first delivered. No need to send it again here.
|
|
630
|
+
// Removing this duplicate sendAck call fixes the duplicate DeliveryAck bug.
|
|
654
631
|
for (const handler of this.eventHandlers) {
|
|
655
632
|
await handler.onEnvelopeReplied?.(trackedEnvelope, envelope);
|
|
656
633
|
}
|
|
@@ -800,8 +777,6 @@ class DefaultDeliveryTracker extends task_spawner_js_1.TaskSpawner {
|
|
|
800
777
|
}
|
|
801
778
|
this.streamDone.clear();
|
|
802
779
|
this.correlationToEnvelope.clear();
|
|
803
|
-
this.recentlyHandled.clear();
|
|
804
|
-
this.recentlyHandledOrder.length = 0;
|
|
805
780
|
return values;
|
|
806
781
|
});
|
|
807
782
|
for (const timer of timers) {
|
|
@@ -1383,39 +1358,6 @@ class DefaultDeliveryTracker extends task_spawner_js_1.TaskSpawner {
|
|
|
1383
1358
|
this.pendingAckDispatches.delete(ackDispatch);
|
|
1384
1359
|
}
|
|
1385
1360
|
}
|
|
1386
|
-
markRecentlyHandled(envelopeId) {
|
|
1387
|
-
const now = Date.now();
|
|
1388
|
-
this.recentlyHandled.set(envelopeId, now);
|
|
1389
|
-
this.recentlyHandledOrder.push(envelopeId);
|
|
1390
|
-
this.trimRecentlyHandled(now);
|
|
1391
|
-
}
|
|
1392
|
-
wasRecentlyHandled(envelopeId) {
|
|
1393
|
-
const now = Date.now();
|
|
1394
|
-
const timestamp = this.recentlyHandled.get(envelopeId);
|
|
1395
|
-
if (timestamp === undefined) {
|
|
1396
|
-
return false;
|
|
1397
|
-
}
|
|
1398
|
-
if (now - timestamp > this.recentlyHandledTtlMs) {
|
|
1399
|
-
this.recentlyHandled.delete(envelopeId);
|
|
1400
|
-
return false;
|
|
1401
|
-
}
|
|
1402
|
-
return true;
|
|
1403
|
-
}
|
|
1404
|
-
trimRecentlyHandled(now) {
|
|
1405
|
-
while (this.recentlyHandledOrder.length > 0) {
|
|
1406
|
-
const candidate = this.recentlyHandledOrder[0];
|
|
1407
|
-
const timestamp = this.recentlyHandled.get(candidate);
|
|
1408
|
-
if (timestamp === undefined) {
|
|
1409
|
-
this.recentlyHandledOrder.shift();
|
|
1410
|
-
continue;
|
|
1411
|
-
}
|
|
1412
|
-
if (now - timestamp <= this.recentlyHandledTtlMs) {
|
|
1413
|
-
break;
|
|
1414
|
-
}
|
|
1415
|
-
this.recentlyHandled.delete(candidate);
|
|
1416
|
-
this.recentlyHandledOrder.shift();
|
|
1417
|
-
}
|
|
1418
|
-
}
|
|
1419
1361
|
getShutdownRetryDeferDelay(nowMs) {
|
|
1420
1362
|
if (!this.isPreparingToStop || this.shutdownRequestedAtMs === null) {
|
|
1421
1363
|
return null;
|
|
@@ -47,14 +47,16 @@ function normalizeBroadcastChannelConnectionGrant(candidate) {
|
|
|
47
47
|
type,
|
|
48
48
|
purpose,
|
|
49
49
|
};
|
|
50
|
-
const channelValue = candidate.channelName ??
|
|
50
|
+
const channelValue = candidate.channelName ??
|
|
51
|
+
candidate['channel_name'];
|
|
51
52
|
if (channelValue !== undefined) {
|
|
52
53
|
if (typeof channelValue !== 'string' || channelValue.trim().length === 0) {
|
|
53
54
|
throw new TypeError('BroadcastChannelConnectionGrant "channelName" must be a non-empty string when provided');
|
|
54
55
|
}
|
|
55
56
|
result.channelName = channelValue.trim();
|
|
56
57
|
}
|
|
57
|
-
const inboxValue = candidate.inboxCapacity ??
|
|
58
|
+
const inboxValue = candidate.inboxCapacity ??
|
|
59
|
+
candidate['inbox_capacity'];
|
|
58
60
|
if (inboxValue !== undefined) {
|
|
59
61
|
if (typeof inboxValue !== 'number' ||
|
|
60
62
|
!Number.isFinite(inboxValue) ||
|
|
@@ -63,7 +65,8 @@ function normalizeBroadcastChannelConnectionGrant(candidate) {
|
|
|
63
65
|
}
|
|
64
66
|
result.inboxCapacity = Math.floor(inboxValue);
|
|
65
67
|
}
|
|
66
|
-
const windowValue = candidate.initialWindow ??
|
|
68
|
+
const windowValue = candidate.initialWindow ??
|
|
69
|
+
candidate['initial_window'];
|
|
67
70
|
if (windowValue !== undefined) {
|
|
68
71
|
if (typeof windowValue !== 'number' ||
|
|
69
72
|
!Number.isFinite(windowValue) ||
|
|
@@ -42,14 +42,16 @@ function normalizeInPageConnectionGrant(candidate) {
|
|
|
42
42
|
type,
|
|
43
43
|
purpose,
|
|
44
44
|
};
|
|
45
|
-
const channelValue = candidate.channelName ??
|
|
45
|
+
const channelValue = candidate.channelName ??
|
|
46
|
+
candidate['channel_name'];
|
|
46
47
|
if (channelValue !== undefined) {
|
|
47
48
|
if (typeof channelValue !== 'string' || channelValue.trim().length === 0) {
|
|
48
49
|
throw new TypeError('InPageConnectionGrant "channelName" must be a non-empty string when provided');
|
|
49
50
|
}
|
|
50
51
|
result.channelName = channelValue.trim();
|
|
51
52
|
}
|
|
52
|
-
const inboxValue = candidate.inboxCapacity ??
|
|
53
|
+
const inboxValue = candidate.inboxCapacity ??
|
|
54
|
+
candidate['inbox_capacity'];
|
|
53
55
|
if (inboxValue !== undefined) {
|
|
54
56
|
if (typeof inboxValue !== 'number' ||
|
|
55
57
|
!Number.isFinite(inboxValue) ||
|
|
@@ -423,7 +423,9 @@ function parseCookies(cookieHeader) {
|
|
|
423
423
|
if (!cookieHeader) {
|
|
424
424
|
return {};
|
|
425
425
|
}
|
|
426
|
-
return cookieHeader
|
|
426
|
+
return cookieHeader
|
|
427
|
+
.split(';')
|
|
428
|
+
.reduce((acc, entry) => {
|
|
427
429
|
const [rawName, ...rawValueParts] = entry.split('=');
|
|
428
430
|
const name = rawName?.trim();
|
|
429
431
|
if (!name) {
|
|
@@ -571,10 +573,7 @@ function setNoCacheHeaders(res) {
|
|
|
571
573
|
res.set('Pragma', 'no-cache');
|
|
572
574
|
}
|
|
573
575
|
function respondInvalidClient(res) {
|
|
574
|
-
res
|
|
575
|
-
.status(401)
|
|
576
|
-
.set('WWW-Authenticate', 'Basic')
|
|
577
|
-
.json({
|
|
576
|
+
res.status(401).set('WWW-Authenticate', 'Basic').json({
|
|
578
577
|
error: 'invalid_client',
|
|
579
578
|
error_description: 'Invalid client credentials',
|
|
580
579
|
});
|
|
@@ -611,10 +610,10 @@ function createOAuth2TokenRouter(options) {
|
|
|
611
610
|
DEFAULT_JWT_ALGORITHM;
|
|
612
611
|
const allowedScopes = getAllowedScopes(configAllowedScopes);
|
|
613
612
|
const resolvedTokenTtlSec = tokenTtlSec ?? 3600;
|
|
614
|
-
const enablePkce = coerceBoolean(process.env[ENV_VAR_ENABLE_PKCE]) ??
|
|
615
|
-
(configEnablePkce ?? true);
|
|
613
|
+
const enablePkce = coerceBoolean(process.env[ENV_VAR_ENABLE_PKCE]) ?? configEnablePkce ?? true;
|
|
616
614
|
const allowPublicClients = coerceBoolean(process.env[ENV_VAR_ALLOW_PUBLIC_CLIENTS]) ??
|
|
617
|
-
|
|
615
|
+
configAllowPublicClients ??
|
|
616
|
+
true;
|
|
618
617
|
const authorizationCodeTtlSec = ensurePositiveInteger(coerceNumber(process.env[ENV_VAR_AUTHORIZATION_CODE_TTL]) ??
|
|
619
618
|
configAuthorizationCodeTtlSec) ?? DEFAULT_AUTHORIZATION_CODE_TTL_SEC;
|
|
620
619
|
const devLoginExplicitlyEnabled = coerceBoolean(process.env[ENV_VAR_ENABLE_DEV_LOGIN]) ??
|
|
@@ -629,7 +628,8 @@ function createOAuth2TokenRouter(options) {
|
|
|
629
628
|
configDevLoginCookieName ??
|
|
630
629
|
DEFAULT_SESSION_COOKIE_NAME;
|
|
631
630
|
const devLoginSecureCookie = coerceBoolean(process.env[ENV_VAR_SESSION_SECURE_COOKIE]) ??
|
|
632
|
-
|
|
631
|
+
configDevLoginSecureCookie ??
|
|
632
|
+
false;
|
|
633
633
|
const devLoginTitle = coerceString(process.env[ENV_VAR_LOGIN_TITLE]) ??
|
|
634
634
|
configDevLoginTitle ??
|
|
635
635
|
DEFAULT_LOGIN_TITLE;
|
|
@@ -11,15 +11,30 @@ class DefaultNodeAttachClient {
|
|
|
11
11
|
constructor(options = {}) {
|
|
12
12
|
this.buffer = [];
|
|
13
13
|
this.inHandshake = false;
|
|
14
|
+
this.expectedSystemId = null;
|
|
14
15
|
this.timeoutMs = options.timeoutMs ?? 10000;
|
|
15
16
|
this.attachmentKeyValidator = options.attachmentKeyValidator;
|
|
16
17
|
this.replicaStickinessManager = options.replicaStickinessManager ?? null;
|
|
17
18
|
}
|
|
18
19
|
async attach(node, originType, connector, welcomeFrame, finalHandler, keys, callbackGrants) {
|
|
19
20
|
this.inHandshake = true;
|
|
21
|
+
this.expectedSystemId = welcomeFrame.systemId;
|
|
20
22
|
const interimHandler = async (envelope, context) => {
|
|
21
23
|
if (this.inHandshake) {
|
|
22
|
-
|
|
24
|
+
// Filter: only buffer frames related to our systemId or frames without systemId info
|
|
25
|
+
const frameSystemId = envelope.frame
|
|
26
|
+
?.systemId;
|
|
27
|
+
if (!frameSystemId || frameSystemId === this.expectedSystemId) {
|
|
28
|
+
this.buffer.push(envelope);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
// Silently ignore frames from other agents during concurrent handshakes
|
|
32
|
+
logger.debug('handshake_ignoring_frame_from_different_system', {
|
|
33
|
+
frame_type: envelope.frame.type,
|
|
34
|
+
frame_system_id: frameSystemId,
|
|
35
|
+
expected_system_id: this.expectedSystemId,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
23
38
|
return null;
|
|
24
39
|
}
|
|
25
40
|
return finalHandler(envelope, context);
|
|
@@ -146,6 +161,7 @@ class DefaultNodeAttachClient {
|
|
|
146
161
|
parent_id: ackFrame.targetSystemId,
|
|
147
162
|
});
|
|
148
163
|
this.inHandshake = false;
|
|
164
|
+
this.expectedSystemId = null;
|
|
149
165
|
await connector.replaceHandler(finalHandler);
|
|
150
166
|
while (this.buffer.length > 0) {
|
|
151
167
|
const bufferedEnvelope = this.buffer.shift();
|
|
@@ -203,7 +219,8 @@ class DefaultNodeAttachClient {
|
|
|
203
219
|
const deadline = Date.now() + this.timeoutMs;
|
|
204
220
|
while (Date.now() < deadline) {
|
|
205
221
|
// Allow both STARTED and PAUSED states (PAUSED = tab hidden but connection alive)
|
|
206
|
-
if (connector.state !== core_1.ConnectorState.STARTED &&
|
|
222
|
+
if (connector.state !== core_1.ConnectorState.STARTED &&
|
|
223
|
+
connector.state !== core_1.ConnectorState.PAUSED) {
|
|
207
224
|
let errorMessage = 'Connector closed while waiting for NodeAttachAck';
|
|
208
225
|
if (connector.closeCode !== undefined) {
|
|
209
226
|
errorMessage += ` (code=${connector.closeCode}`;
|
|
@@ -222,9 +239,21 @@ class DefaultNodeAttachClient {
|
|
|
222
239
|
if (envelope.frame.type === 'NodeAttachAck') {
|
|
223
240
|
return envelope;
|
|
224
241
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
242
|
+
// NodeAttach frames during handshake are expected in multi-agent scenarios
|
|
243
|
+
// where multiple agents attach concurrently to the same channel
|
|
244
|
+
if (envelope.frame.type === 'NodeAttach') {
|
|
245
|
+
logger.debug('handshake_ignoring_concurrent_attach', {
|
|
246
|
+
frame_type: envelope.frame.type,
|
|
247
|
+
frame_system_id: envelope.frame?.systemId ??
|
|
248
|
+
'unknown',
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
// Other unexpected frames are still logged as errors
|
|
253
|
+
logger.error('unexpected_frame_during_handshake', {
|
|
254
|
+
frame_type: envelope.frame.type,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
228
257
|
}
|
|
229
258
|
await (0, task_utils_js_1.delay)(HANDSHAKE_POLL_INTERVAL_MS);
|
|
230
259
|
}
|