request-iframe 0.1.0 → 0.2.0
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/QUICKSTART.CN.md +4 -2
- package/QUICKSTART.md +4 -2
- package/README.CN.md +302 -54
- package/README.md +281 -36
- package/cdn/request-iframe-react.umd.js +3354 -0
- package/cdn/request-iframe-react.umd.js.map +1 -0
- package/cdn/request-iframe-react.umd.min.js +2 -0
- package/cdn/request-iframe-react.umd.min.js.map +1 -0
- package/cdn/request-iframe.umd.js +19735 -0
- package/cdn/request-iframe.umd.js.map +1 -0
- package/cdn/request-iframe.umd.min.js +4 -0
- package/cdn/request-iframe.umd.min.js.map +1 -0
- package/esm/api/client.js +31 -22
- package/esm/api/endpoint.js +229 -0
- package/esm/api/server.js +19 -9
- package/esm/constants/debug.js +17 -0
- package/esm/constants/index.js +115 -66
- package/esm/constants/log.js +11 -0
- package/esm/constants/messages.js +6 -1
- package/esm/constants/warn-once.js +15 -0
- package/esm/endpoint/facade.js +390 -0
- package/esm/endpoint/heartbeat/heartbeat.js +60 -0
- package/esm/endpoint/heartbeat/ping.js +20 -0
- package/esm/endpoint/index.js +13 -0
- package/esm/endpoint/infra/hub.js +316 -0
- package/esm/endpoint/infra/inbox.js +232 -0
- package/esm/endpoint/infra/outbox.js +408 -0
- package/esm/endpoint/stream/dispatcher.js +58 -0
- package/esm/endpoint/stream/errors.js +27 -0
- package/esm/endpoint/stream/factory.js +76 -0
- package/esm/endpoint/stream/file-auto-resolve.js +34 -0
- package/esm/endpoint/stream/file-writable.js +105 -0
- package/esm/endpoint/stream/handler.js +26 -0
- package/esm/{core → impl}/client.js +243 -320
- package/esm/{core → impl}/response.js +120 -154
- package/esm/impl/server.js +568 -0
- package/esm/index.js +13 -6
- package/esm/message/ack.js +27 -0
- package/esm/message/channel-cache.js +108 -0
- package/esm/message/channel.js +92 -5
- package/esm/message/dispatcher.js +149 -98
- package/esm/stream/error.js +22 -0
- package/esm/stream/index.js +3 -1
- package/esm/stream/readable-stream.js +101 -26
- package/esm/stream/stream-core.js +121 -3
- package/esm/stream/writable-stream.js +368 -43
- package/esm/utils/ack.js +36 -0
- package/esm/utils/blob.js +16 -0
- package/esm/utils/cache.js +25 -76
- package/esm/utils/content-type.js +81 -0
- package/esm/utils/debug.js +157 -180
- package/esm/utils/hooks.js +130 -0
- package/esm/utils/id.js +14 -0
- package/esm/utils/iframe.js +20 -0
- package/esm/utils/index.js +12 -162
- package/esm/utils/is.js +3 -0
- package/esm/utils/logger.js +55 -0
- package/esm/utils/origin.js +3 -1
- package/esm/utils/promise.js +3 -0
- package/esm/utils/window.js +31 -0
- package/library/api/client.d.ts.map +1 -1
- package/library/api/client.js +32 -23
- package/library/api/endpoint.d.ts +23 -0
- package/library/api/endpoint.d.ts.map +1 -0
- package/library/api/endpoint.js +235 -0
- package/library/api/server.d.ts +4 -1
- package/library/api/server.d.ts.map +1 -1
- package/library/api/server.js +19 -9
- package/library/constants/debug.d.ts +18 -0
- package/library/constants/debug.d.ts.map +1 -0
- package/library/constants/debug.js +23 -0
- package/library/constants/index.d.ts +58 -7
- package/library/constants/index.d.ts.map +1 -1
- package/library/constants/index.js +143 -67
- package/library/constants/log.d.ts +12 -0
- package/library/constants/log.d.ts.map +1 -0
- package/library/constants/log.js +17 -0
- package/library/constants/messages.d.ts +6 -1
- package/library/constants/messages.d.ts.map +1 -1
- package/library/constants/messages.js +6 -1
- package/library/constants/warn-once.d.ts +12 -0
- package/library/constants/warn-once.d.ts.map +1 -0
- package/library/constants/warn-once.js +22 -0
- package/library/endpoint/facade.d.ts +238 -0
- package/library/endpoint/facade.d.ts.map +1 -0
- package/library/endpoint/facade.js +398 -0
- package/library/endpoint/heartbeat/heartbeat.d.ts +34 -0
- package/library/endpoint/heartbeat/heartbeat.d.ts.map +1 -0
- package/library/endpoint/heartbeat/heartbeat.js +67 -0
- package/library/endpoint/heartbeat/ping.d.ts +18 -0
- package/library/endpoint/heartbeat/ping.d.ts.map +1 -0
- package/library/endpoint/heartbeat/ping.js +26 -0
- package/library/endpoint/index.d.ts +16 -0
- package/library/endpoint/index.d.ts.map +1 -0
- package/library/endpoint/index.js +114 -0
- package/library/endpoint/infra/hub.d.ts +170 -0
- package/library/endpoint/infra/hub.d.ts.map +1 -0
- package/library/endpoint/infra/hub.js +323 -0
- package/library/endpoint/infra/inbox.d.ts +73 -0
- package/library/endpoint/infra/inbox.d.ts.map +1 -0
- package/library/endpoint/infra/inbox.js +239 -0
- package/library/endpoint/infra/outbox.d.ts +149 -0
- package/library/endpoint/infra/outbox.d.ts.map +1 -0
- package/library/endpoint/infra/outbox.js +415 -0
- package/library/endpoint/stream/dispatcher.d.ts +33 -0
- package/library/endpoint/stream/dispatcher.d.ts.map +1 -0
- package/library/endpoint/stream/dispatcher.js +66 -0
- package/library/endpoint/stream/errors.d.ts +20 -0
- package/library/endpoint/stream/errors.d.ts.map +1 -0
- package/library/endpoint/stream/errors.js +32 -0
- package/library/endpoint/stream/factory.d.ts +44 -0
- package/library/endpoint/stream/factory.d.ts.map +1 -0
- package/library/endpoint/stream/factory.js +82 -0
- package/library/endpoint/stream/file-auto-resolve.d.ts +26 -0
- package/library/endpoint/stream/file-auto-resolve.d.ts.map +1 -0
- package/library/endpoint/stream/file-auto-resolve.js +41 -0
- package/library/endpoint/stream/file-writable.d.ts +33 -0
- package/library/endpoint/stream/file-writable.d.ts.map +1 -0
- package/library/endpoint/stream/file-writable.js +115 -0
- package/library/endpoint/stream/handler.d.ts +20 -0
- package/library/endpoint/stream/handler.d.ts.map +1 -0
- package/library/endpoint/stream/handler.js +32 -0
- package/library/{core → impl}/client.d.ts +16 -13
- package/library/impl/client.d.ts.map +1 -0
- package/library/{core → impl}/client.js +254 -333
- package/library/{core → impl}/request.d.ts.map +1 -1
- package/library/{core → impl}/response.d.ts +7 -12
- package/library/impl/response.d.ts.map +1 -0
- package/library/{core → impl}/response.js +120 -154
- package/library/{core → impl}/server.d.ts +26 -55
- package/library/impl/server.d.ts.map +1 -0
- package/library/impl/server.js +575 -0
- package/library/index.d.ts +13 -6
- package/library/index.d.ts.map +1 -1
- package/library/index.js +16 -16
- package/library/message/ack.d.ts +15 -0
- package/library/message/ack.d.ts.map +1 -0
- package/library/message/ack.js +33 -0
- package/library/message/channel-cache.d.ts +26 -0
- package/library/message/channel-cache.d.ts.map +1 -0
- package/library/message/channel-cache.js +115 -0
- package/library/message/channel.d.ts +53 -6
- package/library/message/channel.d.ts.map +1 -1
- package/library/message/channel.js +96 -9
- package/library/message/dispatcher.d.ts +17 -0
- package/library/message/dispatcher.d.ts.map +1 -1
- package/library/message/dispatcher.js +149 -98
- package/library/stream/error.d.ts +24 -0
- package/library/stream/error.d.ts.map +1 -0
- package/library/stream/error.js +29 -0
- package/library/stream/index.d.ts +4 -1
- package/library/stream/index.d.ts.map +1 -1
- package/library/stream/index.js +7 -4
- package/library/stream/readable-stream.d.ts.map +1 -1
- package/library/stream/readable-stream.js +102 -27
- package/library/stream/stream-core.d.ts +22 -1
- package/library/stream/stream-core.d.ts.map +1 -1
- package/library/stream/stream-core.js +120 -2
- package/library/stream/types.d.ts +115 -2
- package/library/stream/types.d.ts.map +1 -1
- package/library/stream/writable-stream.d.ts +20 -2
- package/library/stream/writable-stream.d.ts.map +1 -1
- package/library/stream/writable-stream.js +366 -41
- package/library/types/index.d.ts +17 -22
- package/library/types/index.d.ts.map +1 -1
- package/library/utils/ack.d.ts +2 -0
- package/library/utils/ack.d.ts.map +1 -0
- package/library/utils/ack.js +44 -0
- package/library/utils/blob.d.ts +3 -0
- package/library/utils/blob.d.ts.map +1 -0
- package/library/utils/blob.js +22 -0
- package/library/utils/cache.d.ts +10 -20
- package/library/utils/cache.d.ts.map +1 -1
- package/library/utils/cache.js +25 -79
- package/library/utils/content-type.d.ts +13 -0
- package/library/utils/content-type.d.ts.map +1 -0
- package/library/utils/content-type.js +87 -0
- package/library/utils/debug.d.ts.map +1 -1
- package/library/utils/debug.js +156 -178
- package/library/utils/hooks.d.ts +30 -0
- package/library/utils/hooks.d.ts.map +1 -0
- package/library/utils/hooks.js +139 -0
- package/library/utils/id.d.ts +9 -0
- package/library/utils/id.d.ts.map +1 -0
- package/library/utils/id.js +21 -0
- package/library/utils/iframe.d.ts +5 -0
- package/library/utils/iframe.d.ts.map +1 -0
- package/library/utils/iframe.js +25 -0
- package/library/utils/index.d.ts +7 -34
- package/library/utils/index.d.ts.map +1 -1
- package/library/utils/index.js +58 -193
- package/library/utils/is.d.ts +2 -0
- package/library/utils/is.d.ts.map +1 -0
- package/library/utils/is.js +9 -0
- package/library/utils/logger.d.ts +13 -0
- package/library/utils/logger.d.ts.map +1 -0
- package/library/utils/logger.js +63 -0
- package/library/utils/origin.d.ts.map +1 -1
- package/library/utils/origin.js +2 -1
- package/library/utils/promise.d.ts +2 -0
- package/library/utils/promise.d.ts.map +1 -0
- package/library/utils/promise.js +9 -0
- package/library/utils/window.d.ts +2 -0
- package/library/utils/window.d.ts.map +1 -0
- package/library/utils/window.js +38 -0
- package/package.json +49 -2
- package/react/package.json +2 -1
- package/esm/core/client-server.js +0 -329
- package/esm/core/server.js +0 -767
- package/esm/utils/ack-meta.js +0 -53
- package/library/core/client-server.d.ts +0 -106
- package/library/core/client-server.d.ts.map +0 -1
- package/library/core/client-server.js +0 -336
- package/library/core/client.d.ts.map +0 -1
- package/library/core/response.d.ts.map +0 -1
- package/library/core/server.d.ts.map +0 -1
- package/library/core/server.js +0 -772
- package/library/utils/ack-meta.d.ts +0 -2
- package/library/utils/ack-meta.d.ts.map +0 -1
- package/library/utils/ack-meta.js +0 -59
- /package/esm/{core → impl}/request.js +0 -0
- /package/library/{core → impl}/request.d.ts +0 -0
- /package/library/{core → impl}/request.js +0 -0
|
@@ -41,11 +41,14 @@ var defaultMessages = {
|
|
|
41
41
|
MIDDLEWARE_ERROR: 'Middleware error',
|
|
42
42
|
ERROR: 'Error',
|
|
43
43
|
TOO_MANY_REQUESTS: 'Too many concurrent requests (limit: {0})',
|
|
44
|
+
HUB_REGISTER_HANDLERS_NOT_SET: 'RequestIframeEndpointHub: registerHandlers is not set',
|
|
44
45
|
/** Client errors */
|
|
45
46
|
IFRAME_NOT_READY: 'iframe.contentWindow is not available',
|
|
46
47
|
TARGET_WINDOW_CLOSED: 'Target window is closed or no longer available',
|
|
47
48
|
/** ClientServer warnings */
|
|
48
49
|
CLIENT_SERVER_IGNORED_MESSAGE_WHEN_CLOSED: 'Ignored message because client server is closed/destroyed (type: {0}, requestId: {1})',
|
|
50
|
+
/** Server warnings */
|
|
51
|
+
SERVER_IGNORED_MESSAGE_WHEN_CLOSED: 'Ignored message because server is closed/destroyed (type: {0}, requestId: {1})',
|
|
49
52
|
/** Stream related messages */
|
|
50
53
|
STREAM_NOT_BOUND: 'Stream is not bound to a request context',
|
|
51
54
|
STREAM_ALREADY_STARTED: 'Stream has already started',
|
|
@@ -57,6 +60,8 @@ var defaultMessages = {
|
|
|
57
60
|
STREAM_ENDED: 'Stream has ended',
|
|
58
61
|
STREAM_READ_ERROR: 'Failed to read stream data',
|
|
59
62
|
STREAM_WRITE_ONLY_IN_PUSH_MODE: 'Stream write() is only available when mode is "push"',
|
|
63
|
+
STREAM_PENDING_QUEUE_OVERFLOW: 'Stream pending queue overflow (limit: {0})',
|
|
64
|
+
STREAM_PENDING_BYTES_OVERFLOW: 'Stream pending bytes overflow (limit: {0})',
|
|
60
65
|
/** Debug messages - Client */
|
|
61
66
|
DEBUG_CLIENT_REQUEST_START: '📤 [Client] Request Start',
|
|
62
67
|
DEBUG_CLIENT_REQUEST_SUCCESS: '✅ [Client] Request Success',
|
|
@@ -73,7 +78,7 @@ var defaultMessages = {
|
|
|
73
78
|
DEBUG_CLIENT_REQUEST_TIMEOUT: '⏱️ [Client] Request Timeout',
|
|
74
79
|
DEBUG_CLIENT_SENDING_REQUEST: '📤 [Client] Sending Request',
|
|
75
80
|
DEBUG_CLIENT_SENDING_PING: '📤 [Client] Sending Ping',
|
|
76
|
-
DEBUG_CLIENT_SENDING_RECEIVED_ACK: '📤 [Client] Sending
|
|
81
|
+
DEBUG_CLIENT_SENDING_RECEIVED_ACK: '📤 [Client] Sending ACK',
|
|
77
82
|
/** Debug messages - Server */
|
|
78
83
|
DEBUG_SERVER_RECEIVED_REQUEST: '📥 [Server] Received Request',
|
|
79
84
|
DEBUG_SERVER_SETTING_STATUS_CODE: '📝 [Server] Setting Status Code',
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import "core-js/modules/es.array.map.js";
|
|
2
|
+
/**
|
|
3
|
+
* warnOnce keys (for deduplication).
|
|
4
|
+
*
|
|
5
|
+
* Keep these centralized to avoid scattered magic strings.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export var WarnOnceKey = {
|
|
9
|
+
INBOX_MISSING_PENDING_WHEN_CLOSED: 'inbox:missingPendingWhenClosed',
|
|
10
|
+
SERVER_MISSING_PENDING_WHEN_CLOSED: 'server:missingPendingWhenClosed'
|
|
11
|
+
};
|
|
12
|
+
export function buildWarnOnceKey(prefix, ...parts) {
|
|
13
|
+
if (!parts.length) return prefix;
|
|
14
|
+
return `${prefix}:${parts.map(String).join(':')}`;
|
|
15
|
+
}
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
|
2
|
+
import "core-js/modules/es.promise.js";
|
|
3
|
+
import "core-js/modules/es.string.starts-with.js";
|
|
4
|
+
import "core-js/modules/web.dom-collections.for-each.js";
|
|
5
|
+
import { MessageType } from '../constants';
|
|
6
|
+
import { matchOrigin } from '../utils/origin';
|
|
7
|
+
import { RequestIframeEndpointHub } from './infra/hub';
|
|
8
|
+
import { RequestIframeEndpointInbox } from './infra/inbox';
|
|
9
|
+
import { RequestIframeStreamDispatcher } from './stream/dispatcher';
|
|
10
|
+
import { RequestIframeEndpointHeartbeat } from './heartbeat/heartbeat';
|
|
11
|
+
import { createPingResponder } from './heartbeat/ping';
|
|
12
|
+
import { createReadableStreamFromStart } from './stream/factory';
|
|
13
|
+
import { createStreamMessageHandler } from './stream/handler';
|
|
14
|
+
/**
|
|
15
|
+
* RequestIframeEndpointFacade
|
|
16
|
+
*
|
|
17
|
+
* Centralizes the common "composition/assembly logic" for endpoints so client/server can reuse it as thin wrappers:
|
|
18
|
+
* - hub (MessageDispatcher lifecycle + shared infra)
|
|
19
|
+
* - inbox (inbound message handling: ACK/ASYNC/RESPONSE/ERROR/PING/PONG/STREAM_START, optional)
|
|
20
|
+
* - streamDispatcher (dispatch `stream_*` frames)
|
|
21
|
+
* - heartbeat (ping -> wait pong helper, optional)
|
|
22
|
+
* - originValidator (unified construction for allowedOrigins/validateOrigin)
|
|
23
|
+
*/
|
|
24
|
+
export class RequestIframeEndpointFacade {
|
|
25
|
+
constructor(params) {
|
|
26
|
+
var _params$streamDispatc, _params$streamDispatc2;
|
|
27
|
+
_defineProperty(this, "openHooks", []);
|
|
28
|
+
this.hub = new RequestIframeEndpointHub(params.role, params.instanceId, {
|
|
29
|
+
secretKey: params.secretKey,
|
|
30
|
+
versionValidator: params.versionValidator,
|
|
31
|
+
autoAckMaxMetaLength: params.autoAckMaxMetaLength,
|
|
32
|
+
autoAckMaxIdLength: params.autoAckMaxIdLength
|
|
33
|
+
});
|
|
34
|
+
this.streamDispatcher = new RequestIframeStreamDispatcher({
|
|
35
|
+
handledBy: (_params$streamDispatc = (_params$streamDispatc2 = params.streamDispatcher) === null || _params$streamDispatc2 === void 0 ? void 0 : _params$streamDispatc2.handledBy) !== null && _params$streamDispatc !== void 0 ? _params$streamDispatc : params.instanceId
|
|
36
|
+
});
|
|
37
|
+
this.originValidator = RequestIframeEndpointFacade.buildOriginValidator(params.originValidator);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Facade is the infrastructure owner: always register handlers via facade hooks.
|
|
41
|
+
*/
|
|
42
|
+
this.hub.setRegisterHandlers(() => {
|
|
43
|
+
this.openHooks.forEach(fn => fn());
|
|
44
|
+
});
|
|
45
|
+
if (params.heartbeat) {
|
|
46
|
+
this.heartbeat = new RequestIframeEndpointHeartbeat({
|
|
47
|
+
hub: this.hub,
|
|
48
|
+
pendingBucket: params.heartbeat.pendingBucket,
|
|
49
|
+
handledBy: params.heartbeat.handledBy,
|
|
50
|
+
isOriginAllowed: params.heartbeat.isOriginAllowed,
|
|
51
|
+
warnMissingPendingWhenClosed: params.heartbeat.warnMissingPendingWhenClosed
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
if (params.inbox) {
|
|
55
|
+
this.inbox = new RequestIframeEndpointInbox(this.hub, params.inbox.versionValidator);
|
|
56
|
+
}
|
|
57
|
+
if (params.registerHandlers) {
|
|
58
|
+
this.onOpen(params.registerHandlers);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Add a handler registration hook that will run on core.open().
|
|
64
|
+
*/
|
|
65
|
+
onOpen(fn) {
|
|
66
|
+
this.openHooks.push(fn);
|
|
67
|
+
}
|
|
68
|
+
isOriginAllowedByValidator(origin, data, context) {
|
|
69
|
+
if (!this.originValidator) return true;
|
|
70
|
+
try {
|
|
71
|
+
return this.originValidator(origin, data, context);
|
|
72
|
+
} catch (_unused) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Register client-side stream callback handlers:
|
|
79
|
+
* - stream_* (except stream_start) -> core.getStreamCallback()
|
|
80
|
+
*
|
|
81
|
+
* This makes stream dispatching pluggable and owned by the facade.
|
|
82
|
+
*/
|
|
83
|
+
registerClientStreamCallbackHandlers(params) {
|
|
84
|
+
this.onOpen(() => {
|
|
85
|
+
this.hub.registerHandler(type => type.startsWith('stream_') && type !== MessageType.STREAM_START, (data, context) => {
|
|
86
|
+
var _this$hub$getStreamCa;
|
|
87
|
+
return (_this$hub$getStreamCa = this.hub.getStreamCallback()) === null || _this$hub$getStreamCa === void 0 ? void 0 : _this$hub$getStreamCa(data, context);
|
|
88
|
+
}, params.handlerOptions);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Enable default stream dispatching: dispatch stream_* messages to streamDispatcher.
|
|
94
|
+
*/
|
|
95
|
+
enableStreamDispatcherCallback(params) {
|
|
96
|
+
this.hub.setStreamCallback((data, context) => {
|
|
97
|
+
this.dispatchStreamMessage(data, context, {
|
|
98
|
+
isOriginAllowed: params === null || params === void 0 ? void 0 : params.isOriginAllowed
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
disableStreamDispatcherCallback() {
|
|
103
|
+
this.hub.setStreamCallback(undefined);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Register server-side base handlers:
|
|
108
|
+
* - PING/PONG (heartbeat)
|
|
109
|
+
* - ACK (receipt confirmation waiter)
|
|
110
|
+
* - STREAM_START + stream_* routing (request-body stream)
|
|
111
|
+
*
|
|
112
|
+
* Server wrapper should still register REQUEST handler itself.
|
|
113
|
+
*/
|
|
114
|
+
registerServerBaseHandlers(params) {
|
|
115
|
+
this.registerPingResponderHandler({
|
|
116
|
+
handlerOptions: params.handlerOptions,
|
|
117
|
+
handledBy: params.handledBy,
|
|
118
|
+
includeTargetIdInPong: params.includeTargetIdInPong,
|
|
119
|
+
isOriginAllowed: params.isOriginAllowed
|
|
120
|
+
});
|
|
121
|
+
this.registerHeartbeatPongHandler({
|
|
122
|
+
handlerOptions: params.handlerOptions
|
|
123
|
+
});
|
|
124
|
+
this.registerAckWaiterHandler({
|
|
125
|
+
handlerOptions: params.handlerOptions,
|
|
126
|
+
pendingBucket: params.pendingAckBucket,
|
|
127
|
+
handledBy: params.handledBy,
|
|
128
|
+
isOriginAllowed: params.isOriginAllowed,
|
|
129
|
+
warnMissingPendingWhenClosed: params.warnMissingPendingWhenClosed
|
|
130
|
+
});
|
|
131
|
+
this.registerStreamHandlers({
|
|
132
|
+
handlerOptions: params.handlerOptions,
|
|
133
|
+
expectedRole: params.expectedStreamStartRole,
|
|
134
|
+
pendingBucket: params.pendingStreamStartBucket,
|
|
135
|
+
isOriginAllowed: params.isOriginAllowed,
|
|
136
|
+
warnMissingPendingWhenClosed: params.warnMissingPendingWhenClosed
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Register PING responder (reply PONG).
|
|
142
|
+
*/
|
|
143
|
+
registerPingResponderHandler(params) {
|
|
144
|
+
this.onOpen(() => {
|
|
145
|
+
this.hub.registerHandler(MessageType.PING, (data, context) => {
|
|
146
|
+
this.handlePing(data, context, {
|
|
147
|
+
handledBy: params.handledBy,
|
|
148
|
+
includeTargetId: params.includeTargetIdInPong,
|
|
149
|
+
isOriginAllowed: params.isOriginAllowed
|
|
150
|
+
});
|
|
151
|
+
}, params.handlerOptions);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Register PONG handler for heartbeat waiter (if heartbeat is configured).
|
|
157
|
+
*/
|
|
158
|
+
registerHeartbeatPongHandler(params) {
|
|
159
|
+
this.onOpen(() => {
|
|
160
|
+
this.hub.registerHandler(MessageType.PONG, (data, context) => {
|
|
161
|
+
this.handlePong(data, context);
|
|
162
|
+
}, params.handlerOptions);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Register ACK handler for receipt confirmation waiters.
|
|
168
|
+
*/
|
|
169
|
+
registerAckWaiterHandler(params) {
|
|
170
|
+
this.onOpen(() => {
|
|
171
|
+
this.hub.registerHandler(MessageType.ACK, (data, context) => {
|
|
172
|
+
this.handleAck({
|
|
173
|
+
data,
|
|
174
|
+
context,
|
|
175
|
+
pendingBucket: params.pendingBucket,
|
|
176
|
+
handledBy: params.handledBy,
|
|
177
|
+
isOriginAllowed: params.isOriginAllowed,
|
|
178
|
+
warnMissingPendingWhenClosed: params.warnMissingPendingWhenClosed
|
|
179
|
+
});
|
|
180
|
+
}, params.handlerOptions);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Register stream handlers (STREAM_START + stream_* routing).
|
|
186
|
+
*/
|
|
187
|
+
registerStreamHandlers(params) {
|
|
188
|
+
this.onOpen(() => {
|
|
189
|
+
var isOriginAllowed = params.isOriginAllowed;
|
|
190
|
+
this.hub.registerHandler(MessageType.STREAM_START, (data, context) => {
|
|
191
|
+
this.handleStreamStart({
|
|
192
|
+
data,
|
|
193
|
+
context,
|
|
194
|
+
expectedRole: params.expectedRole,
|
|
195
|
+
pendingBucket: params.pendingBucket,
|
|
196
|
+
isOriginAllowed,
|
|
197
|
+
warnMissingPendingWhenClosed: params.warnMissingPendingWhenClosed
|
|
198
|
+
});
|
|
199
|
+
}, params.handlerOptions);
|
|
200
|
+
this.hub.registerHandler(type => type.startsWith('stream_') && type !== MessageType.STREAM_START, (data, context) => {
|
|
201
|
+
this.dispatchStreamMessage(data, context, {
|
|
202
|
+
isOriginAllowed
|
|
203
|
+
});
|
|
204
|
+
}, params.handlerOptions);
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Server-side: register a waiter for an incoming stream_start (request-body stream handshake).
|
|
210
|
+
*
|
|
211
|
+
* This centralizes:
|
|
212
|
+
* - pending map bookkeeping
|
|
213
|
+
* - timeout cleanup
|
|
214
|
+
* - STREAM_START_TIMEOUT error response hook
|
|
215
|
+
*/
|
|
216
|
+
registerIncomingStreamStartWaiter(params) {
|
|
217
|
+
var timeoutId = this.hub.pending.setTimeout(() => {
|
|
218
|
+
var pending = this.hub.pending.get(params.pendingBucket, params.requestId);
|
|
219
|
+
if (!pending) return;
|
|
220
|
+
this.hub.pending.delete(params.pendingBucket, params.requestId);
|
|
221
|
+
params.onTimeout();
|
|
222
|
+
}, params.timeoutMs);
|
|
223
|
+
this.hub.pending.set(params.pendingBucket, params.requestId, {
|
|
224
|
+
streamId: params.streamId,
|
|
225
|
+
timeoutId,
|
|
226
|
+
targetWindow: params.targetWindow,
|
|
227
|
+
targetOrigin: params.targetOrigin,
|
|
228
|
+
continue: params.continue
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Handle incoming PING and reply PONG.
|
|
234
|
+
*
|
|
235
|
+
* This is a base infrastructure capability for all endpoints.
|
|
236
|
+
*/
|
|
237
|
+
handlePing(data, context, params) {
|
|
238
|
+
if (!context.source) return;
|
|
239
|
+
if (params.isOriginAllowed && !params.isOriginAllowed(data, context)) return;
|
|
240
|
+
createPingResponder({
|
|
241
|
+
hub: this.hub,
|
|
242
|
+
handledBy: params.handledBy,
|
|
243
|
+
includeTargetId: params.includeTargetId
|
|
244
|
+
})(data, context);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Handle incoming PONG for facade heartbeat waiter (if configured).
|
|
249
|
+
*/
|
|
250
|
+
handlePong(data, context) {
|
|
251
|
+
var _this$heartbeat;
|
|
252
|
+
(_this$heartbeat = this.heartbeat) === null || _this$heartbeat === void 0 || _this$heartbeat.handlePong(data, context);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Ping a peer and resolve true when PONG arrives (requires heartbeat configured).
|
|
257
|
+
*/
|
|
258
|
+
pingPeer(targetWindow, targetOrigin, timeoutMs, targetId) {
|
|
259
|
+
if (!this.heartbeat) {
|
|
260
|
+
return Promise.resolve(false);
|
|
261
|
+
}
|
|
262
|
+
var peer = this.hub.createOutbox(targetWindow, targetOrigin, targetId);
|
|
263
|
+
return this.heartbeat.ping(peer, timeoutMs, targetId);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Client-side "isConnect" ping helper (requires inbox configured).
|
|
268
|
+
*
|
|
269
|
+
* - Sends PING(requireAck=true)
|
|
270
|
+
* - Resolves true when ACK or PONG arrives, false on timeout
|
|
271
|
+
*/
|
|
272
|
+
pingIsConnect(params) {
|
|
273
|
+
var inbox = this.inbox;
|
|
274
|
+
if (!inbox) return Promise.resolve(false);
|
|
275
|
+
return inbox.pingIsConnect({
|
|
276
|
+
peer: params.peer,
|
|
277
|
+
timeoutMs: params.timeoutMs,
|
|
278
|
+
targetOrigin: params.targetOrigin,
|
|
279
|
+
targetId: params.targetId,
|
|
280
|
+
onPeerId: params.onPeerId,
|
|
281
|
+
originValidator: this.originValidator
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Pending ACK waiter bucket entry.
|
|
287
|
+
*/
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Register an ACK waiter (used by server response requireAck).
|
|
291
|
+
*/
|
|
292
|
+
registerPendingAck(params) {
|
|
293
|
+
var _params$pendingBucket;
|
|
294
|
+
var bucket = (_params$pendingBucket = params.pendingBucket) !== null && _params$pendingBucket !== void 0 ? _params$pendingBucket : RequestIframeEndpointFacade.DEFAULT_PENDING_ACKS_BUCKET;
|
|
295
|
+
var timeoutId = this.hub.pending.setTimeout(() => {
|
|
296
|
+
this.hub.pending.delete(bucket, params.requestId);
|
|
297
|
+
params.resolve(false);
|
|
298
|
+
}, params.timeoutMs);
|
|
299
|
+
this.hub.pending.set(bucket, params.requestId, {
|
|
300
|
+
resolve: params.resolve,
|
|
301
|
+
timeoutId
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Handle incoming ACK for a registered waiter.
|
|
307
|
+
*/
|
|
308
|
+
handleAck(params) {
|
|
309
|
+
var _params$pendingBucket2;
|
|
310
|
+
var bucket = (_params$pendingBucket2 = params.pendingBucket) !== null && _params$pendingBucket2 !== void 0 ? _params$pendingBucket2 : RequestIframeEndpointFacade.DEFAULT_PENDING_ACKS_BUCKET;
|
|
311
|
+
if (params.isOriginAllowed && !params.isOriginAllowed(params.data, params.context)) return;
|
|
312
|
+
var pending = this.hub.pending.get(bucket, params.data.requestId);
|
|
313
|
+
if (!pending) {
|
|
314
|
+
if (!this.hub.isOpen) {
|
|
315
|
+
var _params$warnMissingPe;
|
|
316
|
+
(_params$warnMissingPe = params.warnMissingPendingWhenClosed) === null || _params$warnMissingPe === void 0 || _params$warnMissingPe.call(params, params.data);
|
|
317
|
+
}
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
params.context.markHandledBy(params.handledBy);
|
|
321
|
+
this.hub.pending.clearTimeout(pending.timeoutId);
|
|
322
|
+
this.hub.pending.delete(bucket, params.data.requestId);
|
|
323
|
+
pending.resolve(true, params.data.ack);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Dispatch incoming stream_* messages (stream_data/stream_end/...) to bound handler.
|
|
328
|
+
*/
|
|
329
|
+
dispatchStreamMessage(data, context, params) {
|
|
330
|
+
if (params !== null && params !== void 0 && params.isOriginAllowed && !params.isOriginAllowed(data, context)) return;
|
|
331
|
+
this.streamDispatcher.dispatch(data, context);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Pending stream_start waiter entry.
|
|
336
|
+
*
|
|
337
|
+
* Server stores this entry when it receives a REQUEST that declares a streamId.
|
|
338
|
+
* When stream_start arrives, facade creates a ReadableStream and calls `continue`.
|
|
339
|
+
*/
|
|
340
|
+
handleStreamStart(params) {
|
|
341
|
+
var data = params.data,
|
|
342
|
+
context = params.context;
|
|
343
|
+
if (params.expectedRole && data.role !== params.expectedRole) return;
|
|
344
|
+
if (params.isOriginAllowed && !params.isOriginAllowed(data, context)) return;
|
|
345
|
+
var body = data.body;
|
|
346
|
+
if (!(body !== null && body !== void 0 && body.streamId)) return;
|
|
347
|
+
var pending = this.hub.pending.get(params.pendingBucket, data.requestId);
|
|
348
|
+
if (!pending) {
|
|
349
|
+
if (!this.hub.isOpen) {
|
|
350
|
+
var _params$warnMissingPe2;
|
|
351
|
+
(_params$warnMissingPe2 = params.warnMissingPendingWhenClosed) === null || _params$warnMissingPe2 === void 0 || _params$warnMissingPe2.call(params, data);
|
|
352
|
+
}
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
if (pending.streamId !== body.streamId) return;
|
|
356
|
+
this.hub.pending.clearTimeout(pending.timeoutId);
|
|
357
|
+
this.hub.pending.delete(params.pendingBucket, data.requestId);
|
|
358
|
+
var streamHandler = createStreamMessageHandler({
|
|
359
|
+
dispatcher: this.streamDispatcher,
|
|
360
|
+
postMessage: message => {
|
|
361
|
+
this.hub.messageDispatcher.send(pending.targetWindow, message, pending.targetOrigin);
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
var created = createReadableStreamFromStart({
|
|
365
|
+
requestId: data.requestId,
|
|
366
|
+
data,
|
|
367
|
+
handler: streamHandler,
|
|
368
|
+
secretKey: data.secretKey
|
|
369
|
+
});
|
|
370
|
+
if (!created) return;
|
|
371
|
+
pending.continue({
|
|
372
|
+
stream: created.stream,
|
|
373
|
+
info: created.info,
|
|
374
|
+
data,
|
|
375
|
+
context
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
static buildOriginValidator(input) {
|
|
379
|
+
if (!input) return undefined;
|
|
380
|
+
if (input.validateOrigin) {
|
|
381
|
+
return (origin, data, context) => input.validateOrigin(origin, data, context);
|
|
382
|
+
}
|
|
383
|
+
if (input.allowedOrigins) {
|
|
384
|
+
var matcher = input.allowedOrigins;
|
|
385
|
+
return origin => matchOrigin(origin, matcher);
|
|
386
|
+
}
|
|
387
|
+
return undefined;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
_defineProperty(RequestIframeEndpointFacade, "DEFAULT_PENDING_ACKS_BUCKET", 'endpoint:pendingAcks');
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import "core-js/modules/es.array.slice.js";
|
|
2
|
+
import "core-js/modules/es.promise.js";
|
|
3
|
+
import "core-js/modules/es.regexp.to-string.js";
|
|
4
|
+
import { MessageType } from '../../constants';
|
|
5
|
+
/**
|
|
6
|
+
* RequestIframeEndpointHeartbeat
|
|
7
|
+
*
|
|
8
|
+
* Shared "ping -> wait pong" helper.
|
|
9
|
+
* - Works for both server and client endpoints
|
|
10
|
+
* - Uses core.pending for timeout management
|
|
11
|
+
*/
|
|
12
|
+
export class RequestIframeEndpointHeartbeat {
|
|
13
|
+
constructor(params) {
|
|
14
|
+
this.hub = params.hub;
|
|
15
|
+
this.pendingBucket = params.pendingBucket;
|
|
16
|
+
this.handledBy = params.handledBy;
|
|
17
|
+
this.isOriginAllowed = params.isOriginAllowed;
|
|
18
|
+
this.warnMissingPendingWhenClosed = params.warnMissingPendingWhenClosed;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Send PING and resolve true when PONG arrives, false on timeout.
|
|
23
|
+
*/
|
|
24
|
+
ping(peer, timeoutMs, targetId) {
|
|
25
|
+
var requestId = `ping_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
26
|
+
return new Promise(resolve => {
|
|
27
|
+
var timeoutId = this.hub.pending.setTimeout(() => {
|
|
28
|
+
this.hub.pending.delete(this.pendingBucket, requestId);
|
|
29
|
+
resolve(false);
|
|
30
|
+
}, timeoutMs);
|
|
31
|
+
this.hub.pending.set(this.pendingBucket, requestId, {
|
|
32
|
+
resolve,
|
|
33
|
+
timeoutId
|
|
34
|
+
});
|
|
35
|
+
peer.sendMessage(MessageType.PING, requestId, {
|
|
36
|
+
requireAck: true,
|
|
37
|
+
targetId
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Handle incoming PONG for ping() waiter.
|
|
44
|
+
*/
|
|
45
|
+
handlePong(data, context) {
|
|
46
|
+
if (this.isOriginAllowed && !this.isOriginAllowed(data, context)) return;
|
|
47
|
+
var pending = this.hub.pending.get(this.pendingBucket, data.requestId);
|
|
48
|
+
if (!pending) {
|
|
49
|
+
if (!this.hub.isOpen) {
|
|
50
|
+
var _this$warnMissingPend;
|
|
51
|
+
(_this$warnMissingPend = this.warnMissingPendingWhenClosed) === null || _this$warnMissingPend === void 0 || _this$warnMissingPend.call(this, data);
|
|
52
|
+
}
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
context.markAcceptedBy(this.handledBy);
|
|
56
|
+
this.hub.pending.clearTimeout(pending.timeoutId);
|
|
57
|
+
this.hub.pending.delete(this.pendingBucket, data.requestId);
|
|
58
|
+
pending.resolve(true);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { MessageType } from '../../constants';
|
|
2
|
+
/**
|
|
3
|
+
* Create a PING responder handler (reply PONG).
|
|
4
|
+
*
|
|
5
|
+
* This is a shared building block for both client/server endpoints.
|
|
6
|
+
*/
|
|
7
|
+
export function createPingResponder(params) {
|
|
8
|
+
var hub = params.hub,
|
|
9
|
+
handledBy = params.handledBy,
|
|
10
|
+
includeTargetId = params.includeTargetId;
|
|
11
|
+
return (data, context) => {
|
|
12
|
+
if (!context.source) return;
|
|
13
|
+
/** Mark accepted so MessageDispatcher can auto-send ACK when requireAck === true */
|
|
14
|
+
context.markAcceptedBy(handledBy);
|
|
15
|
+
/** Reply PONG */
|
|
16
|
+
hub.messageDispatcher.sendMessage(context.source, context.origin, MessageType.PONG, data.requestId, includeTargetId ? {
|
|
17
|
+
targetId: data.creatorId
|
|
18
|
+
} : undefined);
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { RequestIframeEndpointHub } from './infra/hub';
|
|
2
|
+
export { RequestIframeEndpointInbox } from './infra/inbox';
|
|
3
|
+
export { RequestIframeEndpointOutbox } from './infra/outbox';
|
|
4
|
+
export { createPingResponder } from './heartbeat/ping';
|
|
5
|
+
export { buildExpectedAck, isExpectedAckMatch } from '../message/ack';
|
|
6
|
+
export { RequestIframeStreamDispatcher } from './stream/dispatcher';
|
|
7
|
+
export { RequestIframeEndpointHeartbeat } from './heartbeat/heartbeat';
|
|
8
|
+
export { parseStreamStart, createReadableStreamFromStart } from './stream/factory';
|
|
9
|
+
export { RequestIframeEndpointFacade } from './facade';
|
|
10
|
+
export { createStreamMessageHandler } from './stream/handler';
|
|
11
|
+
export { buildStreamStartTimeoutErrorPayload } from './stream/errors';
|
|
12
|
+
export { autoResolveIframeFileReadableStream, parseFilenameFromContentDisposition } from './stream/file-auto-resolve';
|
|
13
|
+
export { createIframeFileWritableStreamFromContent } from './stream/file-writable';
|