@trpc/client 10.43.0 → 11.0.0-next.91

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.
@@ -8,6 +8,7 @@ var TRPCClientError = require('../TRPCClientError-e224e397.js');
8
8
 
9
9
  /* istanbul ignore next -- @preserve */ const retryDelay = (attemptIndex)=>attemptIndex === 0 ? 0 : Math.min(1000 * 2 ** attemptIndex, 30000);
10
10
 
11
+ const run = (fn)=>fn();
11
12
  function createWSClient(opts) {
12
13
  const { url , WebSocket: WebSocketImpl = WebSocket , retryDelayMs: retryDelayFn = retryDelay , onOpen , onClose , } = opts;
13
14
  /* istanbul ignore next -- @preserve */ if (!WebSocketImpl) {
@@ -18,163 +19,171 @@ function createWSClient(opts) {
18
19
  */ let outgoing = [];
19
20
  const pendingRequests = Object.create(null);
20
21
  let connectAttempt = 0;
21
- let dispatchTimer = null;
22
- let connectTimer = null;
23
- let activeConnection = createWS();
24
- let state = 'connecting';
22
+ let connectTimer = undefined;
23
+ let connectionIndex = 0;
24
+ let activeConnection = createConnection();
25
+ /**
26
+ * Global connection has been killed
27
+ */ let killed = false;
25
28
  /**
26
29
  * tries to send the list of messages
27
30
  */ function dispatch() {
28
- if (state !== 'open' || dispatchTimer) {
29
- return;
30
- }
31
- dispatchTimer = setTimeout(()=>{
32
- dispatchTimer = null;
31
+ // using a timeout to batch messages
32
+ setTimeout(()=>{
33
+ if (activeConnection?.state !== 'open') {
34
+ return;
35
+ }
36
+ for (const pending of Object.values(pendingRequests)){
37
+ if (!pending.connection) {
38
+ pending.connection = activeConnection;
39
+ }
40
+ }
33
41
  if (outgoing.length === 1) {
34
42
  // single send
35
- activeConnection.send(JSON.stringify(outgoing.pop()));
43
+ activeConnection.ws.send(JSON.stringify(outgoing.pop()));
36
44
  } else {
37
45
  // batch send
38
- activeConnection.send(JSON.stringify(outgoing));
46
+ activeConnection.ws.send(JSON.stringify(outgoing));
39
47
  }
40
48
  // clear
41
49
  outgoing = [];
42
50
  });
43
51
  }
44
52
  function tryReconnect() {
45
- if (connectTimer !== null || state === 'closed') {
53
+ if (!!connectTimer || killed) {
46
54
  return;
47
55
  }
48
56
  const timeout = retryDelayFn(connectAttempt++);
49
57
  reconnectInMs(timeout);
50
58
  }
51
59
  function reconnect() {
52
- state = 'connecting';
53
60
  const oldConnection = activeConnection;
54
- activeConnection = createWS();
55
- closeIfNoPending(oldConnection);
61
+ activeConnection = createConnection();
62
+ oldConnection && closeIfNoPending(oldConnection);
56
63
  }
57
64
  function reconnectInMs(ms) {
58
65
  if (connectTimer) {
59
66
  return;
60
67
  }
61
- state = 'connecting';
62
68
  connectTimer = setTimeout(reconnect, ms);
63
69
  }
64
70
  function closeIfNoPending(conn) {
65
71
  // disconnect as soon as there are are no pending result
66
- const hasPendingRequests = Object.values(pendingRequests).some((p)=>p.ws === conn);
72
+ const hasPendingRequests = Object.values(pendingRequests).some((p)=>p.connection === conn);
67
73
  if (!hasPendingRequests) {
68
- conn.close();
74
+ conn.ws?.close();
69
75
  }
70
76
  }
71
- function closeActiveSubscriptions() {
72
- Object.values(pendingRequests).forEach((req)=>{
73
- if (req.type === 'subscription') {
74
- req.callbacks.complete();
75
- }
76
- });
77
- }
78
77
  function resumeSubscriptionOnReconnect(req) {
79
78
  if (outgoing.some((r)=>r.id === req.op.id)) {
80
79
  return;
81
80
  }
82
81
  request(req.op, req.callbacks);
83
82
  }
84
- function createWS() {
85
- const urlString = typeof url === 'function' ? url() : url;
86
- const conn = new WebSocketImpl(urlString);
87
- clearTimeout(connectTimer);
88
- connectTimer = null;
89
- conn.addEventListener('open', ()=>{
90
- /* istanbul ignore next -- @preserve */ if (conn !== activeConnection) {
91
- return;
92
- }
93
- connectAttempt = 0;
94
- state = 'open';
95
- onOpen?.();
96
- dispatch();
97
- });
98
- conn.addEventListener('error', ()=>{
99
- if (conn === activeConnection) {
83
+ function createConnection() {
84
+ const self = {
85
+ id: ++connectionIndex,
86
+ state: 'connecting'
87
+ };
88
+ const onError = ()=>{
89
+ self.state = 'closed';
90
+ if (self === activeConnection) {
100
91
  tryReconnect();
101
92
  }
102
- });
103
- const handleIncomingRequest = (req)=>{
104
- if (req.method === 'reconnect' && conn === activeConnection) {
105
- if (state === 'open') {
106
- onClose?.();
93
+ };
94
+ run(async ()=>{
95
+ const urlString = typeof url === 'function' ? await url() : url;
96
+ const ws = new WebSocketImpl(urlString);
97
+ self.ws = ws;
98
+ clearTimeout(connectTimer);
99
+ connectTimer = undefined;
100
+ ws.addEventListener('open', ()=>{
101
+ /* istanbul ignore next -- @preserve */ if (activeConnection?.ws !== ws) {
102
+ return;
103
+ }
104
+ connectAttempt = 0;
105
+ self.state = 'open';
106
+ onOpen?.();
107
+ dispatch();
108
+ });
109
+ ws.addEventListener('error', onError);
110
+ const handleIncomingRequest = (req)=>{
111
+ if (self !== activeConnection) {
112
+ return;
107
113
  }
108
- reconnect();
109
- // notify subscribers
110
- for (const pendingReq of Object.values(pendingRequests)){
111
- if (pendingReq.type === 'subscription') {
112
- resumeSubscriptionOnReconnect(pendingReq);
114
+ if (req.method === 'reconnect') {
115
+ reconnect();
116
+ // notify subscribers
117
+ for (const pendingReq of Object.values(pendingRequests)){
118
+ if (pendingReq.type === 'subscription') {
119
+ resumeSubscriptionOnReconnect(pendingReq);
120
+ }
113
121
  }
114
122
  }
115
- }
116
- };
117
- const handleIncomingResponse = (data)=>{
118
- const req = data.id !== null && pendingRequests[data.id];
119
- if (!req) {
120
- // do something?
121
- return;
122
- }
123
- req.callbacks.next?.(data);
124
- if (req.ws !== activeConnection && conn === activeConnection) {
125
- const oldWs = req.ws;
126
- // gracefully replace old connection with this
127
- req.ws = activeConnection;
128
- closeIfNoPending(oldWs);
129
- }
130
- if ('result' in data && data.result.type === 'stopped' && conn === activeConnection) {
131
- req.callbacks.complete();
132
- }
133
- };
134
- conn.addEventListener('message', ({ data })=>{
135
- const msg = JSON.parse(data);
136
- if ('method' in msg) {
137
- handleIncomingRequest(msg);
138
- } else {
139
- handleIncomingResponse(msg);
140
- }
141
- if (conn !== activeConnection || state === 'closed') {
142
- // when receiving a message, we close old connection that has no pending requests
143
- closeIfNoPending(conn);
144
- }
145
- });
146
- conn.addEventListener('close', ({ code })=>{
147
- if (state === 'open') {
148
- onClose?.({
149
- code
150
- });
151
- }
152
- if (activeConnection === conn) {
153
- // connection might have been replaced already
154
- tryReconnect();
155
- }
156
- for (const [key, req] of Object.entries(pendingRequests)){
157
- if (req.ws !== conn) {
158
- continue;
123
+ };
124
+ const handleIncomingResponse = (data)=>{
125
+ const req = data.id !== null && pendingRequests[data.id];
126
+ if (!req) {
127
+ // do something?
128
+ return;
159
129
  }
160
- if (state === 'closed') {
161
- // If the connection was closed, we just call `complete()` on the request
162
- delete pendingRequests[key];
163
- req.callbacks.complete?.();
164
- continue;
130
+ req.callbacks.next?.(data);
131
+ if (self === activeConnection && req.connection !== activeConnection) {
132
+ // gracefully replace old connection with this
133
+ const oldConn = req.connection;
134
+ req.connection = self;
135
+ oldConn && closeIfNoPending(oldConn);
165
136
  }
166
- // The connection was closed either unexpectedly or because of a reconnect
167
- if (req.type === 'subscription') {
168
- // Subscriptions will resume after we've reconnected
169
- resumeSubscriptionOnReconnect(req);
137
+ if ('result' in data && data.result.type === 'stopped' && activeConnection === self) {
138
+ req.callbacks.complete();
139
+ }
140
+ };
141
+ ws.addEventListener('message', ({ data })=>{
142
+ const msg = JSON.parse(data);
143
+ if ('method' in msg) {
144
+ handleIncomingRequest(msg);
170
145
  } else {
171
- // Queries and mutations will error if interrupted
172
- delete pendingRequests[key];
173
- req.callbacks.error?.(TRPCClientError.TRPCClientError.from(new TRPCWebSocketClosedError('WebSocket closed prematurely')));
146
+ handleIncomingResponse(msg);
174
147
  }
175
- }
176
- });
177
- return conn;
148
+ if (self !== activeConnection) {
149
+ // when receiving a message, we close old connection that has no pending requests
150
+ closeIfNoPending(self);
151
+ }
152
+ });
153
+ ws.addEventListener('close', ({ code })=>{
154
+ if (self.state === 'open') {
155
+ onClose?.({
156
+ code
157
+ });
158
+ }
159
+ self.state = 'closed';
160
+ if (activeConnection === self) {
161
+ // connection might have been replaced already
162
+ tryReconnect();
163
+ }
164
+ for (const [key, req] of Object.entries(pendingRequests)){
165
+ if (req.connection !== self) {
166
+ continue;
167
+ }
168
+ if (self.state === 'closed') {
169
+ // If the connection was closed, we just call `complete()` on the request
170
+ delete pendingRequests[key];
171
+ req.callbacks.complete?.();
172
+ continue;
173
+ }
174
+ // The connection was closed either unexpectedly or because of a reconnect
175
+ if (req.type === 'subscription') {
176
+ // Subscriptions will resume after we've reconnected
177
+ resumeSubscriptionOnReconnect(req);
178
+ } else {
179
+ // Queries and mutations will error if interrupted
180
+ delete pendingRequests[key];
181
+ req.callbacks.error?.(TRPCClientError.TRPCClientError.from(new TRPCWebSocketClosedError('WebSocket closed prematurely')));
182
+ }
183
+ }
184
+ });
185
+ }).catch(onError);
186
+ return self;
178
187
  }
179
188
  function request(op, callbacks) {
180
189
  const { type , input , path , id } = op;
@@ -187,7 +196,7 @@ function createWSClient(opts) {
187
196
  }
188
197
  };
189
198
  pendingRequests[id] = {
190
- ws: activeConnection,
199
+ connection: null,
191
200
  type,
192
201
  callbacks,
193
202
  op
@@ -200,7 +209,7 @@ function createWSClient(opts) {
200
209
  delete pendingRequests[id];
201
210
  outgoing = outgoing.filter((msg)=>msg.id !== id);
202
211
  callbacks?.complete?.();
203
- if (activeConnection.readyState === WebSocketImpl.OPEN && op.type === 'subscription') {
212
+ if (activeConnection?.state === 'open' && op.type === 'subscription') {
204
213
  outgoing.push({
205
214
  id,
206
215
  method: 'subscription.stop'
@@ -211,12 +220,18 @@ function createWSClient(opts) {
211
220
  }
212
221
  return {
213
222
  close: ()=>{
214
- state = 'closed';
215
- onClose?.();
216
- closeActiveSubscriptions();
217
- closeIfNoPending(activeConnection);
223
+ killed = true;
224
+ for (const req of Object.values(pendingRequests)){
225
+ if (req.type === 'subscription') {
226
+ req.callbacks.complete();
227
+ } else if (!req.connection) {
228
+ // close pending requests that aren't attached to a connection yet
229
+ req.callbacks.error(TRPCClientError.TRPCClientError.from(new Error('Closed before connection was established')));
230
+ }
231
+ }
232
+ activeConnection && closeIfNoPending(activeConnection);
218
233
  clearTimeout(connectTimer);
219
- connectTimer = null;
234
+ connectTimer = undefined;
220
235
  },
221
236
  request,
222
237
  getConnection () {
@@ -4,6 +4,7 @@ import { T as TRPCClientError } from '../TRPCClientError-0de4d231.mjs';
4
4
 
5
5
  /* istanbul ignore next -- @preserve */ const retryDelay = (attemptIndex)=>attemptIndex === 0 ? 0 : Math.min(1000 * 2 ** attemptIndex, 30000);
6
6
 
7
+ const run = (fn)=>fn();
7
8
  function createWSClient(opts) {
8
9
  const { url , WebSocket: WebSocketImpl = WebSocket , retryDelayMs: retryDelayFn = retryDelay , onOpen , onClose , } = opts;
9
10
  /* istanbul ignore next -- @preserve */ if (!WebSocketImpl) {
@@ -14,163 +15,171 @@ function createWSClient(opts) {
14
15
  */ let outgoing = [];
15
16
  const pendingRequests = Object.create(null);
16
17
  let connectAttempt = 0;
17
- let dispatchTimer = null;
18
- let connectTimer = null;
19
- let activeConnection = createWS();
20
- let state = 'connecting';
18
+ let connectTimer = undefined;
19
+ let connectionIndex = 0;
20
+ let activeConnection = createConnection();
21
+ /**
22
+ * Global connection has been killed
23
+ */ let killed = false;
21
24
  /**
22
25
  * tries to send the list of messages
23
26
  */ function dispatch() {
24
- if (state !== 'open' || dispatchTimer) {
25
- return;
26
- }
27
- dispatchTimer = setTimeout(()=>{
28
- dispatchTimer = null;
27
+ // using a timeout to batch messages
28
+ setTimeout(()=>{
29
+ if (activeConnection?.state !== 'open') {
30
+ return;
31
+ }
32
+ for (const pending of Object.values(pendingRequests)){
33
+ if (!pending.connection) {
34
+ pending.connection = activeConnection;
35
+ }
36
+ }
29
37
  if (outgoing.length === 1) {
30
38
  // single send
31
- activeConnection.send(JSON.stringify(outgoing.pop()));
39
+ activeConnection.ws.send(JSON.stringify(outgoing.pop()));
32
40
  } else {
33
41
  // batch send
34
- activeConnection.send(JSON.stringify(outgoing));
42
+ activeConnection.ws.send(JSON.stringify(outgoing));
35
43
  }
36
44
  // clear
37
45
  outgoing = [];
38
46
  });
39
47
  }
40
48
  function tryReconnect() {
41
- if (connectTimer !== null || state === 'closed') {
49
+ if (!!connectTimer || killed) {
42
50
  return;
43
51
  }
44
52
  const timeout = retryDelayFn(connectAttempt++);
45
53
  reconnectInMs(timeout);
46
54
  }
47
55
  function reconnect() {
48
- state = 'connecting';
49
56
  const oldConnection = activeConnection;
50
- activeConnection = createWS();
51
- closeIfNoPending(oldConnection);
57
+ activeConnection = createConnection();
58
+ oldConnection && closeIfNoPending(oldConnection);
52
59
  }
53
60
  function reconnectInMs(ms) {
54
61
  if (connectTimer) {
55
62
  return;
56
63
  }
57
- state = 'connecting';
58
64
  connectTimer = setTimeout(reconnect, ms);
59
65
  }
60
66
  function closeIfNoPending(conn) {
61
67
  // disconnect as soon as there are are no pending result
62
- const hasPendingRequests = Object.values(pendingRequests).some((p)=>p.ws === conn);
68
+ const hasPendingRequests = Object.values(pendingRequests).some((p)=>p.connection === conn);
63
69
  if (!hasPendingRequests) {
64
- conn.close();
70
+ conn.ws?.close();
65
71
  }
66
72
  }
67
- function closeActiveSubscriptions() {
68
- Object.values(pendingRequests).forEach((req)=>{
69
- if (req.type === 'subscription') {
70
- req.callbacks.complete();
71
- }
72
- });
73
- }
74
73
  function resumeSubscriptionOnReconnect(req) {
75
74
  if (outgoing.some((r)=>r.id === req.op.id)) {
76
75
  return;
77
76
  }
78
77
  request(req.op, req.callbacks);
79
78
  }
80
- function createWS() {
81
- const urlString = typeof url === 'function' ? url() : url;
82
- const conn = new WebSocketImpl(urlString);
83
- clearTimeout(connectTimer);
84
- connectTimer = null;
85
- conn.addEventListener('open', ()=>{
86
- /* istanbul ignore next -- @preserve */ if (conn !== activeConnection) {
87
- return;
88
- }
89
- connectAttempt = 0;
90
- state = 'open';
91
- onOpen?.();
92
- dispatch();
93
- });
94
- conn.addEventListener('error', ()=>{
95
- if (conn === activeConnection) {
79
+ function createConnection() {
80
+ const self = {
81
+ id: ++connectionIndex,
82
+ state: 'connecting'
83
+ };
84
+ const onError = ()=>{
85
+ self.state = 'closed';
86
+ if (self === activeConnection) {
96
87
  tryReconnect();
97
88
  }
98
- });
99
- const handleIncomingRequest = (req)=>{
100
- if (req.method === 'reconnect' && conn === activeConnection) {
101
- if (state === 'open') {
102
- onClose?.();
89
+ };
90
+ run(async ()=>{
91
+ const urlString = typeof url === 'function' ? await url() : url;
92
+ const ws = new WebSocketImpl(urlString);
93
+ self.ws = ws;
94
+ clearTimeout(connectTimer);
95
+ connectTimer = undefined;
96
+ ws.addEventListener('open', ()=>{
97
+ /* istanbul ignore next -- @preserve */ if (activeConnection?.ws !== ws) {
98
+ return;
99
+ }
100
+ connectAttempt = 0;
101
+ self.state = 'open';
102
+ onOpen?.();
103
+ dispatch();
104
+ });
105
+ ws.addEventListener('error', onError);
106
+ const handleIncomingRequest = (req)=>{
107
+ if (self !== activeConnection) {
108
+ return;
103
109
  }
104
- reconnect();
105
- // notify subscribers
106
- for (const pendingReq of Object.values(pendingRequests)){
107
- if (pendingReq.type === 'subscription') {
108
- resumeSubscriptionOnReconnect(pendingReq);
110
+ if (req.method === 'reconnect') {
111
+ reconnect();
112
+ // notify subscribers
113
+ for (const pendingReq of Object.values(pendingRequests)){
114
+ if (pendingReq.type === 'subscription') {
115
+ resumeSubscriptionOnReconnect(pendingReq);
116
+ }
109
117
  }
110
118
  }
111
- }
112
- };
113
- const handleIncomingResponse = (data)=>{
114
- const req = data.id !== null && pendingRequests[data.id];
115
- if (!req) {
116
- // do something?
117
- return;
118
- }
119
- req.callbacks.next?.(data);
120
- if (req.ws !== activeConnection && conn === activeConnection) {
121
- const oldWs = req.ws;
122
- // gracefully replace old connection with this
123
- req.ws = activeConnection;
124
- closeIfNoPending(oldWs);
125
- }
126
- if ('result' in data && data.result.type === 'stopped' && conn === activeConnection) {
127
- req.callbacks.complete();
128
- }
129
- };
130
- conn.addEventListener('message', ({ data })=>{
131
- const msg = JSON.parse(data);
132
- if ('method' in msg) {
133
- handleIncomingRequest(msg);
134
- } else {
135
- handleIncomingResponse(msg);
136
- }
137
- if (conn !== activeConnection || state === 'closed') {
138
- // when receiving a message, we close old connection that has no pending requests
139
- closeIfNoPending(conn);
140
- }
141
- });
142
- conn.addEventListener('close', ({ code })=>{
143
- if (state === 'open') {
144
- onClose?.({
145
- code
146
- });
147
- }
148
- if (activeConnection === conn) {
149
- // connection might have been replaced already
150
- tryReconnect();
151
- }
152
- for (const [key, req] of Object.entries(pendingRequests)){
153
- if (req.ws !== conn) {
154
- continue;
119
+ };
120
+ const handleIncomingResponse = (data)=>{
121
+ const req = data.id !== null && pendingRequests[data.id];
122
+ if (!req) {
123
+ // do something?
124
+ return;
155
125
  }
156
- if (state === 'closed') {
157
- // If the connection was closed, we just call `complete()` on the request
158
- delete pendingRequests[key];
159
- req.callbacks.complete?.();
160
- continue;
126
+ req.callbacks.next?.(data);
127
+ if (self === activeConnection && req.connection !== activeConnection) {
128
+ // gracefully replace old connection with this
129
+ const oldConn = req.connection;
130
+ req.connection = self;
131
+ oldConn && closeIfNoPending(oldConn);
161
132
  }
162
- // The connection was closed either unexpectedly or because of a reconnect
163
- if (req.type === 'subscription') {
164
- // Subscriptions will resume after we've reconnected
165
- resumeSubscriptionOnReconnect(req);
133
+ if ('result' in data && data.result.type === 'stopped' && activeConnection === self) {
134
+ req.callbacks.complete();
135
+ }
136
+ };
137
+ ws.addEventListener('message', ({ data })=>{
138
+ const msg = JSON.parse(data);
139
+ if ('method' in msg) {
140
+ handleIncomingRequest(msg);
166
141
  } else {
167
- // Queries and mutations will error if interrupted
168
- delete pendingRequests[key];
169
- req.callbacks.error?.(TRPCClientError.from(new TRPCWebSocketClosedError('WebSocket closed prematurely')));
142
+ handleIncomingResponse(msg);
170
143
  }
171
- }
172
- });
173
- return conn;
144
+ if (self !== activeConnection) {
145
+ // when receiving a message, we close old connection that has no pending requests
146
+ closeIfNoPending(self);
147
+ }
148
+ });
149
+ ws.addEventListener('close', ({ code })=>{
150
+ if (self.state === 'open') {
151
+ onClose?.({
152
+ code
153
+ });
154
+ }
155
+ self.state = 'closed';
156
+ if (activeConnection === self) {
157
+ // connection might have been replaced already
158
+ tryReconnect();
159
+ }
160
+ for (const [key, req] of Object.entries(pendingRequests)){
161
+ if (req.connection !== self) {
162
+ continue;
163
+ }
164
+ if (self.state === 'closed') {
165
+ // If the connection was closed, we just call `complete()` on the request
166
+ delete pendingRequests[key];
167
+ req.callbacks.complete?.();
168
+ continue;
169
+ }
170
+ // The connection was closed either unexpectedly or because of a reconnect
171
+ if (req.type === 'subscription') {
172
+ // Subscriptions will resume after we've reconnected
173
+ resumeSubscriptionOnReconnect(req);
174
+ } else {
175
+ // Queries and mutations will error if interrupted
176
+ delete pendingRequests[key];
177
+ req.callbacks.error?.(TRPCClientError.from(new TRPCWebSocketClosedError('WebSocket closed prematurely')));
178
+ }
179
+ }
180
+ });
181
+ }).catch(onError);
182
+ return self;
174
183
  }
175
184
  function request(op, callbacks) {
176
185
  const { type , input , path , id } = op;
@@ -183,7 +192,7 @@ function createWSClient(opts) {
183
192
  }
184
193
  };
185
194
  pendingRequests[id] = {
186
- ws: activeConnection,
195
+ connection: null,
187
196
  type,
188
197
  callbacks,
189
198
  op
@@ -196,7 +205,7 @@ function createWSClient(opts) {
196
205
  delete pendingRequests[id];
197
206
  outgoing = outgoing.filter((msg)=>msg.id !== id);
198
207
  callbacks?.complete?.();
199
- if (activeConnection.readyState === WebSocketImpl.OPEN && op.type === 'subscription') {
208
+ if (activeConnection?.state === 'open' && op.type === 'subscription') {
200
209
  outgoing.push({
201
210
  id,
202
211
  method: 'subscription.stop'
@@ -207,12 +216,18 @@ function createWSClient(opts) {
207
216
  }
208
217
  return {
209
218
  close: ()=>{
210
- state = 'closed';
211
- onClose?.();
212
- closeActiveSubscriptions();
213
- closeIfNoPending(activeConnection);
219
+ killed = true;
220
+ for (const req of Object.values(pendingRequests)){
221
+ if (req.type === 'subscription') {
222
+ req.callbacks.complete();
223
+ } else if (!req.connection) {
224
+ // close pending requests that aren't attached to a connection yet
225
+ req.callbacks.error(TRPCClientError.from(new Error('Closed before connection was established')));
226
+ }
227
+ }
228
+ activeConnection && closeIfNoPending(activeConnection);
214
229
  clearTimeout(connectTimer);
215
- connectTimer = null;
230
+ connectTimer = undefined;
216
231
  },
217
232
  request,
218
233
  getConnection () {