@trpc/client 11.0.0-rc.553 → 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": 54227,
3
- "bundleOrigSize": 71929,
4
- "bundleReduction": 24.61,
2
+ "bundleSize": 54651,
3
+ "bundleOrigSize": 72819,
4
+ "bundleReduction": 24.95,
5
5
  "modules": [
6
6
  {
7
7
  "id": "/src/links/wsLink.ts",
@@ -13,20 +13,20 @@
13
13
  ],
14
14
  "removedExports": [],
15
15
  "dependents": [],
16
- "percent": 28.17,
16
+ "percent": 27.96,
17
17
  "reduction": 10.13
18
18
  },
19
19
  {
20
20
  "id": "/src/links/httpBatchStreamLink.ts",
21
- "size": 5861,
22
- "origSize": 6074,
21
+ "size": 6007,
22
+ "origSize": 6284,
23
23
  "renderedExports": [
24
24
  "unstable_httpBatchStreamLink"
25
25
  ],
26
26
  "removedExports": [],
27
27
  "dependents": [],
28
- "percent": 10.81,
29
- "reduction": 3.51
28
+ "percent": 10.99,
29
+ "reduction": 4.41
30
30
  },
31
31
  {
32
32
  "id": "/src/links/loggerLink.ts",
@@ -37,33 +37,9 @@
37
37
  ],
38
38
  "removedExports": [],
39
39
  "dependents": [],
40
- "percent": 10.06,
40
+ "percent": 9.98,
41
41
  "reduction": 18.48
42
42
  },
43
- {
44
- "id": "/src/links/internals/httpUtils.ts",
45
- "size": 4465,
46
- "origSize": 6645,
47
- "renderedExports": [
48
- "resolveHTTPLinkOptions",
49
- "getInput",
50
- "getUrl",
51
- "getBody",
52
- "jsonHttpRequester",
53
- "fetchHTTPResponse",
54
- "httpRequest",
55
- "mergeAbortSignals"
56
- ],
57
- "removedExports": [],
58
- "dependents": [
59
- "/src/links/httpBatchLink.ts",
60
- "/src/links/httpLink.ts",
61
- "/src/links/httpBatchStreamLink.ts",
62
- "/src/links/httpSubscriptionLink.ts"
63
- ],
64
- "percent": 8.23,
65
- "reduction": 32.81
66
- },
67
43
  {
68
44
  "id": "/src/internals/dataLoader.ts",
69
45
  "size": 4084,
@@ -76,32 +52,55 @@
76
52
  "/src/links/httpBatchLink.ts",
77
53
  "/src/links/httpBatchStreamLink.ts"
78
54
  ],
79
- "percent": 7.53,
55
+ "percent": 7.47,
80
56
  "reduction": 5.64
81
57
  },
82
58
  {
83
59
  "id": "/src/links/httpBatchLink.ts",
84
- "size": 3925,
85
- "origSize": 4118,
60
+ "size": 3938,
61
+ "origSize": 4170,
86
62
  "renderedExports": [
87
63
  "httpBatchLink"
88
64
  ],
89
65
  "removedExports": [],
90
66
  "dependents": [],
91
- "percent": 7.24,
92
- "reduction": 4.69
67
+ "percent": 7.21,
68
+ "reduction": 5.56
93
69
  },
94
70
  {
95
71
  "id": "/src/links/httpSubscriptionLink.ts",
96
- "size": 3805,
97
- "origSize": 4221,
72
+ "size": 3776,
73
+ "origSize": 4507,
98
74
  "renderedExports": [
99
75
  "unstable_httpSubscriptionLink"
100
76
  ],
101
77
  "removedExports": [],
102
78
  "dependents": [],
103
- "percent": 7.02,
104
- "reduction": 9.86
79
+ "percent": 6.91,
80
+ "reduction": 16.22
81
+ },
82
+ {
83
+ "id": "/src/links/internals/httpUtils.ts",
84
+ "size": 3693,
85
+ "origSize": 5873,
86
+ "renderedExports": [
87
+ "resolveHTTPLinkOptions",
88
+ "getInput",
89
+ "getUrl",
90
+ "getBody",
91
+ "jsonHttpRequester",
92
+ "fetchHTTPResponse",
93
+ "httpRequest"
94
+ ],
95
+ "removedExports": [],
96
+ "dependents": [
97
+ "/src/links/httpBatchLink.ts",
98
+ "/src/links/httpLink.ts",
99
+ "/src/links/httpBatchStreamLink.ts",
100
+ "/src/links/httpSubscriptionLink.ts"
101
+ ],
102
+ "percent": 6.76,
103
+ "reduction": 37.12
105
104
  },
106
105
  {
107
106
  "id": "/src/links/httpLink.ts",
@@ -112,13 +111,13 @@
112
111
  ],
113
112
  "removedExports": [],
114
113
  "dependents": [],
115
- "percent": 5.87,
114
+ "percent": 5.82,
116
115
  "reduction": 14.14
117
116
  },
118
117
  {
119
118
  "id": "/src/internals/TRPCUntypedClient.ts",
120
- "size": 2162,
121
- "origSize": 4228,
119
+ "size": 2169,
120
+ "origSize": 4235,
122
121
  "renderedExports": [
123
122
  "TRPCUntypedClient"
124
123
  ],
@@ -127,8 +126,8 @@
127
126
  "/src/createTRPCUntypedClient.ts",
128
127
  "/src/createTRPCClient.ts"
129
128
  ],
130
- "percent": 3.99,
131
- "reduction": 48.86
129
+ "percent": 3.97,
130
+ "reduction": 48.78
132
131
  },
133
132
  {
134
133
  "id": "/src/TRPCClientError.ts",
@@ -141,13 +140,13 @@
141
140
  "dependents": [
142
141
  "/src/index.ts",
143
142
  "/src/links/httpBatchLink.ts",
144
- "/src/links/wsLink.ts",
145
143
  "/src/links/httpLink.ts",
144
+ "/src/links/wsLink.ts",
146
145
  "/src/links/httpBatchStreamLink.ts",
147
146
  "/src/links/httpSubscriptionLink.ts",
148
147
  "/src/internals/TRPCUntypedClient.ts"
149
148
  ],
150
- "percent": 3.58,
149
+ "percent": 3.55,
151
150
  "reduction": 45.43
152
151
  },
153
152
  {
@@ -164,9 +163,26 @@
164
163
  "dependents": [
165
164
  "/src/index.ts"
166
165
  ],
167
- "percent": 2.19,
166
+ "percent": 2.17,
168
167
  "reduction": 73.19
169
168
  },
169
+ {
170
+ "id": "/src/internals/signals.ts",
171
+ "size": 1059,
172
+ "origSize": 1107,
173
+ "renderedExports": [
174
+ "allAbortSignals",
175
+ "raceAbortSignals"
176
+ ],
177
+ "removedExports": [],
178
+ "dependents": [
179
+ "/src/links/httpBatchLink.ts",
180
+ "/src/links/httpBatchStreamLink.ts",
181
+ "/src/links/httpSubscriptionLink.ts"
182
+ ],
183
+ "percent": 1.94,
184
+ "reduction": 4.34
185
+ },
170
186
  {
171
187
  "id": "/src/links/internals/createChain.ts",
172
188
  "size": 690,
@@ -179,7 +195,7 @@
179
195
  "/src/links/splitLink.ts",
180
196
  "/src/internals/TRPCUntypedClient.ts"
181
197
  ],
182
- "percent": 1.27,
198
+ "percent": 1.26,
183
199
  "reduction": 32.75
184
200
  },
185
201
  {
@@ -205,7 +221,7 @@
205
221
  "dependents": [
206
222
  "/src/unstable-internals.ts"
207
223
  ],
208
- "percent": 1.04,
224
+ "percent": 1.03,
209
225
  "reduction": 66.71
210
226
  },
211
227
  {
@@ -220,7 +236,7 @@
220
236
  "/src/index.ts",
221
237
  "/src/links/internals/httpUtils.ts"
222
238
  ],
223
- "percent": 0.79,
239
+ "percent": 0.78,
224
240
  "reduction": 33.54
225
241
  },
226
242
  {
@@ -234,7 +250,7 @@
234
250
  ],
235
251
  "removedExports": [],
236
252
  "dependents": [],
237
- "percent": 0.61,
253
+ "percent": 0.6,
238
254
  "reduction": 15.17
239
255
  },
240
256
  {
@@ -291,5 +307,5 @@
291
307
  "reduction": 100
292
308
  }
293
309
  ],
294
- "moduleCount": 20
310
+ "moduleCount": 21
295
311
  }
@@ -50,7 +50,7 @@ class TRPCUntypedClient {
50
50
  path,
51
51
  input,
52
52
  context: opts?.context,
53
- signal: null
53
+ signal: opts.signal
54
54
  });
55
55
  return observable$.subscribe({
56
56
  next (envelope) {
@@ -48,7 +48,7 @@ class TRPCUntypedClient {
48
48
  path,
49
49
  input,
50
50
  context: opts?.context,
51
- signal: null
51
+ signal: opts.signal
52
52
  });
53
53
  return observable$.subscribe({
54
54
  next (envelope) {
@@ -0,0 +1,12 @@
1
+ import type { Maybe } from '@trpc/server/unstable-core-do-not-import';
2
+ /**
3
+ * Like `Promise.all()` but for abort signals
4
+ * - When all signals have been aborted, the merged signal will be aborted
5
+ * - If one signal is `null`, no signal will be aborted
6
+ */
7
+ export declare function allAbortSignals(...signals: Maybe<AbortSignal>[]): AbortSignal;
8
+ /**
9
+ * Like `Promise.race` but for abort signals
10
+ */
11
+ export declare function raceAbortSignals(...signals: Maybe<AbortSignal>[]): AbortSignal;
12
+ //# sourceMappingURL=signals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signals.d.ts","sourceRoot":"","sources":["../../src/internals/signals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0CAA0C,CAAC;AAEtE;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,WAAW,CAAC,EAAE,GAAG,WAAW,CAwB7E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,OAAO,EAAE,KAAK,CAAC,WAAW,CAAC,EAAE,GAC/B,WAAW,CAYb"}
@@ -0,0 +1,44 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Like `Promise.all()` but for abort signals
5
+ * - When all signals have been aborted, the merged signal will be aborted
6
+ * - If one signal is `null`, no signal will be aborted
7
+ */ function allAbortSignals(...signals) {
8
+ const ac = new AbortController();
9
+ const count = signals.length;
10
+ let abortedCount = 0;
11
+ const onAbort = ()=>{
12
+ if (++abortedCount === count) {
13
+ ac.abort();
14
+ }
15
+ };
16
+ for (const signal of signals){
17
+ if (signal?.aborted) {
18
+ onAbort();
19
+ } else {
20
+ signal?.addEventListener('abort', onAbort, {
21
+ once: true
22
+ });
23
+ }
24
+ }
25
+ return ac.signal;
26
+ }
27
+ /**
28
+ * Like `Promise.race` but for abort signals
29
+ */ function raceAbortSignals(...signals) {
30
+ const ac = new AbortController();
31
+ for (const signal of signals){
32
+ if (signal?.aborted) {
33
+ ac.abort();
34
+ } else {
35
+ signal?.addEventListener('abort', ()=>ac.abort(), {
36
+ once: true
37
+ });
38
+ }
39
+ }
40
+ return ac.signal;
41
+ }
42
+
43
+ exports.allAbortSignals = allAbortSignals;
44
+ exports.raceAbortSignals = raceAbortSignals;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Like `Promise.all()` but for abort signals
3
+ * - When all signals have been aborted, the merged signal will be aborted
4
+ * - If one signal is `null`, no signal will be aborted
5
+ */ function allAbortSignals(...signals) {
6
+ const ac = new AbortController();
7
+ const count = signals.length;
8
+ let abortedCount = 0;
9
+ const onAbort = ()=>{
10
+ if (++abortedCount === count) {
11
+ ac.abort();
12
+ }
13
+ };
14
+ for (const signal of signals){
15
+ if (signal?.aborted) {
16
+ onAbort();
17
+ } else {
18
+ signal?.addEventListener('abort', onAbort, {
19
+ once: true
20
+ });
21
+ }
22
+ }
23
+ return ac.signal;
24
+ }
25
+ /**
26
+ * Like `Promise.race` but for abort signals
27
+ */ function raceAbortSignals(...signals) {
28
+ const ac = new AbortController();
29
+ for (const signal of signals){
30
+ if (signal?.aborted) {
31
+ ac.abort();
32
+ } else {
33
+ signal?.addEventListener('abort', ()=>ac.abort(), {
34
+ once: true
35
+ });
36
+ }
37
+ }
38
+ return ac.signal;
39
+ }
40
+
41
+ export { allAbortSignals, raceAbortSignals };
@@ -1 +1 @@
1
- {"version":3,"file":"httpBatchLink.d.ts","sourceRoot":"","sources":["../../src/links/httpBatchLink.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAiB,MAAM,cAAc,CAAC;AAO7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAQnE,OAAO,KAAK,EAAa,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnD;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,SAAS,SAAS,EACrD,IAAI,EAAE,oBAAoB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GAC/D,QAAQ,CAAC,OAAO,CAAC,CAkHnB"}
1
+ {"version":3,"file":"httpBatchLink.d.ts","sourceRoot":"","sources":["../../src/links/httpBatchLink.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAiB,MAAM,cAAc,CAAC;AAQ7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAOnE,OAAO,KAAK,EAAa,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnD;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,SAAS,SAAS,EACrD,IAAI,EAAE,oBAAoB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GAC/D,QAAQ,CAAC,OAAO,CAAC,CAkHnB"}
@@ -3,6 +3,7 @@
3
3
  var observable = require('@trpc/server/observable');
4
4
  var unstableCoreDoNotImport = require('@trpc/server/unstable-core-do-not-import');
5
5
  var dataLoader = require('../internals/dataLoader.js');
6
+ var signals = require('../internals/signals.js');
6
7
  var TRPCClientError = require('../TRPCClientError.js');
7
8
  var httpUtils = require('./internals/httpUtils.js');
8
9
 
@@ -33,7 +34,7 @@ var httpUtils = require('./internals/httpUtils.js');
33
34
  async fetch (batchOps) {
34
35
  const path = batchOps.map((op)=>op.path).join(',');
35
36
  const inputs = batchOps.map((op)=>op.input);
36
- const ac = httpUtils.mergeAbortSignals(batchOps);
37
+ const signal = signals.allAbortSignals(...batchOps.map((op)=>op.signal));
37
38
  const res = await httpUtils.jsonHttpRequester({
38
39
  ...resolvedOpts,
39
40
  path,
@@ -50,7 +51,7 @@ var httpUtils = require('./internals/httpUtils.js');
50
51
  }
51
52
  return opts.headers;
52
53
  },
53
- signal: ac.signal
54
+ signal
54
55
  });
55
56
  const resJSON = Array.isArray(res.json) ? res.json : batchOps.map(()=>res.json);
56
57
  const result = resJSON.map((item)=>({
@@ -1,8 +1,9 @@
1
1
  import { observable } from '@trpc/server/observable';
2
2
  import { transformResult } from '@trpc/server/unstable-core-do-not-import';
3
3
  import { dataLoader } from '../internals/dataLoader.mjs';
4
+ import { allAbortSignals } from '../internals/signals.mjs';
4
5
  import { TRPCClientError } from '../TRPCClientError.mjs';
5
- import { resolveHTTPLinkOptions, getUrl, mergeAbortSignals, jsonHttpRequester } from './internals/httpUtils.mjs';
6
+ import { resolveHTTPLinkOptions, getUrl, jsonHttpRequester } from './internals/httpUtils.mjs';
6
7
 
7
8
  /**
8
9
  * @see https://trpc.io/docs/client/links/httpBatchLink
@@ -31,7 +32,7 @@ import { resolveHTTPLinkOptions, getUrl, mergeAbortSignals, jsonHttpRequester }
31
32
  async fetch (batchOps) {
32
33
  const path = batchOps.map((op)=>op.path).join(',');
33
34
  const inputs = batchOps.map((op)=>op.input);
34
- const ac = mergeAbortSignals(batchOps);
35
+ const signal = allAbortSignals(...batchOps.map((op)=>op.signal));
35
36
  const res = await jsonHttpRequester({
36
37
  ...resolvedOpts,
37
38
  path,
@@ -48,7 +49,7 @@ import { resolveHTTPLinkOptions, getUrl, mergeAbortSignals, jsonHttpRequester }
48
49
  }
49
50
  return opts.headers;
50
51
  },
51
- signal: ac.signal
52
+ signal
52
53
  });
53
54
  const resJSON = Array.isArray(res.json) ? res.json : batchOps.map(()=>res.json);
54
55
  const result = resJSON.map((item)=>({
@@ -1 +1 @@
1
- {"version":3,"file":"httpBatchStreamLink.d.ts","sourceRoot":"","sources":["../../src/links/httpBatchStreamLink.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAiB,MAAM,cAAc,CAAC;AAG7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0CAA0C,CAAC;AAM7E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AASnE,OAAO,KAAK,EAAa,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnD,MAAM,MAAM,0BAA0B,CAAC,KAAK,SAAS,YAAY,IAC/D,oBAAoB,CAAC,KAAK,CAAC,GAAG;IAC5B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEJ;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,SAAS,SAAS,EACpE,IAAI,EAAE,0BAA0B,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GACrE,QAAQ,CAAC,OAAO,CAAC,CA6JnB"}
1
+ {"version":3,"file":"httpBatchStreamLink.d.ts","sourceRoot":"","sources":["../../src/links/httpBatchStreamLink.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAiB,MAAM,cAAc,CAAC;AAG7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0CAA0C,CAAC;AAO7E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAQnE,OAAO,KAAK,EAAa,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnD,MAAM,MAAM,0BAA0B,CAAC,KAAK,SAAS,YAAY,IAC/D,oBAAoB,CAAC,KAAK,CAAC,GAAG;IAC5B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEJ;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,SAAS,SAAS,EACpE,IAAI,EAAE,0BAA0B,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GACrE,QAAQ,CAAC,OAAO,CAAC,CAgKnB"}
@@ -3,6 +3,7 @@
3
3
  var observable = require('@trpc/server/observable');
4
4
  var unstableCoreDoNotImport = require('@trpc/server/unstable-core-do-not-import');
5
5
  var dataLoader = require('../internals/dataLoader.js');
6
+ var signals = require('../internals/signals.js');
6
7
  var TRPCClientError = require('../TRPCClientError.js');
7
8
  var httpUtils = require('./internals/httpUtils.js');
8
9
 
@@ -37,10 +38,11 @@ var httpUtils = require('./internals/httpUtils.js');
37
38
  async fetch (batchOps) {
38
39
  const path = batchOps.map((op)=>op.path).join(',');
39
40
  const inputs = batchOps.map((op)=>op.input);
40
- const ac = httpUtils.mergeAbortSignals(batchOps);
41
+ const batchSignals = signals.allAbortSignals(...batchOps.map((op)=>op.signal));
42
+ const abortController = new AbortController();
41
43
  const responsePromise = httpUtils.fetchHTTPResponse({
42
44
  ...resolvedOpts,
43
- signal: ac.signal,
45
+ signal: signals.raceAbortSignals(batchSignals, abortController.signal),
44
46
  type,
45
47
  contentTypeHeader: 'application/json',
46
48
  trpcAcceptHeader: 'application/jsonl',
@@ -72,7 +74,7 @@ var httpUtils = require('./internals/httpUtils.js');
72
74
  error
73
75
  });
74
76
  },
75
- abortController: ac
77
+ abortController
76
78
  });
77
79
  const promises = Object.keys(batchOps).map(async (key)=>{
78
80
  let json = await Promise.resolve(head[key]);
@@ -1,8 +1,9 @@
1
1
  import { observable } from '@trpc/server/observable';
2
2
  import { jsonlStreamConsumer } from '@trpc/server/unstable-core-do-not-import';
3
3
  import { dataLoader } from '../internals/dataLoader.mjs';
4
+ import { allAbortSignals, raceAbortSignals } from '../internals/signals.mjs';
4
5
  import { TRPCClientError } from '../TRPCClientError.mjs';
5
- import { resolveHTTPLinkOptions, getUrl, mergeAbortSignals, fetchHTTPResponse, getBody } from './internals/httpUtils.mjs';
6
+ import { resolveHTTPLinkOptions, getUrl, fetchHTTPResponse, getBody } from './internals/httpUtils.mjs';
6
7
 
7
8
  /**
8
9
  * @see https://trpc.io/docs/client/links/httpBatchStreamLink
@@ -35,10 +36,11 @@ import { resolveHTTPLinkOptions, getUrl, mergeAbortSignals, fetchHTTPResponse, g
35
36
  async fetch (batchOps) {
36
37
  const path = batchOps.map((op)=>op.path).join(',');
37
38
  const inputs = batchOps.map((op)=>op.input);
38
- const ac = mergeAbortSignals(batchOps);
39
+ const batchSignals = allAbortSignals(...batchOps.map((op)=>op.signal));
40
+ const abortController = new AbortController();
39
41
  const responsePromise = fetchHTTPResponse({
40
42
  ...resolvedOpts,
41
- signal: ac.signal,
43
+ signal: raceAbortSignals(batchSignals, abortController.signal),
42
44
  type,
43
45
  contentTypeHeader: 'application/json',
44
46
  trpcAcceptHeader: 'application/jsonl',
@@ -70,7 +72,7 @@ import { resolveHTTPLinkOptions, getUrl, mergeAbortSignals, fetchHTTPResponse, g
70
72
  error
71
73
  });
72
74
  },
73
- abortController: ac
75
+ abortController
74
76
  });
75
77
  const promises = Object.keys(batchOps).map(async (key)=>{
76
78
  let json = await Promise.resolve(head[key]);
@@ -1,4 +1,4 @@
1
- import type { AnyClientTypes, inferClientTypes, InferrableClientTypes } from '@trpc/server/unstable-core-do-not-import';
1
+ import type { AnyClientTypes, inferClientTypes, InferrableClientTypes, SSEStreamConsumerOptions } from '@trpc/server/unstable-core-do-not-import';
2
2
  import { type TransformerOptions } from '../unstable-internals';
3
3
  import type { CallbackOrValue } from './internals/urlWithConnectionParams';
4
4
  import { type UrlOptionsWithConnectionParams } from './internals/urlWithConnectionParams';
@@ -8,6 +8,10 @@ type HTTPSubscriptionLinkOptions<TRoot extends AnyClientTypes> = {
8
8
  * EventSource options or a callback that returns them
9
9
  */
10
10
  eventSourceOptions?: CallbackOrValue<EventSourceInit>;
11
+ /**
12
+ * @see https://trpc.io/docs/client/links/httpSubscriptionLink#updatingConfig
13
+ */
14
+ experimental_shouldRecreateOnError?: SSEStreamConsumerOptions['shouldRecreateOnError'];
11
15
  } & TransformerOptions<TRoot> & UrlOptionsWithConnectionParams;
12
16
  /**
13
17
  * @see https://trpc.io/docs/client/links/httpSubscriptionLink
@@ -1 +1 @@
1
- {"version":3,"file":"httpSubscriptionLink.d.ts","sourceRoot":"","sources":["../../src/links/httpSubscriptionLink.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACtB,MAAM,0CAA0C,CAAC;AAMlD,OAAO,EAAkB,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAEL,KAAK,8BAA8B,EACpC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAiBxC,KAAK,2BAA2B,CAAC,KAAK,SAAS,cAAc,IAAI;IAC/D;;OAEG;IACH,kBAAkB,CAAC,EAAE,eAAe,CAAC,eAAe,CAAC,CAAC;CACvD,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAC3B,8BAA8B,CAAC;AAEjC;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,WAAW,SAAS,qBAAqB,EAEzC,IAAI,EAAE,2BAA2B,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,GAC/D,QAAQ,CAAC,WAAW,CAAC,CA2FvB"}
1
+ {"version":3,"file":"httpSubscriptionLink.d.ts","sourceRoot":"","sources":["../../src/links/httpSubscriptionLink.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,EACzB,MAAM,0CAA0C,CAAC;AAOlD,OAAO,EAAkB,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAEL,KAAK,8BAA8B,EACpC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAiBxC,KAAK,2BAA2B,CAAC,KAAK,SAAS,cAAc,IAAI;IAC/D;;OAEG;IACH,kBAAkB,CAAC,EAAE,eAAe,CAAC,eAAe,CAAC,CAAC;IACtD;;OAEG;IACH,kCAAkC,CAAC,EAAE,wBAAwB,CAAC,uBAAuB,CAAC,CAAC;CACxF,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAC3B,8BAA8B,CAAC;AAEjC;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,WAAW,SAAS,qBAAqB,EAEzC,IAAI,EAAE,2BAA2B,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,GAC/D,QAAQ,CAAC,WAAW,CAAC,CA6FvB"}
@@ -2,6 +2,7 @@
2
2
 
3
3
  var observable = require('@trpc/server/observable');
4
4
  var unstableCoreDoNotImport = require('@trpc/server/unstable-core-do-not-import');
5
+ var signals = require('../internals/signals.js');
5
6
  var TRPCClientError = require('../TRPCClientError.js');
6
7
  var transformer = require('../internals/transformer.js');
7
8
  var httpUtils = require('./internals/httpUtils.js');
@@ -27,53 +28,51 @@ async function urlWithConnectionParams(opts) {
27
28
  /* istanbul ignore if -- @preserve */ if (type !== 'subscription') {
28
29
  throw new Error('httpSubscriptionLink only supports subscriptions');
29
30
  }
30
- let eventSource = null;
31
- let unsubscribed = false;
31
+ const ac = new AbortController();
32
+ const signal = signals.raceAbortSignals(op.signal, ac.signal);
33
+ const eventSourceStream = unstableCoreDoNotImport.sseStreamConsumer({
34
+ url: async ()=>httpUtils.getUrl({
35
+ transformer: transformer$1,
36
+ url: await urlWithConnectionParams(opts),
37
+ input,
38
+ path,
39
+ type,
40
+ signal: null
41
+ }),
42
+ init: ()=>urlWithConnectionParams$1.resultOf(opts.eventSourceOptions),
43
+ signal,
44
+ deserialize: transformer$1.output.deserialize,
45
+ shouldRecreateOnError: opts.experimental_shouldRecreateOnError
46
+ });
32
47
  unstableCoreDoNotImport.run(async ()=>{
33
- const url = httpUtils.getUrl({
34
- transformer: transformer$1,
35
- url: await urlWithConnectionParams(opts),
36
- input,
37
- path,
38
- type,
39
- signal: null
40
- });
41
- const eventSourceOptions = await urlWithConnectionParams$1.resultOf(opts.eventSourceOptions);
42
- /* istanbul ignore if -- @preserve */ if (unsubscribed) {
43
- // already unsubscribed - rare race condition
44
- return;
45
- }
46
- eventSource = new EventSource(url, eventSourceOptions);
47
- const onStarted = ()=>{
48
- observer.next({
49
- result: {
50
- type: 'started'
51
- },
52
- context: {
53
- eventSource
54
- }
55
- });
56
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
57
- eventSource.removeEventListener('open', onStarted);
58
- };
59
- // console.log('starting', new Date());
60
- eventSource.addEventListener('open', onStarted);
61
- const iterable = unstableCoreDoNotImport.sseStreamConsumer({
62
- from: eventSource,
63
- deserialize: transformer$1.output.deserialize
64
- });
65
- for await (const chunk of iterable){
66
- if (!chunk.ok) {
67
- continue;
48
+ for await (const chunk of eventSourceStream){
49
+ switch(chunk.type){
50
+ case 'data':
51
+ const chunkData = chunk.data;
52
+ // if the `tracked()`-helper is used, we always have an `id` field
53
+ const data = 'id' in chunkData ? chunkData : chunkData.data;
54
+ observer.next({
55
+ result: {
56
+ data
57
+ },
58
+ context: {
59
+ eventSource: chunk.eventSource
60
+ }
61
+ });
62
+ break;
63
+ case 'opened':
64
+ {
65
+ observer.next({
66
+ result: {
67
+ type: 'started'
68
+ },
69
+ context: {
70
+ eventSource: chunk.eventSource
71
+ }
72
+ });
73
+ break;
74
+ }
68
75
  }
69
- const chunkData = chunk.data;
70
- // if the `tracked()`-helper is used, we always have an `id` field
71
- const data = 'id' in chunkData ? chunkData : chunkData.data;
72
- observer.next({
73
- result: {
74
- data
75
- }
76
- });
77
76
  }
78
77
  observer.next({
79
78
  result: {
@@ -86,8 +85,7 @@ async function urlWithConnectionParams(opts) {
86
85
  });
87
86
  return ()=>{
88
87
  observer.complete();
89
- eventSource?.close();
90
- unsubscribed = true;
88
+ ac.abort();
91
89
  };
92
90
  });
93
91
  };
@@ -1,5 +1,6 @@
1
1
  import { observable } from '@trpc/server/observable';
2
- import { run, sseStreamConsumer } from '@trpc/server/unstable-core-do-not-import';
2
+ import { sseStreamConsumer, run } from '@trpc/server/unstable-core-do-not-import';
3
+ import { raceAbortSignals } from '../internals/signals.mjs';
3
4
  import { TRPCClientError } from '../TRPCClientError.mjs';
4
5
  import { getTransformer } from '../internals/transformer.mjs';
5
6
  import { getUrl } from './internals/httpUtils.mjs';
@@ -25,53 +26,51 @@ async function urlWithConnectionParams(opts) {
25
26
  /* istanbul ignore if -- @preserve */ if (type !== 'subscription') {
26
27
  throw new Error('httpSubscriptionLink only supports subscriptions');
27
28
  }
28
- let eventSource = null;
29
- let unsubscribed = false;
29
+ const ac = new AbortController();
30
+ const signal = raceAbortSignals(op.signal, ac.signal);
31
+ const eventSourceStream = sseStreamConsumer({
32
+ url: async ()=>getUrl({
33
+ transformer,
34
+ url: await urlWithConnectionParams(opts),
35
+ input,
36
+ path,
37
+ type,
38
+ signal: null
39
+ }),
40
+ init: ()=>resultOf(opts.eventSourceOptions),
41
+ signal,
42
+ deserialize: transformer.output.deserialize,
43
+ shouldRecreateOnError: opts.experimental_shouldRecreateOnError
44
+ });
30
45
  run(async ()=>{
31
- const url = getUrl({
32
- transformer,
33
- url: await urlWithConnectionParams(opts),
34
- input,
35
- path,
36
- type,
37
- signal: null
38
- });
39
- const eventSourceOptions = await resultOf(opts.eventSourceOptions);
40
- /* istanbul ignore if -- @preserve */ if (unsubscribed) {
41
- // already unsubscribed - rare race condition
42
- return;
43
- }
44
- eventSource = new EventSource(url, eventSourceOptions);
45
- const onStarted = ()=>{
46
- observer.next({
47
- result: {
48
- type: 'started'
49
- },
50
- context: {
51
- eventSource
52
- }
53
- });
54
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
55
- eventSource.removeEventListener('open', onStarted);
56
- };
57
- // console.log('starting', new Date());
58
- eventSource.addEventListener('open', onStarted);
59
- const iterable = sseStreamConsumer({
60
- from: eventSource,
61
- deserialize: transformer.output.deserialize
62
- });
63
- for await (const chunk of iterable){
64
- if (!chunk.ok) {
65
- continue;
46
+ for await (const chunk of eventSourceStream){
47
+ switch(chunk.type){
48
+ case 'data':
49
+ const chunkData = chunk.data;
50
+ // if the `tracked()`-helper is used, we always have an `id` field
51
+ const data = 'id' in chunkData ? chunkData : chunkData.data;
52
+ observer.next({
53
+ result: {
54
+ data
55
+ },
56
+ context: {
57
+ eventSource: chunk.eventSource
58
+ }
59
+ });
60
+ break;
61
+ case 'opened':
62
+ {
63
+ observer.next({
64
+ result: {
65
+ type: 'started'
66
+ },
67
+ context: {
68
+ eventSource: chunk.eventSource
69
+ }
70
+ });
71
+ break;
72
+ }
66
73
  }
67
- const chunkData = chunk.data;
68
- // if the `tracked()`-helper is used, we always have an `id` field
69
- const data = 'id' in chunkData ? chunkData : chunkData.data;
70
- observer.next({
71
- result: {
72
- data
73
- }
74
- });
75
74
  }
76
75
  observer.next({
77
76
  result: {
@@ -84,8 +83,7 @@ async function urlWithConnectionParams(opts) {
84
83
  });
85
84
  return ()=>{
86
85
  observer.complete();
87
- eventSource?.close();
88
- unsubscribed = true;
86
+ ac.abort();
89
87
  };
90
88
  });
91
89
  };
@@ -64,12 +64,5 @@ export type HTTPRequestOptions = ContentOptions & HTTPBaseRequestOptions & {
64
64
  };
65
65
  export declare function fetchHTTPResponse(opts: HTTPRequestOptions): Promise<ResponseEsque>;
66
66
  export declare function httpRequest(opts: HTTPRequestOptions): Promise<HTTPResult>;
67
- /**
68
- * Merges multiple abort signals into a single one
69
- * - When all signals have been aborted, the merged signal will be aborted
70
- */
71
- export declare function mergeAbortSignals(opts: {
72
- signal: Maybe<AbortSignal>;
73
- }[]): AbortController;
74
67
  export {};
75
68
  //# sourceMappingURL=httpUtils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"httpUtils.d.ts","sourceRoot":"","sources":["../../../src/links/internals/httpUtils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"httpUtils.d.ts","sourceRoot":"","sources":["../../../src/links/internals/httpUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,uBAAuB,EACvB,KAAK,EACL,aAAa,EACb,gBAAgB,EAChB,YAAY,EACb,MAAM,0CAA0C,CAAC;AAElD,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,aAAa,EACd,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C;;GAEG;AACH,MAAM,MAAM,mBAAmB,CAC7B,KAAK,SAAS,IAAI,CAAC,cAAc,EAAE,aAAa,CAAC,IAC/C;IACF,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;IAClB;;OAEG;IACH,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;AAE9B,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,uBAAuB,CAAC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,mBAAmB,CAAC,cAAc,CAAC,GACxC,uBAAuB,CAOzB;AAkBD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE;QACJ,QAAQ,EAAE,aAAa,CAAC;QACxB,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB,CAAC;CACH;AAED,KAAK,eAAe,GAAG;IACrB,WAAW,EAAE,uBAAuB,CAAC;CACtC,GAAG,CAAC;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC,CAAC;AAEjD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,eAAe,OAM7C;AAED,MAAM,MAAM,sBAAsB,GAAG,eAAe,GAClD,uBAAuB,GAAG;IACxB,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;CAC5B,CAAC;AAEJ,KAAK,MAAM,GAAG,CAAC,IAAI,EAAE,sBAAsB,KAAK,MAAM,CAAC;AACvD,KAAK,OAAO,GAAG,CAAC,IAAI,EAAE,sBAAsB,KAAK,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAE1E,MAAM,MAAM,cAAc,GAAG;IAC3B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,MAuBpB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,OAMrB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,CACtB,IAAI,EAAE,sBAAsB,GAAG;IAC7B,OAAO,EAAE,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACnD,KACE,OAAO,CAAC,UAAU,CAAC,CAAC;AAEzB,eAAO,MAAM,iBAAiB,EAAE,SAO/B,CAAC;AAcF,MAAM,MAAM,kBAAkB,GAAG,cAAc,GAC7C,sBAAsB,GAAG;IACvB,OAAO,EAAE,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACnD,CAAC;AAuBJ,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,0BA6B/D;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,UAAU,CAAC,CAcrB"}
@@ -131,34 +131,6 @@ async function httpRequest(opts) {
131
131
  meta
132
132
  };
133
133
  }
134
- /**
135
- * Merges multiple abort signals into a single one
136
- * - When all signals have been aborted, the merged signal will be aborted
137
- */ function mergeAbortSignals(opts) {
138
- const ac = new AbortController();
139
- if (opts.some((o)=>!o.signal)) {
140
- return ac;
141
- }
142
- const count = opts.length;
143
- let abortedCount = 0;
144
- const onAbort = ()=>{
145
- if (++abortedCount === count) {
146
- ac.abort();
147
- }
148
- };
149
- for (const o of opts){
150
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
151
- const signal = o.signal;
152
- if (signal.aborted) {
153
- onAbort();
154
- } else {
155
- signal.addEventListener('abort', onAbort, {
156
- once: true
157
- });
158
- }
159
- }
160
- return ac;
161
- }
162
134
 
163
135
  exports.fetchHTTPResponse = fetchHTTPResponse;
164
136
  exports.getBody = getBody;
@@ -166,5 +138,4 @@ exports.getInput = getInput;
166
138
  exports.getUrl = getUrl;
167
139
  exports.httpRequest = httpRequest;
168
140
  exports.jsonHttpRequester = jsonHttpRequester;
169
- exports.mergeAbortSignals = mergeAbortSignals;
170
141
  exports.resolveHTTPLinkOptions = resolveHTTPLinkOptions;
@@ -129,33 +129,5 @@ async function httpRequest(opts) {
129
129
  meta
130
130
  };
131
131
  }
132
- /**
133
- * Merges multiple abort signals into a single one
134
- * - When all signals have been aborted, the merged signal will be aborted
135
- */ function mergeAbortSignals(opts) {
136
- const ac = new AbortController();
137
- if (opts.some((o)=>!o.signal)) {
138
- return ac;
139
- }
140
- const count = opts.length;
141
- let abortedCount = 0;
142
- const onAbort = ()=>{
143
- if (++abortedCount === count) {
144
- ac.abort();
145
- }
146
- };
147
- for (const o of opts){
148
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
149
- const signal = o.signal;
150
- if (signal.aborted) {
151
- onAbort();
152
- } else {
153
- signal.addEventListener('abort', onAbort, {
154
- once: true
155
- });
156
- }
157
- }
158
- return ac;
159
- }
160
132
 
161
- export { fetchHTTPResponse, getBody, getInput, getUrl, httpRequest, jsonHttpRequester, mergeAbortSignals, resolveHTTPLinkOptions };
133
+ export { fetchHTTPResponse, getBody, getInput, getUrl, httpRequest, jsonHttpRequester, resolveHTTPLinkOptions };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trpc/client",
3
- "version": "11.0.0-rc.553+9b629cc67",
3
+ "version": "11.0.0-rc.561+c50cd4308",
4
4
  "description": "The tRPC client library",
5
5
  "author": "KATT",
6
6
  "license": "MIT",
@@ -76,10 +76,10 @@
76
76
  "!**/*.test.*"
77
77
  ],
78
78
  "peerDependencies": {
79
- "@trpc/server": "11.0.0-rc.553+9b629cc67"
79
+ "@trpc/server": "11.0.0-rc.561+c50cd4308"
80
80
  },
81
81
  "devDependencies": {
82
- "@trpc/server": "11.0.0-rc.553+9b629cc67",
82
+ "@trpc/server": "11.0.0-rc.561+c50cd4308",
83
83
  "@types/isomorphic-fetch": "^0.0.39",
84
84
  "@types/node": "^20.10.0",
85
85
  "eslint": "^8.57.0",
@@ -96,5 +96,5 @@
96
96
  "funding": [
97
97
  "https://trpc.io/sponsor"
98
98
  ],
99
- "gitHead": "9b629cc672aad7908af1d5355e3f2dd8f03f048d"
99
+ "gitHead": "c50cd4308223508184310103938d1fee50046989"
100
100
  }
@@ -135,7 +135,7 @@ export class TRPCUntypedClient<TRouter extends AnyRouter> {
135
135
  path,
136
136
  input,
137
137
  context: opts?.context,
138
- signal: null,
138
+ signal: opts.signal,
139
139
  });
140
140
  return observable$.subscribe({
141
141
  next(envelope) {
@@ -0,0 +1,51 @@
1
+ import type { Maybe } from '@trpc/server/unstable-core-do-not-import';
2
+
3
+ /**
4
+ * Like `Promise.all()` but for abort signals
5
+ * - When all signals have been aborted, the merged signal will be aborted
6
+ * - If one signal is `null`, no signal will be aborted
7
+ */
8
+ export function allAbortSignals(...signals: Maybe<AbortSignal>[]): AbortSignal {
9
+ const ac = new AbortController();
10
+
11
+ const count = signals.length;
12
+
13
+ let abortedCount = 0;
14
+
15
+ const onAbort = () => {
16
+ if (++abortedCount === count) {
17
+ ac.abort();
18
+ }
19
+ };
20
+
21
+ for (const signal of signals) {
22
+ if (signal?.aborted) {
23
+ onAbort();
24
+ } else {
25
+ signal?.addEventListener('abort', onAbort, {
26
+ once: true,
27
+ });
28
+ }
29
+ }
30
+
31
+ return ac.signal;
32
+ }
33
+
34
+ /**
35
+ * Like `Promise.race` but for abort signals
36
+ */
37
+ export function raceAbortSignals(
38
+ ...signals: Maybe<AbortSignal>[]
39
+ ): AbortSignal {
40
+ const ac = new AbortController();
41
+
42
+ for (const signal of signals) {
43
+ if (signal?.aborted) {
44
+ ac.abort();
45
+ } else {
46
+ signal?.addEventListener('abort', () => ac.abort(), { once: true });
47
+ }
48
+ }
49
+
50
+ return ac.signal;
51
+ }
@@ -3,6 +3,7 @@ import { observable } from '@trpc/server/observable';
3
3
  import { transformResult } from '@trpc/server/unstable-core-do-not-import';
4
4
  import type { BatchLoader } from '../internals/dataLoader';
5
5
  import { dataLoader } from '../internals/dataLoader';
6
+ import { allAbortSignals } from '../internals/signals';
6
7
  import type { NonEmptyArray } from '../internals/types';
7
8
  import { TRPCClientError } from '../TRPCClientError';
8
9
  import type { HTTPBatchLinkOptions } from './HTTPBatchLinkOptions';
@@ -10,7 +11,6 @@ import type { HTTPResult } from './internals/httpUtils';
10
11
  import {
11
12
  getUrl,
12
13
  jsonHttpRequester,
13
- mergeAbortSignals,
14
14
  resolveHTTPLinkOptions,
15
15
  } from './internals/httpUtils';
16
16
  import type { Operation, TRPCLink } from './types';
@@ -50,7 +50,7 @@ export function httpBatchLink<TRouter extends AnyRouter>(
50
50
  async fetch(batchOps) {
51
51
  const path = batchOps.map((op) => op.path).join(',');
52
52
  const inputs = batchOps.map((op) => op.input);
53
- const ac = mergeAbortSignals(batchOps);
53
+ const signal = allAbortSignals(...batchOps.map((op) => op.signal));
54
54
 
55
55
  const res = await jsonHttpRequester({
56
56
  ...resolvedOpts,
@@ -68,7 +68,7 @@ export function httpBatchLink<TRouter extends AnyRouter>(
68
68
  }
69
69
  return opts.headers;
70
70
  },
71
- signal: ac.signal,
71
+ signal,
72
72
  });
73
73
  const resJSON = Array.isArray(res.json)
74
74
  ? res.json
@@ -5,6 +5,7 @@ import type { AnyRootTypes } from '@trpc/server/unstable-core-do-not-import';
5
5
  import { jsonlStreamConsumer } from '@trpc/server/unstable-core-do-not-import';
6
6
  import type { BatchLoader } from '../internals/dataLoader';
7
7
  import { dataLoader } from '../internals/dataLoader';
8
+ import { allAbortSignals, raceAbortSignals } from '../internals/signals';
8
9
  import type { NonEmptyArray } from '../internals/types';
9
10
  import { TRPCClientError } from '../TRPCClientError';
10
11
  import type { HTTPBatchLinkOptions } from './HTTPBatchLinkOptions';
@@ -13,7 +14,6 @@ import {
13
14
  fetchHTTPResponse,
14
15
  getBody,
15
16
  getUrl,
16
- mergeAbortSignals,
17
17
  resolveHTTPLinkOptions,
18
18
  } from './internals/httpUtils';
19
19
  import type { Operation, TRPCLink } from './types';
@@ -67,11 +67,14 @@ export function unstable_httpBatchStreamLink<TRouter extends AnyRouter>(
67
67
  const path = batchOps.map((op) => op.path).join(',');
68
68
  const inputs = batchOps.map((op) => op.input);
69
69
 
70
- const ac = mergeAbortSignals(batchOps);
70
+ const batchSignals = allAbortSignals(
71
+ ...batchOps.map((op) => op.signal),
72
+ );
73
+ const abortController = new AbortController();
71
74
 
72
75
  const responsePromise = fetchHTTPResponse({
73
76
  ...resolvedOpts,
74
- signal: ac.signal,
77
+ signal: raceAbortSignals(batchSignals, abortController.signal),
75
78
  type,
76
79
  contentTypeHeader: 'application/json',
77
80
  trpcAcceptHeader: 'application/jsonl',
@@ -106,7 +109,7 @@ export function unstable_httpBatchStreamLink<TRouter extends AnyRouter>(
106
109
  error,
107
110
  });
108
111
  },
109
- abortController: ac,
112
+ abortController,
110
113
  });
111
114
  const promises = Object.keys(batchOps).map(
112
115
  async (key): Promise<HTTPResult> => {
@@ -3,11 +3,13 @@ import type {
3
3
  AnyClientTypes,
4
4
  inferClientTypes,
5
5
  InferrableClientTypes,
6
+ SSEStreamConsumerOptions,
6
7
  } from '@trpc/server/unstable-core-do-not-import';
7
8
  import {
8
9
  run,
9
10
  sseStreamConsumer,
10
11
  } from '@trpc/server/unstable-core-do-not-import';
12
+ import { raceAbortSignals } from '../internals/signals';
11
13
  import { TRPCClientError } from '../TRPCClientError';
12
14
  import { getTransformer, type TransformerOptions } from '../unstable-internals';
13
15
  import { getUrl } from './internals/httpUtils';
@@ -38,6 +40,10 @@ type HTTPSubscriptionLinkOptions<TRoot extends AnyClientTypes> = {
38
40
  * EventSource options or a callback that returns them
39
41
  */
40
42
  eventSourceOptions?: CallbackOrValue<EventSourceInit>;
43
+ /**
44
+ * @see https://trpc.io/docs/client/links/httpSubscriptionLink#updatingConfig
45
+ */
46
+ experimental_shouldRecreateOnError?: SSEStreamConsumerOptions['shouldRecreateOnError'];
41
47
  } & TransformerOptions<TRoot> &
42
48
  UrlOptionsWithConnectionParams;
43
49
 
@@ -55,70 +61,73 @@ export function unstable_httpSubscriptionLink<
55
61
  return ({ op }) => {
56
62
  return observable((observer) => {
57
63
  const { type, path, input } = op;
64
+
58
65
  /* istanbul ignore if -- @preserve */
59
66
  if (type !== 'subscription') {
60
67
  throw new Error('httpSubscriptionLink only supports subscriptions');
61
68
  }
62
69
 
63
- let eventSource: EventSource | null = null;
64
- let unsubscribed = false;
70
+ const ac = new AbortController();
71
+ const signal = raceAbortSignals(op.signal, ac.signal);
72
+ const eventSourceStream = sseStreamConsumer<
73
+ Partial<{
74
+ id?: string;
75
+ data: unknown;
76
+ }>
77
+ >({
78
+ url: async () =>
79
+ getUrl({
80
+ transformer,
81
+ url: await urlWithConnectionParams(opts),
82
+ input,
83
+ path,
84
+ type,
85
+ signal: null,
86
+ }),
87
+ init: () => resultOf(opts.eventSourceOptions),
88
+ signal,
89
+ deserialize: transformer.output.deserialize,
90
+ shouldRecreateOnError: opts.experimental_shouldRecreateOnError,
91
+ });
65
92
 
66
93
  run(async () => {
67
- const url = getUrl({
68
- transformer,
69
- url: await urlWithConnectionParams(opts),
70
- input,
71
- path,
72
- type,
73
- signal: null,
74
- });
94
+ for await (const chunk of eventSourceStream) {
95
+ switch (chunk.type) {
96
+ case 'data':
97
+ const chunkData = chunk.data;
75
98
 
76
- const eventSourceOptions = await resultOf(opts.eventSourceOptions);
77
- /* istanbul ignore if -- @preserve */
78
- if (unsubscribed) {
79
- // already unsubscribed - rare race condition
80
- return;
81
- }
82
- eventSource = new EventSource(url, eventSourceOptions);
83
- const onStarted = () => {
84
- observer.next({
85
- result: {
86
- type: 'started',
87
- },
88
- context: {
89
- eventSource,
90
- },
91
- });
92
-
93
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
94
- eventSource!.removeEventListener('open', onStarted);
95
- };
96
- // console.log('starting', new Date());
97
- eventSource.addEventListener('open', onStarted);
98
- const iterable = sseStreamConsumer<
99
- Partial<{
100
- id?: string;
101
- data: unknown;
102
- }>
103
- >({
104
- from: eventSource,
105
- deserialize: transformer.output.deserialize,
106
- });
99
+ // if the `tracked()`-helper is used, we always have an `id` field
100
+ const data = 'id' in chunkData ? chunkData : chunkData.data;
107
101
 
108
- for await (const chunk of iterable) {
109
- if (!chunk.ok) {
110
- // TODO: handle in https://github.com/trpc/trpc/issues/5871
111
- continue;
102
+ observer.next({
103
+ result: {
104
+ data,
105
+ },
106
+ context: {
107
+ eventSource: chunk.eventSource,
108
+ },
109
+ });
110
+ break;
111
+ case 'opened': {
112
+ observer.next({
113
+ result: {
114
+ type: 'started',
115
+ },
116
+ context: {
117
+ eventSource: chunk.eventSource,
118
+ },
119
+ });
120
+ break;
121
+ }
122
+ case 'error': {
123
+ // TODO: handle in https://github.com/trpc/trpc/issues/5871
124
+ break;
125
+ }
126
+ case 'connecting': {
127
+ // TODO: handle in https://github.com/trpc/trpc/issues/5871
128
+ break;
129
+ }
112
130
  }
113
- const chunkData = chunk.data;
114
-
115
- // if the `tracked()`-helper is used, we always have an `id` field
116
- const data = 'id' in chunkData ? chunkData : chunkData.data;
117
- observer.next({
118
- result: {
119
- data,
120
- },
121
- });
122
131
  }
123
132
 
124
133
  observer.next({
@@ -133,8 +142,7 @@ export function unstable_httpSubscriptionLink<
133
142
 
134
143
  return () => {
135
144
  observer.complete();
136
- eventSource?.close();
137
- unsubscribed = true;
145
+ ac.abort();
138
146
  };
139
147
  });
140
148
  };
@@ -240,43 +240,3 @@ export async function httpRequest(
240
240
  meta,
241
241
  };
242
242
  }
243
-
244
- /**
245
- * Merges multiple abort signals into a single one
246
- * - When all signals have been aborted, the merged signal will be aborted
247
- */
248
- export function mergeAbortSignals(
249
- opts: {
250
- signal: Maybe<AbortSignal>;
251
- }[],
252
- ): AbortController {
253
- const ac = new AbortController();
254
-
255
- if (opts.some((o) => !o.signal)) {
256
- return ac;
257
- }
258
-
259
- const count = opts.length;
260
-
261
- let abortedCount = 0;
262
-
263
- const onAbort = () => {
264
- if (++abortedCount === count) {
265
- ac.abort();
266
- }
267
- };
268
-
269
- for (const o of opts) {
270
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
271
- const signal = o.signal!;
272
- if (signal.aborted) {
273
- onAbort();
274
- } else {
275
- signal.addEventListener('abort', onAbort, {
276
- once: true,
277
- });
278
- }
279
- }
280
-
281
- return ac;
282
- }