request-iframe 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/QUICKSTART.CN.md +35 -8
- package/QUICKSTART.md +35 -8
- package/README.CN.md +439 -36
- package/README.md +496 -30
- package/library/__tests__/channel.test.ts +420 -0
- package/library/__tests__/coverage-branches.test.ts +356 -0
- package/library/__tests__/debug.test.ts +588 -0
- package/library/__tests__/dispatcher.test.ts +481 -0
- package/library/__tests__/requestIframe.test.ts +3163 -185
- package/library/__tests__/server.test.ts +738 -0
- package/library/__tests__/stream.test.ts +46 -15
- package/library/api/client.d.ts.map +1 -1
- package/library/api/client.js +12 -6
- package/library/api/server.d.ts +4 -3
- package/library/api/server.d.ts.map +1 -1
- package/library/api/server.js +25 -7
- package/library/constants/index.d.ts +14 -4
- package/library/constants/index.d.ts.map +1 -1
- package/library/constants/index.js +15 -7
- package/library/constants/messages.d.ts +37 -0
- package/library/constants/messages.d.ts.map +1 -1
- package/library/constants/messages.js +38 -1
- package/library/core/client-server.d.ts +105 -0
- package/library/core/client-server.d.ts.map +1 -0
- package/library/core/client-server.js +289 -0
- package/library/core/client.d.ts +53 -10
- package/library/core/client.d.ts.map +1 -1
- package/library/core/client.js +529 -207
- package/library/core/request.d.ts +3 -1
- package/library/core/request.d.ts.map +1 -1
- package/library/core/request.js +2 -1
- package/library/core/response.d.ts +30 -4
- package/library/core/response.d.ts.map +1 -1
- package/library/core/response.js +176 -100
- package/library/core/server-client.d.ts +3 -1
- package/library/core/server-client.d.ts.map +1 -1
- package/library/core/server-client.js +19 -9
- package/library/core/server.d.ts +22 -1
- package/library/core/server.d.ts.map +1 -1
- package/library/core/server.js +304 -55
- package/library/index.d.ts +3 -2
- package/library/index.d.ts.map +1 -1
- package/library/index.js +34 -5
- package/library/interceptors/index.d.ts.map +1 -1
- package/library/message/channel.d.ts +3 -1
- package/library/message/channel.d.ts.map +1 -1
- package/library/message/dispatcher.d.ts +7 -2
- package/library/message/dispatcher.d.ts.map +1 -1
- package/library/message/dispatcher.js +48 -2
- package/library/message/index.d.ts.map +1 -1
- package/library/stream/file-stream.d.ts +5 -0
- package/library/stream/file-stream.d.ts.map +1 -1
- package/library/stream/file-stream.js +41 -12
- package/library/stream/index.d.ts +11 -1
- package/library/stream/index.d.ts.map +1 -1
- package/library/stream/index.js +21 -3
- package/library/stream/readable-stream.d.ts.map +1 -1
- package/library/stream/readable-stream.js +32 -30
- package/library/stream/types.d.ts +20 -2
- package/library/stream/types.d.ts.map +1 -1
- package/library/stream/writable-stream.d.ts +2 -1
- package/library/stream/writable-stream.d.ts.map +1 -1
- package/library/stream/writable-stream.js +13 -10
- package/library/types/index.d.ts +106 -32
- package/library/types/index.d.ts.map +1 -1
- package/library/utils/cache.d.ts +24 -0
- package/library/utils/cache.d.ts.map +1 -1
- package/library/utils/cache.js +76 -0
- package/library/utils/cookie.d.ts.map +1 -1
- package/library/utils/debug.d.ts.map +1 -1
- package/library/utils/debug.js +382 -20
- package/library/utils/index.d.ts +19 -0
- package/library/utils/index.d.ts.map +1 -1
- package/library/utils/index.js +113 -2
- package/library/utils/path-match.d.ts +16 -0
- package/library/utils/path-match.d.ts.map +1 -1
- package/library/utils/path-match.js +65 -0
- package/library/utils/protocol.d.ts.map +1 -1
- package/package.json +4 -1
- package/react/library/__tests__/index.test.tsx +274 -281
- package/react/library/index.d.ts +4 -3
- package/react/library/index.d.ts.map +1 -1
- package/react/library/index.js +225 -158
- package/react/package.json +7 -0
|
@@ -5,13 +5,15 @@ import { MessageContext } from '../message';
|
|
|
5
5
|
*/
|
|
6
6
|
export declare class ServerRequestImpl implements ServerRequest {
|
|
7
7
|
body: any;
|
|
8
|
+
stream?: ServerRequest['stream'];
|
|
8
9
|
headers: Record<string, string>;
|
|
9
10
|
cookies: Record<string, string>;
|
|
10
11
|
path: string;
|
|
12
|
+
params: Record<string, string>;
|
|
11
13
|
requestId: string;
|
|
12
14
|
origin: string;
|
|
13
15
|
source: Window;
|
|
14
16
|
res: ServerResponse;
|
|
15
|
-
constructor(data: PostMessageData, context: MessageContext, response: ServerResponse);
|
|
17
|
+
constructor(data: PostMessageData, context: MessageContext, response: ServerResponse, params?: Record<string, string>);
|
|
16
18
|
}
|
|
17
19
|
//# sourceMappingURL=request.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["request.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAAE,cAAc,EAAE,eAAe,EAC/C,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C;;GAEG;AACH,qBAAa,iBAAkB,YAAW,aAAa;IAC9C,IAAI,EAAE,GAAG,CAAC;IACV,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,cAAc,CAAC;gBAGzB,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,cAAc;
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/core/request.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAAE,cAAc,EAAE,eAAe,EAC/C,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C;;GAEG;AACH,qBAAa,iBAAkB,YAAW,aAAa;IAC9C,IAAI,EAAE,GAAG,CAAC;IACV,MAAM,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,cAAc,CAAC;gBAGzB,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,cAAc,EACxB,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;CAkBtC"}
|
package/library/core/request.js
CHANGED
|
@@ -11,7 +11,7 @@ require("core-js/modules/es.object.entries.js");
|
|
|
11
11
|
* ServerRequest implementation
|
|
12
12
|
*/
|
|
13
13
|
class ServerRequestImpl {
|
|
14
|
-
constructor(data, context, response) {
|
|
14
|
+
constructor(data, context, response, params = {}) {
|
|
15
15
|
this.body = data.body;
|
|
16
16
|
// headers may contain array values (e.g., Set-Cookie), simplified to string here
|
|
17
17
|
this.headers = {};
|
|
@@ -25,6 +25,7 @@ class ServerRequestImpl {
|
|
|
25
25
|
}
|
|
26
26
|
this.cookies = data.cookies || {};
|
|
27
27
|
this.path = data.path || '';
|
|
28
|
+
this.params = params;
|
|
28
29
|
this.requestId = data.requestId;
|
|
29
30
|
this.origin = context.origin;
|
|
30
31
|
this.source = context.source;
|
|
@@ -16,14 +16,31 @@ export declare class ServerResponseImpl implements ServerResponse {
|
|
|
16
16
|
private readonly secretKey?;
|
|
17
17
|
private readonly targetWindow;
|
|
18
18
|
private readonly targetOrigin;
|
|
19
|
-
private readonly channel
|
|
19
|
+
private readonly channel;
|
|
20
|
+
/** Target client ID (usually the creatorId of the original request) */
|
|
21
|
+
private readonly targetId?;
|
|
22
|
+
/** Server instance ID (for creatorId in responses) */
|
|
23
|
+
private readonly serverId?;
|
|
20
24
|
private onAckCallback?;
|
|
21
25
|
_sent: boolean;
|
|
22
|
-
constructor(requestId: string, path: string, secretKey: string | undefined, targetWindow: Window, targetOrigin: string, channel?:
|
|
26
|
+
constructor(requestId: string, path: string, secretKey: string | undefined, targetWindow: Window, targetOrigin: string, channel: MessageChannel, serverId?: string, targetId?: string);
|
|
23
27
|
/**
|
|
24
|
-
* Send message via channel
|
|
28
|
+
* Send message via channel
|
|
25
29
|
*/
|
|
26
30
|
private sendMessage;
|
|
31
|
+
/**
|
|
32
|
+
* Check if header exists (case-insensitive)
|
|
33
|
+
*/
|
|
34
|
+
private hasHeader;
|
|
35
|
+
/**
|
|
36
|
+
* Detect data type and return appropriate Content-Type
|
|
37
|
+
* Returns null if Content-Type should not be auto-set
|
|
38
|
+
*/
|
|
39
|
+
private detectContentType;
|
|
40
|
+
/**
|
|
41
|
+
* Auto set Content-Type based on data type (only if user not set)
|
|
42
|
+
*/
|
|
43
|
+
private ensureContentTypeIfNeeded;
|
|
27
44
|
/**
|
|
28
45
|
* Set callback waiting for client acknowledgment
|
|
29
46
|
*/
|
|
@@ -32,6 +49,16 @@ export declare class ServerResponseImpl implements ServerResponse {
|
|
|
32
49
|
* Trigger client acknowledgment callback
|
|
33
50
|
*/
|
|
34
51
|
_triggerAck(received: boolean): void;
|
|
52
|
+
/**
|
|
53
|
+
* Internal method: send raw data (used by send after type detection)
|
|
54
|
+
*/
|
|
55
|
+
private _sendRaw;
|
|
56
|
+
/**
|
|
57
|
+
* Universal send method - automatically detects data type and calls appropriate method
|
|
58
|
+
* - If data is IframeWritableStream, calls sendStream
|
|
59
|
+
* - If data is File/Blob, calls sendFile
|
|
60
|
+
* - Otherwise, sends as regular data with auto-detected Content-Type
|
|
61
|
+
*/
|
|
35
62
|
send(data: any, options?: SendOptions): Promise<boolean>;
|
|
36
63
|
json(data: any, options?: SendOptions): Promise<boolean>;
|
|
37
64
|
sendFile(content: string | Blob | File, options?: SendFileOptions): Promise<boolean>;
|
|
@@ -45,7 +72,6 @@ export declare class ServerResponseImpl implements ServerResponse {
|
|
|
45
72
|
set(name: string, value: string | number | string[]): ServerResponse;
|
|
46
73
|
cookie(name: string, value: string, options?: CookieOptions): ServerResponse;
|
|
47
74
|
clearCookie(name: string, options?: CookieOptions): ServerResponse;
|
|
48
|
-
private blobToBase64;
|
|
49
75
|
}
|
|
50
76
|
export {};
|
|
51
77
|
//# sourceMappingURL=response.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response.d.ts","sourceRoot":"","sources":["response.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAGvF,OAAO,EAAE,oBAAoB,
|
|
1
|
+
{"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../src/core/response.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAGvF,OAAO,EAAE,oBAAoB,EAAoD,MAAM,WAAW,CAAC;AACnG,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAI5C;;GAEG;AACH,KAAK,WAAW,GAAG,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;AAE/C;;GAEG;AACH,qBAAa,kBAAmB,YAAW,cAAc;IAChD,UAAU,EAAE,MAAM,CAAiB;IACnC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAM;IACvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,uEAAuE;IACvE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,sDAAsD;IACtD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,OAAO,CAAC,aAAa,CAAC,CAAc;IAC7B,KAAK,UAAS;gBAGnB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,cAAc,EACvB,QAAQ,CAAC,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM;IAYnB;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;OAEG;IACH,OAAO,CAAC,SAAS;IAKjB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAIzB;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAQjC;;OAEG;IACI,iBAAiB,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI;IAIrD;;OAEG;IACI,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAO3C;;OAEG;IACH,OAAO,CAAC,QAAQ;IA8ChB;;;;;OAKG;IACU,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAiC9D,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlD,QAAQ,CACnB,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,EAC7B,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,OAAO,CAAC;IAoDnB;;;OAGG;IACU,UAAU,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB7D,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc;IAKpC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI;IAwBhE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,cAAc;IAMpE,MAAM,CACX,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,aAAa,GACtB,cAAc;IA4BV,WAAW,CAChB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,aAAa,GACtB,cAAc;CAkBlB"}
|
package/library/core/response.js
CHANGED
|
@@ -9,15 +9,14 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
9
9
|
});
|
|
10
10
|
exports.ServerResponseImpl = void 0;
|
|
11
11
|
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
12
|
-
require("core-js/modules/es.array.includes.js");
|
|
13
12
|
require("core-js/modules/es.array.iterator.js");
|
|
14
13
|
require("core-js/modules/es.promise.js");
|
|
15
|
-
require("core-js/modules/es.string.includes.js");
|
|
16
14
|
require("core-js/modules/web.dom-collections.iterator.js");
|
|
17
15
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
18
16
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
19
17
|
var _utils = require("../utils");
|
|
20
18
|
var _constants = require("../constants");
|
|
19
|
+
var _stream = require("../stream");
|
|
21
20
|
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
21
|
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
22
|
/**
|
|
@@ -28,7 +27,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
28
27
|
* ServerResponse implementation
|
|
29
28
|
*/
|
|
30
29
|
class ServerResponseImpl {
|
|
31
|
-
constructor(requestId, path, secretKey, targetWindow, targetOrigin, channel) {
|
|
30
|
+
constructor(requestId, path, secretKey, targetWindow, targetOrigin, channel, serverId, targetId) {
|
|
32
31
|
(0, _defineProperty2.default)(this, "statusCode", _constants.HttpStatus.OK);
|
|
33
32
|
(0, _defineProperty2.default)(this, "headers", {});
|
|
34
33
|
(0, _defineProperty2.default)(this, "_sent", false);
|
|
@@ -38,16 +37,44 @@ class ServerResponseImpl {
|
|
|
38
37
|
this.targetWindow = targetWindow;
|
|
39
38
|
this.targetOrigin = targetOrigin;
|
|
40
39
|
this.channel = channel;
|
|
40
|
+
this.serverId = serverId;
|
|
41
|
+
this.targetId = targetId;
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
/**
|
|
44
|
-
* Send message via channel
|
|
45
|
+
* Send message via channel
|
|
45
46
|
*/
|
|
46
47
|
sendMessage(message) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
this.channel.send(this.targetWindow, message, this.targetOrigin);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Check if header exists (case-insensitive)
|
|
53
|
+
*/
|
|
54
|
+
hasHeader(name) {
|
|
55
|
+
var lower = name.toLowerCase();
|
|
56
|
+
return Object.keys(this.headers).some(k => k.toLowerCase() === lower);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Detect data type and return appropriate Content-Type
|
|
61
|
+
* Returns null if Content-Type should not be auto-set
|
|
62
|
+
*/
|
|
63
|
+
detectContentType(data) {
|
|
64
|
+
return (0, _utils.detectContentType)(data, {
|
|
65
|
+
checkStream: true,
|
|
66
|
+
isIframeWritableStream: _stream.isIframeWritableStream
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Auto set Content-Type based on data type (only if user not set)
|
|
72
|
+
*/
|
|
73
|
+
ensureContentTypeIfNeeded(data) {
|
|
74
|
+
if (this.hasHeader(_constants.HttpHeader.CONTENT_TYPE)) return;
|
|
75
|
+
var contentType = this.detectContentType(data);
|
|
76
|
+
if (contentType) {
|
|
77
|
+
this.setHeader(_constants.HttpHeader.CONTENT_TYPE, contentType);
|
|
51
78
|
}
|
|
52
79
|
}
|
|
53
80
|
|
|
@@ -67,7 +94,11 @@ class ServerResponseImpl {
|
|
|
67
94
|
this.onAckCallback = undefined;
|
|
68
95
|
}
|
|
69
96
|
}
|
|
70
|
-
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Internal method: send raw data (used by send after type detection)
|
|
100
|
+
*/
|
|
101
|
+
_sendRaw(data, options) {
|
|
71
102
|
var _options$requireAck;
|
|
72
103
|
if (this._sent) return Promise.resolve(false);
|
|
73
104
|
this._sent = true;
|
|
@@ -82,7 +113,10 @@ class ServerResponseImpl {
|
|
|
82
113
|
status: this.statusCode,
|
|
83
114
|
statusText: (0, _constants.getStatusText)(this.statusCode),
|
|
84
115
|
headers: this.headers,
|
|
85
|
-
requireAck: false
|
|
116
|
+
requireAck: false,
|
|
117
|
+
role: _constants.MessageRole.SERVER,
|
|
118
|
+
creatorId: this.serverId,
|
|
119
|
+
targetId: this.targetId
|
|
86
120
|
}));
|
|
87
121
|
return Promise.resolve(true);
|
|
88
122
|
}
|
|
@@ -97,19 +131,24 @@ class ServerResponseImpl {
|
|
|
97
131
|
status: this.statusCode,
|
|
98
132
|
statusText: (0, _constants.getStatusText)(this.statusCode),
|
|
99
133
|
headers: this.headers,
|
|
100
|
-
requireAck: true
|
|
134
|
+
requireAck: true,
|
|
135
|
+
role: _constants.MessageRole.SERVER,
|
|
136
|
+
creatorId: this.serverId,
|
|
137
|
+
targetId: this.targetId
|
|
101
138
|
}));
|
|
102
139
|
});
|
|
103
140
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Universal send method - automatically detects data type and calls appropriate method
|
|
144
|
+
* - If data is IframeWritableStream, calls sendStream
|
|
145
|
+
* - If data is File/Blob, calls sendFile
|
|
146
|
+
* - Otherwise, sends as regular data with auto-detected Content-Type
|
|
147
|
+
*/
|
|
148
|
+
send(data, options) {
|
|
109
149
|
var _this = this;
|
|
110
150
|
return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee() {
|
|
111
|
-
var
|
|
112
|
-
var requireAck, base64Content, mimeType, fileName, fileHeaders, messageData;
|
|
151
|
+
var fileOptions;
|
|
113
152
|
return _regenerator.default.wrap(function (_context) {
|
|
114
153
|
while (1) switch (_context.prev = _context.next) {
|
|
115
154
|
case 0:
|
|
@@ -117,73 +156,131 @@ class ServerResponseImpl {
|
|
|
117
156
|
_context.next = 1;
|
|
118
157
|
break;
|
|
119
158
|
}
|
|
120
|
-
return _context.abrupt("return", false);
|
|
159
|
+
return _context.abrupt("return", Promise.resolve(false));
|
|
160
|
+
case 1:
|
|
161
|
+
if (!(0, _stream.isIframeWritableStream)(data)) {
|
|
162
|
+
_context.next = 3;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
_context.next = 2;
|
|
166
|
+
return _this.sendStream(data);
|
|
167
|
+
case 2:
|
|
168
|
+
return _context.abrupt("return", true);
|
|
169
|
+
case 3:
|
|
170
|
+
if (!(typeof File !== 'undefined' && data instanceof File || typeof Blob !== 'undefined' && data instanceof Blob)) {
|
|
171
|
+
_context.next = 4;
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
// Extract options for sendFile
|
|
175
|
+
fileOptions = _objectSpread({
|
|
176
|
+
requireAck: options === null || options === void 0 ? void 0 : options.requireAck
|
|
177
|
+
}, typeof File !== 'undefined' && data instanceof File ? {
|
|
178
|
+
mimeType: data.type,
|
|
179
|
+
fileName: data.name
|
|
180
|
+
} : {});
|
|
181
|
+
return _context.abrupt("return", _this.sendFile(data, fileOptions));
|
|
182
|
+
case 4:
|
|
183
|
+
// For other types, auto-detect and set Content-Type, then send
|
|
184
|
+
_this.ensureContentTypeIfNeeded(data);
|
|
185
|
+
return _context.abrupt("return", _this._sendRaw(data, options));
|
|
186
|
+
case 5:
|
|
187
|
+
case "end":
|
|
188
|
+
return _context.stop();
|
|
189
|
+
}
|
|
190
|
+
}, _callee);
|
|
191
|
+
}))();
|
|
192
|
+
}
|
|
193
|
+
json(data, options) {
|
|
194
|
+
return this.send(data, options);
|
|
195
|
+
}
|
|
196
|
+
sendFile(content, options) {
|
|
197
|
+
var _this2 = this;
|
|
198
|
+
return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee3() {
|
|
199
|
+
var mimeType, fileName, fileContent, stream;
|
|
200
|
+
return _regenerator.default.wrap(function (_context3) {
|
|
201
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
202
|
+
case 0:
|
|
203
|
+
if (!_this2._sent) {
|
|
204
|
+
_context3.next = 1;
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
return _context3.abrupt("return", false);
|
|
121
208
|
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
209
|
mimeType = (options === null || options === void 0 ? void 0 : options.mimeType) || 'application/octet-stream';
|
|
125
210
|
fileName = options === null || options === void 0 ? void 0 : options.fileName;
|
|
126
211
|
if (!(typeof content === 'string')) {
|
|
127
|
-
|
|
212
|
+
_context3.next = 2;
|
|
128
213
|
break;
|
|
129
214
|
}
|
|
130
215
|
// If it's a plain string, convert to base64
|
|
131
|
-
|
|
132
|
-
|
|
216
|
+
fileContent = btoa(unescape(encodeURIComponent(content)));
|
|
217
|
+
_context3.next = 6;
|
|
133
218
|
break;
|
|
134
219
|
case 2:
|
|
135
220
|
if (!(content instanceof File)) {
|
|
136
|
-
|
|
221
|
+
_context3.next = 4;
|
|
137
222
|
break;
|
|
138
223
|
}
|
|
139
224
|
mimeType = content.type || mimeType;
|
|
140
225
|
fileName = fileName || content.name;
|
|
141
|
-
|
|
142
|
-
return
|
|
226
|
+
_context3.next = 3;
|
|
227
|
+
return (0, _utils.blobToBase64)(content);
|
|
143
228
|
case 3:
|
|
144
|
-
|
|
145
|
-
|
|
229
|
+
fileContent = _context3.sent;
|
|
230
|
+
_context3.next = 6;
|
|
146
231
|
break;
|
|
147
232
|
case 4:
|
|
148
|
-
|
|
149
|
-
return
|
|
233
|
+
_context3.next = 5;
|
|
234
|
+
return (0, _utils.blobToBase64)(content);
|
|
150
235
|
case 5:
|
|
151
|
-
|
|
236
|
+
fileContent = _context3.sent;
|
|
152
237
|
case 6:
|
|
153
|
-
//
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
|
|
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;
|
|
238
|
+
// Set file-related headers
|
|
239
|
+
_this2.setHeader(_constants.HttpHeader.CONTENT_TYPE, mimeType);
|
|
240
|
+
if (fileName) {
|
|
241
|
+
_this2.setHeader(_constants.HttpHeader.CONTENT_DISPOSITION, `attachment; filename="${fileName}"`);
|
|
242
|
+
} else {
|
|
243
|
+
_this2.setHeader(_constants.HttpHeader.CONTENT_DISPOSITION, 'attachment');
|
|
174
244
|
}
|
|
175
|
-
|
|
176
|
-
|
|
245
|
+
|
|
246
|
+
// Create file stream with autoResolve enabled
|
|
247
|
+
stream = new _stream.IframeFileWritableStream({
|
|
248
|
+
filename: fileName || 'file',
|
|
249
|
+
mimeType,
|
|
250
|
+
chunked: false,
|
|
251
|
+
// File is sent in one chunk
|
|
252
|
+
autoResolve: true,
|
|
253
|
+
// Client will automatically resolve to fileData
|
|
254
|
+
next: function () {
|
|
255
|
+
var _next = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee2() {
|
|
256
|
+
return _regenerator.default.wrap(function (_context2) {
|
|
257
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
258
|
+
case 0:
|
|
259
|
+
return _context2.abrupt("return", {
|
|
260
|
+
data: fileContent,
|
|
261
|
+
done: true
|
|
262
|
+
});
|
|
263
|
+
case 1:
|
|
264
|
+
case "end":
|
|
265
|
+
return _context2.stop();
|
|
266
|
+
}
|
|
267
|
+
}, _callee2);
|
|
268
|
+
}));
|
|
269
|
+
function next() {
|
|
270
|
+
return _next.apply(this, arguments);
|
|
271
|
+
}
|
|
272
|
+
return next;
|
|
273
|
+
}()
|
|
274
|
+
}); // Send stream (this will handle the requireAck logic internally and set _sent)
|
|
275
|
+
_context3.next = 7;
|
|
276
|
+
return _this2.sendStream(stream);
|
|
177
277
|
case 7:
|
|
178
|
-
return
|
|
179
|
-
_this._setOnAckCallback(resolve);
|
|
180
|
-
_this.sendMessage(messageData);
|
|
181
|
-
}));
|
|
278
|
+
return _context3.abrupt("return", true);
|
|
182
279
|
case 8:
|
|
183
280
|
case "end":
|
|
184
|
-
return
|
|
281
|
+
return _context3.stop();
|
|
185
282
|
}
|
|
186
|
-
},
|
|
283
|
+
}, _callee3);
|
|
187
284
|
}))();
|
|
188
285
|
}
|
|
189
286
|
|
|
@@ -192,36 +289,38 @@ class ServerResponseImpl {
|
|
|
192
289
|
* Bind stream to current request context and start stream transmission
|
|
193
290
|
*/
|
|
194
291
|
sendStream(stream) {
|
|
195
|
-
var
|
|
196
|
-
return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function
|
|
197
|
-
return _regenerator.default.wrap(function (
|
|
198
|
-
while (1) switch (
|
|
292
|
+
var _this3 = this;
|
|
293
|
+
return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee4() {
|
|
294
|
+
return _regenerator.default.wrap(function (_context4) {
|
|
295
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
199
296
|
case 0:
|
|
200
|
-
if (!
|
|
201
|
-
|
|
297
|
+
if (!_this3._sent) {
|
|
298
|
+
_context4.next = 1;
|
|
202
299
|
break;
|
|
203
300
|
}
|
|
204
|
-
return
|
|
301
|
+
return _context4.abrupt("return");
|
|
205
302
|
case 1:
|
|
206
|
-
|
|
303
|
+
_this3._sent = true;
|
|
207
304
|
|
|
208
305
|
// Bind stream to request context
|
|
209
306
|
stream._bind({
|
|
210
|
-
requestId:
|
|
211
|
-
targetWindow:
|
|
212
|
-
targetOrigin:
|
|
213
|
-
secretKey:
|
|
214
|
-
channel:
|
|
307
|
+
requestId: _this3.requestId,
|
|
308
|
+
targetWindow: _this3.targetWindow,
|
|
309
|
+
targetOrigin: _this3.targetOrigin,
|
|
310
|
+
secretKey: _this3.secretKey,
|
|
311
|
+
channel: _this3.channel,
|
|
312
|
+
serverId: _this3.serverId,
|
|
313
|
+
targetId: _this3.targetId
|
|
215
314
|
});
|
|
216
315
|
|
|
217
316
|
// Start stream transmission
|
|
218
|
-
|
|
317
|
+
_context4.next = 2;
|
|
219
318
|
return stream.start();
|
|
220
319
|
case 2:
|
|
221
320
|
case "end":
|
|
222
|
-
return
|
|
321
|
+
return _context4.stop();
|
|
223
322
|
}
|
|
224
|
-
},
|
|
323
|
+
}, _callee4);
|
|
225
324
|
}))();
|
|
226
325
|
}
|
|
227
326
|
status(code) {
|
|
@@ -296,28 +395,5 @@ class ServerResponseImpl {
|
|
|
296
395
|
}
|
|
297
396
|
return this;
|
|
298
397
|
}
|
|
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
398
|
}
|
|
323
399
|
exports.ServerResponseImpl = ServerResponseImpl;
|
|
@@ -14,6 +14,8 @@ export interface ClientServerOptions {
|
|
|
14
14
|
ackTimeout?: number;
|
|
15
15
|
/** Protocol version validator (optional, uses built-in validation by default) */
|
|
16
16
|
versionValidator?: VersionValidator;
|
|
17
|
+
/** Whether to automatically open when creating the client server. Default is true. */
|
|
18
|
+
autoOpen?: boolean;
|
|
17
19
|
}
|
|
18
20
|
/**
|
|
19
21
|
* RequestIframeClientServer - Client-side message server
|
|
@@ -34,7 +36,7 @@ export declare class RequestIframeClientServer {
|
|
|
34
36
|
private readonly unregisterFns;
|
|
35
37
|
/** Whether opened */
|
|
36
38
|
private _isOpen;
|
|
37
|
-
constructor(options?: ClientServerOptions);
|
|
39
|
+
constructor(options?: ClientServerOptions, instanceId?: string);
|
|
38
40
|
/**
|
|
39
41
|
* Open message handling (register message handlers)
|
|
40
42
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-client.d.ts","sourceRoot":"","sources":["server-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAKjF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;AAoB7F;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"server-client.d.ts","sourceRoot":"","sources":["../../src/core/server-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAKjF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;AAoB7F;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,sFAAsF;IACtF,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;GAIG;AACH,qBAAa,yBAAyB;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IAEpD,uDAAuD;IACvD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAiC;IAE7D,yCAAyC;IACzC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqC;IAErE,8BAA8B;IAC9B,OAAO,CAAC,cAAc,CAAC,CAAwB;IAE/C,2CAA2C;IAC3C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAyB;IAEvD,qBAAqB;IACrB,OAAO,CAAC,OAAO,CAAS;gBAEL,OAAO,CAAC,EAAE,mBAAmB,EAAE,UAAU,CAAC,EAAE,MAAM;IAcrE;;OAEG;IACI,IAAI,IAAI,IAAI;IAMnB;;OAEG;IACI,KAAK,IAAI,IAAI;IASpB;;OAEG;IACH,IAAW,MAAM,IAAI,OAAO,CAE3B;IAED;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAoFxB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAW1B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAkB5B;;OAEG;IACH,OAAO,CAAC,cAAc;IAStB;;OAEG;IACH,OAAO,CAAC,UAAU;IAWlB;;OAEG;IACI,iBAAiB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI;IAI/D,oBAAoB;IACpB,IAAW,SAAS,IAAI,MAAM,GAAG,SAAS,CAEzC;IAED,2CAA2C;IAC3C,IAAW,iBAAiB,IAAI,iBAAiB,CAEhD;IAED;;OAEG;IACI,mBAAmB,CACxB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,EACpC,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAC7B,IAAI;IASP;;OAEG;IACI,uBAAuB,CAC5B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,EACxC,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,EAC9B,MAAM,CAAC,EAAE,MAAM,GACd,IAAI;IAIP;;OAEG;IACI,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAIzD;;OAEG;IACI,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAIpF;;OAEG;IACI,OAAO,IAAI,IAAI;CAavB"}
|
|
@@ -37,7 +37,7 @@ var _constants = require("../constants");
|
|
|
37
37
|
* Uses shared MessageDispatcher (backed by MessageChannel) to listen for and send messages
|
|
38
38
|
*/
|
|
39
39
|
class RequestIframeClientServer {
|
|
40
|
-
constructor(options) {
|
|
40
|
+
constructor(options, instanceId) {
|
|
41
41
|
var _options$ackTimeout, _options$versionValid;
|
|
42
42
|
/** Pending responses awaiting client acknowledgment */
|
|
43
43
|
(0, _defineProperty2.default)(this, "pendingAcks", new Map());
|
|
@@ -47,15 +47,17 @@ class RequestIframeClientServer {
|
|
|
47
47
|
(0, _defineProperty2.default)(this, "unregisterFns", []);
|
|
48
48
|
/** Whether opened */
|
|
49
49
|
(0, _defineProperty2.default)(this, "_isOpen", false);
|
|
50
|
-
this.ackTimeout = (_options$ackTimeout = options === null || options === void 0 ? void 0 : options.ackTimeout) !== null && _options$ackTimeout !== void 0 ? _options$ackTimeout : _constants.DefaultTimeout.
|
|
50
|
+
this.ackTimeout = (_options$ackTimeout = options === null || options === void 0 ? void 0 : options.ackTimeout) !== null && _options$ackTimeout !== void 0 ? _options$ackTimeout : _constants.DefaultTimeout.ACK;
|
|
51
51
|
this.versionValidator = (_options$versionValid = options === null || options === void 0 ? void 0 : options.versionValidator) !== null && _options$versionValid !== void 0 ? _options$versionValid : _utils.isCompatibleVersion;
|
|
52
52
|
|
|
53
53
|
// Get or create shared channel and create dispatcher
|
|
54
54
|
var channel = (0, _cache.getOrCreateMessageChannel)(options === null || options === void 0 ? void 0 : options.secretKey);
|
|
55
|
-
this.dispatcher = new _message.MessageDispatcher(channel);
|
|
55
|
+
this.dispatcher = new _message.MessageDispatcher(channel, _constants.MessageRole.CLIENT, instanceId);
|
|
56
56
|
|
|
57
|
-
// Auto-open by default
|
|
58
|
-
|
|
57
|
+
// Auto-open by default (unless explicitly set to false)
|
|
58
|
+
if ((options === null || options === void 0 ? void 0 : options.autoOpen) !== false) {
|
|
59
|
+
this.open();
|
|
60
|
+
}
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
/**
|
|
@@ -113,8 +115,16 @@ class RequestIframeClientServer {
|
|
|
113
115
|
// Handle PONG messages
|
|
114
116
|
this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.PONG, (data, context) => this.handlePong(data, context), handlerOptions));
|
|
115
117
|
|
|
116
|
-
// Handle
|
|
117
|
-
|
|
118
|
+
// Handle stream_start messages (route to handleClientResponse so it reaches send callback)
|
|
119
|
+
// Note: stream_start is handled in send callback, not through streamCallback
|
|
120
|
+
this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.STREAM_START, (data, context) => {
|
|
121
|
+
// Route to handleClientResponse so it reaches send callback
|
|
122
|
+
this.handleClientResponse(data, context);
|
|
123
|
+
// Don't call streamCallback here - stream_start is handled in send callback
|
|
124
|
+
}, handlerOptions));
|
|
125
|
+
|
|
126
|
+
// Handle other stream messages (stream_data, stream_end, etc.)
|
|
127
|
+
this.unregisterFns.push(this.dispatcher.registerHandler(type => type.startsWith('stream_') && type !== _constants.MessageType.STREAM_START, (data, context) => {
|
|
118
128
|
var _this$streamCallback;
|
|
119
129
|
return (_this$streamCallback = this.streamCallback) === null || _this$streamCallback === void 0 ? void 0 : _this$streamCallback.call(this, data, context);
|
|
120
130
|
}, handlerOptions));
|
|
@@ -142,8 +152,8 @@ class RequestIframeClientServer {
|
|
|
142
152
|
if (pending.origin && pending.origin !== '*' && context.origin !== pending.origin) {
|
|
143
153
|
return;
|
|
144
154
|
}
|
|
145
|
-
// ack and
|
|
146
|
-
if (data.type === _constants.MessageType.ACK || data.type === _constants.MessageType.ASYNC) {
|
|
155
|
+
// ack, async, and stream_start don't delete pending (stream_start needs to keep pending for stream_data/stream_end)
|
|
156
|
+
if (data.type === _constants.MessageType.ACK || data.type === _constants.MessageType.ASYNC || data.type === _constants.MessageType.STREAM_START) {
|
|
147
157
|
pending.resolve(data);
|
|
148
158
|
return;
|
|
149
159
|
}
|
package/library/core/server.d.ts
CHANGED
|
@@ -6,16 +6,22 @@ import { MessageDispatcher, VersionValidator } from '../message';
|
|
|
6
6
|
export interface ServerOptions {
|
|
7
7
|
/** Message isolation secret key */
|
|
8
8
|
secretKey?: string;
|
|
9
|
+
/** Custom server instance ID (if specified, server will use this ID instead of generating one) */
|
|
10
|
+
id?: string;
|
|
9
11
|
/** ACK timeout duration */
|
|
10
12
|
ackTimeout?: number;
|
|
11
13
|
/** Protocol version validator (optional, uses built-in validator by default) */
|
|
12
14
|
versionValidator?: VersionValidator;
|
|
15
|
+
/** Whether to automatically open when creating the server. Default is true. */
|
|
16
|
+
autoOpen?: boolean;
|
|
13
17
|
}
|
|
14
18
|
/**
|
|
15
19
|
* RequestIframeServer implementation
|
|
16
20
|
* Uses shared MessageDispatcher (backed by MessageChannel) to listen for and send messages
|
|
17
21
|
*/
|
|
18
22
|
export declare class RequestIframeServerImpl implements RequestIframeServer {
|
|
23
|
+
/** Unique instance ID */
|
|
24
|
+
readonly id: string;
|
|
19
25
|
private readonly dispatcher;
|
|
20
26
|
private readonly ackTimeout;
|
|
21
27
|
private readonly versionValidator;
|
|
@@ -23,6 +29,10 @@ export declare class RequestIframeServerImpl implements RequestIframeServer {
|
|
|
23
29
|
private readonly middlewares;
|
|
24
30
|
/** Responses waiting for client acknowledgment */
|
|
25
31
|
private readonly pendingAcks;
|
|
32
|
+
/** Pending requests waiting for client stream_start (streamId present) */
|
|
33
|
+
private readonly pendingStreamRequests;
|
|
34
|
+
/** Stream message handlers (streamId -> handler) for client→server streams */
|
|
35
|
+
private readonly streamHandlers;
|
|
26
36
|
/** List of functions to unregister handlers */
|
|
27
37
|
private readonly unregisterFns;
|
|
28
38
|
/** Whether it is open */
|
|
@@ -44,6 +54,9 @@ export declare class RequestIframeServerImpl implements RequestIframeServer {
|
|
|
44
54
|
* Register message handlers
|
|
45
55
|
*/
|
|
46
56
|
private registerHandlers;
|
|
57
|
+
/** Handle stream_start from client (stream request with streamId) */
|
|
58
|
+
private handleStreamStart;
|
|
59
|
+
private dispatchStreamMessage;
|
|
47
60
|
/**
|
|
48
61
|
* Handle protocol version error
|
|
49
62
|
*/
|
|
@@ -60,6 +73,14 @@ export declare class RequestIframeServerImpl implements RequestIframeServer {
|
|
|
60
73
|
get secretKey(): string | undefined;
|
|
61
74
|
/** Get the underlying MessageDispatcher */
|
|
62
75
|
get messageDispatcher(): MessageDispatcher;
|
|
76
|
+
private handleRequestError;
|
|
77
|
+
private handleRequestResult;
|
|
78
|
+
/**
|
|
79
|
+
* Find matching handler and extract path parameters
|
|
80
|
+
* @param requestPath The actual request path
|
|
81
|
+
* @returns Handler function and extracted parameters, or null if not found
|
|
82
|
+
*/
|
|
83
|
+
private findHandler;
|
|
63
84
|
/**
|
|
64
85
|
* Handle request
|
|
65
86
|
*/
|
|
@@ -73,7 +94,7 @@ export declare class RequestIframeServerImpl implements RequestIframeServer {
|
|
|
73
94
|
on(path: string, handler: ServerHandler): () => void;
|
|
74
95
|
private runMiddlewares;
|
|
75
96
|
off(path: string | string[]): void;
|
|
76
|
-
map(handlers: Record<string, ServerHandler>): void;
|
|
97
|
+
map(handlers: Record<string, ServerHandler>): (() => void);
|
|
77
98
|
/**
|
|
78
99
|
* Destroy (close and release channel reference)
|
|
79
100
|
*/
|