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,575 @@
1
+ "use strict";
2
+
3
+ require("core-js/modules/es.symbol.description.js");
4
+ require("core-js/modules/es.array.from.js");
5
+ require("core-js/modules/es.array.slice.js");
6
+ require("core-js/modules/es.regexp.to-string.js");
7
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
8
+ Object.defineProperty(exports, "__esModule", {
9
+ value: true
10
+ });
11
+ exports.RequestIframeServerImpl = void 0;
12
+ require("core-js/modules/es.array.includes.js");
13
+ require("core-js/modules/es.array.iterator.js");
14
+ require("core-js/modules/es.map.js");
15
+ require("core-js/modules/es.object.entries.js");
16
+ require("core-js/modules/es.promise.js");
17
+ require("core-js/modules/es.regexp.exec.js");
18
+ require("core-js/modules/es.string.includes.js");
19
+ require("core-js/modules/es.string.match.js");
20
+ require("core-js/modules/web.dom-collections.for-each.js");
21
+ require("core-js/modules/web.dom-collections.iterator.js");
22
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
23
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
24
+ var _pathMatch = require("../utils/path-match");
25
+ var _request = require("./request");
26
+ var _response = require("./response");
27
+ var _id = require("../utils/id");
28
+ var _endpoint = require("../endpoint");
29
+ var _constants = require("../constants");
30
+ var _promise = require("../utils/promise");
31
+ var _is = require("../utils/is");
32
+ var _logger = require("../utils/logger");
33
+ 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; } } }; }
34
+ 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; } }
35
+ 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; }
36
+ /**
37
+ * Middleware item (contains path matcher and middleware function)
38
+ */
39
+
40
+ /**
41
+ * Server configuration options
42
+ */
43
+
44
+ /**
45
+ * RequestIframeServer implementation
46
+ * Uses shared MessageDispatcher (backed by MessageChannel) to listen for and send messages
47
+ */
48
+ class RequestIframeServerImpl {
49
+ constructor(options) {
50
+ var _options$ackTimeout, _options$maxConcurren;
51
+ (0, _defineProperty2.default)(this, "handlers", new Map());
52
+ (0, _defineProperty2.default)(this, "middlewares", []);
53
+ /** Use custom id if provided, otherwise generate one */
54
+ this.id = (options === null || options === void 0 ? void 0 : options.id) || (0, _id.generateInstanceId)();
55
+ var endpoint = new _endpoint.RequestIframeEndpointFacade({
56
+ role: _constants.MessageRole.SERVER,
57
+ instanceId: this.id,
58
+ secretKey: options === null || options === void 0 ? void 0 : options.secretKey,
59
+ versionValidator: options === null || options === void 0 ? void 0 : options.versionValidator,
60
+ autoAckMaxMetaLength: options === null || options === void 0 ? void 0 : options.autoAckMaxMetaLength,
61
+ autoAckMaxIdLength: options === null || options === void 0 ? void 0 : options.autoAckMaxIdLength,
62
+ streamDispatcher: {
63
+ handledBy: this.id
64
+ },
65
+ heartbeat: {
66
+ pendingBucket: RequestIframeServerImpl.PENDING_PONGS,
67
+ handledBy: this.id,
68
+ isOriginAllowed: (d, ctx) => this.isOriginAllowed(d, ctx),
69
+ warnMissingPendingWhenClosed: d => {
70
+ this.hub.warnOnce((0, _constants.buildWarnOnceKey)(_constants.WarnOnceKey.SERVER_MISSING_PENDING_WHEN_CLOSED, d.type, d.requestId), () => {
71
+ (0, _logger.requestIframeLog)('warn', (0, _constants.formatMessage)(_constants.Messages.SERVER_IGNORED_MESSAGE_WHEN_CLOSED, d.type, d.requestId));
72
+ });
73
+ }
74
+ },
75
+ originValidator: {
76
+ allowedOrigins: options === null || options === void 0 ? void 0 : options.allowedOrigins,
77
+ validateOrigin: options === null || options === void 0 ? void 0 : options.validateOrigin
78
+ }
79
+ });
80
+ this.endpoint = endpoint;
81
+ this.hub = endpoint.hub;
82
+ this.originValidator = endpoint.originValidator;
83
+ this.ackTimeout = (_options$ackTimeout = options === null || options === void 0 ? void 0 : options.ackTimeout) !== null && _options$ackTimeout !== void 0 ? _options$ackTimeout : _constants.DefaultTimeout.ACK;
84
+ this.maxConcurrentRequestsPerClient = (_options$maxConcurren = options === null || options === void 0 ? void 0 : options.maxConcurrentRequestsPerClient) !== null && _options$maxConcurren !== void 0 ? _options$maxConcurren : Number.POSITIVE_INFINITY;
85
+ var warnMissingPendingWhenClosed = d => {
86
+ this.hub.warnOnce((0, _constants.buildWarnOnceKey)(_constants.WarnOnceKey.SERVER_MISSING_PENDING_WHEN_CLOSED, d.type, d.requestId), () => {
87
+ (0, _logger.requestIframeLog)('warn', (0, _constants.formatMessage)(_constants.Messages.SERVER_IGNORED_MESSAGE_WHEN_CLOSED, d.type, d.requestId));
88
+ });
89
+ };
90
+ var handlerOptions = this.hub.createHandlerOptions(this.handleVersionError.bind(this));
91
+
92
+ // Server business entry: REQUEST handler
93
+ this.endpoint.onOpen(() => {
94
+ this.hub.registerHandler(_constants.MessageType.REQUEST, (data, context) => this.handleRequest(data, context), handlerOptions);
95
+ });
96
+
97
+ // Server base infra: ping/pong/ack/stream handlers (facade-managed)
98
+ this.endpoint.registerServerBaseHandlers({
99
+ handlerOptions,
100
+ handledBy: this.id,
101
+ includeTargetIdInPong: false,
102
+ isOriginAllowed: (d, ctx) => this.isOriginAllowed(d, ctx),
103
+ warnMissingPendingWhenClosed,
104
+ pendingAckBucket: RequestIframeServerImpl.PENDING_ACKS,
105
+ pendingStreamStartBucket: RequestIframeServerImpl.PENDING_STREAM_REQUESTS,
106
+ expectedStreamStartRole: _constants.MessageRole.CLIENT
107
+ });
108
+
109
+ /** Auto-open by default (unless explicitly set to false) */
110
+ if ((options === null || options === void 0 ? void 0 : options.autoOpen) !== false) {
111
+ this.open();
112
+ }
113
+ }
114
+ get dispatcher() {
115
+ return this.hub.messageDispatcher;
116
+ }
117
+
118
+ /** Message isolation key (read-only) */
119
+ get secretKey() {
120
+ return this.hub.secretKey;
121
+ }
122
+
123
+ /** Whether message handling is enabled */
124
+ get isOpen() {
125
+ return this.hub.isOpen;
126
+ }
127
+
128
+ /** Enable message handling (register message handler) */
129
+ open() {
130
+ this.hub.open();
131
+ }
132
+
133
+ /** Disable message handling (unregister message handler, but don't release resources) */
134
+ close() {
135
+ this.hub.close();
136
+ }
137
+
138
+ /** Get the underlying MessageDispatcher */
139
+ get messageDispatcher() {
140
+ return this.hub.messageDispatcher;
141
+ }
142
+
143
+ /**
144
+ * Check whether an incoming message origin is allowed.
145
+ */
146
+ isOriginAllowed(data, context) {
147
+ if (!this.originValidator) return true;
148
+ try {
149
+ return this.originValidator(context.origin, data, context);
150
+ } catch (_unused) {
151
+ return false;
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Build a per-client key used for concurrency limiting.
157
+ * We intentionally include origin to prevent cross-origin collisions.
158
+ */
159
+ getClientKey(origin, creatorId) {
160
+ return `${origin}::${creatorId || 'unknown'}`;
161
+ }
162
+
163
+ /**
164
+ * Handle protocol version error
165
+ */
166
+ handleVersionError(data, context, version) {
167
+ if (!context.source) return;
168
+
169
+ // Send protocol version incompatibility error
170
+ // Window check is handled in MessageDispatcher
171
+ this.dispatcher.sendMessage(context.source, context.origin, _constants.MessageType.ERROR, data.requestId, {
172
+ path: data.path,
173
+ status: _constants.HttpStatus.BAD_REQUEST,
174
+ statusText: _constants.Messages.PROTOCOL_VERSION_UNSUPPORTED,
175
+ error: {
176
+ message: (0, _constants.formatMessage)(_constants.Messages.PROTOCOL_VERSION_TOO_LOW, version, _constants.ProtocolVersion.MIN_SUPPORTED),
177
+ code: _constants.ErrorCode.PROTOCOL_UNSUPPORTED
178
+ }
179
+ });
180
+ }
181
+ handleRequestError(res, targetWindow, targetOrigin, data, err) {
182
+ if (!res._sent) {
183
+ res._markSent();
184
+ /**
185
+ * Use INTERNAL_SERVER_ERROR (500) for handler errors unless a different error status code was explicitly set.
186
+ * If statusCode is still the default OK (200), override it to INTERNAL_SERVER_ERROR.
187
+ */
188
+ var errorStatus = res.statusCode === _constants.HttpStatus.OK ? _constants.HttpStatus.INTERNAL_SERVER_ERROR : res.statusCode;
189
+
190
+ // Window check is handled in MessageDispatcher
191
+ this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ERROR, data.requestId, {
192
+ path: data.path,
193
+ error: {
194
+ message: err && err.message || _constants.Messages.REQUEST_FAILED,
195
+ code: err && err.code || _constants.ErrorCode.REQUEST_ERROR
196
+ },
197
+ status: errorStatus,
198
+ statusText: _constants.HttpStatusText[errorStatus] || _constants.HttpStatusText[_constants.HttpStatus.INTERNAL_SERVER_ERROR],
199
+ headers: res.headers,
200
+ targetId: data.creatorId
201
+ });
202
+ }
203
+ }
204
+ handleRequestResult(res, targetWindow, targetOrigin, data, result) {
205
+ if (!res._sent && result !== undefined) {
206
+ res.send(result);
207
+ } else if (!res._sent) {
208
+ res._markSent();
209
+ this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ERROR, data.requestId, {
210
+ path: data.path,
211
+ error: {
212
+ message: _constants.Messages.NO_RESPONSE_SENT,
213
+ code: _constants.ErrorCode.NO_RESPONSE
214
+ },
215
+ status: _constants.HttpStatus.INTERNAL_SERVER_ERROR,
216
+ statusText: _constants.HttpStatusText[_constants.HttpStatus.INTERNAL_SERVER_ERROR],
217
+ headers: res.headers
218
+ });
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Find matching handler and extract path parameters
224
+ * @param requestPath The actual request path
225
+ * @returns Handler function and extracted parameters, or null if not found
226
+ */
227
+ findHandler(requestPath) {
228
+ var prefixedRequestPath = this.dispatcher.prefixPath(requestPath);
229
+
230
+ // First try exact match (for backward compatibility and performance)
231
+ var exactHandler = this.handlers.get(prefixedRequestPath);
232
+ if (exactHandler) {
233
+ return {
234
+ handler: exactHandler,
235
+ params: {}
236
+ };
237
+ }
238
+
239
+ // Then try parameter matching (e.g., '/api/users/:id' matches '/api/users/123')
240
+ var _iterator = _createForOfIteratorHelper(this.handlers.entries()),
241
+ _step;
242
+ try {
243
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
244
+ var _step$value = (0, _slicedToArray2.default)(_step.value, 2),
245
+ registeredPath = _step$value[0],
246
+ handler = _step$value[1];
247
+ // Check if registered path contains parameters
248
+ if (registeredPath.includes(':')) {
249
+ var matchResult = (0, _pathMatch.matchPathWithParams)(prefixedRequestPath, registeredPath);
250
+ if (matchResult.match) {
251
+ return {
252
+ handler,
253
+ params: matchResult.params
254
+ };
255
+ }
256
+ }
257
+ }
258
+ } catch (err) {
259
+ _iterator.e(err);
260
+ } finally {
261
+ _iterator.f();
262
+ }
263
+ return null;
264
+ }
265
+
266
+ /**
267
+ * Handle request
268
+ */
269
+ handleRequest(data, context) {
270
+ // If targetId is specified, only process if it matches this server's id
271
+ if (!data.path || data.targetId && data.targetId !== this.id) return;
272
+ if (!context.source) return;
273
+ if (!this.isOriginAllowed(data, context)) return;
274
+
275
+ // If message has already been handled by another server instance, skip processing
276
+ if (context.handledBy) {
277
+ return;
278
+ }
279
+ var targetWindow = context.source;
280
+ var targetOrigin = context.origin;
281
+
282
+ // Find matching handler and extract path parameters
283
+ var handlerMatch = this.findHandler(data.path);
284
+ if (!handlerMatch) {
285
+ // No handler found in this instance
286
+ // Mark as handled by this instance (using special marker) to prevent other instances from processing
287
+ // This ensures only one instance sends the error response
288
+ context.markHandledBy(this.id);
289
+
290
+ // Send METHOD_NOT_FOUND error
291
+ // Use request's creatorId as targetId to route back to the correct client
292
+ // Window check is handled in MessageDispatcher
293
+ this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ERROR, data.requestId, {
294
+ path: data.path,
295
+ error: {
296
+ message: _constants.Messages.METHOD_NOT_FOUND,
297
+ code: _constants.ErrorCode.METHOD_NOT_FOUND
298
+ },
299
+ status: _constants.HttpStatus.NOT_FOUND,
300
+ statusText: _constants.HttpStatusText[_constants.HttpStatus.NOT_FOUND],
301
+ targetId: data.creatorId
302
+ });
303
+ return;
304
+ }
305
+ var handlerFn = handlerMatch.handler,
306
+ params = handlerMatch.params;
307
+ var clientKey = this.getClientKey(targetOrigin, data.creatorId);
308
+ var acquired = this.hub.limiter.tryAcquire(RequestIframeServerImpl.LIMIT_IN_FLIGHT_BY_CLIENT, clientKey, this.maxConcurrentRequestsPerClient);
309
+ if (!acquired) {
310
+ // Prevent other server instances from also responding
311
+ context.markHandledBy(this.id);
312
+ this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ERROR, data.requestId, {
313
+ path: data.path,
314
+ error: {
315
+ message: (0, _constants.formatMessage)(_constants.Messages.TOO_MANY_REQUESTS, this.maxConcurrentRequestsPerClient),
316
+ code: _constants.ErrorCode.TOO_MANY_REQUESTS
317
+ },
318
+ status: _constants.HttpStatus.TOO_MANY_REQUESTS,
319
+ statusText: _constants.HttpStatusText[_constants.HttpStatus.TOO_MANY_REQUESTS],
320
+ requireAck: data.requireAck,
321
+ ack: data.ack,
322
+ targetId: data.creatorId
323
+ });
324
+ return;
325
+ }
326
+
327
+ // Mark as accepted so MessageDispatcher can auto-send ACK (delivery confirmation)
328
+ context.markAcceptedBy(this.id);
329
+
330
+ // Create response object with channel reference
331
+ // Pass request's creatorId as targetId so responses are routed back to the correct client
332
+ var peer = this.hub.createOutbox(targetWindow, targetOrigin, data.creatorId);
333
+ var res = new _response.ServerResponseImpl(data.requestId, data.path || '', this.id, peer, {
334
+ registerStreamHandler: (streamId, handler) => {
335
+ this.endpoint.streamDispatcher.register(streamId, handler);
336
+ },
337
+ unregisterStreamHandler: streamId => {
338
+ this.endpoint.streamDispatcher.unregister(streamId);
339
+ },
340
+ heartbeat: () => this.endpoint.pingPeer(targetWindow, targetOrigin, this.ackTimeout, data.creatorId),
341
+ onSent: () => this.hub.limiter.release(RequestIframeServerImpl.LIMIT_IN_FLIGHT_BY_CLIENT, clientKey)
342
+ });
343
+
344
+ // Register callback waiting for client acknowledgment
345
+ this.endpoint.registerPendingAck({
346
+ requestId: data.requestId,
347
+ timeoutMs: this.ackTimeout,
348
+ pendingBucket: RequestIframeServerImpl.PENDING_ACKS,
349
+ resolve: (received, ack) => {
350
+ res._triggerAck(received, ack);
351
+ }
352
+ });
353
+
354
+ // Client sends body as stream: wait for stream_start, then create readable stream and call handler
355
+ // If streamId is present, this is a stream request
356
+ var streamId = data.streamId;
357
+ if (streamId) {
358
+ var streamStartTimeout = this.ackTimeout;
359
+ this.endpoint.registerIncomingStreamStartWaiter({
360
+ pendingBucket: RequestIframeServerImpl.PENDING_STREAM_REQUESTS,
361
+ requestId: data.requestId,
362
+ streamId,
363
+ timeoutMs: streamStartTimeout,
364
+ targetWindow,
365
+ targetOrigin,
366
+ onTimeout: () => {
367
+ if (!res._sent) {
368
+ res._markSent();
369
+ this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ERROR, data.requestId, (0, _endpoint.buildStreamStartTimeoutErrorPayload)({
370
+ path: data.path || '',
371
+ timeoutMs: streamStartTimeout,
372
+ requireAck: data.requireAck,
373
+ ack: data.ack,
374
+ targetId: data.creatorId
375
+ }));
376
+ }
377
+ },
378
+ continue: ({
379
+ stream,
380
+ info,
381
+ data: streamStartData
382
+ }) => {
383
+ // Create request object with path parameters
384
+ var req = new _request.ServerRequestImpl(data, context, res, params);
385
+
386
+ // File stream: optionally auto-resolve to File/Blob before calling handler
387
+ if ((info === null || info === void 0 ? void 0 : info.type) === _constants.StreamType.FILE) {
388
+ var fileStream = stream;
389
+ if (info !== null && info !== void 0 && info.autoResolve) {
390
+ (0, _endpoint.autoResolveIframeFileReadableStream)({
391
+ fileStream,
392
+ info
393
+ }).then(fileData => {
394
+ req.body = fileData;
395
+ req.stream = undefined;
396
+ this.runMiddlewares(req, res, () => {
397
+ try {
398
+ var result = handlerFn(req, res);
399
+ if ((0, _promise.isPromise)(result)) {
400
+ this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ASYNC, streamStartData.requestId, {
401
+ path: data.path,
402
+ targetId: streamStartData.creatorId
403
+ });
404
+ result.then(this.handleRequestResult.bind(this, res, targetWindow, targetOrigin, data)).catch(this.handleRequestError.bind(this, res, targetWindow, targetOrigin, data));
405
+ } else {
406
+ this.handleRequestResult(res, targetWindow, targetOrigin, data, result);
407
+ }
408
+ } catch (error) {
409
+ this.handleRequestError(res, targetWindow, targetOrigin, data, error);
410
+ }
411
+ });
412
+ }).catch(error => {
413
+ this.handleRequestError(res, targetWindow, targetOrigin, data, error);
414
+ });
415
+ return;
416
+ }
417
+
418
+ // Non-autoResolve: expose stream directly
419
+ req.body = fileStream;
420
+ req.stream = fileStream;
421
+ } else {
422
+ // Non-file stream
423
+ req.body = undefined;
424
+ req.stream = stream;
425
+ }
426
+ this.runMiddlewares(req, res, () => {
427
+ try {
428
+ var result = handlerFn(req, res);
429
+ if ((0, _promise.isPromise)(result)) {
430
+ this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ASYNC, streamStartData.requestId, {
431
+ path: data.path,
432
+ targetId: streamStartData.creatorId
433
+ });
434
+ result.then(this.handleRequestResult.bind(this, res, targetWindow, targetOrigin, data)).catch(this.handleRequestError.bind(this, res, targetWindow, targetOrigin, data));
435
+ } else {
436
+ this.handleRequestResult(res, targetWindow, targetOrigin, data, result);
437
+ }
438
+ } catch (error) {
439
+ this.handleRequestError(res, targetWindow, targetOrigin, data, error);
440
+ }
441
+ });
442
+ }
443
+ });
444
+ return;
445
+ }
446
+
447
+ // Create request object with path parameters
448
+ var req = new _request.ServerRequestImpl(data, context, res, params);
449
+
450
+ // Execute middleware chain
451
+ this.runMiddlewares(req, res, () => {
452
+ try {
453
+ var result = handlerFn(req, res);
454
+ if ((0, _promise.isPromise)(result)) {
455
+ // Async task
456
+ // Window check is handled in MessageDispatcher
457
+ // Use request's creatorId as targetId to route back to the correct client
458
+ this.dispatcher.sendMessage(targetWindow, targetOrigin, _constants.MessageType.ASYNC, data.requestId, {
459
+ path: data.path,
460
+ targetId: data.creatorId
461
+ });
462
+ result.then(this.handleRequestResult.bind(this, res, targetWindow, targetOrigin, data)).catch(this.handleRequestError.bind(this, res, targetWindow, targetOrigin, data));
463
+ } else {
464
+ // Synchronous processing
465
+ this.handleRequestResult(res, targetWindow, targetOrigin, data, result);
466
+ }
467
+ } catch (error) {
468
+ this.handleRequestError(res, targetWindow, targetOrigin, data, error);
469
+ }
470
+ });
471
+ }
472
+ use(pathOrMiddleware, middleware) {
473
+ if ((0, _is.isFunction)(pathOrMiddleware)) {
474
+ this.middlewares.push({
475
+ matcher: null,
476
+ middleware: pathOrMiddleware
477
+ });
478
+ } else if (middleware) {
479
+ this.middlewares.push({
480
+ matcher: pathOrMiddleware,
481
+ middleware
482
+ });
483
+ }
484
+ }
485
+ on(path, handler) {
486
+ var prefixedPath = this.dispatcher.prefixPath(path);
487
+ this.handlers.set(prefixedPath, handler);
488
+
489
+ // Return unregister function
490
+ return () => {
491
+ this.handlers.delete(prefixedPath);
492
+ };
493
+ }
494
+ runMiddlewares(req, res, finalHandler) {
495
+ var path = req.path;
496
+ var index = 0;
497
+ var next = () => {
498
+ if (res._sent) {
499
+ return;
500
+ }
501
+ while (index < this.middlewares.length) {
502
+ var item = this.middlewares[index++];
503
+ if (item.matcher === null || (0, _pathMatch.matchPath)(path, item.matcher)) {
504
+ try {
505
+ var result = item.middleware(req, res, next);
506
+ if (result instanceof Promise) {
507
+ result.catch(err => {
508
+ if (!res._sent) {
509
+ res.status(_constants.HttpStatus.INTERNAL_SERVER_ERROR).send({
510
+ error: err.message || _constants.Messages.MIDDLEWARE_ERROR
511
+ });
512
+ }
513
+ });
514
+ }
515
+ return;
516
+ } catch (err) {
517
+ if (!res._sent) {
518
+ res.status(_constants.HttpStatus.INTERNAL_SERVER_ERROR).send({
519
+ error: (err === null || err === void 0 ? void 0 : err.message) || _constants.Messages.MIDDLEWARE_ERROR
520
+ });
521
+ }
522
+ return;
523
+ }
524
+ }
525
+ }
526
+ if (index >= this.middlewares.length) {
527
+ finalHandler();
528
+ }
529
+ };
530
+ next();
531
+ }
532
+ off(path) {
533
+ if (Array.isArray(path)) {
534
+ // Batch unregister
535
+ path.forEach(p => {
536
+ this.handlers.delete(this.dispatcher.prefixPath(p));
537
+ });
538
+ } else {
539
+ // Single unregister
540
+ this.handlers.delete(this.dispatcher.prefixPath(path));
541
+ }
542
+ }
543
+ map(handlers) {
544
+ var unregisterFns = [];
545
+ Object.entries(handlers).forEach(([path, h]) => {
546
+ unregisterFns.push(this.on(path, h));
547
+ });
548
+ return () => {
549
+ unregisterFns.forEach(fn => fn());
550
+ };
551
+ }
552
+
553
+ /**
554
+ * Cleanup before destroy
555
+ */
556
+ cleanup() {
557
+ // Clean up handlers
558
+ this.handlers.clear();
559
+ this.middlewares.length = 0;
560
+ this.endpoint.streamDispatcher.clear();
561
+ }
562
+
563
+ /**
564
+ * Destroy server (close and release resources)
565
+ */
566
+ destroy() {
567
+ this.cleanup();
568
+ this.hub.destroy();
569
+ }
570
+ }
571
+ exports.RequestIframeServerImpl = RequestIframeServerImpl;
572
+ (0, _defineProperty2.default)(RequestIframeServerImpl, "PENDING_ACKS", 'server:pendingAcks');
573
+ (0, _defineProperty2.default)(RequestIframeServerImpl, "PENDING_PONGS", 'server:pendingPongs');
574
+ (0, _defineProperty2.default)(RequestIframeServerImpl, "PENDING_STREAM_REQUESTS", 'server:pendingStreamRequests');
575
+ (0, _defineProperty2.default)(RequestIframeServerImpl, "LIMIT_IN_FLIGHT_BY_CLIENT", 'server:inFlightByClientKey');
@@ -1,15 +1,22 @@
1
1
  export { requestIframeClient, clearRequestIframeClientCache } from './api/client';
2
2
  export { requestIframeServer, clearRequestIframeServerCache } from './api/server';
3
- export { RequestIframeClientImpl } from './core/client';
4
- export { RequestIframeServerImpl } from './core/server';
5
- export { RequestIframeClientServer } from './core/client-server';
3
+ export { requestIframeEndpoint } from './api/endpoint';
4
+ export { RequestIframeClientImpl } from './impl/client';
5
+ export { RequestIframeServerImpl } from './impl/server';
6
6
  export { MessageChannel, ChannelType, MessageDispatcher } from './message';
7
7
  export type { MessageContext, MessageHandlerFn, MessageTypeMatcher, VersionValidator, HandlerOptions, ChannelType as ChannelTypeValue } from './message';
8
- export { getOrCreateMessageChannel, releaseMessageChannel, clearMessageChannelCache, } from './utils/cache';
9
- export { ServerRequestImpl } from './core/request';
10
- export { ServerResponseImpl } from './core/response';
8
+ export { getOrCreateMessageChannel, releaseMessageChannel, clearMessageChannelCache, } from './message/channel-cache';
9
+ export { ServerRequestImpl } from './impl/request';
10
+ export { ServerResponseImpl } from './impl/response';
11
11
  export { IframeWritableStream, IframeReadableStream, IframeFileWritableStream, IframeFileReadableStream, isIframeReadableStream, isIframeFileReadableStream, isIframeFileWritableStream, isIframeWritableStream } from './stream';
12
12
  export type { StreamType, StreamState, StreamChunk, WritableStreamOptions, ReadableStreamOptions, FileWritableStreamOptions, FileReadableStreamOptions, StreamBindContext, IIframeWritableStream, IIframeReadableStream, IIframeFileReadableStream, StreamMessageData } from './stream';
13
+ /**
14
+ * NOTE:
15
+ * Root entry re-exports are kept for convenience, but for better tree-shaking and clearer dependencies,
16
+ * prefer subpath imports:
17
+ * - `request-iframe/types`
18
+ * - `request-iframe/constants`
19
+ */
13
20
  export * from './types';
14
21
  export { detectContentType, blobToBase64, RequestIframeError } from './utils';
15
22
  export { InterceptorManager, RequestInterceptorManager, ResponseInterceptorManager } from './interceptors';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAC;AAElF,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAEjE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC3E,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,WAAW,IAAI,gBAAgB,EAChC,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,0BAA0B,EAC1B,0BAA0B,EAC1B,sBAAsB,EACvB,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,UAAU,EACV,WAAW,EACX,WAAW,EACX,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EACzB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAElB,cAAc,SAAS,CAAC;AACxB,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,EACnB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAE3G,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAExD,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC3E,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,WAAW,IAAI,gBAAgB,EAChC,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,0BAA0B,EAC1B,0BAA0B,EAC1B,sBAAsB,EACvB,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,UAAU,EACV,WAAW,EACX,WAAW,EACX,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EACzB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAElB;;;;;;GAMG;AACH,cAAc,SAAS,CAAC;AACxB,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,EACnB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAE3G,cAAc,aAAa,CAAC"}