request-iframe 0.0.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 (96) hide show
  1. package/QUICKSTART.CN.md +269 -0
  2. package/QUICKSTART.md +269 -0
  3. package/README.CN.md +1369 -0
  4. package/README.md +1016 -0
  5. package/library/__tests__/interceptors.test.ts +124 -0
  6. package/library/__tests__/requestIframe.test.ts +2216 -0
  7. package/library/__tests__/stream.test.ts +650 -0
  8. package/library/__tests__/utils.test.ts +433 -0
  9. package/library/api/client.d.ts +16 -0
  10. package/library/api/client.d.ts.map +1 -0
  11. package/library/api/client.js +72 -0
  12. package/library/api/server.d.ts +16 -0
  13. package/library/api/server.d.ts.map +1 -0
  14. package/library/api/server.js +44 -0
  15. package/library/constants/index.d.ts +209 -0
  16. package/library/constants/index.d.ts.map +1 -0
  17. package/library/constants/index.js +260 -0
  18. package/library/constants/messages.d.ts +80 -0
  19. package/library/constants/messages.d.ts.map +1 -0
  20. package/library/constants/messages.js +123 -0
  21. package/library/core/client.d.ts +99 -0
  22. package/library/core/client.d.ts.map +1 -0
  23. package/library/core/client.js +440 -0
  24. package/library/core/message-handler.d.ts +110 -0
  25. package/library/core/message-handler.d.ts.map +1 -0
  26. package/library/core/message-handler.js +320 -0
  27. package/library/core/request-response.d.ts +59 -0
  28. package/library/core/request-response.d.ts.map +1 -0
  29. package/library/core/request-response.js +337 -0
  30. package/library/core/request.d.ts +17 -0
  31. package/library/core/request.d.ts.map +1 -0
  32. package/library/core/request.js +34 -0
  33. package/library/core/response.d.ts +51 -0
  34. package/library/core/response.d.ts.map +1 -0
  35. package/library/core/response.js +323 -0
  36. package/library/core/server-base.d.ts +86 -0
  37. package/library/core/server-base.d.ts.map +1 -0
  38. package/library/core/server-base.js +257 -0
  39. package/library/core/server-client.d.ts +99 -0
  40. package/library/core/server-client.d.ts.map +1 -0
  41. package/library/core/server-client.js +256 -0
  42. package/library/core/server.d.ts +82 -0
  43. package/library/core/server.d.ts.map +1 -0
  44. package/library/core/server.js +338 -0
  45. package/library/index.d.ts +16 -0
  46. package/library/index.d.ts.map +1 -0
  47. package/library/index.js +211 -0
  48. package/library/interceptors/index.d.ts +41 -0
  49. package/library/interceptors/index.d.ts.map +1 -0
  50. package/library/interceptors/index.js +126 -0
  51. package/library/message/channel.d.ts +107 -0
  52. package/library/message/channel.d.ts.map +1 -0
  53. package/library/message/channel.js +184 -0
  54. package/library/message/dispatcher.d.ts +119 -0
  55. package/library/message/dispatcher.d.ts.map +1 -0
  56. package/library/message/dispatcher.js +249 -0
  57. package/library/message/index.d.ts +5 -0
  58. package/library/message/index.d.ts.map +1 -0
  59. package/library/message/index.js +25 -0
  60. package/library/stream/file-stream.d.ts +48 -0
  61. package/library/stream/file-stream.d.ts.map +1 -0
  62. package/library/stream/file-stream.js +240 -0
  63. package/library/stream/index.d.ts +15 -0
  64. package/library/stream/index.d.ts.map +1 -0
  65. package/library/stream/index.js +83 -0
  66. package/library/stream/readable-stream.d.ts +83 -0
  67. package/library/stream/readable-stream.d.ts.map +1 -0
  68. package/library/stream/readable-stream.js +249 -0
  69. package/library/stream/types.d.ts +165 -0
  70. package/library/stream/types.d.ts.map +1 -0
  71. package/library/stream/types.js +5 -0
  72. package/library/stream/writable-stream.d.ts +60 -0
  73. package/library/stream/writable-stream.d.ts.map +1 -0
  74. package/library/stream/writable-stream.js +348 -0
  75. package/library/types/index.d.ts +408 -0
  76. package/library/types/index.d.ts.map +1 -0
  77. package/library/types/index.js +5 -0
  78. package/library/utils/cache.d.ts +19 -0
  79. package/library/utils/cache.d.ts.map +1 -0
  80. package/library/utils/cache.js +83 -0
  81. package/library/utils/cookie.d.ts +117 -0
  82. package/library/utils/cookie.d.ts.map +1 -0
  83. package/library/utils/cookie.js +365 -0
  84. package/library/utils/debug.d.ts +11 -0
  85. package/library/utils/debug.d.ts.map +1 -0
  86. package/library/utils/debug.js +162 -0
  87. package/library/utils/index.d.ts +13 -0
  88. package/library/utils/index.d.ts.map +1 -0
  89. package/library/utils/index.js +132 -0
  90. package/library/utils/path-match.d.ts +17 -0
  91. package/library/utils/path-match.d.ts.map +1 -0
  92. package/library/utils/path-match.js +90 -0
  93. package/library/utils/protocol.d.ts +61 -0
  94. package/library/utils/protocol.d.ts.map +1 -0
  95. package/library/utils/protocol.js +169 -0
  96. package/package.json +58 -0
@@ -0,0 +1,323 @@
1
+ "use strict";
2
+
3
+ require("core-js/modules/es.array.filter.js");
4
+ require("core-js/modules/es.object.get-own-property-descriptors.js");
5
+ require("core-js/modules/web.dom-collections.for-each.js");
6
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
7
+ Object.defineProperty(exports, "__esModule", {
8
+ value: true
9
+ });
10
+ exports.ServerResponseImpl = void 0;
11
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
12
+ require("core-js/modules/es.array.includes.js");
13
+ require("core-js/modules/es.array.iterator.js");
14
+ require("core-js/modules/es.promise.js");
15
+ require("core-js/modules/es.string.includes.js");
16
+ require("core-js/modules/web.dom-collections.iterator.js");
17
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
18
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
19
+ var _utils = require("../utils");
20
+ var _constants = require("../constants");
21
+ 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; }
22
+ 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; }
23
+ /**
24
+ * Callback waiting for client acknowledgment
25
+ */
26
+
27
+ /**
28
+ * ServerResponse implementation
29
+ */
30
+ class ServerResponseImpl {
31
+ constructor(requestId, path, secretKey, targetWindow, targetOrigin, channel) {
32
+ (0, _defineProperty2.default)(this, "statusCode", _constants.HttpStatus.OK);
33
+ (0, _defineProperty2.default)(this, "headers", {});
34
+ (0, _defineProperty2.default)(this, "_sent", false);
35
+ this.requestId = requestId;
36
+ this.path = path;
37
+ this.secretKey = secretKey;
38
+ this.targetWindow = targetWindow;
39
+ this.targetOrigin = targetOrigin;
40
+ this.channel = channel;
41
+ }
42
+
43
+ /**
44
+ * Send message via channel or direct postMessage
45
+ */
46
+ sendMessage(message) {
47
+ if (this.channel) {
48
+ this.channel.send(this.targetWindow, message, this.targetOrigin);
49
+ } else {
50
+ this.targetWindow.postMessage(message, this.targetOrigin);
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Set callback waiting for client acknowledgment
56
+ */
57
+ _setOnAckCallback(callback) {
58
+ this.onAckCallback = callback;
59
+ }
60
+
61
+ /**
62
+ * Trigger client acknowledgment callback
63
+ */
64
+ _triggerAck(received) {
65
+ if (this.onAckCallback) {
66
+ this.onAckCallback(received);
67
+ this.onAckCallback = undefined;
68
+ }
69
+ }
70
+ send(data, options) {
71
+ var _options$requireAck;
72
+ if (this._sent) return Promise.resolve(false);
73
+ this._sent = true;
74
+ var requireAck = (_options$requireAck = options === null || options === void 0 ? void 0 : options.requireAck) !== null && _options$requireAck !== void 0 ? _options$requireAck : false;
75
+
76
+ // If acknowledgment not required, send directly and return true
77
+ if (!requireAck) {
78
+ this.sendMessage((0, _utils.createPostMessage)(_constants.MessageType.RESPONSE, this.requestId, {
79
+ path: this.path,
80
+ secretKey: this.secretKey,
81
+ data,
82
+ status: this.statusCode,
83
+ statusText: (0, _constants.getStatusText)(this.statusCode),
84
+ headers: this.headers,
85
+ requireAck: false
86
+ }));
87
+ return Promise.resolve(true);
88
+ }
89
+
90
+ // Acknowledgment required, wait for client response
91
+ return new Promise(resolve => {
92
+ this._setOnAckCallback(resolve);
93
+ this.sendMessage((0, _utils.createPostMessage)(_constants.MessageType.RESPONSE, this.requestId, {
94
+ path: this.path,
95
+ secretKey: this.secretKey,
96
+ data,
97
+ status: this.statusCode,
98
+ statusText: (0, _constants.getStatusText)(this.statusCode),
99
+ headers: this.headers,
100
+ requireAck: true
101
+ }));
102
+ });
103
+ }
104
+ json(data, options) {
105
+ this.setHeader(_constants.HttpHeader.CONTENT_TYPE, 'application/json');
106
+ return this.send(data, options);
107
+ }
108
+ sendFile(content, options) {
109
+ var _this = this;
110
+ return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee() {
111
+ var _options$requireAck2;
112
+ var requireAck, base64Content, mimeType, fileName, fileHeaders, messageData;
113
+ return _regenerator.default.wrap(function (_context) {
114
+ while (1) switch (_context.prev = _context.next) {
115
+ case 0:
116
+ if (!_this._sent) {
117
+ _context.next = 1;
118
+ break;
119
+ }
120
+ return _context.abrupt("return", false);
121
+ case 1:
122
+ _this._sent = true;
123
+ requireAck = (_options$requireAck2 = options === null || options === void 0 ? void 0 : options.requireAck) !== null && _options$requireAck2 !== void 0 ? _options$requireAck2 : false;
124
+ mimeType = (options === null || options === void 0 ? void 0 : options.mimeType) || 'application/octet-stream';
125
+ fileName = options === null || options === void 0 ? void 0 : options.fileName;
126
+ if (!(typeof content === 'string')) {
127
+ _context.next = 2;
128
+ break;
129
+ }
130
+ // If it's a plain string, convert to base64
131
+ base64Content = btoa(unescape(encodeURIComponent(content)));
132
+ _context.next = 6;
133
+ break;
134
+ case 2:
135
+ if (!(content instanceof File)) {
136
+ _context.next = 4;
137
+ break;
138
+ }
139
+ mimeType = content.type || mimeType;
140
+ fileName = fileName || content.name;
141
+ _context.next = 3;
142
+ return _this.blobToBase64(content);
143
+ case 3:
144
+ base64Content = _context.sent;
145
+ _context.next = 6;
146
+ break;
147
+ case 4:
148
+ _context.next = 5;
149
+ return _this.blobToBase64(content);
150
+ case 5:
151
+ base64Content = _context.sent;
152
+ case 6:
153
+ // Merge file-related headers
154
+ fileHeaders = _objectSpread(_objectSpread({}, _this.headers), {}, {
155
+ [_constants.HttpHeader.CONTENT_TYPE]: mimeType,
156
+ [_constants.HttpHeader.CONTENT_DISPOSITION]: fileName ? `attachment; filename="${fileName}"` : 'attachment'
157
+ });
158
+ messageData = (0, _utils.createPostMessage)(_constants.MessageType.RESPONSE, _this.requestId, {
159
+ path: _this.path,
160
+ secretKey: _this.secretKey,
161
+ status: _this.statusCode,
162
+ statusText: (0, _constants.getStatusText)(_this.statusCode),
163
+ headers: fileHeaders,
164
+ fileData: {
165
+ content: base64Content,
166
+ mimeType,
167
+ fileName
168
+ },
169
+ requireAck
170
+ }); // If acknowledgment not required, send directly and return true
171
+ if (requireAck) {
172
+ _context.next = 7;
173
+ break;
174
+ }
175
+ _this.sendMessage(messageData);
176
+ return _context.abrupt("return", true);
177
+ case 7:
178
+ return _context.abrupt("return", new Promise(resolve => {
179
+ _this._setOnAckCallback(resolve);
180
+ _this.sendMessage(messageData);
181
+ }));
182
+ case 8:
183
+ case "end":
184
+ return _context.stop();
185
+ }
186
+ }, _callee);
187
+ }))();
188
+ }
189
+
190
+ /**
191
+ * Send stream response
192
+ * Bind stream to current request context and start stream transmission
193
+ */
194
+ sendStream(stream) {
195
+ var _this2 = this;
196
+ return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee2() {
197
+ return _regenerator.default.wrap(function (_context2) {
198
+ while (1) switch (_context2.prev = _context2.next) {
199
+ case 0:
200
+ if (!_this2._sent) {
201
+ _context2.next = 1;
202
+ break;
203
+ }
204
+ return _context2.abrupt("return");
205
+ case 1:
206
+ _this2._sent = true;
207
+
208
+ // Bind stream to request context
209
+ stream._bind({
210
+ requestId: _this2.requestId,
211
+ targetWindow: _this2.targetWindow,
212
+ targetOrigin: _this2.targetOrigin,
213
+ secretKey: _this2.secretKey,
214
+ channel: _this2.channel
215
+ });
216
+
217
+ // Start stream transmission
218
+ _context2.next = 2;
219
+ return stream.start();
220
+ case 2:
221
+ case "end":
222
+ return _context2.stop();
223
+ }
224
+ }, _callee2);
225
+ }))();
226
+ }
227
+ status(code) {
228
+ this.statusCode = code;
229
+ return this;
230
+ }
231
+ setHeader(name, value) {
232
+ // Consistent with Express, returns void
233
+ // Special handling for Set-Cookie, keep as array
234
+ if (name.toLowerCase() === _constants.HttpHeader.SET_COOKIE.toLowerCase()) {
235
+ var existing = this.headers[_constants.HttpHeader.SET_COOKIE];
236
+ if (Array.isArray(value)) {
237
+ this.headers[_constants.HttpHeader.SET_COOKIE] = Array.isArray(existing) ? [...existing, ...value] : value;
238
+ } else {
239
+ var newValue = String(value);
240
+ if (Array.isArray(existing)) {
241
+ existing.push(newValue);
242
+ } else {
243
+ this.headers[_constants.HttpHeader.SET_COOKIE] = [newValue];
244
+ }
245
+ }
246
+ } else if (Array.isArray(value)) {
247
+ this.headers[name] = value.join(', ');
248
+ } else {
249
+ this.headers[name] = String(value);
250
+ }
251
+ }
252
+ set(name, value) {
253
+ // Chainable version, compatible with Express res.set
254
+ this.setHeader(name, value);
255
+ return this;
256
+ }
257
+ cookie(name, value, options) {
258
+ /**
259
+ * Set Cookie (similar to HTTP Set-Cookie)
260
+ * Generate Set-Cookie string and add to headers[HttpHeader.SET_COOKIE] array
261
+ * Client will parse and save to cookie storage upon receiving
262
+ */
263
+ var setCookieStr = (0, _utils.createSetCookie)(name, value, {
264
+ path: options === null || options === void 0 ? void 0 : options.path,
265
+ expires: options === null || options === void 0 ? void 0 : options.expires,
266
+ maxAge: options === null || options === void 0 ? void 0 : options.maxAge,
267
+ httpOnly: options === null || options === void 0 ? void 0 : options.httpOnly,
268
+ secure: options === null || options === void 0 ? void 0 : options.secure,
269
+ sameSite: (options === null || options === void 0 ? void 0 : options.sameSite) === true ? 'Strict' : (options === null || options === void 0 ? void 0 : options.sameSite) === false ? undefined : options === null || options === void 0 ? void 0 : options.sameSite
270
+ });
271
+
272
+ // Add to Set-Cookie header array
273
+ var existing = this.headers[_constants.HttpHeader.SET_COOKIE];
274
+ if (Array.isArray(existing)) {
275
+ existing.push(setCookieStr);
276
+ } else {
277
+ this.headers[_constants.HttpHeader.SET_COOKIE] = [setCookieStr];
278
+ }
279
+ return this;
280
+ }
281
+ clearCookie(name, options) {
282
+ /**
283
+ * Clear specified Cookie
284
+ * Generate an expired Set-Cookie string, client will delete this cookie upon receiving
285
+ */
286
+ var setCookieStr = (0, _utils.createClearCookie)(name, {
287
+ path: options === null || options === void 0 ? void 0 : options.path
288
+ });
289
+
290
+ // Add to Set-Cookie header array
291
+ var existing = this.headers[_constants.HttpHeader.SET_COOKIE];
292
+ if (Array.isArray(existing)) {
293
+ existing.push(setCookieStr);
294
+ } else {
295
+ this.headers[_constants.HttpHeader.SET_COOKIE] = [setCookieStr];
296
+ }
297
+ return this;
298
+ }
299
+ blobToBase64(blob) {
300
+ return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee3() {
301
+ return _regenerator.default.wrap(function (_context3) {
302
+ while (1) switch (_context3.prev = _context3.next) {
303
+ case 0:
304
+ return _context3.abrupt("return", new Promise((resolve, reject) => {
305
+ var reader = new FileReader();
306
+ reader.onloadend = () => {
307
+ var result = reader.result;
308
+ // Remove data URL prefix (e.g., "data:image/png;base64,")
309
+ var base64 = result.includes(',') ? result.split(',')[1] : result;
310
+ resolve(base64);
311
+ };
312
+ reader.onerror = reject;
313
+ reader.readAsDataURL(blob);
314
+ }));
315
+ case 1:
316
+ case "end":
317
+ return _context3.stop();
318
+ }
319
+ }, _callee3);
320
+ }))();
321
+ }
322
+ }
323
+ exports.ServerResponseImpl = ServerResponseImpl;
@@ -0,0 +1,86 @@
1
+ import { PostMessageData, ServerEventName } from '../types';
2
+ /**
3
+ * server 内部事件监听器集合
4
+ */
5
+ type ServerListeners = Record<ServerEventName, Set<(payload: any, event?: MessageEvent) => void>>;
6
+ /**
7
+ * 等待客户端确认的响应
8
+ */
9
+ interface PendingAck {
10
+ resolve: (received: boolean) => void;
11
+ reject: (error: Error) => void;
12
+ timeoutId: ReturnType<typeof setTimeout>;
13
+ }
14
+ /**
15
+ * RequestIframeBaseServer 基类(封装基本的请求交互逻辑)
16
+ */
17
+ export declare abstract class RequestIframeBaseServer {
18
+ protected readonly uniqueKey?: string;
19
+ protected readonly ackTimeout: number;
20
+ protected readonly listeners: ServerListeners;
21
+ /** 等待客户端确认的响应 */
22
+ protected readonly pendingAcks: Map<string, PendingAck>;
23
+ /** 客户端等待响应的请求 */
24
+ protected readonly pendingClientRequests: Map<string, {
25
+ resolve: (data: PostMessageData) => void;
26
+ reject: (error: Error) => void;
27
+ origin?: string;
28
+ }>;
29
+ protected readonly onMessage: (event: MessageEvent) => void;
30
+ constructor(options?: {
31
+ uniqueKey?: string;
32
+ ackTimeout?: number;
33
+ });
34
+ /**
35
+ * 处理请求(由子类实现)
36
+ */
37
+ protected abstract handleRequest(data: PostMessageData, event: MessageEvent): void;
38
+ /**
39
+ * 处理客户端响应(ack、async、response、error)
40
+ */
41
+ protected handleClientResponse(data: PostMessageData, event: MessageEvent): void;
42
+ /**
43
+ * 处理客户端确认收到
44
+ */
45
+ protected handleReceived(data: PostMessageData): void;
46
+ /**
47
+ * 处理 ping 请求(用于 isConnect)
48
+ */
49
+ protected handlePing(data: PostMessageData, event: MessageEvent): void;
50
+ /**
51
+ * 处理 pong 响应(用于 isConnect)
52
+ */
53
+ protected handlePong(data: PostMessageData, event: MessageEvent): void;
54
+ /**
55
+ * 注册等待客户端确认的响应
56
+ */
57
+ _registerPendingAck(requestId: string, resolve: (received: boolean) => void, reject: (error: Error) => void): void;
58
+ /**
59
+ * 内部方法:监听底层事件
60
+ */
61
+ _on(event: ServerEventName, fn: (payload: any, messageEvent?: MessageEvent) => void): void;
62
+ /**
63
+ * 内部方法:取消监听底层事件
64
+ */
65
+ _off(event: ServerEventName, fn?: (payload: any, messageEvent?: MessageEvent) => void): void;
66
+ /**
67
+ * 内部方法:供 client 注册等待响应的 Promise
68
+ */
69
+ _registerPendingRequest(requestId: string, resolve: (data: PostMessageData) => void, reject: (error: Error) => void, origin?: string): void;
70
+ /**
71
+ * 内部方法:供 client 取消等待
72
+ */
73
+ _unregisterPendingRequest(requestId: string): void;
74
+ /**
75
+ * 销毁 server(移除 message 监听)
76
+ */
77
+ destroy(): void;
78
+ protected emit(event: ServerEventName, payload: any, messageEvent?: MessageEvent): void;
79
+ protected prefixPath(path: string): string;
80
+ /**
81
+ * 发送协议版本不兼容错误(版本过低)
82
+ */
83
+ protected sendProtocolError(data: PostMessageData, event: MessageEvent, remoteVersion: number): void;
84
+ }
85
+ export {};
86
+ //# sourceMappingURL=server-base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-base.d.ts","sourceRoot":"","sources":["../../src/core/server-base.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,257 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.RequestIframeBaseServer = void 0;
8
+ require("core-js/modules/es.array.iterator.js");
9
+ require("core-js/modules/es.map.js");
10
+ require("core-js/modules/es.set.js");
11
+ require("core-js/modules/web.dom-collections.for-each.js");
12
+ require("core-js/modules/web.dom-collections.iterator.js");
13
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
14
+ var _utils = require("../utils");
15
+ var _constants = require("../constants");
16
+ /**
17
+ * server 内部事件监听器集合
18
+ */
19
+
20
+ /**
21
+ * 等待客户端确认的响应
22
+ */
23
+
24
+ /**
25
+ * RequestIframeBaseServer 基类(封装基本的请求交互逻辑)
26
+ */
27
+ class RequestIframeBaseServer {
28
+ constructor(options) {
29
+ var _options$ackTimeout;
30
+ (0, _defineProperty2.default)(this, "listeners", {
31
+ request: new Set(),
32
+ ack: new Set(),
33
+ async: new Set(),
34
+ response: new Set(),
35
+ error: new Set(),
36
+ received: new Set(),
37
+ ping: new Set(),
38
+ pong: new Set()
39
+ });
40
+ /** 等待客户端确认的响应 */
41
+ (0, _defineProperty2.default)(this, "pendingAcks", new Map());
42
+ /** 客户端等待响应的请求 */
43
+ (0, _defineProperty2.default)(this, "pendingClientRequests", new Map());
44
+ (0, _defineProperty2.default)(this, "onMessage", event => {
45
+ var data = event.data;
46
+
47
+ // 检查是否是 request-iframe 框架的消息(基本格式验证)
48
+ if (!(0, _utils.isValidPostMessage)(data)) {
49
+ return;
50
+ }
51
+
52
+ // 检查协议版本兼容性
53
+ var version = (0, _utils.getProtocolVersion)(data);
54
+ if (version !== undefined && !(0, _utils.isCompatibleVersion)(version)) {
55
+ // 协议版本不兼容,通知对方
56
+ this.sendProtocolError(data, event, version);
57
+ return;
58
+ }
59
+
60
+ // uniqueKey 隔离:不匹配则忽略
61
+ if (this.uniqueKey) {
62
+ if (data.uniqueKey !== this.uniqueKey) return;
63
+ } else {
64
+ if (data.uniqueKey) return;
65
+ }
66
+
67
+ // 触发框架内部事件监听器
68
+ this.emit(data.type, data, event);
69
+
70
+ // 处理请求(由子类实现)
71
+ if (data.type === _constants.MessageType.REQUEST) {
72
+ this.handleRequest(data, event);
73
+ return;
74
+ }
75
+
76
+ // 处理响应和错误(供 client 使用)
77
+ if (data.type === _constants.MessageType.RESPONSE || data.type === _constants.MessageType.ERROR || data.type === _constants.MessageType.ACK || data.type === _constants.MessageType.ASYNC) {
78
+ this.handleClientResponse(data, event);
79
+ return;
80
+ }
81
+
82
+ // 处理客户端确认收到(received)
83
+ if (data.type === _constants.MessageType.RECEIVED) {
84
+ this.handleReceived(data);
85
+ return;
86
+ }
87
+
88
+ // 处理 ping(用于 isConnect)
89
+ if (data.type === _constants.MessageType.PING) {
90
+ this.handlePing(data, event);
91
+ return;
92
+ }
93
+
94
+ // 处理 pong(用于 isConnect)
95
+ if (data.type === _constants.MessageType.PONG) {
96
+ this.handlePong(data, event);
97
+ return;
98
+ }
99
+ });
100
+ this.uniqueKey = options === null || options === void 0 ? void 0 : options.uniqueKey;
101
+ this.ackTimeout = (_options$ackTimeout = options === null || options === void 0 ? void 0 : options.ackTimeout) !== null && _options$ackTimeout !== void 0 ? _options$ackTimeout : _constants.DefaultTimeout.SERVER_ACK;
102
+ window.addEventListener('message', this.onMessage);
103
+ }
104
+
105
+ /**
106
+ * 处理请求(由子类实现)
107
+ */
108
+
109
+ /**
110
+ * 处理客户端响应(ack、async、response、error)
111
+ */
112
+ handleClientResponse(data, event) {
113
+ var pending = this.pendingClientRequests.get(data.requestId);
114
+ if (pending) {
115
+ // 验证 origin(如果指定了)
116
+ if (pending.origin && pending.origin !== '*' && event.origin !== pending.origin) {
117
+ return;
118
+ }
119
+ // 对于 ack 和 async,不删除 pending,只触发回调
120
+ if (data.type === _constants.MessageType.ACK || data.type === _constants.MessageType.ASYNC) {
121
+ pending.resolve(data);
122
+ return;
123
+ }
124
+ // 对于 response 和 error,删除 pending 并触发回调
125
+ this.pendingClientRequests.delete(data.requestId);
126
+ pending.resolve(data);
127
+ }
128
+ }
129
+
130
+ /**
131
+ * 处理客户端确认收到
132
+ */
133
+ handleReceived(data) {
134
+ var pending = this.pendingAcks.get(data.requestId);
135
+ if (pending) {
136
+ clearTimeout(pending.timeoutId);
137
+ this.pendingAcks.delete(data.requestId);
138
+ pending.resolve(true);
139
+ }
140
+ }
141
+
142
+ /**
143
+ * 处理 ping 请求(用于 isConnect)
144
+ */
145
+ handlePing(data, event) {
146
+ if (!event.source) return;
147
+ event.source.postMessage((0, _utils.createPostMessage)(_constants.MessageType.PONG, data.requestId, {
148
+ uniqueKey: data.uniqueKey
149
+ }), event.origin);
150
+ }
151
+
152
+ /**
153
+ * 处理 pong 响应(用于 isConnect)
154
+ */
155
+ handlePong(data, event) {
156
+ var pending = this.pendingClientRequests.get(data.requestId);
157
+ if (pending) {
158
+ if (pending.origin && pending.origin !== '*' && event.origin !== pending.origin) {
159
+ return;
160
+ }
161
+ this.pendingClientRequests.delete(data.requestId);
162
+ pending.resolve(data);
163
+ }
164
+ }
165
+
166
+ /**
167
+ * 注册等待客户端确认的响应
168
+ */
169
+ _registerPendingAck(requestId, resolve, reject) {
170
+ var timeoutId = setTimeout(() => {
171
+ this.pendingAcks.delete(requestId);
172
+ resolve(false); // 超时未收到确认,但不报错
173
+ }, this.ackTimeout);
174
+ this.pendingAcks.set(requestId, {
175
+ resolve,
176
+ reject,
177
+ timeoutId
178
+ });
179
+ }
180
+
181
+ /**
182
+ * 内部方法:监听底层事件
183
+ */
184
+ _on(event, fn) {
185
+ this.listeners[event].add(fn);
186
+ }
187
+
188
+ /**
189
+ * 内部方法:取消监听底层事件
190
+ */
191
+ _off(event, fn) {
192
+ if (!fn) {
193
+ this.listeners[event].clear();
194
+ return;
195
+ }
196
+ this.listeners[event].delete(fn);
197
+ }
198
+
199
+ /**
200
+ * 内部方法:供 client 注册等待响应的 Promise
201
+ */
202
+ _registerPendingRequest(requestId, resolve, reject, origin) {
203
+ this.pendingClientRequests.set(requestId, {
204
+ resolve,
205
+ reject,
206
+ origin
207
+ });
208
+ }
209
+
210
+ /**
211
+ * 内部方法:供 client 取消等待
212
+ */
213
+ _unregisterPendingRequest(requestId) {
214
+ this.pendingClientRequests.delete(requestId);
215
+ }
216
+
217
+ /**
218
+ * 销毁 server(移除 message 监听)
219
+ */
220
+ destroy() {
221
+ window.removeEventListener('message', this.onMessage);
222
+ this.pendingClientRequests.clear();
223
+ this.pendingAcks.forEach(pending => clearTimeout(pending.timeoutId));
224
+ this.pendingAcks.clear();
225
+ Object.keys(this.listeners).forEach(k => this.listeners[k].clear());
226
+ }
227
+ emit(event, payload, messageEvent) {
228
+ this.listeners[event].forEach(fn => {
229
+ try {
230
+ fn(payload, messageEvent);
231
+ } catch (e) {
232
+ // 忽略监听器异常
233
+ }
234
+ });
235
+ }
236
+ prefixPath(path) {
237
+ return this.uniqueKey ? `${this.uniqueKey}:${path}` : path;
238
+ }
239
+
240
+ /**
241
+ * 发送协议版本不兼容错误(版本过低)
242
+ */
243
+ sendProtocolError(data, event, remoteVersion) {
244
+ if (!event.source) return;
245
+ event.source.postMessage((0, _utils.createPostMessage)(_constants.MessageType.ERROR, data.requestId, {
246
+ path: data.path,
247
+ uniqueKey: data.uniqueKey,
248
+ status: _constants.HttpStatus.BAD_REQUEST,
249
+ statusText: _constants.Messages.PROTOCOL_VERSION_UNSUPPORTED,
250
+ error: {
251
+ message: (0, _constants.formatMessage)(_constants.Messages.PROTOCOL_VERSION_TOO_LOW, remoteVersion, _constants.ProtocolVersion.MIN_SUPPORTED),
252
+ code: _constants.ErrorCode.PROTOCOL_UNSUPPORTED
253
+ }
254
+ }), event.origin);
255
+ }
256
+ }
257
+ exports.RequestIframeBaseServer = RequestIframeBaseServer;