@trpc/server 11.0.0-rc.560 → 11.0.0-rc.561

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.
@@ -1,7 +1,7 @@
1
1
  {
2
- "bundleSize": 136868,
3
- "bundleOrigSize": 183401,
4
- "bundleReduction": 25.37,
2
+ "bundleSize": 139502,
3
+ "bundleOrigSize": 186355,
4
+ "bundleReduction": 25.14,
5
5
  "modules": [
6
6
  {
7
7
  "id": "/src/unstable-core-do-not-import/http/resolveResponse.ts",
@@ -14,13 +14,13 @@
14
14
  "dependents": [
15
15
  "/src/unstable-core-do-not-import.ts"
16
16
  ],
17
- "percent": 13.47,
17
+ "percent": 13.22,
18
18
  "reduction": 0
19
19
  },
20
20
  {
21
21
  "id": "/src/unstable-core-do-not-import/stream/jsonl.ts",
22
22
  "size": 17567,
23
- "origSize": 18359,
23
+ "origSize": 18465,
24
24
  "renderedExports": [
25
25
  "isPromise",
26
26
  "jsonlStreamProducer",
@@ -31,8 +31,8 @@
31
31
  "/src/unstable-core-do-not-import.ts",
32
32
  "/src/unstable-core-do-not-import/http/resolveResponse.ts"
33
33
  ],
34
- "percent": 12.83,
35
- "reduction": 4.31
34
+ "percent": 12.59,
35
+ "reduction": 4.86
36
36
  },
37
37
  {
38
38
  "id": "/src/adapters/ws.ts",
@@ -47,9 +47,26 @@
47
47
  "dependents": [
48
48
  "/src/adapters/fastify/fastifyTRPCPlugin.ts"
49
49
  ],
50
- "percent": 11.9,
50
+ "percent": 11.67,
51
51
  "reduction": 0
52
52
  },
53
+ {
54
+ "id": "/src/unstable-core-do-not-import/stream/sse.ts",
55
+ "size": 9020,
56
+ "origSize": 10407,
57
+ "renderedExports": [
58
+ "sseStreamProducer",
59
+ "sseStreamConsumer",
60
+ "sseHeaders"
61
+ ],
62
+ "removedExports": [],
63
+ "dependents": [
64
+ "/src/unstable-core-do-not-import.ts",
65
+ "/src/unstable-core-do-not-import/http/resolveResponse.ts"
66
+ ],
67
+ "percent": 6.47,
68
+ "reduction": 13.33
69
+ },
53
70
  {
54
71
  "id": "/src/unstable-core-do-not-import/http/contentType.ts",
55
72
  "size": 7688,
@@ -62,7 +79,7 @@
62
79
  "/src/unstable-core-do-not-import.ts",
63
80
  "/src/unstable-core-do-not-import/http/resolveResponse.ts"
64
81
  ],
65
- "percent": 5.62,
82
+ "percent": 5.51,
66
83
  "reduction": 0
67
84
  },
68
85
  {
@@ -80,26 +97,9 @@
80
97
  "/src/unstable-core-do-not-import.ts",
81
98
  "/src/unstable-core-do-not-import/initTRPC.ts"
82
99
  ],
83
- "percent": 4.69,
100
+ "percent": 4.6,
84
101
  "reduction": 40.09
85
102
  },
86
- {
87
- "id": "/src/unstable-core-do-not-import/stream/sse.ts",
88
- "size": 6386,
89
- "origSize": 7559,
90
- "renderedExports": [
91
- "sseStreamProducer",
92
- "sseStreamConsumer",
93
- "sseHeaders"
94
- ],
95
- "removedExports": [],
96
- "dependents": [
97
- "/src/unstable-core-do-not-import.ts",
98
- "/src/unstable-core-do-not-import/http/resolveResponse.ts"
99
- ],
100
- "percent": 4.67,
101
- "reduction": 15.52
102
- },
103
103
  {
104
104
  "id": "/src/unstable-core-do-not-import/procedureBuilder.ts",
105
105
  "size": 5795,
@@ -112,7 +112,7 @@
112
112
  "/src/unstable-core-do-not-import.ts",
113
113
  "/src/unstable-core-do-not-import/initTRPC.ts"
114
114
  ],
115
- "percent": 4.23,
115
+ "percent": 4.15,
116
116
  "reduction": 64.74
117
117
  },
118
118
  {
@@ -126,7 +126,7 @@
126
126
  "dependents": [
127
127
  "/src/adapters/aws-lambda/index.ts"
128
128
  ],
129
- "percent": 3.96,
129
+ "percent": 3.88,
130
130
  "reduction": 11.38
131
131
  },
132
132
  {
@@ -146,7 +146,7 @@
146
146
  "/src/unstable-core-do-not-import/http/resolveResponse.ts",
147
147
  "/src/observable/operators.ts"
148
148
  ],
149
- "percent": 3.01,
149
+ "percent": 2.95,
150
150
  "reduction": 0
151
151
  },
152
152
  {
@@ -160,7 +160,7 @@
160
160
  "dependents": [
161
161
  "/src/adapters/next-app-dir.ts"
162
162
  ],
163
- "percent": 2.35,
163
+ "percent": 2.31,
164
164
  "reduction": 22.57
165
165
  },
166
166
  {
@@ -174,7 +174,7 @@
174
174
  "dependents": [
175
175
  "/src/adapters/node-http/index.ts"
176
176
  ],
177
- "percent": 2.09,
177
+ "percent": 2.05,
178
178
  "reduction": 6.07
179
179
  },
180
180
  {
@@ -190,7 +190,7 @@
190
190
  "dependents": [
191
191
  "/src/observable/index.ts"
192
192
  ],
193
- "percent": 2.01,
193
+ "percent": 1.98,
194
194
  "reduction": 0
195
195
  },
196
196
  {
@@ -210,7 +210,7 @@
210
210
  "/src/unstable-core-do-not-import/initTRPC.ts",
211
211
  "/src/unstable-core-do-not-import/router.ts"
212
212
  ],
213
- "percent": 2,
213
+ "percent": 1.97,
214
214
  "reduction": 45.94
215
215
  },
216
216
  {
@@ -224,7 +224,7 @@
224
224
  "dependents": [
225
225
  "/src/unstable-core-do-not-import.ts"
226
226
  ],
227
- "percent": 1.97,
227
+ "percent": 1.93,
228
228
  "reduction": 40.98
229
229
  },
230
230
  {
@@ -244,7 +244,7 @@
244
244
  "/src/unstable-core-do-not-import/initTRPC.ts",
245
245
  "/src/unstable-core-do-not-import/procedureBuilder.ts"
246
246
  ],
247
- "percent": 1.92,
247
+ "percent": 1.88,
248
248
  "reduction": 55.78
249
249
  },
250
250
  {
@@ -260,7 +260,7 @@
260
260
  "/src/unstable-core-do-not-import.ts",
261
261
  "/src/unstable-core-do-not-import/router.ts"
262
262
  ],
263
- "percent": 1.7,
263
+ "percent": 1.67,
264
264
  "reduction": 0
265
265
  },
266
266
  {
@@ -274,7 +274,7 @@
274
274
  "dependents": [
275
275
  "/src/adapters/fetch/index.ts"
276
276
  ],
277
- "percent": 1.65,
277
+ "percent": 1.62,
278
278
  "reduction": 2.17
279
279
  },
280
280
  {
@@ -289,7 +289,7 @@
289
289
  "/src/adapters/node-http/index.ts",
290
290
  "/src/adapters/node-http/nodeHTTPRequestHandler.ts"
291
291
  ],
292
- "percent": 1.6,
292
+ "percent": 1.57,
293
293
  "reduction": 13.79
294
294
  },
295
295
  {
@@ -303,7 +303,7 @@
303
303
  "dependents": [
304
304
  "/src/adapters/next-app-dir/nextAppDirCaller.ts"
305
305
  ],
306
- "percent": 1.5,
306
+ "percent": 1.47,
307
307
  "reduction": 5.79
308
308
  },
309
309
  {
@@ -317,7 +317,7 @@
317
317
  "dependents": [
318
318
  "/src/adapters/fastify/index.ts"
319
319
  ],
320
- "percent": 1.3,
320
+ "percent": 1.28,
321
321
  "reduction": 29.88
322
322
  },
323
323
  {
@@ -341,7 +341,7 @@
341
341
  "/src/unstable-core-do-not-import/stream/jsonl.ts",
342
342
  "/src/unstable-core-do-not-import/stream/sse.ts"
343
343
  ],
344
- "percent": 1.27,
344
+ "percent": 1.24,
345
345
  "reduction": 19.47
346
346
  },
347
347
  {
@@ -353,7 +353,7 @@
353
353
  ],
354
354
  "removedExports": [],
355
355
  "dependents": [],
356
- "percent": 1.24,
356
+ "percent": 1.22,
357
357
  "reduction": 19.29
358
358
  },
359
359
  {
@@ -366,7 +366,7 @@
366
366
  ],
367
367
  "removedExports": [],
368
368
  "dependents": [],
369
- "percent": 1.18,
369
+ "percent": 1.15,
370
370
  "reduction": 27.47
371
371
  },
372
372
  {
@@ -378,7 +378,7 @@
378
378
  ],
379
379
  "removedExports": [],
380
380
  "dependents": [],
381
- "percent": 1.13,
381
+ "percent": 1.11,
382
382
  "reduction": 26.94
383
383
  },
384
384
  {
@@ -395,7 +395,7 @@
395
395
  "/src/unstable-core-do-not-import/http/resolveResponse.ts",
396
396
  "/src/unstable-core-do-not-import/error/getErrorShape.ts"
397
397
  ],
398
- "percent": 1.05,
398
+ "percent": 1.03,
399
399
  "reduction": 16.73
400
400
  },
401
401
  {
@@ -410,7 +410,7 @@
410
410
  "/src/unstable-core-do-not-import.ts",
411
411
  "/src/unstable-core-do-not-import/procedureBuilder.ts"
412
412
  ],
413
- "percent": 0.95,
413
+ "percent": 0.93,
414
414
  "reduction": 55.21
415
415
  },
416
416
  {
@@ -432,17 +432,17 @@
432
432
  "/src/unstable-core-do-not-import/http/getHTTPStatusCode.ts",
433
433
  "/src/unstable-core-do-not-import/http/parseConnectionParams.ts",
434
434
  "/src/unstable-core-do-not-import/http/resolveResponse.ts",
435
- "/src/unstable-core-do-not-import/rpc/parseTRPCMessage.ts",
436
435
  "/src/unstable-core-do-not-import/error/TRPCError.ts",
437
436
  "/src/unstable-core-do-not-import/transformer.ts",
438
437
  "/src/unstable-core-do-not-import/middleware.ts",
439
438
  "/src/unstable-core-do-not-import/router.ts",
439
+ "/src/unstable-core-do-not-import/rpc/parseTRPCMessage.ts",
440
440
  "/src/unstable-core-do-not-import/http/contentType.ts",
441
441
  "/src/unstable-core-do-not-import/procedureBuilder.ts",
442
442
  "/src/unstable-core-do-not-import/stream/jsonl.ts",
443
443
  "/src/unstable-core-do-not-import/stream/sse.ts"
444
444
  ],
445
- "percent": 0.87,
445
+ "percent": 0.85,
446
446
  "reduction": 28.34
447
447
  },
448
448
  {
@@ -457,7 +457,7 @@
457
457
  "/src/adapters/fastify/index.ts",
458
458
  "/src/adapters/fastify/fastifyTRPCPlugin.ts"
459
459
  ],
460
- "percent": 0.83,
460
+ "percent": 0.81,
461
461
  "reduction": 47.59
462
462
  },
463
463
  {
@@ -473,7 +473,7 @@
473
473
  "/src/unstable-core-do-not-import.ts",
474
474
  "/src/unstable-core-do-not-import/http/contentType.ts"
475
475
  ],
476
- "percent": 0.81,
476
+ "percent": 0.79,
477
477
  "reduction": 15.08
478
478
  },
479
479
  {
@@ -487,7 +487,7 @@
487
487
  "dependents": [
488
488
  "/src/unstable-core-do-not-import.ts"
489
489
  ],
490
- "percent": 0.77,
490
+ "percent": 0.76,
491
491
  "reduction": 0
492
492
  },
493
493
  {
@@ -504,7 +504,7 @@
504
504
  "/src/adapters/next-app-dir/nextAppDirCaller.ts",
505
505
  "/src/adapters/next-app-dir/rethrowNextErrors.ts"
506
506
  ],
507
- "percent": 0.72,
507
+ "percent": 0.71,
508
508
  "reduction": 13.65
509
509
  },
510
510
  {
@@ -522,7 +522,7 @@
522
522
  "/src/unstable-core-do-not-import/stream/sse.ts",
523
523
  "/src/unstable-core-do-not-import/stream/utils/createReadableStream.ts"
524
524
  ],
525
- "percent": 0.72,
525
+ "percent": 0.7,
526
526
  "reduction": 15.69
527
527
  },
528
528
  {
@@ -539,7 +539,7 @@
539
539
  "/src/unstable-core-do-not-import.ts",
540
540
  "/src/unstable-core-do-not-import/stream/sse.ts"
541
541
  ],
542
- "percent": 0.57,
542
+ "percent": 0.56,
543
543
  "reduction": 44.37
544
544
  },
545
545
  {
@@ -551,7 +551,7 @@
551
551
  ],
552
552
  "removedExports": [],
553
553
  "dependents": [],
554
- "percent": 0.55,
554
+ "percent": 0.54,
555
555
  "reduction": 66.9
556
556
  },
557
557
  {
@@ -567,7 +567,7 @@
567
567
  "/src/unstable-core-do-not-import/stream/jsonl.ts",
568
568
  "/src/unstable-core-do-not-import/stream/sse.ts"
569
569
  ],
570
- "percent": 0.52,
570
+ "percent": 0.51,
571
571
  "reduction": 21.32
572
572
  },
573
573
  {
@@ -581,7 +581,7 @@
581
581
  "dependents": [
582
582
  "/src/unstable-core-do-not-import.ts"
583
583
  ],
584
- "percent": 0.49,
584
+ "percent": 0.48,
585
585
  "reduction": 0.6
586
586
  },
587
587
  {
@@ -596,7 +596,7 @@
596
596
  "/src/unstable-core-do-not-import.ts",
597
597
  "/src/unstable-core-do-not-import/http/resolveResponse.ts"
598
598
  ],
599
- "percent": 0.46,
599
+ "percent": 0.45,
600
600
  "reduction": 43.49
601
601
  },
602
602
  {
@@ -609,7 +609,7 @@
609
609
  ],
610
610
  "removedExports": [],
611
611
  "dependents": [],
612
- "percent": 0.38,
612
+ "percent": 0.37,
613
613
  "reduction": 67.09
614
614
  },
615
615
  {
@@ -678,7 +678,7 @@
678
678
  "dependents": [
679
679
  "/src/unstable-core-do-not-import.ts"
680
680
  ],
681
- "percent": 0.12,
681
+ "percent": 0.11,
682
682
  "reduction": 14.13
683
683
  },
684
684
  {
@@ -725,9 +725,9 @@
725
725
  "reduction": 100
726
726
  },
727
727
  {
728
- "id": "/src/rpc.ts",
728
+ "id": "/src/index.ts",
729
729
  "size": 0,
730
- "origSize": 36,
730
+ "origSize": 32,
731
731
  "renderedExports": [],
732
732
  "removedExports": [],
733
733
  "dependents": [],
@@ -735,9 +735,9 @@
735
735
  "reduction": 100
736
736
  },
737
737
  {
738
- "id": "/src/index.ts",
738
+ "id": "/src/rpc.ts",
739
739
  "size": 0,
740
- "origSize": 32,
740
+ "origSize": 36,
741
741
  "renderedExports": [],
742
742
  "removedExports": [],
743
743
  "dependents": [],
@@ -97,6 +97,9 @@ export declare function jsonlStreamConsumer<THead>(opts: {
97
97
  formatError?: (opts: {
98
98
  error: unknown;
99
99
  }) => Error;
100
+ /**
101
+ * This `AbortController` will be triggered when there are no more listeners to the stream.
102
+ */
100
103
  abortController: AbortController | null;
101
104
  }): Promise<readonly [Awaited<THead>, {
102
105
  readonly controllers: Map<ChunkIndex, {
@@ -1 +1 @@
1
- {"version":3,"file":"jsonl.d.ts","sourceRoot":"","sources":["../../../src/unstable-core-do-not-import/stream/jsonl.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"jsonl.d.ts","sourceRoot":"","sources":["../../../src/unstable-core-do-not-import/stream/jsonl.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { ConsumerOnError } from './jsonl';
1
+ import type { MaybePromise } from '../types';
2
2
  import type { inferTrackedOutput } from './tracked';
3
3
  type Serialize = (value: any) => any;
4
4
  type Deserialize = (value: any) => any;
@@ -43,22 +43,41 @@ export interface SSEStreamProducerOptions {
43
43
  * @see https://html.spec.whatwg.org/multipage/server-sent-events.html
44
44
  */
45
45
  export declare function sseStreamProducer(opts: SSEStreamProducerOptions): ReadableStream<string>;
46
- type ConsumerStreamResult<TData> = {
47
- ok: true;
46
+ interface ConsumerStreamResultBase {
47
+ eventSource: EventSource;
48
+ }
49
+ interface ConsumerStreamResultData<TData> extends ConsumerStreamResultBase {
50
+ type: 'data';
48
51
  data: inferTrackedOutput<TData>;
49
- } | {
50
- ok: false;
52
+ }
53
+ interface ConsumerStreamResultError extends ConsumerStreamResultBase {
54
+ type: 'error';
51
55
  error: unknown;
52
- };
56
+ }
57
+ interface ConsumerStreamResultOpened extends ConsumerStreamResultBase {
58
+ type: 'opened';
59
+ }
60
+ interface ConsumerStreamResultConnecting extends ConsumerStreamResultBase {
61
+ type: 'connecting';
62
+ }
63
+ type ConsumerStreamResult<TData> = ConsumerStreamResultData<TData> | ConsumerStreamResultError | ConsumerStreamResultOpened | ConsumerStreamResultConnecting;
64
+ export interface SSEStreamConsumerOptions {
65
+ url: () => MaybePromise<string>;
66
+ init: () => MaybePromise<EventSourceInit> | undefined;
67
+ signal: AbortSignal;
68
+ shouldRecreateOnError?: (opts: {
69
+ type: 'event';
70
+ event: Event;
71
+ } | {
72
+ type: 'serialized-error';
73
+ error: unknown;
74
+ }) => boolean | Promise<boolean>;
75
+ deserialize?: Deserialize;
76
+ }
53
77
  /**
54
78
  * @see https://html.spec.whatwg.org/multipage/server-sent-events.html
55
79
  */
56
- export declare function sseStreamConsumer<TData>(opts: {
57
- from: Pick<EventSource, 'addEventListener' | 'readyState'>;
58
- onError?: ConsumerOnError;
59
- deserialize?: Deserialize;
60
- tryHandleError?: (error: Event) => Promise<boolean>;
61
- }): AsyncIterable<ConsumerStreamResult<TData>>;
80
+ export declare function sseStreamConsumer<TData>(opts: SSEStreamConsumerOptions): AsyncIterable<ConsumerStreamResult<TData>>;
62
81
  export declare const sseHeaders: {
63
82
  readonly 'Content-Type': "text/event-stream";
64
83
  readonly 'Cache-Control': "no-cache, no-transform";
@@ -1 +1 @@
1
- {"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../../src/unstable-core-do-not-import/stream/sse.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAKpD,KAAK,SAAS,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC;AACrC,KAAK,WAAW,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC;CACrD;AAUD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,wBAAwB,0BAoH/D;AAED,KAAK,oBAAoB,CAAC,KAAK,IAC3B;IACE,EAAE,EAAE,IAAI,CAAC;IACT,IAAI,EAAE,kBAAkB,CAAC,KAAK,CAAC,CAAC;CACjC,GACD;IACE,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEN;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,IAAI,EAAE;IAC7C,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,kBAAkB,GAAG,YAAY,CAAC,CAAC;IAC3D,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACrD,GAAG,aAAa,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAgG7C;AAED,eAAO,MAAM,UAAU;;;;;CAKb,CAAC"}
1
+ {"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../../src/unstable-core-do-not-import/stream/sse.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAKpD,KAAK,SAAS,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC;AACrC,KAAK,WAAW,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC;CACrD;AAUD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,wBAAwB,0BAoH/D;AAED,UAAU,wBAAwB;IAChC,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,UAAU,wBAAwB,CAAC,KAAK,CAAE,SAAQ,wBAAwB;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,kBAAkB,CAAC,KAAK,CAAC,CAAC;CACjC;AAED,UAAU,yBAA0B,SAAQ,wBAAwB;IAClE,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,UAAU,0BAA2B,SAAQ,wBAAwB;IACnE,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,UAAU,8BAA+B,SAAQ,wBAAwB;IACvE,IAAI,EAAE,YAAY,CAAC;CACpB;AAED,KAAK,oBAAoB,CAAC,KAAK,IAC3B,wBAAwB,CAAC,KAAK,CAAC,GAC/B,yBAAyB,GACzB,0BAA0B,GAC1B,8BAA8B,CAAC;AAEnC,MAAM,WAAW,wBAAwB;IACvC,GAAG,EAAE,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,YAAY,CAAC,eAAe,CAAC,GAAG,SAAS,CAAC;IACtD,MAAM,EAAE,WAAW,CAAC;IACpB,qBAAqB,CAAC,EAAE,CACtB,IAAI,EACA;QACE,IAAI,EAAE,OAAO,CAAC;QACd,KAAK,EAAE,KAAK,CAAC;KACd,GACD;QACE,IAAI,EAAE,kBAAkB,CAAC;QACzB,KAAK,EAAE,OAAO,CAAC;KAChB,KACF,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AACD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EACrC,IAAI,EAAE,wBAAwB,GAC7B,aAAa,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAkL5C;AAED,eAAO,MAAM,UAAU;;;;;CAKb,CAAC"}
@@ -105,60 +105,141 @@ const SERIALIZED_ERROR_EVENT = 'serialized-error';
105
105
  /**
106
106
  * @see https://html.spec.whatwg.org/multipage/server-sent-events.html
107
107
  */ function sseStreamConsumer(opts) {
108
- const { deserialize =(v)=>v } = opts;
109
- const eventSource = opts.from;
108
+ const { deserialize =(v)=>v , shouldRecreateOnError } = opts;
109
+ const signal = opts.signal;
110
+ let eventSource = null;
111
+ let lock = null;
110
112
  const stream = createReadableStream.createReadableStream();
111
- const transform = new TransformStream({
112
- async transform (chunk, controller) {
113
- const data = deserialize(JSON.parse(chunk.data));
114
- if (chunk.type === SERIALIZED_ERROR_EVENT) {
115
- controller.enqueue({
116
- ok: false,
117
- error: data
118
- });
113
+ function createEventSource(...args) {
114
+ const es = new EventSource(...args);
115
+ if (signal.aborted) {
116
+ es.close();
117
+ } else {
118
+ signal.addEventListener('abort', ()=>es.close());
119
+ }
120
+ /**
121
+ * Dispatch an event to the stream controller
122
+ *
123
+ * Will be a no-op if the event source has been replaced
124
+ */ const dispatch = (fn)=>{
125
+ utils.run(async ()=>{
126
+ while(lock){
127
+ await lock;
128
+ }
129
+ if (es === eventSource) {
130
+ await fn(stream.controller);
131
+ }
132
+ }).catch((error)=>{
133
+ stream.controller.error(error);
134
+ });
135
+ };
136
+ const pauseDispatch = async (fn)=>{
137
+ while(lock){
138
+ await lock;
139
+ }
140
+ if (es !== eventSource) {
119
141
  return;
120
142
  }
121
- // console.debug('transforming', chunk.type, chunk.data);
122
- const def = {
123
- data
124
- };
125
- if (chunk.lastEventId) {
126
- def.id = chunk.lastEventId;
143
+ const deferred = createDeferred.createDeferred();
144
+ lock = deferred.promise;
145
+ try {
146
+ await fn();
147
+ } finally{
148
+ lock = null;
149
+ deferred.resolve();
127
150
  }
128
- controller.enqueue({
129
- ok: true,
130
- data: def
151
+ };
152
+ es.addEventListener('open', ()=>{
153
+ dispatch((controller)=>{
154
+ controller.enqueue({
155
+ type: 'opened',
156
+ eventSource: es
157
+ });
131
158
  });
132
- }
133
- });
134
- let errorLock = undefined;
135
- eventSource.addEventListener('message', (msg)=>{
136
- stream.controller.enqueue(msg);
137
- });
138
- eventSource.addEventListener(SERIALIZED_ERROR_EVENT, (msg)=>{
139
- stream.controller.enqueue(msg);
140
- });
141
- eventSource.addEventListener('error', async (cause)=>{
142
- // We prevent more than 1 error handler from waiting at the same time
143
- const result = await errorLock;
144
- if (result === 'CANCEL_ALL') {
145
- return;
146
- }
147
- const resolvable = createDeferred.createDeferred();
148
- errorLock = resolvable.promise;
149
- const handled = await opts.tryHandleError?.(cause);
150
- resolvable.resolve();
151
- if (handled === true) {
152
- return;
153
- }
154
- if (eventSource.readyState === EventSource.CLOSED) {
155
- stream.controller.error(cause);
156
- }
159
+ });
160
+ es.addEventListener(SERIALIZED_ERROR_EVENT, (msg)=>{
161
+ dispatch(async ()=>{
162
+ if (shouldRecreateOnError) {
163
+ await pauseDispatch(async ()=>{
164
+ const recreate = await shouldRecreateOnError({
165
+ type: SERIALIZED_ERROR_EVENT,
166
+ error: deserialize(JSON.parse(msg.data))
167
+ });
168
+ if (recreate) {
169
+ await recreateEventSource();
170
+ }
171
+ });
172
+ }
173
+ dispatch((controller)=>{
174
+ controller.enqueue({
175
+ type: 'error',
176
+ error: deserialize(JSON.parse(msg.data)),
177
+ eventSource: es
178
+ });
179
+ });
180
+ });
181
+ });
182
+ es.addEventListener('error', (event)=>{
183
+ dispatch(async ()=>{
184
+ if (shouldRecreateOnError) {
185
+ await pauseDispatch(async ()=>{
186
+ const recreate = await shouldRecreateOnError({
187
+ type: 'event',
188
+ event
189
+ });
190
+ if (recreate) {
191
+ await recreateEventSource();
192
+ }
193
+ });
194
+ }
195
+ dispatch((controller)=>{
196
+ if (es.readyState === EventSource.CLOSED) {
197
+ controller.error(event);
198
+ } else {
199
+ controller.enqueue({
200
+ type: 'connecting',
201
+ eventSource: es
202
+ });
203
+ }
204
+ });
205
+ });
206
+ });
207
+ es.addEventListener('message', (msg)=>{
208
+ dispatch((controller)=>{
209
+ const chunk = deserialize(JSON.parse(msg.data));
210
+ const def = {
211
+ data: chunk
212
+ };
213
+ if (msg.lastEventId) {
214
+ def.id = msg.lastEventId;
215
+ }
216
+ controller.enqueue({
217
+ type: 'data',
218
+ data: def,
219
+ eventSource: es
220
+ });
221
+ });
222
+ });
223
+ return es;
224
+ }
225
+ async function recreateEventSource() {
226
+ eventSource?.close();
227
+ const [url, init] = await Promise.all([
228
+ opts.url(),
229
+ opts.init()
230
+ ]);
231
+ eventSource = createEventSource(url, init);
232
+ stream.controller.enqueue({
233
+ type: 'connecting',
234
+ eventSource
235
+ });
236
+ }
237
+ recreateEventSource().catch(()=>{
238
+ // prevent unhandled promise rejection
157
239
  });
158
- const readable = stream.readable.pipeThrough(transform);
159
240
  return {
160
241
  [Symbol.asyncIterator] () {
161
- const reader = readable.getReader();
242
+ const reader = stream.readable.getReader();
162
243
  const iterator = {
163
244
  async next () {
164
245
  const value = await reader.read();
@@ -103,60 +103,141 @@ const SERIALIZED_ERROR_EVENT = 'serialized-error';
103
103
  /**
104
104
  * @see https://html.spec.whatwg.org/multipage/server-sent-events.html
105
105
  */ function sseStreamConsumer(opts) {
106
- const { deserialize =(v)=>v } = opts;
107
- const eventSource = opts.from;
106
+ const { deserialize =(v)=>v , shouldRecreateOnError } = opts;
107
+ const signal = opts.signal;
108
+ let eventSource = null;
109
+ let lock = null;
108
110
  const stream = createReadableStream();
109
- const transform = new TransformStream({
110
- async transform (chunk, controller) {
111
- const data = deserialize(JSON.parse(chunk.data));
112
- if (chunk.type === SERIALIZED_ERROR_EVENT) {
113
- controller.enqueue({
114
- ok: false,
115
- error: data
116
- });
111
+ function createEventSource(...args) {
112
+ const es = new EventSource(...args);
113
+ if (signal.aborted) {
114
+ es.close();
115
+ } else {
116
+ signal.addEventListener('abort', ()=>es.close());
117
+ }
118
+ /**
119
+ * Dispatch an event to the stream controller
120
+ *
121
+ * Will be a no-op if the event source has been replaced
122
+ */ const dispatch = (fn)=>{
123
+ run(async ()=>{
124
+ while(lock){
125
+ await lock;
126
+ }
127
+ if (es === eventSource) {
128
+ await fn(stream.controller);
129
+ }
130
+ }).catch((error)=>{
131
+ stream.controller.error(error);
132
+ });
133
+ };
134
+ const pauseDispatch = async (fn)=>{
135
+ while(lock){
136
+ await lock;
137
+ }
138
+ if (es !== eventSource) {
117
139
  return;
118
140
  }
119
- // console.debug('transforming', chunk.type, chunk.data);
120
- const def = {
121
- data
122
- };
123
- if (chunk.lastEventId) {
124
- def.id = chunk.lastEventId;
141
+ const deferred = createDeferred();
142
+ lock = deferred.promise;
143
+ try {
144
+ await fn();
145
+ } finally{
146
+ lock = null;
147
+ deferred.resolve();
125
148
  }
126
- controller.enqueue({
127
- ok: true,
128
- data: def
149
+ };
150
+ es.addEventListener('open', ()=>{
151
+ dispatch((controller)=>{
152
+ controller.enqueue({
153
+ type: 'opened',
154
+ eventSource: es
155
+ });
129
156
  });
130
- }
131
- });
132
- let errorLock = undefined;
133
- eventSource.addEventListener('message', (msg)=>{
134
- stream.controller.enqueue(msg);
135
- });
136
- eventSource.addEventListener(SERIALIZED_ERROR_EVENT, (msg)=>{
137
- stream.controller.enqueue(msg);
138
- });
139
- eventSource.addEventListener('error', async (cause)=>{
140
- // We prevent more than 1 error handler from waiting at the same time
141
- const result = await errorLock;
142
- if (result === 'CANCEL_ALL') {
143
- return;
144
- }
145
- const resolvable = createDeferred();
146
- errorLock = resolvable.promise;
147
- const handled = await opts.tryHandleError?.(cause);
148
- resolvable.resolve();
149
- if (handled === true) {
150
- return;
151
- }
152
- if (eventSource.readyState === EventSource.CLOSED) {
153
- stream.controller.error(cause);
154
- }
157
+ });
158
+ es.addEventListener(SERIALIZED_ERROR_EVENT, (msg)=>{
159
+ dispatch(async ()=>{
160
+ if (shouldRecreateOnError) {
161
+ await pauseDispatch(async ()=>{
162
+ const recreate = await shouldRecreateOnError({
163
+ type: SERIALIZED_ERROR_EVENT,
164
+ error: deserialize(JSON.parse(msg.data))
165
+ });
166
+ if (recreate) {
167
+ await recreateEventSource();
168
+ }
169
+ });
170
+ }
171
+ dispatch((controller)=>{
172
+ controller.enqueue({
173
+ type: 'error',
174
+ error: deserialize(JSON.parse(msg.data)),
175
+ eventSource: es
176
+ });
177
+ });
178
+ });
179
+ });
180
+ es.addEventListener('error', (event)=>{
181
+ dispatch(async ()=>{
182
+ if (shouldRecreateOnError) {
183
+ await pauseDispatch(async ()=>{
184
+ const recreate = await shouldRecreateOnError({
185
+ type: 'event',
186
+ event
187
+ });
188
+ if (recreate) {
189
+ await recreateEventSource();
190
+ }
191
+ });
192
+ }
193
+ dispatch((controller)=>{
194
+ if (es.readyState === EventSource.CLOSED) {
195
+ controller.error(event);
196
+ } else {
197
+ controller.enqueue({
198
+ type: 'connecting',
199
+ eventSource: es
200
+ });
201
+ }
202
+ });
203
+ });
204
+ });
205
+ es.addEventListener('message', (msg)=>{
206
+ dispatch((controller)=>{
207
+ const chunk = deserialize(JSON.parse(msg.data));
208
+ const def = {
209
+ data: chunk
210
+ };
211
+ if (msg.lastEventId) {
212
+ def.id = msg.lastEventId;
213
+ }
214
+ controller.enqueue({
215
+ type: 'data',
216
+ data: def,
217
+ eventSource: es
218
+ });
219
+ });
220
+ });
221
+ return es;
222
+ }
223
+ async function recreateEventSource() {
224
+ eventSource?.close();
225
+ const [url, init] = await Promise.all([
226
+ opts.url(),
227
+ opts.init()
228
+ ]);
229
+ eventSource = createEventSource(url, init);
230
+ stream.controller.enqueue({
231
+ type: 'connecting',
232
+ eventSource
233
+ });
234
+ }
235
+ recreateEventSource().catch(()=>{
236
+ // prevent unhandled promise rejection
155
237
  });
156
- const readable = stream.readable.pipeThrough(transform);
157
238
  return {
158
239
  [Symbol.asyncIterator] () {
159
- const reader = readable.getReader();
240
+ const reader = stream.readable.getReader();
160
241
  const iterator = {
161
242
  async next () {
162
243
  const value = await reader.read();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trpc/server",
3
- "version": "11.0.0-rc.560+137b085f8",
3
+ "version": "11.0.0-rc.561+c50cd4308",
4
4
  "description": "The tRPC server library",
5
5
  "author": "KATT",
6
6
  "license": "MIT",
@@ -149,5 +149,5 @@
149
149
  "funding": [
150
150
  "https://trpc.io/sponsor"
151
151
  ],
152
- "gitHead": "137b085f86cb4ceb397b29c69ccbe38a93dbe79a"
152
+ "gitHead": "c50cd4308223508184310103938d1fee50046989"
153
153
  }
@@ -436,6 +436,9 @@ export async function jsonlStreamConsumer<THead>(opts: {
436
436
  deserialize?: Deserialize;
437
437
  onError?: ConsumerOnError;
438
438
  formatError?: (opts: { error: unknown }) => Error;
439
+ /**
440
+ * This `AbortController` will be triggered when there are no more listeners to the stream.
441
+ */
439
442
  abortController: AbortController | null;
440
443
  }) {
441
444
  const { deserialize = (v) => v } = opts;
@@ -1,6 +1,6 @@
1
1
  import { getTRPCErrorFromUnknown } from '../error/TRPCError';
2
+ import type { MaybePromise } from '../types';
2
3
  import { run } from '../utils';
3
- import type { ConsumerOnError } from './jsonl';
4
4
  import type { inferTrackedOutput } from './tracked';
5
5
  import { isTrackedEnvelope } from './tracked';
6
6
  import { createDeferred, createTimeoutPromise } from './utils/createDeferred';
@@ -175,98 +175,212 @@ export function sseStreamProducer(opts: SSEStreamProducerOptions) {
175
175
  );
176
176
  }
177
177
 
178
- type ConsumerStreamResult<TData> =
179
- | {
180
- ok: true;
181
- data: inferTrackedOutput<TData>;
182
- }
183
- | {
184
- ok: false;
185
- error: unknown;
186
- };
178
+ interface ConsumerStreamResultBase {
179
+ eventSource: EventSource;
180
+ }
181
+
182
+ interface ConsumerStreamResultData<TData> extends ConsumerStreamResultBase {
183
+ type: 'data';
184
+ data: inferTrackedOutput<TData>;
185
+ }
186
+
187
+ interface ConsumerStreamResultError extends ConsumerStreamResultBase {
188
+ type: 'error';
189
+ error: unknown;
190
+ }
187
191
 
192
+ interface ConsumerStreamResultOpened extends ConsumerStreamResultBase {
193
+ type: 'opened';
194
+ }
195
+
196
+ interface ConsumerStreamResultConnecting extends ConsumerStreamResultBase {
197
+ type: 'connecting';
198
+ }
199
+
200
+ type ConsumerStreamResult<TData> =
201
+ | ConsumerStreamResultData<TData>
202
+ | ConsumerStreamResultError
203
+ | ConsumerStreamResultOpened
204
+ | ConsumerStreamResultConnecting;
205
+
206
+ export interface SSEStreamConsumerOptions {
207
+ url: () => MaybePromise<string>;
208
+ init: () => MaybePromise<EventSourceInit> | undefined;
209
+ signal: AbortSignal;
210
+ shouldRecreateOnError?: (
211
+ opts:
212
+ | {
213
+ type: 'event';
214
+ event: Event;
215
+ }
216
+ | {
217
+ type: 'serialized-error';
218
+ error: unknown;
219
+ },
220
+ ) => boolean | Promise<boolean>;
221
+ deserialize?: Deserialize;
222
+ }
188
223
  /**
189
224
  * @see https://html.spec.whatwg.org/multipage/server-sent-events.html
190
225
  */
191
- export function sseStreamConsumer<TData>(opts: {
192
- from: Pick<EventSource, 'addEventListener' | 'readyState'>;
193
- onError?: ConsumerOnError;
194
- deserialize?: Deserialize;
195
- tryHandleError?: (error: Event) => Promise<boolean>;
196
- }): AsyncIterable<ConsumerStreamResult<TData>> {
197
- const { deserialize = (v) => v } = opts;
198
- const eventSource = opts.from;
199
-
200
- const stream = createReadableStream<MessageEvent>();
201
-
202
- const transform = new TransformStream<
203
- MessageEvent,
204
- ConsumerStreamResult<TData>
205
- >({
206
- async transform(chunk, controller) {
207
- const data = deserialize(JSON.parse(chunk.data));
208
- if (chunk.type === SERIALIZED_ERROR_EVENT) {
209
- controller.enqueue({
210
- ok: false,
211
- error: data,
212
- });
213
- return;
214
- }
215
- // console.debug('transforming', chunk.type, chunk.data);
216
- const def: SSEvent = {
217
- data,
218
- };
226
+ export function sseStreamConsumer<TData>(
227
+ opts: SSEStreamConsumerOptions,
228
+ ): AsyncIterable<ConsumerStreamResult<TData>> {
229
+ const { deserialize = (v) => v, shouldRecreateOnError } = opts;
219
230
 
220
- if (chunk.lastEventId) {
221
- def.id = chunk.lastEventId;
222
- }
231
+ const signal = opts.signal;
223
232
 
224
- controller.enqueue({
225
- ok: true,
226
- data: def as inferTrackedOutput<TData>,
227
- });
228
- },
229
- });
233
+ let eventSource: EventSource | null = null;
234
+ let lock: Promise<void> | null = null;
230
235
 
231
- let errorLock: Promise<void | 'CANCEL_ALL'> | undefined = undefined;
232
- eventSource.addEventListener('message', (msg) => {
233
- stream.controller.enqueue(msg);
234
- });
235
- eventSource.addEventListener(SERIALIZED_ERROR_EVENT, (msg) => {
236
- stream.controller.enqueue(msg);
237
- });
238
- eventSource.addEventListener('error', async (cause) => {
239
- // We prevent more than 1 error handler from waiting at the same time
240
- const result = await errorLock;
241
- if (result === 'CANCEL_ALL') {
242
- return;
243
- }
236
+ const stream = createReadableStream<ConsumerStreamResult<TData>>();
244
237
 
245
- const resolvable = createDeferred<void | 'CANCEL_ALL'>();
246
- errorLock = resolvable.promise;
238
+ function createEventSource(
239
+ ...args: ConstructorParameters<typeof EventSource>
240
+ ) {
241
+ const es = new EventSource(...args);
247
242
 
248
- const handled = await opts.tryHandleError?.(cause);
243
+ if (signal.aborted) {
244
+ es.close();
245
+ } else {
246
+ signal.addEventListener('abort', () => es.close());
247
+ }
249
248
 
250
- resolvable.resolve();
249
+ /**
250
+ * Dispatch an event to the stream controller
251
+ *
252
+ * Will be a no-op if the event source has been replaced
253
+ */
254
+ const dispatch = (
255
+ fn: (controller: typeof stream.controller) => void | Promise<void>,
256
+ ): void => {
257
+ run(async () => {
258
+ while (lock) {
259
+ await lock;
260
+ }
261
+ if (es === eventSource) {
262
+ await fn(stream.controller);
263
+ }
264
+ }).catch((error) => {
265
+ stream.controller.error(error);
266
+ });
267
+ };
251
268
 
252
- if (handled === true) {
253
- return;
254
- }
269
+ const pauseDispatch = async (fn: () => Promise<void>): Promise<void> => {
270
+ while (lock) {
271
+ await lock;
272
+ }
273
+ if (es !== eventSource) {
274
+ return;
275
+ }
255
276
 
256
- if (eventSource.readyState === EventSource.CLOSED) {
257
- stream.controller.error(cause);
258
- }
259
- });
277
+ const deferred = createDeferred<void>();
278
+ lock = deferred.promise;
279
+ try {
280
+ await fn();
281
+ } finally {
282
+ lock = null;
283
+ deferred.resolve();
284
+ }
285
+ };
260
286
 
261
- const readable = stream.readable.pipeThrough(transform);
287
+ es.addEventListener('open', () => {
288
+ dispatch((controller) => {
289
+ controller.enqueue({
290
+ type: 'opened',
291
+ eventSource: es,
292
+ });
293
+ });
294
+ });
295
+
296
+ es.addEventListener(SERIALIZED_ERROR_EVENT, (msg) => {
297
+ dispatch(async () => {
298
+ if (shouldRecreateOnError) {
299
+ await pauseDispatch(async () => {
300
+ const recreate = await shouldRecreateOnError({
301
+ type: SERIALIZED_ERROR_EVENT,
302
+ error: deserialize(JSON.parse(msg.data)),
303
+ });
304
+ if (recreate) {
305
+ await recreateEventSource();
306
+ }
307
+ });
308
+ }
309
+ dispatch((controller) => {
310
+ controller.enqueue({
311
+ type: 'error',
312
+ error: deserialize(JSON.parse(msg.data)),
313
+ eventSource: es,
314
+ });
315
+ });
316
+ });
317
+ });
318
+ es.addEventListener('error', (event) => {
319
+ dispatch(async () => {
320
+ if (shouldRecreateOnError) {
321
+ await pauseDispatch(async () => {
322
+ const recreate = await shouldRecreateOnError({
323
+ type: 'event',
324
+ event,
325
+ });
326
+ if (recreate) {
327
+ await recreateEventSource();
328
+ }
329
+ });
330
+ }
262
331
 
332
+ dispatch((controller) => {
333
+ if (es.readyState === EventSource.CLOSED) {
334
+ controller.error(event);
335
+ } else {
336
+ controller.enqueue({
337
+ type: 'connecting',
338
+ eventSource: es,
339
+ });
340
+ }
341
+ });
342
+ });
343
+ });
344
+ es.addEventListener('message', (msg) => {
345
+ dispatch((controller) => {
346
+ const chunk = deserialize(JSON.parse(msg.data));
347
+
348
+ const def: SSEvent = {
349
+ data: chunk,
350
+ };
351
+ if (msg.lastEventId) {
352
+ def.id = msg.lastEventId;
353
+ }
354
+ controller.enqueue({
355
+ type: 'data',
356
+ data: def as inferTrackedOutput<TData>,
357
+ eventSource: es,
358
+ });
359
+ });
360
+ });
361
+ return es;
362
+ }
363
+ async function recreateEventSource() {
364
+ eventSource?.close();
365
+ const [url, init] = await Promise.all([opts.url(), opts.init()]);
366
+ eventSource = createEventSource(url, init);
367
+ stream.controller.enqueue({
368
+ type: 'connecting',
369
+ eventSource,
370
+ });
371
+ }
372
+
373
+ recreateEventSource().catch(() => {
374
+ // prevent unhandled promise rejection
375
+ });
263
376
  return {
264
377
  [Symbol.asyncIterator]() {
265
- const reader = readable.getReader();
378
+ const reader = stream.readable.getReader();
266
379
 
267
380
  const iterator: AsyncIterator<ConsumerStreamResult<TData>> = {
268
381
  async next() {
269
382
  const value = await reader.read();
383
+
270
384
  if (value.done) {
271
385
  return {
272
386
  value: undefined,