request-iframe 0.1.1 → 0.2.1

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 (208) hide show
  1. package/QUICKSTART.CN.md +4 -2
  2. package/QUICKSTART.md +4 -2
  3. package/README.CN.md +129 -33
  4. package/README.md +116 -15
  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 +19761 -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 +29 -21
  14. package/esm/api/endpoint.js +229 -0
  15. package/esm/api/server.js +16 -8
  16. package/esm/constants/debug.js +17 -0
  17. package/esm/constants/index.js +84 -67
  18. package/esm/constants/log.js +11 -0
  19. package/esm/constants/messages.js +3 -0
  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 +240 -317
  35. package/esm/{core → impl}/response.js +113 -155
  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 +90 -4
  41. package/esm/message/dispatcher.js +115 -75
  42. package/esm/stream/error.js +22 -0
  43. package/esm/stream/index.js +3 -1
  44. package/esm/stream/readable-stream.js +45 -9
  45. package/esm/stream/stream-core.js +7 -2
  46. package/esm/stream/writable-stream.js +97 -26
  47. package/esm/utils/blob.js +16 -0
  48. package/esm/utils/cache.js +25 -76
  49. package/esm/utils/content-type.js +81 -0
  50. package/esm/utils/debug.js +156 -179
  51. package/esm/utils/hooks.js +130 -0
  52. package/esm/utils/id.js +14 -0
  53. package/esm/utils/iframe.js +20 -0
  54. package/esm/utils/index.js +11 -163
  55. package/esm/utils/is.js +3 -0
  56. package/esm/utils/logger.js +55 -0
  57. package/esm/utils/promise.js +3 -0
  58. package/esm/utils/window.js +31 -0
  59. package/library/api/client.d.ts.map +1 -1
  60. package/library/api/client.js +30 -22
  61. package/library/api/endpoint.d.ts +23 -0
  62. package/library/api/endpoint.d.ts.map +1 -0
  63. package/library/api/endpoint.js +235 -0
  64. package/library/api/server.d.ts +4 -1
  65. package/library/api/server.d.ts.map +1 -1
  66. package/library/api/server.js +16 -8
  67. package/library/constants/debug.d.ts +18 -0
  68. package/library/constants/debug.d.ts.map +1 -0
  69. package/library/constants/debug.js +23 -0
  70. package/library/constants/index.d.ts +22 -2
  71. package/library/constants/index.d.ts.map +1 -1
  72. package/library/constants/index.js +110 -67
  73. package/library/constants/log.d.ts +12 -0
  74. package/library/constants/log.d.ts.map +1 -0
  75. package/library/constants/log.js +17 -0
  76. package/library/constants/messages.d.ts +3 -0
  77. package/library/constants/messages.d.ts.map +1 -1
  78. package/library/constants/messages.js +3 -0
  79. package/library/constants/warn-once.d.ts +12 -0
  80. package/library/constants/warn-once.d.ts.map +1 -0
  81. package/library/constants/warn-once.js +22 -0
  82. package/library/endpoint/facade.d.ts +238 -0
  83. package/library/endpoint/facade.d.ts.map +1 -0
  84. package/library/endpoint/facade.js +398 -0
  85. package/library/endpoint/heartbeat/heartbeat.d.ts +34 -0
  86. package/library/endpoint/heartbeat/heartbeat.d.ts.map +1 -0
  87. package/library/endpoint/heartbeat/heartbeat.js +67 -0
  88. package/library/endpoint/heartbeat/ping.d.ts +18 -0
  89. package/library/endpoint/heartbeat/ping.d.ts.map +1 -0
  90. package/library/endpoint/heartbeat/ping.js +26 -0
  91. package/library/endpoint/index.d.ts +16 -0
  92. package/library/endpoint/index.d.ts.map +1 -0
  93. package/library/endpoint/index.js +114 -0
  94. package/library/endpoint/infra/hub.d.ts +170 -0
  95. package/library/endpoint/infra/hub.d.ts.map +1 -0
  96. package/library/endpoint/infra/hub.js +323 -0
  97. package/library/endpoint/infra/inbox.d.ts +73 -0
  98. package/library/endpoint/infra/inbox.d.ts.map +1 -0
  99. package/library/endpoint/infra/inbox.js +239 -0
  100. package/library/endpoint/infra/outbox.d.ts +149 -0
  101. package/library/endpoint/infra/outbox.d.ts.map +1 -0
  102. package/library/endpoint/infra/outbox.js +415 -0
  103. package/library/endpoint/stream/dispatcher.d.ts +33 -0
  104. package/library/endpoint/stream/dispatcher.d.ts.map +1 -0
  105. package/library/endpoint/stream/dispatcher.js +66 -0
  106. package/library/endpoint/stream/errors.d.ts +20 -0
  107. package/library/endpoint/stream/errors.d.ts.map +1 -0
  108. package/library/endpoint/stream/errors.js +32 -0
  109. package/library/endpoint/stream/factory.d.ts +44 -0
  110. package/library/endpoint/stream/factory.d.ts.map +1 -0
  111. package/library/endpoint/stream/factory.js +82 -0
  112. package/library/endpoint/stream/file-auto-resolve.d.ts +26 -0
  113. package/library/endpoint/stream/file-auto-resolve.d.ts.map +1 -0
  114. package/library/endpoint/stream/file-auto-resolve.js +41 -0
  115. package/library/endpoint/stream/file-writable.d.ts +33 -0
  116. package/library/endpoint/stream/file-writable.d.ts.map +1 -0
  117. package/library/endpoint/stream/file-writable.js +115 -0
  118. package/library/endpoint/stream/handler.d.ts +20 -0
  119. package/library/endpoint/stream/handler.d.ts.map +1 -0
  120. package/library/endpoint/stream/handler.js +32 -0
  121. package/library/{core → impl}/client.d.ts +16 -13
  122. package/library/impl/client.d.ts.map +1 -0
  123. package/library/{core → impl}/client.js +251 -330
  124. package/library/{core → impl}/request.d.ts.map +1 -1
  125. package/library/{core → impl}/response.d.ts +5 -10
  126. package/library/impl/response.d.ts.map +1 -0
  127. package/library/{core → impl}/response.js +113 -155
  128. package/library/{core → impl}/server.d.ts +22 -55
  129. package/library/impl/server.d.ts.map +1 -0
  130. package/library/impl/server.js +575 -0
  131. package/library/index.d.ts +13 -6
  132. package/library/index.d.ts.map +1 -1
  133. package/library/index.js +16 -16
  134. package/library/message/ack.d.ts +15 -0
  135. package/library/message/ack.d.ts.map +1 -0
  136. package/library/message/ack.js +33 -0
  137. package/library/message/channel-cache.d.ts +26 -0
  138. package/library/message/channel-cache.d.ts.map +1 -0
  139. package/library/message/channel-cache.js +115 -0
  140. package/library/message/channel.d.ts +53 -6
  141. package/library/message/channel.d.ts.map +1 -1
  142. package/library/message/channel.js +94 -8
  143. package/library/message/dispatcher.d.ts +7 -0
  144. package/library/message/dispatcher.d.ts.map +1 -1
  145. package/library/message/dispatcher.js +116 -76
  146. package/library/stream/error.d.ts +24 -0
  147. package/library/stream/error.d.ts.map +1 -0
  148. package/library/stream/error.js +29 -0
  149. package/library/stream/index.d.ts +4 -1
  150. package/library/stream/index.d.ts.map +1 -1
  151. package/library/stream/index.js +7 -4
  152. package/library/stream/readable-stream.d.ts.map +1 -1
  153. package/library/stream/readable-stream.js +46 -10
  154. package/library/stream/stream-core.d.ts.map +1 -1
  155. package/library/stream/stream-core.js +6 -1
  156. package/library/stream/writable-stream.d.ts.map +1 -1
  157. package/library/stream/writable-stream.js +99 -28
  158. package/library/types/index.d.ts +15 -19
  159. package/library/types/index.d.ts.map +1 -1
  160. package/library/utils/blob.d.ts +3 -0
  161. package/library/utils/blob.d.ts.map +1 -0
  162. package/library/utils/blob.js +22 -0
  163. package/library/utils/cache.d.ts +10 -20
  164. package/library/utils/cache.d.ts.map +1 -1
  165. package/library/utils/cache.js +25 -79
  166. package/library/utils/content-type.d.ts +13 -0
  167. package/library/utils/content-type.d.ts.map +1 -0
  168. package/library/utils/content-type.js +87 -0
  169. package/library/utils/debug.d.ts.map +1 -1
  170. package/library/utils/debug.js +155 -177
  171. package/library/utils/hooks.d.ts +30 -0
  172. package/library/utils/hooks.d.ts.map +1 -0
  173. package/library/utils/hooks.js +139 -0
  174. package/library/utils/id.d.ts +9 -0
  175. package/library/utils/id.d.ts.map +1 -0
  176. package/library/utils/id.js +21 -0
  177. package/library/utils/iframe.d.ts +5 -0
  178. package/library/utils/iframe.d.ts.map +1 -0
  179. package/library/utils/iframe.js +25 -0
  180. package/library/utils/index.d.ts +7 -34
  181. package/library/utils/index.d.ts.map +1 -1
  182. package/library/utils/index.js +58 -194
  183. package/library/utils/is.d.ts +2 -0
  184. package/library/utils/is.d.ts.map +1 -0
  185. package/library/utils/is.js +9 -0
  186. package/library/utils/logger.d.ts +13 -0
  187. package/library/utils/logger.d.ts.map +1 -0
  188. package/library/utils/logger.js +63 -0
  189. package/library/utils/promise.d.ts +2 -0
  190. package/library/utils/promise.d.ts.map +1 -0
  191. package/library/utils/promise.js +9 -0
  192. package/library/utils/window.d.ts +2 -0
  193. package/library/utils/window.d.ts.map +1 -0
  194. package/library/utils/window.js +38 -0
  195. package/package.json +49 -2
  196. package/react/package.json +2 -1
  197. package/esm/core/client-server.js +0 -294
  198. package/esm/core/server.js +0 -776
  199. package/library/core/client-server.d.ts +0 -97
  200. package/library/core/client-server.d.ts.map +0 -1
  201. package/library/core/client-server.js +0 -301
  202. package/library/core/client.d.ts.map +0 -1
  203. package/library/core/response.d.ts.map +0 -1
  204. package/library/core/server.d.ts.map +0 -1
  205. package/library/core/server.js +0 -781
  206. /package/esm/{core → impl}/request.js +0 -0
  207. /package/library/{core → impl}/request.d.ts +0 -0
  208. /package/library/{core → impl}/request.js +0 -0
@@ -1,781 +0,0 @@
1
- "use strict";
2
-
3
- require("core-js/modules/es.symbol.description.js");
4
- require("core-js/modules/es.array.filter.js");
5
- require("core-js/modules/es.array.from.js");
6
- require("core-js/modules/es.array.slice.js");
7
- require("core-js/modules/es.object.get-own-property-descriptors.js");
8
- require("core-js/modules/es.regexp.to-string.js");
9
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
10
- Object.defineProperty(exports, "__esModule", {
11
- value: true
12
- });
13
- exports.RequestIframeServerImpl = void 0;
14
- require("core-js/modules/es.array.includes.js");
15
- require("core-js/modules/es.array.iterator.js");
16
- require("core-js/modules/es.map.js");
17
- require("core-js/modules/es.object.entries.js");
18
- require("core-js/modules/es.promise.js");
19
- require("core-js/modules/es.regexp.exec.js");
20
- require("core-js/modules/es.string.includes.js");
21
- require("core-js/modules/es.string.match.js");
22
- require("core-js/modules/es.string.replace.js");
23
- require("core-js/modules/es.string.starts-with.js");
24
- require("core-js/modules/web.dom-collections.for-each.js");
25
- require("core-js/modules/web.dom-collections.iterator.js");
26
- var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
27
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
28
- var _utils = require("../utils");
29
- var _pathMatch = require("../utils/path-match");
30
- var _origin = require("../utils/origin");
31
- var _request = require("./request");
32
- var _response = require("./response");
33
- var _message = require("../message");
34
- var _cache = require("../utils/cache");
35
- var _constants = require("../constants");
36
- var _stream = require("../stream");
37
- function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
38
- function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
39
- function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
40
- function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
41
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
42
- /**
43
- * Middleware item (contains path matcher and middleware function)
44
- */
45
-
46
- /**
47
- * Pending acknowledgment
48
- */
49
-
50
- /** Pending request waiting for client stream (streamId present) */
51
-
52
- /**
53
- * Server configuration options
54
- */
55
-
56
- /**
57
- * RequestIframeServer implementation
58
- * Uses shared MessageDispatcher (backed by MessageChannel) to listen for and send messages
59
- */
60
- class RequestIframeServerImpl {
61
- constructor(options) {
62
- var _options$ackTimeout, _options$versionValid, _options$maxConcurren;
63
- /** Unique instance ID */
64
- (0, _defineProperty2.default)(this, "handlers", new Map());
65
- (0, _defineProperty2.default)(this, "middlewares", []);
66
- (0, _defineProperty2.default)(this, "inFlightByClientKey", new Map());
67
- /** Responses waiting for client acknowledgment */
68
- (0, _defineProperty2.default)(this, "pendingAcks", new Map());
69
- /** Pending pings waiting for client PONG (server -> client heartbeat) */
70
- (0, _defineProperty2.default)(this, "pendingPongs", new Map());
71
- /** Pending requests waiting for client stream_start (streamId present) */
72
- (0, _defineProperty2.default)(this, "pendingStreamRequests", new Map());
73
- /** Stream message handlers (streamId -> handler) for client→server streams */
74
- (0, _defineProperty2.default)(this, "streamHandlers", new Map());
75
- /** List of functions to unregister handlers */
76
- (0, _defineProperty2.default)(this, "unregisterFns", []);
77
- /** Whether it is open */
78
- (0, _defineProperty2.default)(this, "_isOpen", false);
79
- // Use custom id if provided, otherwise generate one
80
- this.id = (options === null || options === void 0 ? void 0 : options.id) || (0, _utils.generateInstanceId)();
81
- this.ackTimeout = (_options$ackTimeout = options === null || options === void 0 ? void 0 : options.ackTimeout) !== null && _options$ackTimeout !== void 0 ? _options$ackTimeout : _constants.DefaultTimeout.ACK;
82
- this.versionValidator = (_options$versionValid = options === null || options === void 0 ? void 0 : options.versionValidator) !== null && _options$versionValid !== void 0 ? _options$versionValid : _utils.isCompatibleVersion;
83
- this.maxConcurrentRequestsPerClient = (_options$maxConcurren = options === null || options === void 0 ? void 0 : options.maxConcurrentRequestsPerClient) !== null && _options$maxConcurren !== void 0 ? _options$maxConcurren : Number.POSITIVE_INFINITY;
84
-
85
- // Build origin validator (incoming messages)
86
- if (options !== null && options !== void 0 && options.validateOrigin) {
87
- this.originValidator = (origin, data, context) => options.validateOrigin(origin, data, context);
88
- } else if (options !== null && options !== void 0 && options.allowedOrigins) {
89
- var matcher = options.allowedOrigins;
90
- this.originValidator = origin => (0, _origin.matchOrigin)(origin, matcher);
91
- }
92
-
93
- // Get or create shared channel and create dispatcher
94
- var channel = (0, _cache.getOrCreateMessageChannel)(options === null || options === void 0 ? void 0 : options.secretKey);
95
- this.dispatcher = new _message.MessageDispatcher(channel, _constants.MessageRole.SERVER, this.id);
96
- this.dispatcher.setAutoAckLimits({
97
- maxMetaLength: options === null || options === void 0 ? void 0 : options.autoAckMaxMetaLength,
98
- maxIdLength: options === null || options === void 0 ? void 0 : options.autoAckMaxIdLength
99
- });
100
-
101
- // Auto-open by default (unless explicitly set to false)
102
- if ((options === null || options === void 0 ? void 0 : options.autoOpen) !== false) {
103
- this.open();
104
- }
105
- }
106
-
107
- /**
108
- * Check whether an incoming message origin is allowed.
109
- */
110
- isOriginAllowed(data, context) {
111
- if (!this.originValidator) return true;
112
- try {
113
- return this.originValidator(context.origin, data, context);
114
- } catch (_unused) {
115
- return false;
116
- }
117
- }
118
-
119
- /**
120
- * Build a per-client key used for concurrency limiting.
121
- * We intentionally include origin to prevent cross-origin collisions.
122
- */
123
- getClientKey(origin, creatorId) {
124
- return `${origin}::${creatorId || 'unknown'}`;
125
- }
126
- incInFlight(clientKey) {
127
- var current = this.inFlightByClientKey.get(clientKey) || 0;
128
- this.inFlightByClientKey.set(clientKey, current + 1);
129
- }
130
- decInFlight(clientKey) {
131
- var current = this.inFlightByClientKey.get(clientKey) || 0;
132
- var next = current - 1;
133
- if (next <= 0) {
134
- this.inFlightByClientKey.delete(clientKey);
135
- return;
136
- }
137
- this.inFlightByClientKey.set(clientKey, next);
138
- }
139
-
140
- /**
141
- * Open message processing (register message handlers)
142
- */
143
- open() {
144
- if (this._isOpen) return;
145
- this._isOpen = true;
146
- this.registerHandlers();
147
- }
148
-
149
- /**
150
- * Close message processing (unregister message handlers, but don't release channel)
151
- */
152
- close() {
153
- if (!this._isOpen) return;
154
- this._isOpen = false;
155
-
156
- // Unregister all handlers
157
- this.unregisterFns.forEach(fn => fn());
158
- this.unregisterFns.length = 0;
159
- }
160
-
161
- /**
162
- * Whether it is open
163
- */
164
- get isOpen() {
165
- return this._isOpen;
166
- }
167
-
168
- /**
169
- * Register message handlers
170
- */
171
- registerHandlers() {
172
- var handlerOptions = {
173
- versionValidator: this.versionValidator,
174
- onVersionError: this.handleVersionError.bind(this)
175
- };
176
-
177
- // Handle REQUEST messages
178
- this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.REQUEST, (data, context) => this.handleRequest(data, context), handlerOptions));
179
-
180
- // Handle PING messages
181
- this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.PING, (data, context) => this.handlePing(data, context), handlerOptions));
182
-
183
- // Handle PONG messages (server -> client heartbeat)
184
- this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.PONG, (data, context) => this.handlePong(data, context), handlerOptions));
185
-
186
- // Handle ACK messages (for confirming response delivery when requireAck === true)
187
- this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.ACK, (data, context) => this.handleAck(data, context), handlerOptions));
188
-
189
- // Handle stream_* messages (client→server stream)
190
- this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.STREAM_START, (data, ctx) => this.handleStreamStart(data, ctx), handlerOptions));
191
- this.unregisterFns.push(this.dispatcher.registerHandler(type => type.startsWith('stream_') && type !== _constants.MessageType.STREAM_START, (data, context) => this.dispatchStreamMessage(data, context), handlerOptions));
192
- }
193
-
194
- /** Handle stream_start from client (stream request with streamId) */
195
- handleStreamStart(data, context) {
196
- var _body$chunked;
197
- if (data.role !== _constants.MessageRole.CLIENT) return;
198
- if (!this.isOriginAllowed(data, context)) return;
199
- var body = data.body;
200
- if (!(body !== null && body !== void 0 && body.streamId)) return;
201
- var pending = this.pendingStreamRequests.get(data.requestId);
202
- if (!pending || pending.streamId !== body.streamId) return;
203
- clearTimeout(pending.timeoutId);
204
- this.pendingStreamRequests.delete(data.requestId);
205
- var targetWindow = pending.targetWindow,
206
- targetOrigin = pending.targetOrigin,
207
- res = pending.res,
208
- reqData = pending.data,
209
- reqContext = pending.context,
210
- handlerFn = pending.handlerFn;
211
- var streamHandler = {
212
- registerStreamHandler: (streamId, handler) => {
213
- this.streamHandlers.set(streamId, handler);
214
- },
215
- unregisterStreamHandler: streamId => {
216
- this.streamHandlers.delete(streamId);
217
- },
218
- postMessage: message => {
219
- this.dispatcher.send(targetWindow, message, targetOrigin);
220
- }
221
- };
222
- var streamType = body.type || _constants.StreamType.DATA;
223
- var streamMode = body.mode;
224
- var streamChunked = (_body$chunked = body.chunked) !== null && _body$chunked !== void 0 ? _body$chunked : true;
225
- var streamMetadata = body.metadata;
226
- var req = new _request.ServerRequestImpl(reqData, reqContext, res, pending.params);
227
-
228
- // File stream: optionally auto-resolve to File/Blob before calling handler
229
- if (streamType === _constants.StreamType.FILE) {
230
- var _body$autoResolve;
231
- var fileStream = new _stream.IframeFileReadableStream(body.streamId, data.requestId, streamHandler, {
232
- chunked: streamChunked,
233
- metadata: streamMetadata,
234
- secretKey: data.secretKey,
235
- mode: streamMode,
236
- filename: streamMetadata === null || streamMetadata === void 0 ? void 0 : streamMetadata.filename,
237
- mimeType: streamMetadata === null || streamMetadata === void 0 ? void 0 : streamMetadata.mimeType,
238
- size: streamMetadata === null || streamMetadata === void 0 ? void 0 : streamMetadata.size
239
- });
240
- var autoResolve = (_body$autoResolve = body.autoResolve) !== null && _body$autoResolve !== void 0 ? _body$autoResolve : false;
241
- if (autoResolve) {
242
- var name = fileStream.filename || (streamMetadata === null || streamMetadata === void 0 ? void 0 : streamMetadata.filename);
243
- var promise = name ? fileStream.readAsFile(name) : fileStream.readAsBlob();
244
- promise.then(fileData => {
245
- req.body = fileData;
246
- req.stream = undefined;
247
- this.runMiddlewares(req, res, () => {
248
- try {
249
- var result = handlerFn(req, res);
250
- if ((0, _utils.isPromise)(result)) {
251
- // Window check is handled in MessageDispatcher
252
- this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ASYNC, data.requestId, {
253
- path: reqData.path,
254
- targetId: data.creatorId
255
- });
256
- result.then(this.handleRequestResult.bind(this, res, targetWindow, targetOrigin, reqData)).catch(this.handleRequestError.bind(this, res, targetWindow, targetOrigin, reqData));
257
- } else {
258
- this.handleRequestResult(res, targetWindow, targetOrigin, reqData, result);
259
- }
260
- } catch (error) {
261
- this.handleRequestError(res, targetWindow, targetOrigin, reqData, error);
262
- }
263
- });
264
- }).catch(error => {
265
- this.handleRequestError(res, targetWindow, targetOrigin, reqData, error);
266
- });
267
- return;
268
- }
269
-
270
- // Non-autoResolve: expose stream directly
271
- req.body = fileStream;
272
- req.stream = fileStream;
273
- } else {
274
- // Non-file stream
275
- var readableStream = new _stream.IframeReadableStream(body.streamId, data.requestId, streamHandler, {
276
- type: streamType,
277
- mode: streamMode,
278
- chunked: streamChunked,
279
- metadata: streamMetadata,
280
- secretKey: data.secretKey
281
- });
282
- req.body = undefined;
283
- req.stream = readableStream;
284
- }
285
- this.runMiddlewares(req, res, () => {
286
- try {
287
- var result = handlerFn(req, res);
288
- if ((0, _utils.isPromise)(result)) {
289
- // Window check is handled in MessageDispatcher
290
- this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ASYNC, data.requestId, {
291
- path: reqData.path,
292
- targetId: data.creatorId
293
- });
294
- result.then(this.handleRequestResult.bind(this, res, targetWindow, targetOrigin, reqData)).catch(this.handleRequestError.bind(this, res, targetWindow, targetOrigin, reqData));
295
- } else {
296
- this.handleRequestResult(res, targetWindow, targetOrigin, reqData, result);
297
- }
298
- } catch (error) {
299
- this.handleRequestError(res, targetWindow, targetOrigin, reqData, error);
300
- }
301
- });
302
- }
303
- dispatchStreamMessage(data, context) {
304
- if (!this.isOriginAllowed(data, context)) return;
305
- var body = data.body;
306
- if (!(body !== null && body !== void 0 && body.streamId)) return;
307
- var handler = this.streamHandlers.get(body.streamId);
308
- if (handler) {
309
- // Mark as accepted/handled so MessageDispatcher can auto-ack when requireAck === true
310
- if (!context.handledBy) {
311
- context.accepted = true;
312
- context.handledBy = this.id;
313
- }
314
- var messageType = data.type.replace('stream_', '');
315
- handler(_objectSpread(_objectSpread({}, body), {}, {
316
- type: messageType
317
- }));
318
- }
319
- }
320
-
321
- /**
322
- * Handle protocol version error
323
- */
324
- handleVersionError(data, context, version) {
325
- if (!context.source) return;
326
-
327
- // Send protocol version incompatibility error
328
- // Window check is handled in MessageDispatcher
329
- this.dispatcher.sendMessage(context.source, context.origin, _constants.MessageType.ERROR, data.requestId, {
330
- path: data.path,
331
- status: _constants.HttpStatus.BAD_REQUEST,
332
- statusText: _constants.Messages.PROTOCOL_VERSION_UNSUPPORTED,
333
- error: {
334
- message: (0, _constants.formatMessage)(_constants.Messages.PROTOCOL_VERSION_TOO_LOW, version, _constants.ProtocolVersion.MIN_SUPPORTED),
335
- code: _constants.ErrorCode.PROTOCOL_UNSUPPORTED
336
- }
337
- });
338
- }
339
-
340
- /**
341
- * Handle ping message
342
- */
343
- handlePing(data, context) {
344
- if (!context.source) return;
345
- if (!this.isOriginAllowed(data, context)) return;
346
-
347
- /**
348
- * Only allow one server instance to respond.
349
- * This is important when multiple server instances share the same channel.
350
- */
351
- if (!context.handledBy) {
352
- // Mark as accepted so MessageDispatcher can auto-send ACK when requireAck === true
353
- context.accepted = true;
354
- context.handledBy = this.id;
355
- }
356
-
357
- // Window check is handled in MessageDispatcher
358
- this.dispatcher.sendMessage(context.source, context.origin, _constants.MessageType.PONG, data.requestId);
359
- }
360
- handlePong(data, context) {
361
- if (!this.isOriginAllowed(data, context)) return;
362
- var pending = this.pendingPongs.get(data.requestId);
363
- if (pending) {
364
- if (!context.handledBy) {
365
- context.accepted = true;
366
- context.handledBy = this.id;
367
- }
368
- clearTimeout(pending.timeoutId);
369
- this.pendingPongs.delete(data.requestId);
370
- pending.resolve(true);
371
- }
372
- }
373
- pingClient(targetWindow, targetOrigin, targetClientId) {
374
- var requestId = (0, _utils.generateRequestId)();
375
- return new Promise(resolve => {
376
- var timeoutId = setTimeout(() => {
377
- this.pendingPongs.delete(requestId);
378
- resolve(false);
379
- }, this.ackTimeout);
380
- this.pendingPongs.set(requestId, {
381
- resolve,
382
- timeoutId
383
- });
384
- // Window check is handled in MessageDispatcher
385
- this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.PING, requestId, {
386
- requireAck: true,
387
- targetId: targetClientId
388
- });
389
- });
390
- }
391
-
392
- /**
393
- * Handle ACK (receipt confirmation for responses when requireAck === true).
394
- */
395
- handleAck(data, context) {
396
- if (!this.isOriginAllowed(data, context)) return;
397
- var pending = this.pendingAcks.get(data.requestId);
398
- if (pending) {
399
- // Best-effort: prevent other server instances from also resolving
400
- if (!context.handledBy) {
401
- context.handledBy = this.id;
402
- }
403
- clearTimeout(pending.timeoutId);
404
- this.pendingAcks.delete(data.requestId);
405
- pending.resolve(true, data.ack);
406
- }
407
- }
408
-
409
- /** Get secretKey */
410
- get secretKey() {
411
- return this.dispatcher.secretKey;
412
- }
413
-
414
- /** Get the underlying MessageDispatcher */
415
- get messageDispatcher() {
416
- return this.dispatcher;
417
- }
418
- handleRequestError(res, targetWindow, targetOrigin, data, err) {
419
- if (!res._sent) {
420
- res._markSent();
421
- /**
422
- * Use INTERNAL_SERVER_ERROR (500) for handler errors unless a different error status code was explicitly set.
423
- * If statusCode is still the default OK (200), override it to INTERNAL_SERVER_ERROR.
424
- */
425
- var errorStatus = res.statusCode === _constants.HttpStatus.OK ? _constants.HttpStatus.INTERNAL_SERVER_ERROR : res.statusCode;
426
-
427
- // Window check is handled in MessageDispatcher
428
- this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ERROR, data.requestId, {
429
- path: data.path,
430
- error: {
431
- message: err && err.message || _constants.Messages.REQUEST_FAILED,
432
- code: err && err.code || _constants.ErrorCode.REQUEST_ERROR
433
- },
434
- status: errorStatus,
435
- statusText: _constants.HttpStatusText[errorStatus] || _constants.HttpStatusText[_constants.HttpStatus.INTERNAL_SERVER_ERROR],
436
- headers: res.headers,
437
- targetId: data.creatorId
438
- });
439
- }
440
- }
441
- handleRequestResult(res, targetWindow, targetOrigin, data, result) {
442
- if (!res._sent && result !== undefined) {
443
- res.send(result);
444
- } else if (!res._sent) {
445
- res._markSent();
446
- this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ERROR, data.requestId, {
447
- path: data.path,
448
- error: {
449
- message: _constants.Messages.NO_RESPONSE_SENT,
450
- code: _constants.ErrorCode.NO_RESPONSE
451
- },
452
- status: _constants.HttpStatus.INTERNAL_SERVER_ERROR,
453
- statusText: _constants.HttpStatusText[_constants.HttpStatus.INTERNAL_SERVER_ERROR],
454
- headers: res.headers
455
- });
456
- }
457
- }
458
-
459
- /**
460
- * Find matching handler and extract path parameters
461
- * @param requestPath The actual request path
462
- * @returns Handler function and extracted parameters, or null if not found
463
- */
464
- findHandler(requestPath) {
465
- var prefixedRequestPath = this.dispatcher.prefixPath(requestPath);
466
-
467
- // First try exact match (for backward compatibility and performance)
468
- var exactHandler = this.handlers.get(prefixedRequestPath);
469
- if (exactHandler) {
470
- return {
471
- handler: exactHandler,
472
- params: {}
473
- };
474
- }
475
-
476
- // Then try parameter matching (e.g., '/api/users/:id' matches '/api/users/123')
477
- var _iterator = _createForOfIteratorHelper(this.handlers.entries()),
478
- _step;
479
- try {
480
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
481
- var _step$value = (0, _slicedToArray2.default)(_step.value, 2),
482
- registeredPath = _step$value[0],
483
- handler = _step$value[1];
484
- // Check if registered path contains parameters
485
- if (registeredPath.includes(':')) {
486
- var matchResult = (0, _pathMatch.matchPathWithParams)(prefixedRequestPath, registeredPath);
487
- if (matchResult.match) {
488
- return {
489
- handler,
490
- params: matchResult.params
491
- };
492
- }
493
- }
494
- }
495
- } catch (err) {
496
- _iterator.e(err);
497
- } finally {
498
- _iterator.f();
499
- }
500
- return null;
501
- }
502
-
503
- /**
504
- * Handle request
505
- */
506
- handleRequest(data, context) {
507
- // If targetId is specified, only process if it matches this server's id
508
- if (!data.path || data.targetId && data.targetId !== this.id) return;
509
- if (!context.source) return;
510
- if (!this.isOriginAllowed(data, context)) return;
511
-
512
- // If message has already been handled by another server instance, skip processing
513
- if (context.handledBy) {
514
- return;
515
- }
516
- var targetWindow = context.source;
517
- var targetOrigin = context.origin;
518
-
519
- // Find matching handler and extract path parameters
520
- var handlerMatch = this.findHandler(data.path);
521
- if (!handlerMatch) {
522
- // No handler found in this instance
523
- // Mark as handled by this instance (using special marker) to prevent other instances from processing
524
- // This ensures only one instance sends the error response
525
- context.handledBy = this.id;
526
-
527
- // Send METHOD_NOT_FOUND error
528
- // Use request's creatorId as targetId to route back to the correct client
529
- // Window check is handled in MessageDispatcher
530
- this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ERROR, data.requestId, {
531
- path: data.path,
532
- error: {
533
- message: _constants.Messages.METHOD_NOT_FOUND,
534
- code: _constants.ErrorCode.METHOD_NOT_FOUND
535
- },
536
- status: _constants.HttpStatus.NOT_FOUND,
537
- statusText: _constants.HttpStatusText[_constants.HttpStatus.NOT_FOUND],
538
- targetId: data.creatorId
539
- });
540
- return;
541
- }
542
- var handlerFn = handlerMatch.handler,
543
- params = handlerMatch.params;
544
- var clientKey = this.getClientKey(targetOrigin, data.creatorId);
545
- if (Number.isFinite(this.maxConcurrentRequestsPerClient)) {
546
- var inFlight = this.inFlightByClientKey.get(clientKey) || 0;
547
- if (inFlight >= this.maxConcurrentRequestsPerClient) {
548
- // Prevent other server instances from also responding
549
- context.handledBy = this.id;
550
- this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ERROR, data.requestId, {
551
- path: data.path,
552
- error: {
553
- message: (0, _constants.formatMessage)(_constants.Messages.TOO_MANY_REQUESTS, this.maxConcurrentRequestsPerClient),
554
- code: _constants.ErrorCode.TOO_MANY_REQUESTS
555
- },
556
- status: _constants.HttpStatus.TOO_MANY_REQUESTS,
557
- statusText: _constants.HttpStatusText[_constants.HttpStatus.TOO_MANY_REQUESTS],
558
- requireAck: data.requireAck,
559
- ack: data.ack,
560
- targetId: data.creatorId
561
- });
562
- return;
563
- }
564
- }
565
- this.incInFlight(clientKey);
566
-
567
- // Mark as accepted so MessageDispatcher can auto-send ACK (delivery confirmation)
568
- context.accepted = true;
569
-
570
- // Mark message as handled by this server instance to prevent other server instances from processing it
571
- context.handledBy = this.id;
572
-
573
- // Create response object with channel reference
574
- // Pass request's creatorId as targetId so responses are routed back to the correct client
575
- var res = new _response.ServerResponseImpl(data.requestId, data.path || '', data.secretKey, targetWindow, targetOrigin, this.dispatcher.getChannel(), this.id, data.creatorId, {
576
- registerStreamHandler: (streamId, handler) => {
577
- this.streamHandlers.set(streamId, handler);
578
- },
579
- unregisterStreamHandler: streamId => {
580
- this.streamHandlers.delete(streamId);
581
- },
582
- heartbeat: () => this.pingClient(targetWindow, targetOrigin, data.creatorId),
583
- onSent: () => this.decInFlight(clientKey)
584
- });
585
-
586
- // Register callback waiting for client acknowledgment
587
- this.registerPendingAck(data.requestId, (received, ack) => {
588
- res._triggerAck(received, ack);
589
- }, () => {
590
- res._triggerAck(false);
591
- });
592
-
593
- // Client sends body as stream: wait for stream_start, then create readable stream and call handler
594
- // If streamId is present, this is a stream request
595
- var streamId = data.streamId;
596
- if (streamId) {
597
- var streamStartTimeout = this.ackTimeout;
598
- var timeoutId = setTimeout(() => {
599
- var pending = this.pendingStreamRequests.get(data.requestId);
600
- if (!pending) return;
601
- this.pendingStreamRequests.delete(data.requestId);
602
- if (!pending.res._sent) {
603
- pending.res._markSent();
604
- this.dispatcher.sendMessage(pending.targetWindow, pending.targetOrigin, _constants.MessageType.ERROR, pending.requestId, {
605
- path: pending.path,
606
- error: {
607
- message: (0, _constants.formatMessage)(_constants.Messages.STREAM_START_TIMEOUT, streamStartTimeout),
608
- code: _constants.ErrorCode.STREAM_START_TIMEOUT
609
- },
610
- status: _constants.HttpStatus.REQUEST_TIMEOUT,
611
- statusText: _constants.HttpStatusText[_constants.HttpStatus.REQUEST_TIMEOUT],
612
- requireAck: pending.data.requireAck,
613
- ack: pending.data.ack,
614
- targetId: pending.data.creatorId
615
- });
616
- }
617
- }, streamStartTimeout);
618
- this.pendingStreamRequests.set(data.requestId, {
619
- path: data.path || '',
620
- requestId: data.requestId,
621
- streamId,
622
- timeoutId,
623
- handlerFn,
624
- targetWindow,
625
- targetOrigin,
626
- res,
627
- data,
628
- context,
629
- params
630
- });
631
- return;
632
- }
633
-
634
- // Create request object with path parameters
635
- var req = new _request.ServerRequestImpl(data, context, res, params);
636
-
637
- // Execute middleware chain
638
- this.runMiddlewares(req, res, () => {
639
- try {
640
- var result = handlerFn(req, res);
641
- if ((0, _utils.isPromise)(result)) {
642
- // Async task
643
- // Window check is handled in MessageDispatcher
644
- // Use request's creatorId as targetId to route back to the correct client
645
- this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ASYNC, data.requestId, {
646
- path: data.path,
647
- targetId: data.creatorId
648
- });
649
- result.then(this.handleRequestResult.bind(this, res, targetWindow, targetOrigin, data)).catch(this.handleRequestError.bind(this, res, targetWindow, targetOrigin, data));
650
- } else {
651
- // Synchronous processing
652
- this.handleRequestResult(res, targetWindow, targetOrigin, data, result);
653
- }
654
- } catch (error) {
655
- this.handleRequestError(res, targetWindow, targetOrigin, data, error);
656
- }
657
- });
658
- }
659
-
660
- /**
661
- * Register pending acknowledgment response
662
- */
663
- registerPendingAck(requestId, resolve, reject) {
664
- var timeoutId = setTimeout(() => {
665
- this.pendingAcks.delete(requestId);
666
- resolve(false);
667
- }, this.ackTimeout);
668
- this.pendingAcks.set(requestId, {
669
- resolve,
670
- reject,
671
- timeoutId
672
- });
673
- }
674
- use(pathOrMiddleware, middleware) {
675
- if (typeof pathOrMiddleware === 'function') {
676
- this.middlewares.push({
677
- matcher: null,
678
- middleware: pathOrMiddleware
679
- });
680
- } else if (middleware) {
681
- this.middlewares.push({
682
- matcher: pathOrMiddleware,
683
- middleware
684
- });
685
- }
686
- }
687
- on(path, handler) {
688
- var prefixedPath = this.dispatcher.prefixPath(path);
689
- this.handlers.set(prefixedPath, handler);
690
-
691
- // Return unregister function
692
- return () => {
693
- this.handlers.delete(prefixedPath);
694
- };
695
- }
696
- runMiddlewares(req, res, finalHandler) {
697
- var path = req.path;
698
- var index = 0;
699
- var next = () => {
700
- if (res._sent) {
701
- return;
702
- }
703
- while (index < this.middlewares.length) {
704
- var item = this.middlewares[index++];
705
- if (item.matcher === null || (0, _pathMatch.matchPath)(path, item.matcher)) {
706
- try {
707
- var result = item.middleware(req, res, next);
708
- if (result instanceof Promise) {
709
- result.catch(err => {
710
- if (!res._sent) {
711
- res.status(_constants.HttpStatus.INTERNAL_SERVER_ERROR).send({
712
- error: err.message || _constants.Messages.MIDDLEWARE_ERROR
713
- });
714
- }
715
- });
716
- }
717
- return;
718
- } catch (err) {
719
- if (!res._sent) {
720
- res.status(_constants.HttpStatus.INTERNAL_SERVER_ERROR).send({
721
- error: (err === null || err === void 0 ? void 0 : err.message) || _constants.Messages.MIDDLEWARE_ERROR
722
- });
723
- }
724
- return;
725
- }
726
- }
727
- }
728
- if (index >= this.middlewares.length) {
729
- finalHandler();
730
- }
731
- };
732
- next();
733
- }
734
- off(path) {
735
- if (Array.isArray(path)) {
736
- // Batch unregister
737
- path.forEach(p => {
738
- this.handlers.delete(this.dispatcher.prefixPath(p));
739
- });
740
- } else {
741
- // Single unregister
742
- this.handlers.delete(this.dispatcher.prefixPath(path));
743
- }
744
- }
745
- map(handlers) {
746
- var unregisterFns = [];
747
- Object.entries(handlers).forEach(([path, h]) => {
748
- unregisterFns.push(this.on(path, h));
749
- });
750
- return () => {
751
- unregisterFns.forEach(fn => fn());
752
- };
753
- }
754
-
755
- /**
756
- * Destroy (close and release channel reference)
757
- */
758
- destroy() {
759
- // Close first
760
- this.close();
761
-
762
- // Clean up pending
763
- this.pendingAcks.forEach(pending => clearTimeout(pending.timeoutId));
764
- this.pendingAcks.clear();
765
- this.pendingPongs.forEach(pending => clearTimeout(pending.timeoutId));
766
- this.pendingPongs.clear();
767
- this.pendingStreamRequests.forEach(pending => clearTimeout(pending.timeoutId));
768
- this.pendingStreamRequests.clear();
769
- this.inFlightByClientKey.clear();
770
-
771
- // Clean up handlers
772
- this.handlers.clear();
773
- this.middlewares.length = 0;
774
- this.streamHandlers.clear();
775
-
776
- // Destroy dispatcher and release channel reference
777
- this.dispatcher.destroy();
778
- (0, _cache.releaseMessageChannel)(this.dispatcher.getChannel());
779
- }
780
- }
781
- exports.RequestIframeServerImpl = RequestIframeServerImpl;