@trpc/server 11.0.0-alpha-tmp-12-06-react.674 → 11.0.0-alpha-tmp-issues-6374.696

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/adapters/fastify/fastifyRequestHandler.d.ts.map +1 -1
  2. package/dist/adapters/node-http/incomingMessageToRequest.d.ts +10 -3
  3. package/dist/adapters/node-http/incomingMessageToRequest.d.ts.map +1 -1
  4. package/dist/adapters/node-http/incomingMessageToRequest.js +8 -6
  5. package/dist/adapters/node-http/incomingMessageToRequest.mjs +8 -6
  6. package/dist/adapters/ws.js +1 -1
  7. package/dist/adapters/ws.mjs +1 -1
  8. package/dist/bundle-analysis.json +128 -112
  9. package/dist/unstable-core-do-not-import/createProxy.d.ts +1 -1
  10. package/dist/unstable-core-do-not-import/createProxy.d.ts.map +1 -1
  11. package/dist/unstable-core-do-not-import/createProxy.js +2 -1
  12. package/dist/unstable-core-do-not-import/createProxy.mjs +2 -1
  13. package/dist/unstable-core-do-not-import/stream/jsonl.d.ts.map +1 -1
  14. package/dist/unstable-core-do-not-import/stream/jsonl.js +154 -188
  15. package/dist/unstable-core-do-not-import/stream/jsonl.mjs +156 -190
  16. package/dist/unstable-core-do-not-import/stream/sse.d.ts +1 -1
  17. package/dist/unstable-core-do-not-import/stream/sse.d.ts.map +1 -1
  18. package/dist/unstable-core-do-not-import/stream/sse.js +7 -3
  19. package/dist/unstable-core-do-not-import/stream/sse.mjs +7 -3
  20. package/dist/unstable-core-do-not-import/stream/utils/mergeAsyncIterables.d.ts +17 -0
  21. package/dist/unstable-core-do-not-import/stream/utils/mergeAsyncIterables.d.ts.map +1 -0
  22. package/dist/unstable-core-do-not-import/stream/utils/mergeAsyncIterables.js +241 -0
  23. package/dist/unstable-core-do-not-import/stream/utils/mergeAsyncIterables.mjs +239 -0
  24. package/package.json +7 -7
  25. package/src/adapters/fastify/fastifyRequestHandler.ts +2 -2
  26. package/src/adapters/node-http/incomingMessageToRequest.ts +19 -11
  27. package/src/unstable-core-do-not-import/createProxy.ts +3 -2
  28. package/src/unstable-core-do-not-import/stream/jsonl.ts +14 -46
  29. package/src/unstable-core-do-not-import/stream/sse.ts +28 -21
  30. package/src/unstable-core-do-not-import/stream/utils/mergeAsyncIterables.ts +193 -0
@@ -0,0 +1,241 @@
1
+ 'use strict';
2
+
3
+ var createDeferred = require('./createDeferred.js');
4
+ var disposable = require('./disposable.js');
5
+
6
+ function _ts_add_disposable_resource(env, value, async) {
7
+ if (value !== null && value !== void 0) {
8
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
9
+ var dispose, inner;
10
+ {
11
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
12
+ dispose = value[Symbol.asyncDispose];
13
+ }
14
+ if (dispose === void 0) {
15
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
16
+ dispose = value[Symbol.dispose];
17
+ inner = dispose;
18
+ }
19
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
20
+ if (inner) dispose = function() {
21
+ try {
22
+ inner.call(this);
23
+ } catch (e) {
24
+ return Promise.reject(e);
25
+ }
26
+ };
27
+ env.stack.push({
28
+ value: value,
29
+ dispose: dispose,
30
+ async: async
31
+ });
32
+ } else {
33
+ env.stack.push({
34
+ async: true
35
+ });
36
+ }
37
+ return value;
38
+ }
39
+ function _ts_dispose_resources(env) {
40
+ var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
41
+ var e = new Error(message);
42
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
43
+ };
44
+ return (_ts_dispose_resources = function _ts_dispose_resources(env) {
45
+ function fail(e) {
46
+ env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
47
+ env.hasError = true;
48
+ }
49
+ var r, s = 0;
50
+ function next() {
51
+ while(r = env.stack.pop()){
52
+ try {
53
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
54
+ if (r.dispose) {
55
+ var result = r.dispose.call(r.value);
56
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
57
+ fail(e);
58
+ return next();
59
+ });
60
+ } else s |= 1;
61
+ } catch (e) {
62
+ fail(e);
63
+ }
64
+ }
65
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
66
+ if (env.hasError) throw env.error;
67
+ }
68
+ return next();
69
+ })(env);
70
+ }
71
+ function createManagedIterator(iterable, onResult) {
72
+ const iterator = iterable[Symbol.asyncIterator]();
73
+ let state = 'idle';
74
+ function cleanup() {
75
+ state = 'done';
76
+ onResult = ()=>{
77
+ // noop
78
+ };
79
+ }
80
+ function pull() {
81
+ if (state !== 'idle') {
82
+ return;
83
+ }
84
+ state = 'pending';
85
+ const next = iterator.next();
86
+ next.then((result)=>{
87
+ if (result.done) {
88
+ state = 'done';
89
+ onResult({
90
+ status: 'return',
91
+ value: result.value
92
+ });
93
+ cleanup();
94
+ return;
95
+ }
96
+ state = 'idle';
97
+ onResult({
98
+ status: 'yield',
99
+ value: result.value
100
+ });
101
+ }).catch((cause)=>{
102
+ onResult({
103
+ status: 'error',
104
+ error: cause
105
+ });
106
+ cleanup();
107
+ });
108
+ }
109
+ return {
110
+ pull,
111
+ destroy: async ()=>{
112
+ cleanup();
113
+ await iterator.return?.();
114
+ }
115
+ };
116
+ }
117
+ /**
118
+ * Creates a new async iterable that merges multiple async iterables into a single stream.
119
+ * Values from the input iterables are yielded in the order they resolve, similar to Promise.race().
120
+ *
121
+ * New iterables can be added dynamically using the returned {@link MergedAsyncIterables.add} method, even after iteration has started.
122
+ *
123
+ * If any of the input iterables throws an error, that error will be propagated through the merged stream.
124
+ * Other iterables will not continue to be processed.
125
+ *
126
+ * @template TYield The type of values yielded by the input iterables
127
+ */ function mergeAsyncIterables() {
128
+ let state = 'idle';
129
+ let flushSignal = createDeferred.createDeferred();
130
+ /**
131
+ * used while {@link state} is `idle`
132
+ */ const iterables = [];
133
+ /**
134
+ * used while {@link state} is `pending`
135
+ */ const iterators = new Set();
136
+ const buffer = [];
137
+ function initIterable(iterable) {
138
+ if (state !== 'pending') {
139
+ // shouldn't happen
140
+ return;
141
+ }
142
+ const iterator = createManagedIterator(iterable, (result)=>{
143
+ if (state !== 'pending') {
144
+ // shouldn't happen
145
+ return;
146
+ }
147
+ switch(result.status){
148
+ case 'yield':
149
+ buffer.push([
150
+ iterator,
151
+ result
152
+ ]);
153
+ break;
154
+ case 'return':
155
+ iterators.delete(iterator);
156
+ break;
157
+ case 'error':
158
+ buffer.push([
159
+ iterator,
160
+ result
161
+ ]);
162
+ iterators.delete(iterator);
163
+ break;
164
+ }
165
+ flushSignal.resolve();
166
+ });
167
+ iterators.add(iterator);
168
+ iterator.pull();
169
+ }
170
+ return {
171
+ add (iterable) {
172
+ switch(state){
173
+ case 'idle':
174
+ iterables.push(iterable);
175
+ break;
176
+ case 'pending':
177
+ initIterable(iterable);
178
+ break;
179
+ }
180
+ },
181
+ async *[Symbol.asyncIterator] () {
182
+ const env = {
183
+ stack: [],
184
+ error: void 0,
185
+ hasError: false
186
+ };
187
+ try {
188
+ if (state !== 'idle') {
189
+ throw new Error('Cannot iterate twice');
190
+ }
191
+ state = 'pending';
192
+ const _finally = _ts_add_disposable_resource(env, disposable.makeAsyncResource({}, async ()=>{
193
+ state = 'done';
194
+ const errors = [];
195
+ await Promise.all(Array.from(iterators.values()).map(async (it)=>{
196
+ try {
197
+ await it.destroy();
198
+ } catch (cause) {
199
+ errors.push(cause);
200
+ }
201
+ }));
202
+ buffer.length = 0;
203
+ iterators.clear();
204
+ flushSignal.resolve();
205
+ if (errors.length > 0) {
206
+ throw new AggregateError(errors);
207
+ }
208
+ }), true);
209
+ ;
210
+ while(iterables.length > 0){
211
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
212
+ initIterable(iterables.shift());
213
+ }
214
+ while(iterators.size > 0){
215
+ await flushSignal.promise;
216
+ while(buffer.length > 0){
217
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
218
+ const [iterator, result] = buffer.shift();
219
+ switch(result.status){
220
+ case 'yield':
221
+ yield result.value;
222
+ iterator.pull();
223
+ break;
224
+ case 'error':
225
+ throw result.error;
226
+ }
227
+ }
228
+ flushSignal = createDeferred.createDeferred();
229
+ }
230
+ } catch (e) {
231
+ env.error = e;
232
+ env.hasError = true;
233
+ } finally{
234
+ const result = _ts_dispose_resources(env);
235
+ if (result) await result;
236
+ }
237
+ }
238
+ };
239
+ }
240
+
241
+ exports.mergeAsyncIterables = mergeAsyncIterables;
@@ -0,0 +1,239 @@
1
+ import { createDeferred } from './createDeferred.mjs';
2
+ import { makeAsyncResource } from './disposable.mjs';
3
+
4
+ function _ts_add_disposable_resource(env, value, async) {
5
+ if (value !== null && value !== void 0) {
6
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
7
+ var dispose, inner;
8
+ {
9
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
10
+ dispose = value[Symbol.asyncDispose];
11
+ }
12
+ if (dispose === void 0) {
13
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
14
+ dispose = value[Symbol.dispose];
15
+ inner = dispose;
16
+ }
17
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
18
+ if (inner) dispose = function() {
19
+ try {
20
+ inner.call(this);
21
+ } catch (e) {
22
+ return Promise.reject(e);
23
+ }
24
+ };
25
+ env.stack.push({
26
+ value: value,
27
+ dispose: dispose,
28
+ async: async
29
+ });
30
+ } else {
31
+ env.stack.push({
32
+ async: true
33
+ });
34
+ }
35
+ return value;
36
+ }
37
+ function _ts_dispose_resources(env) {
38
+ var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
39
+ var e = new Error(message);
40
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
41
+ };
42
+ return (_ts_dispose_resources = function _ts_dispose_resources(env) {
43
+ function fail(e) {
44
+ env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
45
+ env.hasError = true;
46
+ }
47
+ var r, s = 0;
48
+ function next() {
49
+ while(r = env.stack.pop()){
50
+ try {
51
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
52
+ if (r.dispose) {
53
+ var result = r.dispose.call(r.value);
54
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
55
+ fail(e);
56
+ return next();
57
+ });
58
+ } else s |= 1;
59
+ } catch (e) {
60
+ fail(e);
61
+ }
62
+ }
63
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
64
+ if (env.hasError) throw env.error;
65
+ }
66
+ return next();
67
+ })(env);
68
+ }
69
+ function createManagedIterator(iterable, onResult) {
70
+ const iterator = iterable[Symbol.asyncIterator]();
71
+ let state = 'idle';
72
+ function cleanup() {
73
+ state = 'done';
74
+ onResult = ()=>{
75
+ // noop
76
+ };
77
+ }
78
+ function pull() {
79
+ if (state !== 'idle') {
80
+ return;
81
+ }
82
+ state = 'pending';
83
+ const next = iterator.next();
84
+ next.then((result)=>{
85
+ if (result.done) {
86
+ state = 'done';
87
+ onResult({
88
+ status: 'return',
89
+ value: result.value
90
+ });
91
+ cleanup();
92
+ return;
93
+ }
94
+ state = 'idle';
95
+ onResult({
96
+ status: 'yield',
97
+ value: result.value
98
+ });
99
+ }).catch((cause)=>{
100
+ onResult({
101
+ status: 'error',
102
+ error: cause
103
+ });
104
+ cleanup();
105
+ });
106
+ }
107
+ return {
108
+ pull,
109
+ destroy: async ()=>{
110
+ cleanup();
111
+ await iterator.return?.();
112
+ }
113
+ };
114
+ }
115
+ /**
116
+ * Creates a new async iterable that merges multiple async iterables into a single stream.
117
+ * Values from the input iterables are yielded in the order they resolve, similar to Promise.race().
118
+ *
119
+ * New iterables can be added dynamically using the returned {@link MergedAsyncIterables.add} method, even after iteration has started.
120
+ *
121
+ * If any of the input iterables throws an error, that error will be propagated through the merged stream.
122
+ * Other iterables will not continue to be processed.
123
+ *
124
+ * @template TYield The type of values yielded by the input iterables
125
+ */ function mergeAsyncIterables() {
126
+ let state = 'idle';
127
+ let flushSignal = createDeferred();
128
+ /**
129
+ * used while {@link state} is `idle`
130
+ */ const iterables = [];
131
+ /**
132
+ * used while {@link state} is `pending`
133
+ */ const iterators = new Set();
134
+ const buffer = [];
135
+ function initIterable(iterable) {
136
+ if (state !== 'pending') {
137
+ // shouldn't happen
138
+ return;
139
+ }
140
+ const iterator = createManagedIterator(iterable, (result)=>{
141
+ if (state !== 'pending') {
142
+ // shouldn't happen
143
+ return;
144
+ }
145
+ switch(result.status){
146
+ case 'yield':
147
+ buffer.push([
148
+ iterator,
149
+ result
150
+ ]);
151
+ break;
152
+ case 'return':
153
+ iterators.delete(iterator);
154
+ break;
155
+ case 'error':
156
+ buffer.push([
157
+ iterator,
158
+ result
159
+ ]);
160
+ iterators.delete(iterator);
161
+ break;
162
+ }
163
+ flushSignal.resolve();
164
+ });
165
+ iterators.add(iterator);
166
+ iterator.pull();
167
+ }
168
+ return {
169
+ add (iterable) {
170
+ switch(state){
171
+ case 'idle':
172
+ iterables.push(iterable);
173
+ break;
174
+ case 'pending':
175
+ initIterable(iterable);
176
+ break;
177
+ }
178
+ },
179
+ async *[Symbol.asyncIterator] () {
180
+ const env = {
181
+ stack: [],
182
+ error: void 0,
183
+ hasError: false
184
+ };
185
+ try {
186
+ if (state !== 'idle') {
187
+ throw new Error('Cannot iterate twice');
188
+ }
189
+ state = 'pending';
190
+ const _finally = _ts_add_disposable_resource(env, makeAsyncResource({}, async ()=>{
191
+ state = 'done';
192
+ const errors = [];
193
+ await Promise.all(Array.from(iterators.values()).map(async (it)=>{
194
+ try {
195
+ await it.destroy();
196
+ } catch (cause) {
197
+ errors.push(cause);
198
+ }
199
+ }));
200
+ buffer.length = 0;
201
+ iterators.clear();
202
+ flushSignal.resolve();
203
+ if (errors.length > 0) {
204
+ throw new AggregateError(errors);
205
+ }
206
+ }), true);
207
+ ;
208
+ while(iterables.length > 0){
209
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
210
+ initIterable(iterables.shift());
211
+ }
212
+ while(iterators.size > 0){
213
+ await flushSignal.promise;
214
+ while(buffer.length > 0){
215
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
216
+ const [iterator, result] = buffer.shift();
217
+ switch(result.status){
218
+ case 'yield':
219
+ yield result.value;
220
+ iterator.pull();
221
+ break;
222
+ case 'error':
223
+ throw result.error;
224
+ }
225
+ }
226
+ flushSignal = createDeferred();
227
+ }
228
+ } catch (e) {
229
+ env.error = e;
230
+ env.hasError = true;
231
+ } finally{
232
+ const result = _ts_dispose_resources(env);
233
+ if (result) await result;
234
+ }
235
+ }
236
+ };
237
+ }
238
+
239
+ export { mergeAsyncIterables };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trpc/server",
3
- "version": "11.0.0-alpha-tmp-12-06-react.674+d396198ca",
3
+ "version": "11.0.0-alpha-tmp-issues-6374.696+c944cfbf2",
4
4
  "description": "The tRPC server library",
5
5
  "author": "KATT",
6
6
  "license": "MIT",
@@ -118,7 +118,7 @@
118
118
  },
119
119
  "devDependencies": {
120
120
  "@fastify/websocket": "^10.0.1",
121
- "@tanstack/react-query": "^5.59.15",
121
+ "@tanstack/react-query": "^5.62.8",
122
122
  "@types/aws-lambda": "^8.10.137",
123
123
  "@types/express": "^4.17.17",
124
124
  "@types/hash-sum": "^1.0.0",
@@ -128,19 +128,19 @@
128
128
  "@types/ws": "^8.2.0",
129
129
  "devalue": "^5.0.0",
130
130
  "eslint": "^9.13.0",
131
- "express": "^4.17.1",
131
+ "express": "^5.0.0",
132
132
  "fastify": "^4.16.0",
133
133
  "fastify-plugin": "^5.0.0",
134
134
  "hash-sum": "^2.0.0",
135
135
  "myzod": "^1.3.1",
136
- "next": "^15.0.4",
136
+ "next": "^15.1.3",
137
137
  "react": "^19.0.0",
138
138
  "react-dom": "^19.0.0",
139
139
  "rollup": "^4.24.4",
140
140
  "superjson": "^1.12.4",
141
141
  "superstruct": "^2.0.0",
142
142
  "tsx": "^4.0.0",
143
- "typescript": "^5.7.0",
143
+ "typescript": "^5.7.2",
144
144
  "valibot": "^0.42.0",
145
145
  "ws": "^8.0.0",
146
146
  "yup": "^1.0.0",
@@ -150,7 +150,7 @@
150
150
  "https://trpc.io/sponsor"
151
151
  ],
152
152
  "peerDependencies": {
153
- "typescript": ">=5.6.2"
153
+ "typescript": ">=5.7.2"
154
154
  },
155
- "gitHead": "d396198ca526f56f0a5954cdee0fd407476d9475"
155
+ "gitHead": "c944cfbf28c0723b087dfd4b2d26c554457374f0"
156
156
  }
@@ -19,8 +19,8 @@ import {
19
19
  // @trpc/server/node-http
20
20
  import {
21
21
  incomingMessageToRequest,
22
- type IncomingMessageWithBody,
23
22
  type NodeHTTPCreateContextOption,
23
+ type UniversalIncomingMessage,
24
24
  } from '../node-http';
25
25
 
26
26
  export type FastifyHandlerOptions<
@@ -54,7 +54,7 @@ export async function fastifyRequestHandler<
54
54
  });
55
55
  };
56
56
 
57
- const incomingMessage = opts.req.raw as IncomingMessageWithBody;
57
+ const incomingMessage: UniversalIncomingMessage = opts.req.raw;
58
58
 
59
59
  // monkey-path body to the IncomingMessage
60
60
  if ('body' in opts.req) {
@@ -1,15 +1,23 @@
1
1
  import type * as http from 'http';
2
2
  import { TRPCError } from '../../@trpc/server';
3
3
 
4
- export interface IncomingMessageWithBody extends http.IncomingMessage {
4
+ export interface UniversalIncomingMessage
5
+ extends Omit<http.IncomingMessage, 'socket'> {
5
6
  /**
6
7
  * Many adapters will add a `body` property to the incoming message and pre-parse the body
7
8
  */
8
9
  body?: unknown;
10
+ /**
11
+ * Socket is not always available in all deployments, so we need to make it optional
12
+ * @see https://github.com/trpc/trpc/issues/6341
13
+ * The socket object provided in the request does not fully implement the expected Node.js Socket interface.
14
+ * @see https://github.com/trpc/trpc/pull/6358
15
+ */
16
+ socket?: Partial<http.IncomingMessage['socket']>;
9
17
  }
10
18
 
11
19
  function createBody(
12
- req: http.IncomingMessage,
20
+ req: UniversalIncomingMessage,
13
21
  opts: {
14
22
  /**
15
23
  * Max body size in bytes. If the body is larger than this, the request will be aborted
@@ -19,16 +27,16 @@ function createBody(
19
27
  ): RequestInit['body'] {
20
28
  // Some adapters will pre-parse the body and add it to the request object
21
29
  if ('body' in req) {
30
+ if (req.body === undefined) {
31
+ // If body property exists but is undefined, return undefined
32
+ return undefined;
33
+ }
22
34
  // If the body is already a string, return it directly
23
35
  if (typeof req.body === 'string') {
24
36
  return req.body;
25
37
  }
26
38
  // If body exists but isn't a string, stringify it as JSON
27
- else if (req.body !== undefined) {
28
- return JSON.stringify(req.body);
29
- }
30
- // If body property exists but is undefined, return undefined
31
- return undefined;
39
+ return JSON.stringify(req.body);
32
40
  }
33
41
  let size = 0;
34
42
  let hasClosed = false;
@@ -71,7 +79,7 @@ function createBody(
71
79
  },
72
80
  });
73
81
  }
74
- export function createURL(req: http.IncomingMessage): URL {
82
+ export function createURL(req: UniversalIncomingMessage): URL {
75
83
  try {
76
84
  const protocol =
77
85
  req.socket && 'encrypted' in req.socket && req.socket.encrypted
@@ -117,7 +125,7 @@ function createHeaders(incoming: http.IncomingHttpHeaders): Headers {
117
125
  * Convert an [`IncomingMessage`](https://nodejs.org/api/http.html#class-httpincomingmessage) to a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
118
126
  */
119
127
  export function incomingMessageToRequest(
120
- req: http.IncomingMessage,
128
+ req: UniversalIncomingMessage,
121
129
  res: http.ServerResponse,
122
130
  opts: {
123
131
  /**
@@ -130,14 +138,14 @@ export function incomingMessageToRequest(
130
138
 
131
139
  const onAbort = () => {
132
140
  res.off('close', onAbort);
133
- req.socket.off('end', onAbort);
141
+ req.socket?.off?.('end', onAbort);
134
142
 
135
143
  // abort the request
136
144
  ac.abort();
137
145
  };
138
146
 
139
147
  res.once('close', onAbort);
140
- req.socket.once('end', onAbort);
148
+ req.socket?.once?.('end', onAbort);
141
149
 
142
150
  // Get host from either regular header or HTTP/2 pseudo-header
143
151
  const url = createURL(req);
@@ -70,11 +70,12 @@ export const createRecursiveProxy = <TFaux = unknown>(
70
70
  * @internal
71
71
  */
72
72
  export const createFlatProxy = <TFaux>(
73
- callback: (path: string & keyof TFaux) => any,
73
+ callback: (path: (string & keyof TFaux) | symbol) => any,
74
74
  ): TFaux => {
75
75
  return new Proxy(noop, {
76
76
  get(_obj, name) {
77
- if (typeof name !== 'string' || name === 'then') {
77
+ const type = typeof name;
78
+ if ((type !== 'string' && type !== 'symbol') || name === 'then') {
78
79
  // special case for if the proxy is accidentally treated
79
80
  // like a PromiseLike (like in `Promise.resolve(proxy)`)
80
81
  return undefined;