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.
Files changed (84) hide show
  1. package/QUICKSTART.CN.md +35 -8
  2. package/QUICKSTART.md +35 -8
  3. package/README.CN.md +439 -36
  4. package/README.md +496 -30
  5. package/library/__tests__/channel.test.ts +420 -0
  6. package/library/__tests__/coverage-branches.test.ts +356 -0
  7. package/library/__tests__/debug.test.ts +588 -0
  8. package/library/__tests__/dispatcher.test.ts +481 -0
  9. package/library/__tests__/requestIframe.test.ts +3163 -185
  10. package/library/__tests__/server.test.ts +738 -0
  11. package/library/__tests__/stream.test.ts +46 -15
  12. package/library/api/client.d.ts.map +1 -1
  13. package/library/api/client.js +12 -6
  14. package/library/api/server.d.ts +4 -3
  15. package/library/api/server.d.ts.map +1 -1
  16. package/library/api/server.js +25 -7
  17. package/library/constants/index.d.ts +14 -4
  18. package/library/constants/index.d.ts.map +1 -1
  19. package/library/constants/index.js +15 -7
  20. package/library/constants/messages.d.ts +37 -0
  21. package/library/constants/messages.d.ts.map +1 -1
  22. package/library/constants/messages.js +38 -1
  23. package/library/core/client-server.d.ts +105 -0
  24. package/library/core/client-server.d.ts.map +1 -0
  25. package/library/core/client-server.js +289 -0
  26. package/library/core/client.d.ts +53 -10
  27. package/library/core/client.d.ts.map +1 -1
  28. package/library/core/client.js +529 -207
  29. package/library/core/request.d.ts +3 -1
  30. package/library/core/request.d.ts.map +1 -1
  31. package/library/core/request.js +2 -1
  32. package/library/core/response.d.ts +30 -4
  33. package/library/core/response.d.ts.map +1 -1
  34. package/library/core/response.js +176 -100
  35. package/library/core/server-client.d.ts +3 -1
  36. package/library/core/server-client.d.ts.map +1 -1
  37. package/library/core/server-client.js +19 -9
  38. package/library/core/server.d.ts +22 -1
  39. package/library/core/server.d.ts.map +1 -1
  40. package/library/core/server.js +304 -55
  41. package/library/index.d.ts +3 -2
  42. package/library/index.d.ts.map +1 -1
  43. package/library/index.js +34 -5
  44. package/library/interceptors/index.d.ts.map +1 -1
  45. package/library/message/channel.d.ts +3 -1
  46. package/library/message/channel.d.ts.map +1 -1
  47. package/library/message/dispatcher.d.ts +7 -2
  48. package/library/message/dispatcher.d.ts.map +1 -1
  49. package/library/message/dispatcher.js +48 -2
  50. package/library/message/index.d.ts.map +1 -1
  51. package/library/stream/file-stream.d.ts +5 -0
  52. package/library/stream/file-stream.d.ts.map +1 -1
  53. package/library/stream/file-stream.js +41 -12
  54. package/library/stream/index.d.ts +11 -1
  55. package/library/stream/index.d.ts.map +1 -1
  56. package/library/stream/index.js +21 -3
  57. package/library/stream/readable-stream.d.ts.map +1 -1
  58. package/library/stream/readable-stream.js +32 -30
  59. package/library/stream/types.d.ts +20 -2
  60. package/library/stream/types.d.ts.map +1 -1
  61. package/library/stream/writable-stream.d.ts +2 -1
  62. package/library/stream/writable-stream.d.ts.map +1 -1
  63. package/library/stream/writable-stream.js +13 -10
  64. package/library/types/index.d.ts +106 -32
  65. package/library/types/index.d.ts.map +1 -1
  66. package/library/utils/cache.d.ts +24 -0
  67. package/library/utils/cache.d.ts.map +1 -1
  68. package/library/utils/cache.js +76 -0
  69. package/library/utils/cookie.d.ts.map +1 -1
  70. package/library/utils/debug.d.ts.map +1 -1
  71. package/library/utils/debug.js +382 -20
  72. package/library/utils/index.d.ts +19 -0
  73. package/library/utils/index.d.ts.map +1 -1
  74. package/library/utils/index.js +113 -2
  75. package/library/utils/path-match.d.ts +16 -0
  76. package/library/utils/path-match.d.ts.map +1 -1
  77. package/library/utils/path-match.js +65 -0
  78. package/library/utils/protocol.d.ts.map +1 -1
  79. package/package.json +4 -1
  80. package/react/library/__tests__/index.test.tsx +274 -281
  81. package/react/library/index.d.ts +4 -3
  82. package/react/library/index.d.ts.map +1 -1
  83. package/react/library/index.js +225 -158
  84. 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;CAiB3B"}
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"}
@@ -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?: MessageChannel);
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 or direct postMessage
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,EAAE,MAAM,WAAW,CAAC;AACjD,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,CAAC,CAAiB;IAC1C,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,CAAC,EAAE,cAAc;IAU1B;;OAEG;IACH,OAAO,CAAC,WAAW;IAQnB;;OAEG;IACI,iBAAiB,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI;IAIrD;;OAEG;IACI,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAOpC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAwCxD,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAKlD,QAAQ,CACnB,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,EAC7B,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,OAAO,CAAC;IAyDnB;;;OAGG;IACU,UAAU,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB7D,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;YAkBH,YAAY;CAa3B"}
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"}
@@ -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 or direct postMessage
45
+ * Send message via channel
45
46
  */
46
47
  sendMessage(message) {
47
- if (this.channel) {
48
- this.channel.send(this.targetWindow, message, this.targetOrigin);
49
- } else {
50
- this.targetWindow.postMessage(message, this.targetOrigin);
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
- send(data, options) {
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
- json(data, options) {
105
- this.setHeader(_constants.HttpHeader.CONTENT_TYPE, 'application/json');
106
- return this.send(data, options);
107
- }
108
- sendFile(content, options) {
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 _options$requireAck2;
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
- _context.next = 2;
212
+ _context3.next = 2;
128
213
  break;
129
214
  }
130
215
  // If it's a plain string, convert to base64
131
- base64Content = btoa(unescape(encodeURIComponent(content)));
132
- _context.next = 6;
216
+ fileContent = btoa(unescape(encodeURIComponent(content)));
217
+ _context3.next = 6;
133
218
  break;
134
219
  case 2:
135
220
  if (!(content instanceof File)) {
136
- _context.next = 4;
221
+ _context3.next = 4;
137
222
  break;
138
223
  }
139
224
  mimeType = content.type || mimeType;
140
225
  fileName = fileName || content.name;
141
- _context.next = 3;
142
- return _this.blobToBase64(content);
226
+ _context3.next = 3;
227
+ return (0, _utils.blobToBase64)(content);
143
228
  case 3:
144
- base64Content = _context.sent;
145
- _context.next = 6;
229
+ fileContent = _context3.sent;
230
+ _context3.next = 6;
146
231
  break;
147
232
  case 4:
148
- _context.next = 5;
149
- return _this.blobToBase64(content);
233
+ _context3.next = 5;
234
+ return (0, _utils.blobToBase64)(content);
150
235
  case 5:
151
- base64Content = _context.sent;
236
+ fileContent = _context3.sent;
152
237
  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;
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
- _this.sendMessage(messageData);
176
- return _context.abrupt("return", true);
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 _context.abrupt("return", new Promise(resolve => {
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 _context.stop();
281
+ return _context3.stop();
185
282
  }
186
- }, _callee);
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 _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) {
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 (!_this2._sent) {
201
- _context2.next = 1;
297
+ if (!_this3._sent) {
298
+ _context4.next = 1;
202
299
  break;
203
300
  }
204
- return _context2.abrupt("return");
301
+ return _context4.abrupt("return");
205
302
  case 1:
206
- _this2._sent = true;
303
+ _this3._sent = true;
207
304
 
208
305
  // Bind stream to request context
209
306
  stream._bind({
210
- requestId: _this2.requestId,
211
- targetWindow: _this2.targetWindow,
212
- targetOrigin: _this2.targetOrigin,
213
- secretKey: _this2.secretKey,
214
- channel: _this2.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
- _context2.next = 2;
317
+ _context4.next = 2;
219
318
  return stream.start();
220
319
  case 2:
221
320
  case "end":
222
- return _context2.stop();
321
+ return _context4.stop();
223
322
  }
224
- }, _callee2);
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;CACrC;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;IAYhD;;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;IAsExB;;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"}
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.SERVER_ACK;
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
- this.open();
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 stream messages (stream_*)
117
- this.unregisterFns.push(this.dispatcher.registerHandler(type => type.startsWith('stream_'), (data, context) => {
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 async don't delete pending
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
  }
@@ -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
  */