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.
Files changed (223) hide show
  1. package/QUICKSTART.CN.md +4 -2
  2. package/QUICKSTART.md +4 -2
  3. package/README.CN.md +302 -54
  4. package/README.md +281 -36
  5. package/cdn/request-iframe-react.umd.js +3354 -0
  6. package/cdn/request-iframe-react.umd.js.map +1 -0
  7. package/cdn/request-iframe-react.umd.min.js +2 -0
  8. package/cdn/request-iframe-react.umd.min.js.map +1 -0
  9. package/cdn/request-iframe.umd.js +19735 -0
  10. package/cdn/request-iframe.umd.js.map +1 -0
  11. package/cdn/request-iframe.umd.min.js +4 -0
  12. package/cdn/request-iframe.umd.min.js.map +1 -0
  13. package/esm/api/client.js +31 -22
  14. package/esm/api/endpoint.js +229 -0
  15. package/esm/api/server.js +19 -9
  16. package/esm/constants/debug.js +17 -0
  17. package/esm/constants/index.js +115 -66
  18. package/esm/constants/log.js +11 -0
  19. package/esm/constants/messages.js +6 -1
  20. package/esm/constants/warn-once.js +15 -0
  21. package/esm/endpoint/facade.js +390 -0
  22. package/esm/endpoint/heartbeat/heartbeat.js +60 -0
  23. package/esm/endpoint/heartbeat/ping.js +20 -0
  24. package/esm/endpoint/index.js +13 -0
  25. package/esm/endpoint/infra/hub.js +316 -0
  26. package/esm/endpoint/infra/inbox.js +232 -0
  27. package/esm/endpoint/infra/outbox.js +408 -0
  28. package/esm/endpoint/stream/dispatcher.js +58 -0
  29. package/esm/endpoint/stream/errors.js +27 -0
  30. package/esm/endpoint/stream/factory.js +76 -0
  31. package/esm/endpoint/stream/file-auto-resolve.js +34 -0
  32. package/esm/endpoint/stream/file-writable.js +105 -0
  33. package/esm/endpoint/stream/handler.js +26 -0
  34. package/esm/{core → impl}/client.js +243 -320
  35. package/esm/{core → impl}/response.js +120 -154
  36. package/esm/impl/server.js +568 -0
  37. package/esm/index.js +13 -6
  38. package/esm/message/ack.js +27 -0
  39. package/esm/message/channel-cache.js +108 -0
  40. package/esm/message/channel.js +92 -5
  41. package/esm/message/dispatcher.js +149 -98
  42. package/esm/stream/error.js +22 -0
  43. package/esm/stream/index.js +3 -1
  44. package/esm/stream/readable-stream.js +101 -26
  45. package/esm/stream/stream-core.js +121 -3
  46. package/esm/stream/writable-stream.js +368 -43
  47. package/esm/utils/ack.js +36 -0
  48. package/esm/utils/blob.js +16 -0
  49. package/esm/utils/cache.js +25 -76
  50. package/esm/utils/content-type.js +81 -0
  51. package/esm/utils/debug.js +157 -180
  52. package/esm/utils/hooks.js +130 -0
  53. package/esm/utils/id.js +14 -0
  54. package/esm/utils/iframe.js +20 -0
  55. package/esm/utils/index.js +12 -162
  56. package/esm/utils/is.js +3 -0
  57. package/esm/utils/logger.js +55 -0
  58. package/esm/utils/origin.js +3 -1
  59. package/esm/utils/promise.js +3 -0
  60. package/esm/utils/window.js +31 -0
  61. package/library/api/client.d.ts.map +1 -1
  62. package/library/api/client.js +32 -23
  63. package/library/api/endpoint.d.ts +23 -0
  64. package/library/api/endpoint.d.ts.map +1 -0
  65. package/library/api/endpoint.js +235 -0
  66. package/library/api/server.d.ts +4 -1
  67. package/library/api/server.d.ts.map +1 -1
  68. package/library/api/server.js +19 -9
  69. package/library/constants/debug.d.ts +18 -0
  70. package/library/constants/debug.d.ts.map +1 -0
  71. package/library/constants/debug.js +23 -0
  72. package/library/constants/index.d.ts +58 -7
  73. package/library/constants/index.d.ts.map +1 -1
  74. package/library/constants/index.js +143 -67
  75. package/library/constants/log.d.ts +12 -0
  76. package/library/constants/log.d.ts.map +1 -0
  77. package/library/constants/log.js +17 -0
  78. package/library/constants/messages.d.ts +6 -1
  79. package/library/constants/messages.d.ts.map +1 -1
  80. package/library/constants/messages.js +6 -1
  81. package/library/constants/warn-once.d.ts +12 -0
  82. package/library/constants/warn-once.d.ts.map +1 -0
  83. package/library/constants/warn-once.js +22 -0
  84. package/library/endpoint/facade.d.ts +238 -0
  85. package/library/endpoint/facade.d.ts.map +1 -0
  86. package/library/endpoint/facade.js +398 -0
  87. package/library/endpoint/heartbeat/heartbeat.d.ts +34 -0
  88. package/library/endpoint/heartbeat/heartbeat.d.ts.map +1 -0
  89. package/library/endpoint/heartbeat/heartbeat.js +67 -0
  90. package/library/endpoint/heartbeat/ping.d.ts +18 -0
  91. package/library/endpoint/heartbeat/ping.d.ts.map +1 -0
  92. package/library/endpoint/heartbeat/ping.js +26 -0
  93. package/library/endpoint/index.d.ts +16 -0
  94. package/library/endpoint/index.d.ts.map +1 -0
  95. package/library/endpoint/index.js +114 -0
  96. package/library/endpoint/infra/hub.d.ts +170 -0
  97. package/library/endpoint/infra/hub.d.ts.map +1 -0
  98. package/library/endpoint/infra/hub.js +323 -0
  99. package/library/endpoint/infra/inbox.d.ts +73 -0
  100. package/library/endpoint/infra/inbox.d.ts.map +1 -0
  101. package/library/endpoint/infra/inbox.js +239 -0
  102. package/library/endpoint/infra/outbox.d.ts +149 -0
  103. package/library/endpoint/infra/outbox.d.ts.map +1 -0
  104. package/library/endpoint/infra/outbox.js +415 -0
  105. package/library/endpoint/stream/dispatcher.d.ts +33 -0
  106. package/library/endpoint/stream/dispatcher.d.ts.map +1 -0
  107. package/library/endpoint/stream/dispatcher.js +66 -0
  108. package/library/endpoint/stream/errors.d.ts +20 -0
  109. package/library/endpoint/stream/errors.d.ts.map +1 -0
  110. package/library/endpoint/stream/errors.js +32 -0
  111. package/library/endpoint/stream/factory.d.ts +44 -0
  112. package/library/endpoint/stream/factory.d.ts.map +1 -0
  113. package/library/endpoint/stream/factory.js +82 -0
  114. package/library/endpoint/stream/file-auto-resolve.d.ts +26 -0
  115. package/library/endpoint/stream/file-auto-resolve.d.ts.map +1 -0
  116. package/library/endpoint/stream/file-auto-resolve.js +41 -0
  117. package/library/endpoint/stream/file-writable.d.ts +33 -0
  118. package/library/endpoint/stream/file-writable.d.ts.map +1 -0
  119. package/library/endpoint/stream/file-writable.js +115 -0
  120. package/library/endpoint/stream/handler.d.ts +20 -0
  121. package/library/endpoint/stream/handler.d.ts.map +1 -0
  122. package/library/endpoint/stream/handler.js +32 -0
  123. package/library/{core → impl}/client.d.ts +16 -13
  124. package/library/impl/client.d.ts.map +1 -0
  125. package/library/{core → impl}/client.js +254 -333
  126. package/library/{core → impl}/request.d.ts.map +1 -1
  127. package/library/{core → impl}/response.d.ts +7 -12
  128. package/library/impl/response.d.ts.map +1 -0
  129. package/library/{core → impl}/response.js +120 -154
  130. package/library/{core → impl}/server.d.ts +26 -55
  131. package/library/impl/server.d.ts.map +1 -0
  132. package/library/impl/server.js +575 -0
  133. package/library/index.d.ts +13 -6
  134. package/library/index.d.ts.map +1 -1
  135. package/library/index.js +16 -16
  136. package/library/message/ack.d.ts +15 -0
  137. package/library/message/ack.d.ts.map +1 -0
  138. package/library/message/ack.js +33 -0
  139. package/library/message/channel-cache.d.ts +26 -0
  140. package/library/message/channel-cache.d.ts.map +1 -0
  141. package/library/message/channel-cache.js +115 -0
  142. package/library/message/channel.d.ts +53 -6
  143. package/library/message/channel.d.ts.map +1 -1
  144. package/library/message/channel.js +96 -9
  145. package/library/message/dispatcher.d.ts +17 -0
  146. package/library/message/dispatcher.d.ts.map +1 -1
  147. package/library/message/dispatcher.js +149 -98
  148. package/library/stream/error.d.ts +24 -0
  149. package/library/stream/error.d.ts.map +1 -0
  150. package/library/stream/error.js +29 -0
  151. package/library/stream/index.d.ts +4 -1
  152. package/library/stream/index.d.ts.map +1 -1
  153. package/library/stream/index.js +7 -4
  154. package/library/stream/readable-stream.d.ts.map +1 -1
  155. package/library/stream/readable-stream.js +102 -27
  156. package/library/stream/stream-core.d.ts +22 -1
  157. package/library/stream/stream-core.d.ts.map +1 -1
  158. package/library/stream/stream-core.js +120 -2
  159. package/library/stream/types.d.ts +115 -2
  160. package/library/stream/types.d.ts.map +1 -1
  161. package/library/stream/writable-stream.d.ts +20 -2
  162. package/library/stream/writable-stream.d.ts.map +1 -1
  163. package/library/stream/writable-stream.js +366 -41
  164. package/library/types/index.d.ts +17 -22
  165. package/library/types/index.d.ts.map +1 -1
  166. package/library/utils/ack.d.ts +2 -0
  167. package/library/utils/ack.d.ts.map +1 -0
  168. package/library/utils/ack.js +44 -0
  169. package/library/utils/blob.d.ts +3 -0
  170. package/library/utils/blob.d.ts.map +1 -0
  171. package/library/utils/blob.js +22 -0
  172. package/library/utils/cache.d.ts +10 -20
  173. package/library/utils/cache.d.ts.map +1 -1
  174. package/library/utils/cache.js +25 -79
  175. package/library/utils/content-type.d.ts +13 -0
  176. package/library/utils/content-type.d.ts.map +1 -0
  177. package/library/utils/content-type.js +87 -0
  178. package/library/utils/debug.d.ts.map +1 -1
  179. package/library/utils/debug.js +156 -178
  180. package/library/utils/hooks.d.ts +30 -0
  181. package/library/utils/hooks.d.ts.map +1 -0
  182. package/library/utils/hooks.js +139 -0
  183. package/library/utils/id.d.ts +9 -0
  184. package/library/utils/id.d.ts.map +1 -0
  185. package/library/utils/id.js +21 -0
  186. package/library/utils/iframe.d.ts +5 -0
  187. package/library/utils/iframe.d.ts.map +1 -0
  188. package/library/utils/iframe.js +25 -0
  189. package/library/utils/index.d.ts +7 -34
  190. package/library/utils/index.d.ts.map +1 -1
  191. package/library/utils/index.js +58 -193
  192. package/library/utils/is.d.ts +2 -0
  193. package/library/utils/is.d.ts.map +1 -0
  194. package/library/utils/is.js +9 -0
  195. package/library/utils/logger.d.ts +13 -0
  196. package/library/utils/logger.d.ts.map +1 -0
  197. package/library/utils/logger.js +63 -0
  198. package/library/utils/origin.d.ts.map +1 -1
  199. package/library/utils/origin.js +2 -1
  200. package/library/utils/promise.d.ts +2 -0
  201. package/library/utils/promise.d.ts.map +1 -0
  202. package/library/utils/promise.js +9 -0
  203. package/library/utils/window.d.ts +2 -0
  204. package/library/utils/window.d.ts.map +1 -0
  205. package/library/utils/window.js +38 -0
  206. package/package.json +49 -2
  207. package/react/package.json +2 -1
  208. package/esm/core/client-server.js +0 -329
  209. package/esm/core/server.js +0 -767
  210. package/esm/utils/ack-meta.js +0 -53
  211. package/library/core/client-server.d.ts +0 -106
  212. package/library/core/client-server.d.ts.map +0 -1
  213. package/library/core/client-server.js +0 -336
  214. package/library/core/client.d.ts.map +0 -1
  215. package/library/core/response.d.ts.map +0 -1
  216. package/library/core/server.d.ts.map +0 -1
  217. package/library/core/server.js +0 -772
  218. package/library/utils/ack-meta.d.ts +0 -2
  219. package/library/utils/ack-meta.d.ts.map +0 -1
  220. package/library/utils/ack-meta.js +0 -59
  221. /package/esm/{core → impl}/request.js +0 -0
  222. /package/library/{core → impl}/request.d.ts +0 -0
  223. /package/library/{core → impl}/request.js +0 -0
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Log level constants for request-iframe.
3
+ */
4
+
5
+ export var LogLevel = {
6
+ TRACE: 'trace',
7
+ INFO: 'info',
8
+ WARN: 'warn',
9
+ ERROR: 'error',
10
+ SILENT: 'silent'
11
+ };
@@ -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 Received ACK',
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';