@trpc/client 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.
@@ -2,12 +2,12 @@
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');
8
9
  var urlWithConnectionParams$1 = require('./internals/urlWithConnectionParams.js');
9
10
 
10
- var _listeners, _type, _listeners1, _type1;
11
11
  async function urlWithConnectionParams(opts) {
12
12
  let url = await urlWithConnectionParams$1.resultOf(opts.url);
13
13
  if (opts.connectionParams) {
@@ -28,72 +28,51 @@ async function urlWithConnectionParams(opts) {
28
28
  /* istanbul ignore if -- @preserve */ if (type !== 'subscription') {
29
29
  throw new Error('httpSubscriptionLink only supports subscriptions');
30
30
  }
31
- let eventSource = null;
32
- 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
+ });
33
47
  unstableCoreDoNotImport.run(async ()=>{
34
- const url = httpUtils.getUrl({
35
- transformer: transformer$1,
36
- url: await urlWithConnectionParams(opts),
37
- input,
38
- path,
39
- type,
40
- signal: null
41
- });
42
- const eventSourceOptions = await urlWithConnectionParams$1.resultOf(opts.eventSourceOptions);
43
- /* istanbul ignore if -- @preserve */ if (unsubscribed) {
44
- // already unsubscribed - rare race condition
45
- return;
46
- }
47
- eventSource = new EventSourceWrapper(url, eventSourceOptions);
48
- const onStarted = ()=>{
49
- observer.next({
50
- result: {
51
- type: 'started'
52
- },
53
- context: {
54
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
55
- eventSource: eventSource.getEventSource()
56
- }
57
- });
58
- };
59
- eventSource.addEventListener('open', onStarted, {
60
- once: true
61
- });
62
- const iterable = unstableCoreDoNotImport.sseStreamConsumer({
63
- from: eventSource,
64
- deserialize: transformer$1.output.deserialize,
65
- tryHandleError: async (ev)=>{
66
- if (typeof opts.shouldRecreateOnError !== 'function' || !eventSource) {
67
- return false;
68
- }
69
- const recreateOnErrorOpts = createRecreateOnErrorOpts(ev);
70
- const shouldRestart = await opts.shouldRecreateOnError(recreateOnErrorOpts);
71
- if (!shouldRestart) {
72
- return false;
73
- }
74
- eventSource.restart(httpUtils.getUrl({
75
- transformer: transformer$1,
76
- url: await urlWithConnectionParams(opts),
77
- input,
78
- path,
79
- type,
80
- signal: null
81
- }), await urlWithConnectionParams$1.resultOf(opts.eventSourceOptions));
82
- return true;
83
- }
84
- });
85
- for await (const chunk of iterable){
86
- if (!chunk.ok) {
87
- 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
+ }
88
75
  }
89
- const chunkData = chunk.data;
90
- // if the `tracked()`-helper is used, we always have an `id` field
91
- const data = 'id' in chunkData ? chunkData : chunkData.data;
92
- observer.next({
93
- result: {
94
- data
95
- }
96
- });
97
76
  }
98
77
  observer.next({
99
78
  result: {
@@ -106,78 +85,11 @@ async function urlWithConnectionParams(opts) {
106
85
  });
107
86
  return ()=>{
108
87
  observer.complete();
109
- eventSource?.close();
110
- unsubscribed = true;
88
+ ac.abort();
111
89
  };
112
90
  });
113
91
  };
114
92
  };
115
93
  }
116
- function createRecreateOnErrorOpts(ev) {
117
- if ('status' in ev && typeof ev.status === 'number') {
118
- return {
119
- type: 'http-error',
120
- status: ev.status,
121
- event: ev
122
- };
123
- }
124
- return {
125
- type: 'raw',
126
- event: ev
127
- };
128
- }
129
- /**
130
- * We wrap EventSource so that is can be reinitialized with new options
131
- */ class EventSourceWrapper {
132
- *getAllEventListeners() {
133
- for(const _type in this.listeners){
134
- const type = _type;
135
- for (const listener of this.listeners[type] ?? []){
136
- yield listener;
137
- }
138
- }
139
- }
140
- restart(url, options) {
141
- for (const [type, callback, options1] of this.getAllEventListeners()){
142
- this.es.removeEventListener(type, callback, options1);
143
- }
144
- this.es.close();
145
- this.es = new EventSource(url, options);
146
- for (const [type1, callback1, options2] of this.getAllEventListeners()){
147
- this.es.addEventListener(type1, callback1, options2);
148
- }
149
- }
150
- close() {
151
- this.listeners = {};
152
- this.es.close();
153
- }
154
- getEventSource() {
155
- return this.es;
156
- }
157
- get readyState() {
158
- return this.es.readyState;
159
- }
160
- addEventListener(type, listener, options) {
161
- (_listeners = this.listeners)[_type = type] ?? (_listeners[_type] = []);
162
- this.listeners[type].push([
163
- type,
164
- listener,
165
- options
166
- ]);
167
- this.es.addEventListener(type, listener, options);
168
- }
169
- removeEventListener(type, listener, options) {
170
- (_listeners1 = this.listeners)[_type1 = type] ?? (_listeners1[_type1] = []);
171
- const indexToRemove = this.listeners[type]?.findIndex(([_type, thisListener])=>thisListener === listener);
172
- if (typeof indexToRemove === 'number' && indexToRemove >= 0) {
173
- this.listeners[type].splice(indexToRemove, 1);
174
- }
175
- this.es.removeEventListener(type, listener, options);
176
- }
177
- constructor(url, options){
178
- this.listeners = {};
179
- this.es = new EventSource(url, options);
180
- }
181
- }
182
94
 
183
95
  exports.unstable_httpSubscriptionLink = unstable_httpSubscriptionLink;
@@ -1,11 +1,11 @@
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';
6
7
  import { resultOf } from './internals/urlWithConnectionParams.mjs';
7
8
 
8
- var _listeners, _type, _listeners1, _type1;
9
9
  async function urlWithConnectionParams(opts) {
10
10
  let url = await resultOf(opts.url);
11
11
  if (opts.connectionParams) {
@@ -26,72 +26,51 @@ async function urlWithConnectionParams(opts) {
26
26
  /* istanbul ignore if -- @preserve */ if (type !== 'subscription') {
27
27
  throw new Error('httpSubscriptionLink only supports subscriptions');
28
28
  }
29
- let eventSource = null;
30
- 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
+ });
31
45
  run(async ()=>{
32
- const url = getUrl({
33
- transformer,
34
- url: await urlWithConnectionParams(opts),
35
- input,
36
- path,
37
- type,
38
- signal: null
39
- });
40
- const eventSourceOptions = await resultOf(opts.eventSourceOptions);
41
- /* istanbul ignore if -- @preserve */ if (unsubscribed) {
42
- // already unsubscribed - rare race condition
43
- return;
44
- }
45
- eventSource = new EventSourceWrapper(url, eventSourceOptions);
46
- const onStarted = ()=>{
47
- observer.next({
48
- result: {
49
- type: 'started'
50
- },
51
- context: {
52
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
53
- eventSource: eventSource.getEventSource()
54
- }
55
- });
56
- };
57
- eventSource.addEventListener('open', onStarted, {
58
- once: true
59
- });
60
- const iterable = sseStreamConsumer({
61
- from: eventSource,
62
- deserialize: transformer.output.deserialize,
63
- tryHandleError: async (ev)=>{
64
- if (typeof opts.shouldRecreateOnError !== 'function' || !eventSource) {
65
- return false;
66
- }
67
- const recreateOnErrorOpts = createRecreateOnErrorOpts(ev);
68
- const shouldRestart = await opts.shouldRecreateOnError(recreateOnErrorOpts);
69
- if (!shouldRestart) {
70
- return false;
71
- }
72
- eventSource.restart(getUrl({
73
- transformer,
74
- url: await urlWithConnectionParams(opts),
75
- input,
76
- path,
77
- type,
78
- signal: null
79
- }), await resultOf(opts.eventSourceOptions));
80
- return true;
81
- }
82
- });
83
- for await (const chunk of iterable){
84
- if (!chunk.ok) {
85
- 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
+ }
86
73
  }
87
- const chunkData = chunk.data;
88
- // if the `tracked()`-helper is used, we always have an `id` field
89
- const data = 'id' in chunkData ? chunkData : chunkData.data;
90
- observer.next({
91
- result: {
92
- data
93
- }
94
- });
95
74
  }
96
75
  observer.next({
97
76
  result: {
@@ -104,78 +83,11 @@ async function urlWithConnectionParams(opts) {
104
83
  });
105
84
  return ()=>{
106
85
  observer.complete();
107
- eventSource?.close();
108
- unsubscribed = true;
86
+ ac.abort();
109
87
  };
110
88
  });
111
89
  };
112
90
  };
113
91
  }
114
- function createRecreateOnErrorOpts(ev) {
115
- if ('status' in ev && typeof ev.status === 'number') {
116
- return {
117
- type: 'http-error',
118
- status: ev.status,
119
- event: ev
120
- };
121
- }
122
- return {
123
- type: 'raw',
124
- event: ev
125
- };
126
- }
127
- /**
128
- * We wrap EventSource so that is can be reinitialized with new options
129
- */ class EventSourceWrapper {
130
- *getAllEventListeners() {
131
- for(const _type in this.listeners){
132
- const type = _type;
133
- for (const listener of this.listeners[type] ?? []){
134
- yield listener;
135
- }
136
- }
137
- }
138
- restart(url, options) {
139
- for (const [type, callback, options1] of this.getAllEventListeners()){
140
- this.es.removeEventListener(type, callback, options1);
141
- }
142
- this.es.close();
143
- this.es = new EventSource(url, options);
144
- for (const [type1, callback1, options2] of this.getAllEventListeners()){
145
- this.es.addEventListener(type1, callback1, options2);
146
- }
147
- }
148
- close() {
149
- this.listeners = {};
150
- this.es.close();
151
- }
152
- getEventSource() {
153
- return this.es;
154
- }
155
- get readyState() {
156
- return this.es.readyState;
157
- }
158
- addEventListener(type, listener, options) {
159
- (_listeners = this.listeners)[_type = type] ?? (_listeners[_type] = []);
160
- this.listeners[type].push([
161
- type,
162
- listener,
163
- options
164
- ]);
165
- this.es.addEventListener(type, listener, options);
166
- }
167
- removeEventListener(type, listener, options) {
168
- (_listeners1 = this.listeners)[_type1 = type] ?? (_listeners1[_type1] = []);
169
- const indexToRemove = this.listeners[type]?.findIndex(([_type, thisListener])=>thisListener === listener);
170
- if (typeof indexToRemove === 'number' && indexToRemove >= 0) {
171
- this.listeners[type].splice(indexToRemove, 1);
172
- }
173
- this.es.removeEventListener(type, listener, options);
174
- }
175
- constructor(url, options){
176
- this.listeners = {};
177
- this.es = new EventSource(url, options);
178
- }
179
- }
180
92
 
181
93
  export { unstable_httpSubscriptionLink };
@@ -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.560+137b085f8",
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.560+137b085f8"
79
+ "@trpc/server": "11.0.0-rc.561+c50cd4308"
80
80
  },
81
81
  "devDependencies": {
82
- "@trpc/server": "11.0.0-rc.560+137b085f8",
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": "137b085f86cb4ceb397b29c69ccbe38a93dbe79a"
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