@whatwg-node/node-fetch 0.8.0-alpha-20241212160430-140b66f028923f44368e67598b6b66f47f690454 → 0.8.0-alpha-20250917053118-2dc604e028627df01a83e41a3dd6dd3f89ca0b40

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 (73) hide show
  1. package/cjs/AbortError.js +10 -3
  2. package/cjs/Blob.js +21 -19
  3. package/cjs/Body.js +146 -76
  4. package/cjs/FormData.js +54 -41
  5. package/cjs/Headers.js +54 -15
  6. package/cjs/ReadableStream.js +62 -26
  7. package/cjs/Request.js +9 -16
  8. package/cjs/Response.js +56 -10
  9. package/cjs/TextEncoderDecoder.js +6 -5
  10. package/cjs/TextEncoderDecoderStream.js +2 -6
  11. package/cjs/TransformStream.js +2 -1
  12. package/cjs/URL.js +10 -66
  13. package/cjs/URLSearchParams.js +1 -117
  14. package/cjs/WritableStream.js +35 -111
  15. package/cjs/fetch.js +37 -8
  16. package/cjs/fetchCurl.js +30 -61
  17. package/cjs/fetchNodeHttp.js +60 -64
  18. package/cjs/index.js +1 -7
  19. package/cjs/utils.js +76 -55
  20. package/esm/AbortError.js +10 -3
  21. package/esm/Blob.js +6 -4
  22. package/esm/Body.js +134 -63
  23. package/esm/FormData.js +54 -41
  24. package/esm/Headers.js +54 -15
  25. package/esm/ReadableStream.js +57 -21
  26. package/esm/Request.js +7 -14
  27. package/esm/Response.js +55 -9
  28. package/esm/TextEncoderDecoder.js +1 -0
  29. package/esm/TextEncoderDecoderStream.js +2 -6
  30. package/esm/TransformStream.js +2 -1
  31. package/esm/URL.js +9 -64
  32. package/esm/URLSearchParams.js +1 -115
  33. package/esm/WritableStream.js +33 -109
  34. package/esm/fetch.js +35 -6
  35. package/esm/fetchCurl.js +28 -59
  36. package/esm/fetchNodeHttp.js +55 -59
  37. package/esm/index.js +0 -3
  38. package/esm/utils.js +70 -53
  39. package/package.json +4 -5
  40. package/typings/AbortError.d.cts +2 -2
  41. package/typings/AbortError.d.ts +2 -2
  42. package/typings/Blob.d.cts +5 -4
  43. package/typings/Blob.d.ts +5 -4
  44. package/typings/Body.d.cts +11 -6
  45. package/typings/Body.d.ts +11 -6
  46. package/typings/Headers.d.cts +1 -1
  47. package/typings/Headers.d.ts +1 -1
  48. package/typings/ReadableStream.d.cts +8 -2
  49. package/typings/ReadableStream.d.ts +8 -2
  50. package/typings/Request.d.cts +9 -10
  51. package/typings/Request.d.ts +9 -10
  52. package/typings/Response.d.cts +6 -5
  53. package/typings/Response.d.ts +6 -5
  54. package/typings/TextEncoderDecoder.d.cts +2 -1
  55. package/typings/TextEncoderDecoder.d.ts +2 -1
  56. package/typings/URL.d.cts +12 -16
  57. package/typings/URL.d.ts +12 -16
  58. package/typings/URLSearchParams.d.cts +4 -21
  59. package/typings/URLSearchParams.d.ts +4 -21
  60. package/typings/WritableStream.d.cts +1 -1
  61. package/typings/WritableStream.d.ts +1 -1
  62. package/typings/index.d.cts +0 -3
  63. package/typings/index.d.ts +0 -3
  64. package/typings/utils.d.cts +13 -8
  65. package/typings/utils.d.ts +13 -8
  66. package/cjs/AbortController.js +0 -18
  67. package/cjs/AbortSignal.js +0 -92
  68. package/esm/AbortController.js +0 -14
  69. package/esm/AbortSignal.js +0 -88
  70. package/typings/AbortController.d.cts +0 -8
  71. package/typings/AbortController.d.ts +0 -8
  72. package/typings/AbortSignal.d.cts +0 -15
  73. package/typings/AbortSignal.d.ts +0 -15
@@ -1,5 +1,7 @@
1
- import { Writable } from 'stream';
2
- import { fakePromise } from './utils.js';
1
+ import { once } from 'node:events';
2
+ import { Writable } from 'node:stream';
3
+ import { fakeRejectPromise } from '@whatwg-node/promise-helpers';
4
+ import { endStream, fakePromise, safeWrite } from './utils.js';
3
5
  export class PonyfillWritableStream {
4
6
  writable;
5
7
  constructor(underlyingSink) {
@@ -41,55 +43,15 @@ export class PonyfillWritableStream {
41
43
  },
42
44
  });
43
45
  this.writable = writable;
44
- let onabort;
45
- let reason;
46
+ const abortCtrl = new AbortController();
46
47
  const controller = {
47
- signal: {
48
- any(signals) {
49
- return AbortSignal.any([...signals]);
50
- },
51
- get reason() {
52
- return reason;
53
- },
54
- get aborted() {
55
- return writable.destroyed;
56
- },
57
- addEventListener: (_event, eventListener) => {
58
- writable.once('error', eventListener);
59
- writable.once('close', eventListener);
60
- },
61
- removeEventListener: (_event, eventListener) => {
62
- writable.off('error', eventListener);
63
- writable.off('close', eventListener);
64
- },
65
- dispatchEvent: (_event) => {
66
- return false;
67
- },
68
- get onabort() {
69
- return onabort;
70
- },
71
- set onabort(value) {
72
- if (onabort) {
73
- this.removeEventListener('abort', onabort);
74
- }
75
- onabort = value;
76
- if (onabort) {
77
- this.addEventListener('abort', onabort, { once: true });
78
- }
79
- },
80
- throwIfAborted() {
81
- if (writable.destroyed) {
82
- throw reason;
83
- }
84
- },
85
- },
86
- error: e => {
87
- this.writable.destroy(e);
48
+ signal: abortCtrl.signal,
49
+ error(e) {
50
+ writable.destroy(e);
88
51
  },
89
52
  };
90
- this.writable.once('error', err => {
91
- reason = err;
92
- });
53
+ writable.once('error', err => abortCtrl.abort(err));
54
+ writable.once('close', () => abortCtrl.abort());
93
55
  }
94
56
  else {
95
57
  this.writable = new Writable();
@@ -98,90 +60,52 @@ export class PonyfillWritableStream {
98
60
  getWriter() {
99
61
  const writable = this.writable;
100
62
  return {
101
- closed: new Promise(resolve => {
102
- writable.once('close', () => {
103
- resolve(undefined);
104
- });
105
- }),
63
+ get closed() {
64
+ return once(writable, 'close');
65
+ },
106
66
  get desiredSize() {
107
67
  return writable.writableLength;
108
68
  },
109
- ready: new Promise(resolve => {
110
- writable.once('drain', () => {
111
- resolve(undefined);
112
- });
113
- }),
69
+ get ready() {
70
+ return once(writable, 'drain');
71
+ },
114
72
  releaseLock() {
115
73
  // no-op
116
74
  },
117
75
  write(chunk) {
76
+ const promise = fakePromise();
118
77
  if (chunk == null) {
119
- return fakePromise(undefined);
78
+ return promise;
120
79
  }
121
- return new Promise((resolve, reject) => {
122
- writable.write(chunk, (err) => {
123
- if (err) {
124
- reject(err);
125
- }
126
- else {
127
- resolve();
128
- }
129
- });
130
- });
80
+ return promise.then(() => safeWrite(chunk, writable));
131
81
  },
132
82
  close() {
133
83
  if (!writable.errored && writable.closed) {
134
- return fakePromise(undefined);
84
+ return fakePromise();
135
85
  }
136
- return new Promise((resolve, reject) => {
137
- if (writable.errored) {
138
- reject(writable.errored);
139
- }
140
- else {
141
- writable.end((err) => {
142
- if (err) {
143
- reject(err);
144
- }
145
- else {
146
- resolve();
147
- }
148
- });
149
- }
150
- });
86
+ if (writable.errored) {
87
+ return fakeRejectPromise(writable.errored);
88
+ }
89
+ return fakePromise().then(() => endStream(writable));
151
90
  },
152
91
  abort(reason) {
153
- return new Promise(resolve => {
154
- writable.destroy(reason);
155
- writable.once('close', resolve);
156
- });
92
+ writable.destroy(reason);
93
+ return once(writable, 'close');
157
94
  },
158
95
  };
159
96
  }
160
97
  close() {
161
98
  if (!this.writable.errored && this.writable.closed) {
162
- return fakePromise(undefined);
99
+ return fakePromise();
163
100
  }
164
- return new Promise((resolve, reject) => {
165
- if (this.writable.errored) {
166
- reject(this.writable.errored);
167
- }
168
- else {
169
- this.writable.end((err) => {
170
- if (err) {
171
- reject(err);
172
- }
173
- else {
174
- resolve();
175
- }
176
- });
177
- }
178
- });
101
+ if (this.writable.errored) {
102
+ return fakeRejectPromise(this.writable.errored);
103
+ }
104
+ return fakePromise().then(() => endStream(this.writable));
179
105
  }
180
106
  abort(reason) {
181
- return new Promise(resolve => {
182
- this.writable.destroy(reason);
183
- this.writable.once('close', resolve);
184
- });
107
+ this.writable.destroy(reason);
108
+ return once(this.writable, 'close');
185
109
  }
186
110
  locked = false;
187
111
  }
package/esm/fetch.js CHANGED
@@ -1,5 +1,6 @@
1
- import { createReadStream } from 'fs';
2
- import { fileURLToPath } from 'url';
1
+ import { Buffer } from 'node:buffer';
2
+ import { createReadStream, promises as fsPromises } from 'node:fs';
3
+ import { fileURLToPath } from 'node:url';
3
4
  import { fetchCurl } from './fetchCurl.js';
4
5
  import { fetchNodeHttp } from './fetchNodeHttp.js';
5
6
  import { PonyfillRequest } from './Request.js';
@@ -7,10 +8,38 @@ import { PonyfillResponse } from './Response.js';
7
8
  import { PonyfillURL } from './URL.js';
8
9
  import { fakePromise } from './utils.js';
9
10
  const BASE64_SUFFIX = ';base64';
10
- function getResponseForFile(url) {
11
+ async function getResponseForFile(url) {
11
12
  const path = fileURLToPath(url);
12
- const readable = createReadStream(path);
13
- return new PonyfillResponse(readable);
13
+ try {
14
+ await fsPromises.access(path, fsPromises.constants.R_OK);
15
+ const stats = await fsPromises.stat(path, {
16
+ bigint: true,
17
+ });
18
+ const readable = createReadStream(path);
19
+ return new PonyfillResponse(readable, {
20
+ status: 200,
21
+ statusText: 'OK',
22
+ headers: {
23
+ 'content-type': 'application/octet-stream',
24
+ 'last-modified': stats.mtime.toUTCString(),
25
+ },
26
+ });
27
+ }
28
+ catch (err) {
29
+ if (err.code === 'ENOENT') {
30
+ return new PonyfillResponse(null, {
31
+ status: 404,
32
+ statusText: 'Not Found',
33
+ });
34
+ }
35
+ else if (err.code === 'EACCES') {
36
+ return new PonyfillResponse(null, {
37
+ status: 403,
38
+ statusText: 'Forbidden',
39
+ });
40
+ }
41
+ throw err;
42
+ }
14
43
  }
15
44
  function getResponseForDataUri(url) {
16
45
  const [mimeType = 'text/plain', ...datas] = url.substring(5).split(',');
@@ -62,7 +91,7 @@ export function fetchPonyfill(info, init) {
62
91
  }
63
92
  if (fetchRequest.url.startsWith('file:')) {
64
93
  const response = getResponseForFile(fetchRequest.url);
65
- return fakePromise(response);
94
+ return response;
66
95
  }
67
96
  if (fetchRequest.url.startsWith('blob:')) {
68
97
  const response = getResponseForBlob(fetchRequest.url);
package/esm/fetchCurl.js CHANGED
@@ -1,7 +1,8 @@
1
- import { PassThrough, Readable, promises as streamPromises } from 'stream';
2
- import { rootCertificates } from 'tls';
1
+ import { PassThrough, Readable } from 'node:stream';
2
+ import { rootCertificates } from 'node:tls';
3
+ import { createDeferredPromise } from '@whatwg-node/promise-helpers';
3
4
  import { PonyfillResponse } from './Response.js';
4
- import { createDeferredPromise, defaultHeadersSerializer, isNodeReadable } from './utils.js';
5
+ import { defaultHeadersSerializer, isNodeReadable, shouldRedirect } from './utils.js';
5
6
  export function fetchCurl(fetchRequest) {
6
7
  const { Curl, CurlFeature, CurlPause, CurlProgressFunc } = globalThis['libcurl'];
7
8
  const curlHandle = new Curl();
@@ -17,12 +18,15 @@ export function fetchCurl(fetchRequest) {
17
18
  curlHandle.setOpt('CAINFO_BLOB', rootCertificates.join('\n'));
18
19
  }
19
20
  curlHandle.enable(CurlFeature.StreamResponse);
21
+ let signal;
22
+ if (fetchRequest._signal === null) {
23
+ signal = undefined;
24
+ }
25
+ else if (fetchRequest._signal) {
26
+ signal = fetchRequest._signal;
27
+ }
20
28
  curlHandle.setStreamProgressCallback(function () {
21
- return fetchRequest['_signal']?.aborted
22
- ? process.env.DEBUG
23
- ? CurlProgressFunc.Continue
24
- : 1
25
- : 0;
29
+ return signal?.aborted ? (process.env.DEBUG ? CurlProgressFunc.Continue : 1) : 0;
26
30
  });
27
31
  if (fetchRequest['bodyType'] === 'String') {
28
32
  curlHandle.setOpt('POSTFIELDS', fetchRequest['bodyInit']);
@@ -59,18 +63,17 @@ export function fetchCurl(fetchRequest) {
59
63
  curlHandle.enable(CurlFeature.NoHeaderParsing);
60
64
  const deferredPromise = createDeferredPromise();
61
65
  let streamResolved;
62
- if (fetchRequest['_signal']) {
63
- fetchRequest['_signal'].onabort = () => {
64
- if (curlHandle.isOpen) {
65
- try {
66
- curlHandle.pause(CurlPause.Recv);
67
- }
68
- catch (e) {
69
- deferredPromise.reject(e);
70
- }
66
+ function onAbort() {
67
+ if (curlHandle.isOpen) {
68
+ try {
69
+ curlHandle.pause(CurlPause.Recv);
70
+ }
71
+ catch (e) {
72
+ deferredPromise.reject(e);
71
73
  }
72
- };
74
+ }
73
75
  }
76
+ signal?.addEventListener('abort', onAbort, { once: true });
74
77
  curlHandle.once('end', function endListener() {
75
78
  try {
76
79
  curlHandle.close();
@@ -78,6 +81,7 @@ export function fetchCurl(fetchRequest) {
78
81
  catch (e) {
79
82
  deferredPromise.reject(e);
80
83
  }
84
+ signal?.removeEventListener('abort', onAbort);
81
85
  });
82
86
  curlHandle.once('error', function errorListener(error) {
83
87
  if (streamResolved && !streamResolved.closed && !streamResolved.destroyed) {
@@ -97,42 +101,17 @@ export function fetchCurl(fetchRequest) {
97
101
  }
98
102
  });
99
103
  curlHandle.once('stream', function streamListener(stream, status, headersBuf) {
100
- const outputStream = new PassThrough();
101
- streamPromises
102
- .pipeline(stream, outputStream, {
104
+ const outputStream = stream.pipe(new PassThrough(), {
103
105
  end: true,
104
- signal: fetchRequest['_signal'] ?? undefined,
105
- })
106
- .then(() => {
107
- if (!stream.destroyed) {
108
- stream.resume();
109
- }
110
- })
111
- .catch(deferredPromise.reject);
112
- if (fetchRequest['_signal']) {
113
- outputStream.once('error', () => {
114
- if (!fetchRequest['_signal']?.aborted) {
115
- fetchRequest['_signal']?.sendAbort?.();
116
- }
117
- });
118
- outputStream.once('close', () => {
119
- if (!fetchRequest['_signal']?.aborted) {
120
- fetchRequest['_signal']?.sendAbort?.();
121
- }
122
- });
123
- outputStream.once('destroy', () => {
124
- if (!fetchRequest['_signal']?.aborted) {
125
- fetchRequest['_signal']?.sendAbort?.();
126
- }
127
- });
128
- }
106
+ });
129
107
  const headersFlat = headersBuf
130
108
  .toString('utf8')
131
109
  .split(/\r?\n|\r/g)
132
110
  .filter(headerFilter => {
133
111
  if (headerFilter && !headerFilter.startsWith('HTTP/')) {
134
112
  if (fetchRequest.redirect === 'error' &&
135
- (headerFilter.includes('location') || headerFilter.includes('Location'))) {
113
+ headerFilter.toLowerCase().includes('location') &&
114
+ shouldRedirect(status)) {
136
115
  if (!stream.destroyed) {
137
116
  stream.resume();
138
117
  }
@@ -153,18 +132,8 @@ export function fetchCurl(fetchRequest) {
153
132
  deferredPromise.resolve(ponyfillResponse);
154
133
  streamResolved = outputStream;
155
134
  });
156
- let count = 0;
157
- try {
158
- count = Curl.getCount();
159
- }
160
- catch { }
161
- if (count > 0) {
162
- setImmediate(() => {
163
- curlHandle.perform();
164
- });
165
- }
166
- else {
135
+ setImmediate(() => {
167
136
  curlHandle.perform();
168
- }
137
+ });
169
138
  return deferredPromise.promise;
170
139
  }
@@ -1,11 +1,12 @@
1
- import { request as httpRequest } from 'http';
2
- import { request as httpsRequest } from 'https';
3
- import { PassThrough, Readable, promises as streamPromises } from 'stream';
4
- import { createBrotliDecompress, createGunzip, createInflate, createInflateRaw } from 'zlib';
1
+ import { request as httpRequest, STATUS_CODES } from 'node:http';
2
+ import { request as httpsRequest } from 'node:https';
3
+ import { PassThrough, Readable } from 'node:stream';
4
+ import { createBrotliDecompress, createGunzip, createInflate, createInflateRaw } from 'node:zlib';
5
+ import { handleMaybePromise } from '@whatwg-node/promise-helpers';
5
6
  import { PonyfillRequest } from './Request.js';
6
7
  import { PonyfillResponse } from './Response.js';
7
8
  import { PonyfillURL } from './URL.js';
8
- import { getHeadersObj, isNodeReadable } from './utils.js';
9
+ import { endStream, getHeadersObj, isNodeReadable, pipeThrough, safeWrite, shouldRedirect, } from './utils.js';
9
10
  function getRequestFnForProtocol(url) {
10
11
  if (url.startsWith('http:')) {
11
12
  return httpRequest;
@@ -19,30 +20,24 @@ export function fetchNodeHttp(fetchRequest) {
19
20
  return new Promise((resolve, reject) => {
20
21
  try {
21
22
  const requestFn = getRequestFnForProtocol(fetchRequest.parsedUrl?.protocol || fetchRequest.url);
22
- const nodeReadable = (fetchRequest.body != null
23
- ? isNodeReadable(fetchRequest.body)
24
- ? fetchRequest.body
25
- : Readable.from(fetchRequest.body)
26
- : null);
27
23
  const headersSerializer = fetchRequest.headersSerializer || getHeadersObj;
28
24
  const nodeHeaders = headersSerializer(fetchRequest.headers);
29
- if (nodeHeaders['accept-encoding'] == null) {
30
- nodeHeaders['accept-encoding'] = 'gzip, deflate, br';
25
+ nodeHeaders['accept-encoding'] ||= 'gzip, deflate, br';
26
+ nodeHeaders['user-agent'] ||= 'node';
27
+ let signal;
28
+ if (fetchRequest._signal == null) {
29
+ signal = undefined;
30
+ }
31
+ else if (fetchRequest._signal) {
32
+ signal = fetchRequest._signal;
31
33
  }
32
34
  let nodeRequest;
33
- // Skip using parsed URL if it's an IPv6 address (starting with brackets)
34
- if (fetchRequest.parsedUrl && !fetchRequest.parsedUrl.hostname?.startsWith('[')) {
35
- nodeRequest = requestFn({
36
- auth: fetchRequest.parsedUrl.username
37
- ? `${fetchRequest.parsedUrl.username}:${fetchRequest.parsedUrl.password}`
38
- : undefined,
39
- hostname: fetchRequest.parsedUrl.hostname,
35
+ // If it is our ponyfilled Request, it should have `parsedUrl` which is a `URL` object
36
+ if (fetchRequest.parsedUrl) {
37
+ nodeRequest = requestFn(fetchRequest.parsedUrl, {
40
38
  method: fetchRequest.method,
41
- path: fetchRequest.parsedUrl.pathname + (fetchRequest.parsedUrl.search || ''),
42
- port: fetchRequest.parsedUrl.port,
43
- protocol: fetchRequest.parsedUrl.protocol,
44
39
  headers: nodeHeaders,
45
- signal: fetchRequest['_signal'] ?? undefined,
40
+ signal,
46
41
  agent: fetchRequest.agent,
47
42
  });
48
43
  }
@@ -50,10 +45,11 @@ export function fetchNodeHttp(fetchRequest) {
50
45
  nodeRequest = requestFn(fetchRequest.url, {
51
46
  method: fetchRequest.method,
52
47
  headers: nodeHeaders,
53
- signal: fetchRequest['_signal'] ?? undefined,
48
+ signal,
54
49
  agent: fetchRequest.agent,
55
50
  });
56
51
  }
52
+ nodeRequest.once('error', reject);
57
53
  nodeRequest.once('response', nodeResponse => {
58
54
  let outputStream;
59
55
  const contentEncoding = nodeResponse.headers['content-encoding'];
@@ -73,10 +69,8 @@ export function fetchNodeHttp(fetchRequest) {
73
69
  case 'br':
74
70
  outputStream = createBrotliDecompress();
75
71
  break;
76
- default:
77
- outputStream = new PassThrough();
78
72
  }
79
- if (nodeResponse.headers.location) {
73
+ if (nodeResponse.headers.location && shouldRedirect(nodeResponse.statusCode)) {
80
74
  if (fetchRequest.redirect === 'error') {
81
75
  const redirectError = new Error('Redirects are not allowed');
82
76
  reject(redirectError);
@@ -94,48 +88,50 @@ export function fetchNodeHttp(fetchRequest) {
94
88
  return;
95
89
  }
96
90
  }
97
- streamPromises
98
- .pipeline(nodeResponse, outputStream, {
99
- signal: fetchRequest['_signal'] ?? undefined,
100
- end: true,
101
- })
102
- .then(() => {
103
- if (!nodeResponse.destroyed) {
104
- nodeResponse.resume();
105
- }
106
- })
107
- .catch(reject);
108
- if (fetchRequest['_signal']) {
109
- outputStream.once('error', () => {
110
- if (!fetchRequest['_signal']?.aborted) {
111
- fetchRequest['_signal']?.sendAbort?.();
112
- }
113
- });
114
- outputStream.once('close', () => {
115
- if (!fetchRequest['_signal']?.aborted) {
116
- fetchRequest['_signal']?.sendAbort?.();
91
+ outputStream ||= new PassThrough();
92
+ pipeThrough({
93
+ src: nodeResponse,
94
+ dest: outputStream,
95
+ signal,
96
+ onError: e => {
97
+ if (!nodeResponse.destroyed) {
98
+ nodeResponse.destroy(e);
117
99
  }
118
- });
119
- outputStream.once('destroy', () => {
120
- if (!fetchRequest['_signal']?.aborted) {
121
- fetchRequest['_signal']?.sendAbort?.();
100
+ if (!outputStream.destroyed) {
101
+ outputStream.destroy(e);
122
102
  }
123
- });
103
+ reject(e);
104
+ },
105
+ });
106
+ const statusCode = nodeResponse.statusCode || 200;
107
+ let statusText = nodeResponse.statusMessage || STATUS_CODES[statusCode];
108
+ if (statusText == null) {
109
+ statusText = '';
124
110
  }
125
- const ponyfillResponse = new PonyfillResponse(outputStream, {
126
- status: nodeResponse.statusCode,
127
- statusText: nodeResponse.statusMessage,
111
+ const ponyfillResponse = new PonyfillResponse(outputStream || nodeResponse, {
112
+ status: statusCode,
113
+ statusText,
128
114
  headers: nodeResponse.headers,
129
115
  url: fetchRequest.url,
116
+ signal,
130
117
  });
131
118
  resolve(ponyfillResponse);
132
119
  });
133
- nodeRequest.once('error', reject);
134
- if (nodeReadable) {
135
- nodeReadable.pipe(nodeRequest);
120
+ if (fetchRequest['_buffer'] != null) {
121
+ handleMaybePromise(() => safeWrite(fetchRequest['_buffer'], nodeRequest), () => endStream(nodeRequest), reject);
136
122
  }
137
123
  else {
138
- nodeRequest.end();
124
+ const nodeReadable = (fetchRequest.body != null
125
+ ? isNodeReadable(fetchRequest.body)
126
+ ? fetchRequest.body
127
+ : Readable.from(fetchRequest.body)
128
+ : null);
129
+ if (nodeReadable) {
130
+ nodeReadable.pipe(nodeRequest);
131
+ }
132
+ else {
133
+ endStream(nodeRequest);
134
+ }
139
135
  }
140
136
  }
141
137
  catch (e) {
package/esm/index.js CHANGED
@@ -16,6 +16,3 @@ export { PonyfillCompressionStream as CompressionStream } from './CompressionStr
16
16
  export { PonyfillDecompressionStream as DecompressionStream } from './DecompressionStream.js';
17
17
  export { PonyfillIteratorObject as IteratorObject } from './IteratorObject.js';
18
18
  export { PonyfillTextDecoderStream as TextDecoderStream, PonyfillTextEncoderStream as TextEncoderStream, } from './TextEncoderDecoderStream.js';
19
- export { PonyfillAbortController as AbortController } from './AbortController.js';
20
- export { PonyfillAbortSignal as AbortSignal } from './AbortSignal.js';
21
- export { PonyfillAbortError as AbortError } from './AbortError.js';