request-iframe 0.0.3 → 0.0.5

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 (69) hide show
  1. package/QUICKSTART.CN.md +35 -8
  2. package/QUICKSTART.md +35 -8
  3. package/README.CN.md +177 -24
  4. package/README.md +237 -19
  5. package/library/__tests__/channel.test.ts +16 -4
  6. package/library/__tests__/coverage-branches.test.ts +356 -0
  7. package/library/__tests__/debug.test.ts +22 -0
  8. package/library/__tests__/dispatcher.test.ts +8 -4
  9. package/library/__tests__/requestIframe.test.ts +1243 -87
  10. package/library/__tests__/stream.test.ts +92 -16
  11. package/library/__tests__/utils.test.ts +41 -1
  12. package/library/api/client.d.ts.map +1 -1
  13. package/library/api/client.js +1 -0
  14. package/library/constants/index.d.ts +2 -0
  15. package/library/constants/index.d.ts.map +1 -1
  16. package/library/constants/index.js +3 -1
  17. package/library/constants/messages.d.ts +3 -0
  18. package/library/constants/messages.d.ts.map +1 -1
  19. package/library/constants/messages.js +3 -0
  20. package/library/core/client-server.d.ts +4 -0
  21. package/library/core/client-server.d.ts.map +1 -1
  22. package/library/core/client-server.js +45 -22
  23. package/library/core/client.d.ts +36 -4
  24. package/library/core/client.d.ts.map +1 -1
  25. package/library/core/client.js +508 -285
  26. package/library/core/request.d.ts +3 -1
  27. package/library/core/request.d.ts.map +1 -1
  28. package/library/core/request.js +2 -1
  29. package/library/core/response.d.ts +26 -4
  30. package/library/core/response.d.ts.map +1 -1
  31. package/library/core/response.js +192 -112
  32. package/library/core/server.d.ts +13 -0
  33. package/library/core/server.d.ts.map +1 -1
  34. package/library/core/server.js +221 -6
  35. package/library/index.d.ts +2 -1
  36. package/library/index.d.ts.map +1 -1
  37. package/library/index.js +39 -3
  38. package/library/message/channel.d.ts +2 -2
  39. package/library/message/channel.d.ts.map +1 -1
  40. package/library/message/channel.js +5 -1
  41. package/library/message/dispatcher.d.ts +2 -2
  42. package/library/message/dispatcher.d.ts.map +1 -1
  43. package/library/message/dispatcher.js +6 -5
  44. package/library/stream/index.d.ts +11 -1
  45. package/library/stream/index.d.ts.map +1 -1
  46. package/library/stream/index.js +21 -3
  47. package/library/stream/types.d.ts +2 -2
  48. package/library/stream/types.d.ts.map +1 -1
  49. package/library/stream/writable-stream.d.ts +1 -1
  50. package/library/stream/writable-stream.d.ts.map +1 -1
  51. package/library/stream/writable-stream.js +87 -47
  52. package/library/types/index.d.ts +29 -5
  53. package/library/types/index.d.ts.map +1 -1
  54. package/library/utils/debug.d.ts.map +1 -1
  55. package/library/utils/debug.js +6 -2
  56. package/library/utils/error.d.ts +21 -0
  57. package/library/utils/error.d.ts.map +1 -0
  58. package/library/utils/error.js +34 -0
  59. package/library/utils/index.d.ts +21 -0
  60. package/library/utils/index.d.ts.map +1 -1
  61. package/library/utils/index.js +141 -2
  62. package/library/utils/path-match.d.ts +16 -0
  63. package/library/utils/path-match.d.ts.map +1 -1
  64. package/library/utils/path-match.js +65 -0
  65. package/package.json +2 -1
  66. package/react/library/__tests__/index.test.tsx +44 -22
  67. package/react/library/index.d.ts.map +1 -1
  68. package/react/library/index.js +81 -23
  69. package/react/package.json +7 -0
@@ -1,13 +1,15 @@
1
1
  /**
2
2
  * Stream functionality tests
3
3
  */
4
+ import type { MessageChannel } from '../message';
4
5
  import {
5
6
  IframeWritableStream,
6
7
  IframeReadableStream,
7
8
  IframeFileWritableStream,
8
9
  IframeFileReadableStream,
9
10
  isIframeReadableStream,
10
- isIframeFileStream,
11
+ isIframeFileReadableStream,
12
+ isIframeFileWritableStream,
11
13
  StreamMessageHandler
12
14
  } from '../stream';
13
15
 
@@ -15,12 +17,20 @@ describe('Stream', () => {
15
17
  describe('IframeWritableStream', () => {
16
18
  let mockTargetWindow: Window;
17
19
  let mockPostMessage: jest.Mock;
20
+ /** Mock channel: only send() is used by WritableStream */
21
+ let mockChannel: MessageChannel;
18
22
 
19
23
  beforeEach(() => {
20
24
  mockPostMessage = jest.fn();
21
25
  mockTargetWindow = {
22
26
  postMessage: mockPostMessage
23
27
  } as any;
28
+ mockChannel = {
29
+ send: (target: Window, message: any, origin: string) => {
30
+ target.postMessage(message, origin);
31
+ return true;
32
+ }
33
+ } as unknown as MessageChannel;
24
34
  });
25
35
 
26
36
  it('should create stream with default options', () => {
@@ -69,7 +79,8 @@ describe('Stream', () => {
69
79
  requestId: 'req-123',
70
80
  targetWindow: mockTargetWindow,
71
81
  targetOrigin: 'https://example.com',
72
- secretKey: 'test'
82
+ secretKey: 'test',
83
+ channel: mockChannel
73
84
  });
74
85
 
75
86
  await stream.start();
@@ -79,6 +90,48 @@ describe('Stream', () => {
79
90
  expect(mockPostMessage).toHaveBeenCalledTimes(5);
80
91
  });
81
92
 
93
+ it('should stop streaming when target window is closed', async () => {
94
+ let streamDataCount = 0;
95
+ mockPostMessage.mockImplementation((msg: any) => {
96
+ if (msg?.type === 'stream_data') {
97
+ streamDataCount += 1;
98
+ // After first chunk, simulate target window closed
99
+ (mockTargetWindow as any).closed = true;
100
+ }
101
+ });
102
+
103
+ // Make mockChannel respect closed flag
104
+ (mockChannel as any).send = (target: any, message: any, origin: string) => {
105
+ if (target?.closed === true) return false;
106
+ target.postMessage(message, origin);
107
+ return true;
108
+ };
109
+
110
+ const stream = new IframeWritableStream({
111
+ iterator: async function* () {
112
+ yield 'chunk1';
113
+ yield 'chunk2';
114
+ yield 'chunk3';
115
+ }
116
+ });
117
+
118
+ // mockTargetWindow now supports closed/document checks in isWindowAvailable
119
+ (mockTargetWindow as any).closed = false;
120
+ (mockTargetWindow as any).document = {};
121
+
122
+ stream._bind({
123
+ requestId: 'req-123',
124
+ targetWindow: mockTargetWindow,
125
+ targetOrigin: 'https://example.com',
126
+ secretKey: 'test',
127
+ channel: mockChannel
128
+ });
129
+
130
+ await expect(stream.start()).rejects.toThrow('Stream was cancelled');
131
+ expect(stream.state).toBe('cancelled');
132
+ expect(streamDataCount).toBe(1);
133
+ });
134
+
82
135
  it('should start stream with next function', async () => {
83
136
  let callCount = 0;
84
137
  const stream = new IframeWritableStream({
@@ -98,7 +151,8 @@ describe('Stream', () => {
98
151
  requestId: 'req-123',
99
152
  targetWindow: mockTargetWindow,
100
153
  targetOrigin: 'https://example.com',
101
- secretKey: 'test'
154
+ secretKey: 'test',
155
+ channel: mockChannel
102
156
  });
103
157
 
104
158
  await stream.start();
@@ -115,7 +169,8 @@ describe('Stream', () => {
115
169
  requestId: 'req-123',
116
170
  targetWindow: mockTargetWindow,
117
171
  targetOrigin: 'https://example.com',
118
- secretKey: 'test'
172
+ secretKey: 'test',
173
+ channel: mockChannel
119
174
  });
120
175
 
121
176
  await stream.start();
@@ -136,7 +191,8 @@ describe('Stream', () => {
136
191
  requestId: 'req-123',
137
192
  targetWindow: mockTargetWindow,
138
193
  targetOrigin: 'https://example.com',
139
- secretKey: 'test'
194
+ secretKey: 'test',
195
+ channel: mockChannel
140
196
  });
141
197
 
142
198
  await stream.start();
@@ -159,7 +215,8 @@ describe('Stream', () => {
159
215
  requestId: 'req-123',
160
216
  targetWindow: mockTargetWindow,
161
217
  targetOrigin: 'https://example.com',
162
- secretKey: 'test'
218
+ secretKey: 'test',
219
+ channel: mockChannel
163
220
  });
164
221
 
165
222
  await stream.start();
@@ -174,7 +231,8 @@ describe('Stream', () => {
174
231
  requestId: 'req-123',
175
232
  targetWindow: mockTargetWindow,
176
233
  targetOrigin: 'https://example.com',
177
- secretKey: 'test'
234
+ secretKey: 'test',
235
+ channel: mockChannel
178
236
  });
179
237
 
180
238
  stream.cancel('User cancelled');
@@ -192,7 +250,8 @@ describe('Stream', () => {
192
250
  requestId: 'req-123',
193
251
  targetWindow: mockTargetWindow,
194
252
  targetOrigin: 'https://example.com',
195
- secretKey: 'test'
253
+ secretKey: 'test',
254
+ channel: mockChannel
196
255
  });
197
256
 
198
257
  // Manually set state to ended (simulating already ended)
@@ -207,7 +266,7 @@ describe('Stream', () => {
207
266
 
208
267
  it('should use channel if provided', async () => {
209
268
  const mockChannel = {
210
- send: jest.fn()
269
+ send: jest.fn(() => true)
211
270
  } as any;
212
271
 
213
272
  const stream = new IframeWritableStream();
@@ -237,7 +296,8 @@ describe('Stream', () => {
237
296
  requestId: 'req-123',
238
297
  targetWindow: mockTargetWindow,
239
298
  targetOrigin: 'https://example.com',
240
- secretKey: 'test'
299
+ secretKey: 'test',
300
+ channel: mockChannel
241
301
  });
242
302
 
243
303
  stream.cancel('User cancelled');
@@ -261,7 +321,8 @@ describe('Stream', () => {
261
321
  requestId: 'req-123',
262
322
  targetWindow: mockTargetWindow,
263
323
  targetOrigin: 'https://example.com',
264
- secretKey: 'test'
324
+ secretKey: 'test',
325
+ channel: mockChannel
265
326
  });
266
327
 
267
328
  await stream.start();
@@ -284,7 +345,8 @@ describe('Stream', () => {
284
345
  requestId: 'req-123',
285
346
  targetWindow: mockTargetWindow,
286
347
  targetOrigin: 'https://example.com',
287
- secretKey: 'test'
348
+ secretKey: 'test',
349
+ channel: mockChannel
288
350
  });
289
351
 
290
352
  const startPromise = stream.start();
@@ -637,14 +699,28 @@ describe('Stream', () => {
637
699
  expect(isIframeReadableStream('string')).toBe(false);
638
700
  });
639
701
 
640
- it('isIframeFileStream should return true for IframeFileReadableStream', () => {
702
+ it('isIframeFileReadableStream should return true for IframeFileReadableStream', () => {
641
703
  const stream = new IframeFileReadableStream('id', 'reqId', mockHandler);
642
- expect(isIframeFileStream(stream)).toBe(true);
704
+ expect(isIframeFileReadableStream(stream)).toBe(true);
643
705
  });
644
706
 
645
- it('isIframeFileStream should return false for regular IframeReadableStream', () => {
707
+ it('isIframeFileReadableStream should return false for regular IframeReadableStream', () => {
646
708
  const stream = new IframeReadableStream('id', 'reqId', mockHandler);
647
- expect(isIframeFileStream(stream)).toBe(false);
709
+ expect(isIframeFileReadableStream(stream)).toBe(false);
710
+ });
711
+
712
+ it('isIframeFileWritableStream should return true for IframeFileWritableStream', () => {
713
+ const stream = new IframeFileWritableStream({
714
+ filename: 'test.txt',
715
+ mimeType: 'text/plain',
716
+ next: async () => ({ data: btoa('test'), done: true })
717
+ });
718
+ expect(isIframeFileWritableStream(stream)).toBe(true);
719
+ });
720
+
721
+ it('isIframeFileWritableStream should return false for regular IframeWritableStream', () => {
722
+ const stream = new IframeWritableStream();
723
+ expect(isIframeFileWritableStream(stream)).toBe(false);
648
724
  });
649
725
  });
650
726
  });
@@ -7,7 +7,8 @@ import {
7
7
  createSetCookie,
8
8
  createClearCookie,
9
9
  matchCookiePath,
10
- CookieStore
10
+ CookieStore,
11
+ isWindowAvailable
11
12
  } from '../utils';
12
13
  import {
13
14
  validateProtocolVersion,
@@ -430,4 +431,43 @@ describe('utils', () => {
430
431
  });
431
432
  });
432
433
  });
434
+
435
+ describe('isWindowAvailable', () => {
436
+ it('should return true for valid window', () => {
437
+ expect(isWindowAvailable(window)).toBe(true);
438
+ });
439
+
440
+ it('should return false for null', () => {
441
+ expect(isWindowAvailable(null)).toBe(false);
442
+ });
443
+
444
+ it('should return false for undefined', () => {
445
+ expect(isWindowAvailable(undefined)).toBe(false);
446
+ });
447
+
448
+ it('should return false for closed window (window.open)', () => {
449
+ const mockWindow = {
450
+ closed: true,
451
+ document: {},
452
+ postMessage: jest.fn()
453
+ } as any;
454
+ expect(isWindowAvailable(mockWindow)).toBe(false);
455
+ });
456
+
457
+ it('should return true for open window (window.open)', () => {
458
+ const mockWindow = {
459
+ closed: false,
460
+ document: {},
461
+ postMessage: jest.fn()
462
+ } as any;
463
+ expect(isWindowAvailable(mockWindow)).toBe(true);
464
+ });
465
+
466
+ it('should return false when postMessage is missing', () => {
467
+ const mockWindow = {
468
+ closed: false
469
+ } as any;
470
+ expect(isWindowAvailable(mockWindow)).toBe(false);
471
+ });
472
+ });
433
473
  });
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;AAO1F;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,iBAAiB,GAAG,MAAM,EAClC,OAAO,CAAC,EAAE,0BAA0B,GACnC,mBAAmB,CA+CrB;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAKtE"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;AAO1F;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,iBAAiB,GAAG,MAAM,EAClC,OAAO,CAAC,EAAE,0BAA0B,GACnC,mBAAmB,CAgDrB;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAKtE"}
@@ -55,6 +55,7 @@ function requestIframeClient(target, options) {
55
55
  ackTimeout: options === null || options === void 0 ? void 0 : options.ackTimeout,
56
56
  timeout: options === null || options === void 0 ? void 0 : options.timeout,
57
57
  asyncTimeout: options === null || options === void 0 ? void 0 : options.asyncTimeout,
58
+ returnData: options === null || options === void 0 ? void 0 : options.returnData,
58
59
  headers: options === null || options === void 0 ? void 0 : options.headers
59
60
  }, instanceId);
60
61
 
@@ -79,6 +79,8 @@ export declare const ErrorCode: {
79
79
  readonly STREAM_CANCELLED: "STREAM_CANCELLED";
80
80
  /** Stream not bound */
81
81
  readonly STREAM_NOT_BOUND: "STREAM_NOT_BOUND";
82
+ /** Target window closed */
83
+ readonly TARGET_WINDOW_CLOSED: "TARGET_WINDOW_CLOSED";
82
84
  };
83
85
  /**
84
86
  * Message type constants
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"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"}
@@ -125,7 +125,9 @@ var ErrorCode = exports.ErrorCode = {
125
125
  /** Stream cancelled */
126
126
  STREAM_CANCELLED: 'STREAM_CANCELLED',
127
127
  /** Stream not bound */
128
- STREAM_NOT_BOUND: 'STREAM_NOT_BOUND'
128
+ STREAM_NOT_BOUND: 'STREAM_NOT_BOUND',
129
+ /** Target window closed */
130
+ TARGET_WINDOW_CLOSED: 'TARGET_WINDOW_CLOSED'
129
131
  };
130
132
 
131
133
  /**
@@ -33,6 +33,9 @@ declare const defaultMessages: {
33
33
  readonly ERROR: "Error";
34
34
  /** Client errors */
35
35
  readonly IFRAME_NOT_READY: "iframe.contentWindow is not available";
36
+ readonly TARGET_WINDOW_CLOSED: "Target window is closed or no longer available";
37
+ /** ClientServer warnings */
38
+ readonly CLIENT_SERVER_IGNORED_MESSAGE_WHEN_CLOSED: "Ignored message because client server is closed/destroyed (type: {0}, requestId: {1})";
36
39
  /** Stream related messages */
37
40
  readonly STREAM_NOT_BOUND: "Stream is not bound to a request context";
38
41
  readonly STREAM_ALREADY_STARTED: "Stream has already started";
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/constants/messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;GAEG;AACH,QAAA,MAAM,eAAe;IACnB,8BAA8B;;;;IAK9B,4BAA4B;;;;;IAM5B,qBAAqB;;;;IAKrB,8BAA8B;;;;;;IAO9B,oBAAoB;;IAGpB,8BAA8B;;;;;;;IAQ9B,8BAA8B;;;;;;;;;;;;;;;;;IAkB9B,8BAA8B;;;;;;;;;;;;;;;;;;CAkBtB,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,eAAe,CAAC;AAOtD;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAIxD,CAAC;AAEH;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI,CAE/E;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,MAAM,CAKpF;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAElE"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/constants/messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;GAEG;AACH,QAAA,MAAM,eAAe;IACnB,8BAA8B;;;;IAK9B,4BAA4B;;;;;IAM5B,qBAAqB;;;;IAKrB,8BAA8B;;;;;;IAO9B,oBAAoB;;;IAIpB,4BAA4B;;IAI5B,8BAA8B;;;;;;;IAQ9B,8BAA8B;;;;;;;;;;;;;;;;;IAkB9B,8BAA8B;;;;;;;;;;;;;;;;;;CAkBtB,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,eAAe,CAAC;AAOtD;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAIxD,CAAC;AAEH;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI,CAE/E;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,MAAM,CAKpF;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAElE"}
@@ -53,6 +53,9 @@ var defaultMessages = {
53
53
  ERROR: 'Error',
54
54
  /** Client errors */
55
55
  IFRAME_NOT_READY: 'iframe.contentWindow is not available',
56
+ TARGET_WINDOW_CLOSED: 'Target window is closed or no longer available',
57
+ /** ClientServer warnings */
58
+ CLIENT_SERVER_IGNORED_MESSAGE_WHEN_CLOSED: 'Ignored message because client server is closed/destroyed (type: {0}, requestId: {1})',
56
59
  /** Stream related messages */
57
60
  STREAM_NOT_BOUND: 'Stream is not bound to a request context',
58
61
  STREAM_ALREADY_STARTED: 'Stream has already started',
@@ -30,6 +30,10 @@ export declare class RequestIframeClientServer {
30
30
  private readonly pendingAcks;
31
31
  /** Pending requests awaiting response */
32
32
  private readonly pendingRequests;
33
+ /**
34
+ * Avoid spamming logs for the same requestId when closed/destroyed
35
+ */
36
+ private readonly warnedMissingPendingWhenClosed;
33
37
  /** Stream message callback */
34
38
  private streamCallback?;
35
39
  /** List of unregister handler functions */
@@ -1 +1 @@
1
- {"version":3,"file":"client-server.d.ts","sourceRoot":"","sources":["../../src/core/client-server.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"}
1
+ {"version":3,"file":"client-server.d.ts","sourceRoot":"","sources":["../../src/core/client-server.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;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,8BAA8B,CAAqB;IAEpE,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;IAmFxB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAW1B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAoC5B;;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;CAcvB"}
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.RequestIframeClientServer = void 0;
8
8
  require("core-js/modules/es.array.iterator.js");
9
9
  require("core-js/modules/es.map.js");
10
+ require("core-js/modules/es.set.js");
10
11
  require("core-js/modules/es.string.starts-with.js");
11
12
  require("core-js/modules/web.dom-collections.for-each.js");
12
13
  require("core-js/modules/web.dom-collections.iterator.js");
@@ -43,6 +44,10 @@ class RequestIframeClientServer {
43
44
  (0, _defineProperty2.default)(this, "pendingAcks", new Map());
44
45
  /** Pending requests awaiting response */
45
46
  (0, _defineProperty2.default)(this, "pendingRequests", new Map());
47
+ /**
48
+ * Avoid spamming logs for the same requestId when closed/destroyed
49
+ */
50
+ (0, _defineProperty2.default)(this, "warnedMissingPendingWhenClosed", new Set());
46
51
  /** List of unregister handler functions */
47
52
  (0, _defineProperty2.default)(this, "unregisterFns", []);
48
53
  /** Whether opened */
@@ -97,31 +102,30 @@ class RequestIframeClientServer {
97
102
  onVersionError: this.handleVersionError.bind(this)
98
103
  };
99
104
 
105
+ // Bind handleClientResponse to ensure correct 'this' context
106
+ var boundHandleClientResponse = this.handleClientResponse.bind(this);
107
+
100
108
  // Handle ACK messages
101
- this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.ACK, (data, context) => this.handleClientResponse(data, context), handlerOptions));
109
+ this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.ACK, boundHandleClientResponse, handlerOptions));
102
110
 
103
111
  // Handle ASYNC messages
104
- this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.ASYNC, (data, context) => this.handleClientResponse(data, context), handlerOptions));
112
+ this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.ASYNC, boundHandleClientResponse, handlerOptions));
105
113
 
106
114
  // Handle RESPONSE messages
107
- this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.RESPONSE, (data, context) => this.handleClientResponse(data, context), handlerOptions));
115
+ this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.RESPONSE, boundHandleClientResponse, handlerOptions));
108
116
 
109
117
  // Handle ERROR messages
110
- this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.ERROR, (data, context) => this.handleClientResponse(data, context), handlerOptions));
118
+ this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.ERROR, boundHandleClientResponse, handlerOptions));
111
119
 
112
120
  // Handle RECEIVED messages
113
- this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.RECEIVED, data => this.handleReceived(data), handlerOptions));
121
+ this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.RECEIVED, this.handleReceived.bind(this), handlerOptions));
114
122
 
115
123
  // Handle PONG messages
116
- this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.PONG, (data, context) => this.handlePong(data, context), handlerOptions));
124
+ this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.PONG, this.handlePong.bind(this), handlerOptions));
117
125
 
118
126
  // Handle stream_start messages (route to handleClientResponse so it reaches send callback)
119
127
  // 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));
128
+ this.unregisterFns.push(this.dispatcher.registerHandler(_constants.MessageType.STREAM_START, boundHandleClientResponse, handlerOptions));
125
129
 
126
130
  // Handle other stream messages (stream_data, stream_end, etc.)
127
131
  this.unregisterFns.push(this.dispatcher.registerHandler(type => type.startsWith('stream_') && type !== _constants.MessageType.STREAM_START, (data, context) => {
@@ -147,20 +151,38 @@ class RequestIframeClientServer {
147
151
  */
148
152
  handleClientResponse(data, context) {
149
153
  var pending = this.pendingRequests.get(data.requestId);
150
- if (pending) {
151
- // Validate origin
152
- if (pending.origin && pending.origin !== '*' && context.origin !== pending.origin) {
153
- return;
154
- }
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) {
157
- pending.resolve(data);
158
- return;
154
+ if (!pending) {
155
+ /**
156
+ * Pending request not found - ignore by default.
157
+ *
158
+ * If client server is already closed/destroyed, emit a warning to help debugging:
159
+ * this usually means the client was recreated/unmounted before the response arrived.
160
+ */
161
+ if (!this._isOpen) {
162
+ var key = data.requestId;
163
+ if (!this.warnedMissingPendingWhenClosed.has(key)) {
164
+ this.warnedMissingPendingWhenClosed.add(key);
165
+ // eslint-disable-next-line no-console
166
+ console.warn((0, _constants.formatMessage)(_constants.Messages.CLIENT_SERVER_IGNORED_MESSAGE_WHEN_CLOSED, data.type, data.requestId));
167
+ }
159
168
  }
160
- // response and error delete pending
161
- this.pendingRequests.delete(data.requestId);
169
+ return;
170
+ }
171
+
172
+ // Validate origin
173
+ if (pending.origin && pending.origin !== '*' && context.origin !== pending.origin) {
174
+ return;
175
+ }
176
+
177
+ // ack, async, and stream_start don't delete pending (stream_start needs to keep pending for stream_data/stream_end)
178
+ if (data.type === _constants.MessageType.ACK || data.type === _constants.MessageType.ASYNC || data.type === _constants.MessageType.STREAM_START) {
162
179
  pending.resolve(data);
180
+ return;
163
181
  }
182
+
183
+ // response and error delete pending
184
+ this.pendingRequests.delete(data.requestId);
185
+ pending.resolve(data);
164
186
  }
165
187
 
166
188
  /**
@@ -257,6 +279,7 @@ class RequestIframeClientServer {
257
279
  this.pendingRequests.clear();
258
280
  this.pendingAcks.forEach(pending => clearTimeout(pending.timeoutId));
259
281
  this.pendingAcks.clear();
282
+ this.warnedMissingPendingWhenClosed.clear();
260
283
 
261
284
  // Destroy dispatcher and release channel reference
262
285
  this.dispatcher.destroy();
@@ -1,7 +1,7 @@
1
1
  import { RequestOptions, Response, RequestIframeClient, RequestDefaults, HeadersConfig } from '../types';
2
2
  import { RequestInterceptorManager, ResponseInterceptorManager } from '../interceptors';
3
3
  import { RequestIframeClientServer } from './client-server';
4
- import { StreamMessageHandler, StreamMessageData } from '../stream';
4
+ import { IframeWritableStream, StreamMessageHandler, StreamMessageData } from '../stream';
5
5
  /**
6
6
  * Client configuration options
7
7
  */
@@ -19,7 +19,7 @@ export declare class RequestIframeClientImpl implements RequestIframeClient, Str
19
19
  request: RequestInterceptorManager;
20
20
  response: ResponseInterceptorManager;
21
21
  };
22
- private readonly targetWindow;
22
+ readonly targetWindow: Window;
23
23
  private readonly targetOrigin;
24
24
  private readonly server;
25
25
  private readonly secretKey?;
@@ -27,6 +27,8 @@ export declare class RequestIframeClientImpl implements RequestIframeClient, Str
27
27
  private readonly defaultAckTimeout;
28
28
  private readonly defaultTimeout;
29
29
  private readonly defaultAsyncTimeout;
30
+ /** Default returnData configuration */
31
+ private readonly defaultReturnData;
30
32
  /** Initial headers configuration */
31
33
  private readonly initialHeaders?;
32
34
  /**
@@ -64,17 +66,42 @@ export declare class RequestIframeClientImpl implements RequestIframeClient, Str
64
66
  * Resolve header value (handle function type headers)
65
67
  */
66
68
  private resolveHeaderValue;
69
+ /**
70
+ * Detect Content-Type for request body
71
+ */
72
+ private detectContentTypeForBody;
73
+ /**
74
+ * Check if header exists (case-insensitive)
75
+ */
76
+ private hasHeader;
67
77
  /**
68
78
  * Merge and resolve headers (initial headers + request headers)
69
79
  * Request headers take precedence over initial headers
80
+ * Also auto-detects and sets Content-Type if not already set
70
81
  */
71
82
  private mergeHeaders;
72
83
  /**
73
84
  * Check if server is reachable
74
85
  */
75
86
  isConnect(): Promise<boolean>;
76
- send<T = any>(path: string, body?: Record<string, any>, options?: RequestOptions): Promise<Response<T>>;
77
- private prefixPath;
87
+ send<T = any>(path: string, body?: any, options?: RequestOptions): Promise<Response<T> | T>;
88
+ /**
89
+ * Send file as request body (stream only; server receives stream or auto-resolved File/Blob via autoResolve).
90
+ */
91
+ sendFile<T = any>(path: string, content: string | Blob | File, options?: RequestOptions & {
92
+ mimeType?: string;
93
+ fileName?: string;
94
+ autoResolve?: boolean;
95
+ }): Promise<Response<T> | T>;
96
+ /**
97
+ * Send stream as request body (server receives readable stream).
98
+ * Sends REQUEST with streamId and stream: true, then starts the writable stream.
99
+ */
100
+ sendStream<T = any>(path: string, stream: IframeWritableStream, options?: RequestOptions): Promise<Response<T> | T>;
101
+ /**
102
+ * Internal: send REQUEST and wait for response (used by send, sendFile, sendStream).
103
+ */
104
+ private _sendRequest;
78
105
  /**
79
106
  * Get internal server instance (for debugging)
80
107
  */
@@ -83,6 +110,11 @@ export declare class RequestIframeClientImpl implements RequestIframeClient, Str
83
110
  * Whether message handling is enabled
84
111
  */
85
112
  get isOpen(): boolean;
113
+ /**
114
+ * Check if target window is still available (not closed/removed)
115
+ * @returns true if target window is available, false otherwise
116
+ */
117
+ isAvailable(): boolean;
86
118
  /**
87
119
  * Enable message handling (register message handlers)
88
120
  */
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,cAAc,EACd,QAAQ,EAGR,mBAAmB,EACnB,eAAe,EACf,aAAa,EAEd,MAAM,UAAU,CAAC;AAQlB,OAAO,EACL,yBAAyB,EACzB,0BAA0B,EAG3B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAY5D,OAAO,EAGL,oBAAoB,EAEpB,oBAAoB,EACpB,iBAAiB,EAClB,MAAM,WAAW,CAAC;AAEnB;;GAEG;AACH,MAAM,WAAW,aAAc,SAAQ,eAAe;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED;;GAEG;AACH,qBAAa,uBAAwB,YAAW,mBAAmB,EAAE,oBAAoB;IACvF,yBAAyB;IACzB,SAAgB,EAAE,EAAE,MAAM,CAAC;IAEpB,YAAY;;;MAGjB;IAEF,SAAgB,YAAY,EAAE,MAAM,CAAC;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;IACnD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAS;IAEpC,oCAAoC;IACpC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAE7C,uCAAuC;IACvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAU;IAE5C,oCAAoC;IACpC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAgB;IAEhD;;;;OAIG;IACH,OAAO,CAAC,YAAY,CAAkC;IAEtD;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAwD;IAEvF;;;OAGG;IACH,OAAO,CAAC,eAAe,CAAC,CAAS;gBAG/B,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,yBAAyB,EACjC,OAAO,CAAC,EAAE,aAAa,EACvB,UAAU,CAAC,EAAE,MAAM;IAyBrB;;OAEG;IACI,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,GAAG,IAAI;IAIhG;;OAEG;IACI,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAO/C,WAAW,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAKtC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAY7B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAO1B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAIhC;;OAEG;IACH,OAAO,CAAC,SAAS;IAKjB;;;;OAIG;IACH,OAAO,CAAC,YAAY;IA4BpB;;OAEG;IACI,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IA0DvB,IAAI,CAAC,CAAC,GAAG,GAAG,EACvB,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,GAAG,EACV,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAgD3B;;OAEG;IACU,QAAQ,CAAC,CAAC,GAAG,GAAG,EAC3B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,EAC7B,OAAO,CAAC,EAAE,cAAc,GAAG;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,GACzF,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAuB3B;;;OAGG;IACU,UAAU,CAAC,CAAC,GAAG,GAAG,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,oBAAoB,EAC5B,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IA6C3B;;OAEG;IACH,OAAO,CAAC,YAAY;IAsXpB;;OAEG;IACI,SAAS,IAAI,yBAAyB;IAI7C;;OAEG;IACH,IAAW,MAAM,IAAI,OAAO,CAE3B;IAED;;;OAGG;IACI,WAAW,IAAI,OAAO;IAI7B;;OAEG;IACI,IAAI,IAAI,IAAI;IAInB;;OAEG;IACI,KAAK,IAAI,IAAI;IAIpB;;OAEG;IACI,OAAO,IAAI,IAAI;IAetB;;;OAGG;IACI,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAOxD;;;;OAIG;IACI,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIjE;;;;;OAKG;IACI,SAAS,CACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3D,IAAI;IAgBP;;;;OAIG;IACI,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAItD;;OAEG;IACI,YAAY,IAAI,IAAI;CAG5B"}