@whatwg-node/node-fetch 0.7.8-alpha-20250122135958-d7c45737356867271ee584ba6eb3446d0bfa504b → 0.7.8-alpha-20250122150621-99aa3b02dabf84434a687202da321ea8807e453d

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.
package/cjs/fetch.js CHANGED
@@ -98,7 +98,20 @@ function getNativeGlobalDispatcher() {
98
98
  function createFetchFn() {
99
99
  const libcurlModuleName = 'node-libcurl';
100
100
  const undiciModuleName = 'undici';
101
- return Promise.resolve(`${libcurlModuleName}`).then(s => __importStar(require(s))).then(libcurl => (0, fetchCurl_js_1.createFetchCurl)(libcurl), () => Promise.resolve(`${undiciModuleName}`).then(s => __importStar(require(s))).then((undici) => (0, fetchUndici_js_1.createFetchUndici)(() => undici.getGlobalDispatcher()), () => (0, fetchUndici_js_1.createFetchUndici)(getNativeGlobalDispatcher)));
101
+ if (process.env.DEBUG) {
102
+ console.debug(`[@whatwg-node/node-fetch] - Trying to import ${libcurlModuleName} for fetch ponyfill`);
103
+ }
104
+ return Promise.resolve(`${libcurlModuleName}`).then(s => __importStar(require(s))).then(libcurl => (0, fetchCurl_js_1.createFetchCurl)(libcurl), () => {
105
+ if (process.env.DEBUG) {
106
+ console.debug(`[@whatwg-node/node-fetch] - Failed to import ${libcurlModuleName}, trying ${undiciModuleName}`);
107
+ }
108
+ return Promise.resolve(`${undiciModuleName}`).then(s => __importStar(require(s))).then((undici) => (0, fetchUndici_js_1.createFetchUndici)(() => undici.getGlobalDispatcher()), () => {
109
+ if (process.env.DEBUG) {
110
+ console.debug(`[@whatwg-node/node-fetch] - Failed to import ${undiciModuleName}, falling back to built-in undici in Node`);
111
+ }
112
+ return (0, fetchUndici_js_1.createFetchUndici)(getNativeGlobalDispatcher);
113
+ });
114
+ });
102
115
  }
103
116
  function fetchNonHttp(fetchRequest) {
104
117
  if (fetchRequest.url.startsWith('data:')) {
@@ -13,168 +13,178 @@ function createFetchUndici(getGlobalDispatcher) {
13
13
  return function fetchUndici(fetchRequest) {
14
14
  const dispatcher = fetchRequest.dispatcher || getGlobalDispatcher();
15
15
  if (!dispatcher) {
16
+ if (process.env.DEBUG) {
17
+ console.debug('[@whatwg-node/node-fetch] - native undici dispatcher not available, falling back to node:http');
18
+ }
16
19
  return (0, fetchNodeHttp_js_1.fetchNodeHttp)(fetchRequest);
17
20
  }
18
- return new Promise((resolve, reject) => {
19
- let abortListener;
20
- let passthrough;
21
- let response;
22
- let body = null;
23
- const bodyInit = fetchRequest['bodyInit'];
24
- if (bodyInit != null) {
25
- if (typeof bodyInit === 'string' ||
26
- Buffer.isBuffer(bodyInit) ||
27
- (0, types_1.isUint8Array)(bodyInit) ||
28
- bodyInit instanceof node_stream_1.Readable) {
29
- body = bodyInit;
30
- }
31
- else if (fetchRequest.body != null) {
32
- if ((0, utils_js_1.isNodeReadable)(fetchRequest.body?.readable)) {
33
- body = fetchRequest.body.readable;
34
- }
35
- else {
36
- body = node_stream_1.Readable.from(fetchRequest.body);
37
- }
38
- }
21
+ const deferred = (0, utils_js_1.createDeferredPromise)();
22
+ let abortListener;
23
+ let passthrough;
24
+ let response;
25
+ let body = null;
26
+ const bodyInit = fetchRequest['bodyInit'];
27
+ if (bodyInit != null) {
28
+ if (typeof bodyInit === 'string' ||
29
+ Buffer.isBuffer(bodyInit) ||
30
+ (0, types_1.isUint8Array)(bodyInit) ||
31
+ bodyInit instanceof node_stream_1.Readable) {
32
+ body = bodyInit;
39
33
  }
40
- function setPassthrough(contentEncoding) {
41
- switch (contentEncoding) {
42
- case 'x-gzip':
43
- case 'gzip':
44
- passthrough = (0, node_zlib_1.createGunzip)();
45
- break;
46
- case 'x-deflate':
47
- case 'deflate':
48
- passthrough = (0, node_zlib_1.createInflate)();
49
- break;
50
- case 'x-deflate-raw':
51
- case 'deflate-raw':
52
- passthrough = (0, node_zlib_1.createInflateRaw)();
53
- break;
54
- case 'br':
55
- passthrough = (0, node_zlib_1.createBrotliDecompress)();
56
- break;
57
- default:
58
- passthrough = new node_stream_1.PassThrough();
34
+ else if (fetchRequest.body != null) {
35
+ if ((0, utils_js_1.isNodeReadable)(fetchRequest.body?.readable)) {
36
+ body = fetchRequest.body.readable;
37
+ }
38
+ else {
39
+ body = node_stream_1.Readable.from(fetchRequest.body);
59
40
  }
60
- return passthrough;
61
41
  }
62
- const headersSerializer = fetchRequest.headersSerializer || utils_js_1.getHeadersObj;
63
- const nodeHeaders = headersSerializer(fetchRequest.headers);
64
- if (nodeHeaders['accept-encoding'] == null) {
65
- nodeHeaders['accept-encoding'] = 'gzip, deflate, br';
42
+ }
43
+ function setPassthrough(contentEncoding) {
44
+ switch (contentEncoding) {
45
+ case 'x-gzip':
46
+ case 'gzip':
47
+ passthrough = (0, node_zlib_1.createGunzip)();
48
+ break;
49
+ case 'x-deflate':
50
+ case 'deflate':
51
+ passthrough = (0, node_zlib_1.createInflate)();
52
+ break;
53
+ case 'x-deflate-raw':
54
+ case 'deflate-raw':
55
+ passthrough = (0, node_zlib_1.createInflateRaw)();
56
+ break;
57
+ case 'br':
58
+ passthrough = (0, node_zlib_1.createBrotliDecompress)();
59
+ break;
60
+ default:
61
+ passthrough = new node_stream_1.PassThrough();
66
62
  }
67
- (fetchRequest.dispatcher || getGlobalDispatcher()).dispatch({
68
- origin: fetchRequest.parsedUrl.origin,
69
- path: fetchRequest.parsedUrl.pathname,
70
- query: Object.fromEntries(fetchRequest.parsedUrl.searchParams),
71
- method: fetchRequest.method,
72
- headers: nodeHeaders,
73
- body,
74
- }, {
75
- onRequestStart(controller) {
76
- abortListener = function abortListener() {
77
- controller.abort(fetchRequest['_signal']?.reason);
78
- };
79
- fetchRequest['_signal']?.addEventListener('abort', abortListener, { once: true });
80
- },
81
- onRequestUpgrade(_controller, statusCode, headers, socket) {
82
- response = new Response_js_1.PonyfillResponse(socket, {
83
- status: statusCode,
84
- headers: headers,
85
- url: fetchRequest.url,
86
- });
87
- resolve(response);
88
- },
89
- onResponseStart(controller, statusCode, headers, statusMessage) {
90
- if (headers.location) {
91
- if (fetchRequest.redirect === 'error') {
92
- const redirectError = new Error('Redirects are not allowed');
93
- reject(redirectError);
94
- controller.resume();
95
- return;
96
- }
97
- if (fetchRequest.redirect === 'follow') {
98
- const redirectedUrl = new URL_js_1.PonyfillURL(headers.location, fetchRequest.parsedUrl || fetchRequest.url);
99
- const redirectResponse$ = fetchUndici(new Request_js_1.PonyfillRequest(redirectedUrl, fetchRequest));
100
- resolve(redirectResponse$.then(redirectResponse => {
101
- redirectResponse.redirected = true;
102
- return redirectResponse;
103
- }));
104
- controller.resume();
105
- return;
106
- }
107
- }
108
- passthrough = setPassthrough(headers['content-encoding']);
109
- resolve(new Response_js_1.PonyfillResponse(passthrough, {
110
- status: statusCode,
111
- statusText: statusMessage,
112
- headers: headers,
113
- url: fetchRequest.url,
114
- }));
115
- },
116
- onResponseData(_controller, chunk) {
117
- passthrough.write(chunk);
118
- },
119
- onResponseEnd(_controller, _trailers) {
120
- passthrough.end();
121
- fetchRequest['_signal']?.removeEventListener('abort', abortListener);
122
- },
123
- onResponseError(_controller, error) {
124
- if (passthrough) {
125
- passthrough.destroy(error);
126
- }
127
- else {
128
- reject(error);
129
- }
130
- fetchRequest['_signal']?.removeEventListener('abort', abortListener);
131
- },
132
- // Old Undici support
133
- onConnect(abort) {
134
- abortListener = function abortListener() {
135
- abort(fetchRequest['_signal']?.reason);
136
- };
137
- fetchRequest['_signal']?.addEventListener('abort', abortListener, { once: true });
138
- },
139
- onError(error) {
140
- if (passthrough) {
141
- passthrough.destroy(error);
63
+ return passthrough;
64
+ }
65
+ function onAbort(e) {
66
+ fetchRequest['_signal']?.removeEventListener('abort', abortListener);
67
+ passthrough?.destroy(e);
68
+ deferred.reject(e);
69
+ }
70
+ const headersSerializer = fetchRequest.headersSerializer || utils_js_1.getHeadersObj;
71
+ const nodeHeaders = headersSerializer(fetchRequest.headers);
72
+ if (nodeHeaders['accept-encoding'] == null) {
73
+ nodeHeaders['accept-encoding'] = 'gzip, deflate, br';
74
+ }
75
+ const dispatcherReturn = dispatcher.dispatch({
76
+ origin: fetchRequest.parsedUrl.origin,
77
+ path: fetchRequest.parsedUrl.pathname,
78
+ query: Object.fromEntries(fetchRequest.parsedUrl.searchParams),
79
+ method: fetchRequest.method,
80
+ headers: nodeHeaders,
81
+ body,
82
+ }, {
83
+ onRequestStart(controller) {
84
+ abortListener = function abortListener() {
85
+ onAbort(fetchRequest['_signal']?.reason);
86
+ controller.abort(fetchRequest['_signal']?.reason);
87
+ };
88
+ fetchRequest['_signal']?.addEventListener('abort', abortListener, { once: true });
89
+ },
90
+ onRequestUpgrade(_controller, statusCode, headers, socket) {
91
+ response = new Response_js_1.PonyfillResponse(socket, {
92
+ status: statusCode,
93
+ headers: headers,
94
+ url: fetchRequest.url,
95
+ });
96
+ deferred.resolve(response);
97
+ fetchRequest['_signal']?.removeEventListener('abort', abortListener);
98
+ },
99
+ onResponseStart(controller, statusCode, headers, statusMessage) {
100
+ if (headers.location) {
101
+ if (fetchRequest.redirect === 'error') {
102
+ const redirectError = new Error('Redirects are not allowed');
103
+ deferred.reject(redirectError);
104
+ controller.resume();
105
+ return;
142
106
  }
143
- else {
144
- reject(error);
107
+ if (fetchRequest.redirect === 'follow') {
108
+ const redirectedUrl = new URL_js_1.PonyfillURL(headers.location, fetchRequest.parsedUrl || fetchRequest.url);
109
+ const redirectResponse$ = fetchUndici(new Request_js_1.PonyfillRequest(redirectedUrl, fetchRequest));
110
+ deferred.resolve(redirectResponse$.then(redirectResponse => {
111
+ redirectResponse.redirected = true;
112
+ return redirectResponse;
113
+ }));
114
+ controller.resume();
115
+ return;
145
116
  }
146
- fetchRequest['_signal']?.removeEventListener('abort', abortListener);
147
- },
148
- // TODO: onUpgrade
149
- onHeaders(statusCode, headersBuf, _resume, statusText) {
150
- const headers = headersBuf.map(headerBuf => {
151
- const header = headerBuf
152
- .toString('utf-8')
153
- .split(/:\s(.+)/)
154
- .slice(0, 2);
155
- if (header[0] === 'content-encoding') {
156
- const contentEncoding = header[1];
157
- setPassthrough(contentEncoding);
158
- }
159
- return header;
160
- });
161
- passthrough ||= new node_stream_1.PassThrough();
162
- resolve(new Response_js_1.PonyfillResponse(passthrough, {
163
- status: statusCode,
164
- statusText,
165
- headers,
166
- url: fetchRequest.url,
167
- }));
168
- return true;
169
- },
170
- onData(chunk) {
171
- return passthrough.write(chunk);
172
- },
173
- onComplete() {
117
+ }
118
+ passthrough = setPassthrough(headers['content-encoding']);
119
+ deferred.resolve(new Response_js_1.PonyfillResponse(passthrough, {
120
+ status: statusCode,
121
+ statusText: statusMessage,
122
+ headers: headers,
123
+ url: fetchRequest.url,
124
+ }));
125
+ },
126
+ onResponseData(controller, chunk) {
127
+ passthrough.write(chunk);
128
+ if (controller.reason) {
129
+ onAbort(controller.reason);
130
+ }
131
+ },
132
+ onResponseEnd(controller, _trailers) {
133
+ if (controller.reason) {
134
+ onAbort(controller.reason);
135
+ }
136
+ else {
174
137
  passthrough.end();
175
138
  fetchRequest['_signal']?.removeEventListener('abort', abortListener);
176
- },
177
- });
139
+ }
140
+ },
141
+ onResponseError(controller, error) {
142
+ onAbort(error || controller.reason);
143
+ },
144
+ // Old Undici support
145
+ onConnect(abort) {
146
+ abortListener = function abortListener() {
147
+ abort(fetchRequest['_signal']?.reason);
148
+ onAbort(fetchRequest['_signal']?.reason);
149
+ };
150
+ fetchRequest['_signal']?.addEventListener('abort', abortListener, { once: true });
151
+ },
152
+ onError(error) {
153
+ onAbort(error);
154
+ },
155
+ // TODO: onUpgrade
156
+ onHeaders(statusCode, headersBuf, _resume, statusText) {
157
+ const headers = headersBuf.map(headerBuf => {
158
+ const header = headerBuf
159
+ .toString('utf-8')
160
+ .split(/:\s(.+)/)
161
+ .slice(0, 2);
162
+ if (header[0] === 'content-encoding') {
163
+ const contentEncoding = header[1];
164
+ setPassthrough(contentEncoding);
165
+ }
166
+ return header;
167
+ });
168
+ passthrough ||= new node_stream_1.PassThrough();
169
+ deferred.resolve(new Response_js_1.PonyfillResponse(passthrough, {
170
+ status: statusCode,
171
+ statusText,
172
+ headers,
173
+ url: fetchRequest.url,
174
+ }));
175
+ return true;
176
+ },
177
+ onData(chunk) {
178
+ return passthrough.write(chunk);
179
+ },
180
+ onComplete() {
181
+ passthrough.end();
182
+ fetchRequest['_signal']?.removeEventListener('abort', abortListener);
183
+ },
178
184
  });
185
+ if (!dispatcherReturn) {
186
+ console.warn('Undici dispatcher returned false');
187
+ }
188
+ return deferred.promise;
179
189
  };
180
190
  }
package/esm/fetch.js CHANGED
@@ -61,7 +61,20 @@ function getNativeGlobalDispatcher() {
61
61
  function createFetchFn() {
62
62
  const libcurlModuleName = 'node-libcurl';
63
63
  const undiciModuleName = 'undici';
64
- return import(libcurlModuleName).then(libcurl => createFetchCurl(libcurl), () => import(undiciModuleName).then((undici) => createFetchUndici(() => undici.getGlobalDispatcher()), () => createFetchUndici(getNativeGlobalDispatcher)));
64
+ if (process.env.DEBUG) {
65
+ console.debug(`[@whatwg-node/node-fetch] - Trying to import ${libcurlModuleName} for fetch ponyfill`);
66
+ }
67
+ return import(libcurlModuleName).then(libcurl => createFetchCurl(libcurl), () => {
68
+ if (process.env.DEBUG) {
69
+ console.debug(`[@whatwg-node/node-fetch] - Failed to import ${libcurlModuleName}, trying ${undiciModuleName}`);
70
+ }
71
+ return import(undiciModuleName).then((undici) => createFetchUndici(() => undici.getGlobalDispatcher()), () => {
72
+ if (process.env.DEBUG) {
73
+ console.debug(`[@whatwg-node/node-fetch] - Failed to import ${undiciModuleName}, falling back to built-in undici in Node`);
74
+ }
75
+ return createFetchUndici(getNativeGlobalDispatcher);
76
+ });
77
+ });
65
78
  }
66
79
  function fetchNonHttp(fetchRequest) {
67
80
  if (fetchRequest.url.startsWith('data:')) {
@@ -5,173 +5,183 @@ import { fetchNodeHttp } from './fetchNodeHttp.js';
5
5
  import { PonyfillRequest } from './Request.js';
6
6
  import { PonyfillResponse } from './Response.js';
7
7
  import { PonyfillURL } from './URL.js';
8
- import { getHeadersObj, isNodeReadable } from './utils.js';
8
+ import { createDeferredPromise, getHeadersObj, isNodeReadable } from './utils.js';
9
9
  export function createFetchUndici(getGlobalDispatcher) {
10
10
  return function fetchUndici(fetchRequest) {
11
11
  const dispatcher = fetchRequest.dispatcher || getGlobalDispatcher();
12
12
  if (!dispatcher) {
13
+ if (process.env.DEBUG) {
14
+ console.debug('[@whatwg-node/node-fetch] - native undici dispatcher not available, falling back to node:http');
15
+ }
13
16
  return fetchNodeHttp(fetchRequest);
14
17
  }
15
- return new Promise((resolve, reject) => {
16
- let abortListener;
17
- let passthrough;
18
- let response;
19
- let body = null;
20
- const bodyInit = fetchRequest['bodyInit'];
21
- if (bodyInit != null) {
22
- if (typeof bodyInit === 'string' ||
23
- Buffer.isBuffer(bodyInit) ||
24
- isUint8Array(bodyInit) ||
25
- bodyInit instanceof Readable) {
26
- body = bodyInit;
27
- }
28
- else if (fetchRequest.body != null) {
29
- if (isNodeReadable(fetchRequest.body?.readable)) {
30
- body = fetchRequest.body.readable;
31
- }
32
- else {
33
- body = Readable.from(fetchRequest.body);
34
- }
35
- }
18
+ const deferred = createDeferredPromise();
19
+ let abortListener;
20
+ let passthrough;
21
+ let response;
22
+ let body = null;
23
+ const bodyInit = fetchRequest['bodyInit'];
24
+ if (bodyInit != null) {
25
+ if (typeof bodyInit === 'string' ||
26
+ Buffer.isBuffer(bodyInit) ||
27
+ isUint8Array(bodyInit) ||
28
+ bodyInit instanceof Readable) {
29
+ body = bodyInit;
36
30
  }
37
- function setPassthrough(contentEncoding) {
38
- switch (contentEncoding) {
39
- case 'x-gzip':
40
- case 'gzip':
41
- passthrough = createGunzip();
42
- break;
43
- case 'x-deflate':
44
- case 'deflate':
45
- passthrough = createInflate();
46
- break;
47
- case 'x-deflate-raw':
48
- case 'deflate-raw':
49
- passthrough = createInflateRaw();
50
- break;
51
- case 'br':
52
- passthrough = createBrotliDecompress();
53
- break;
54
- default:
55
- passthrough = new PassThrough();
31
+ else if (fetchRequest.body != null) {
32
+ if (isNodeReadable(fetchRequest.body?.readable)) {
33
+ body = fetchRequest.body.readable;
34
+ }
35
+ else {
36
+ body = Readable.from(fetchRequest.body);
56
37
  }
57
- return passthrough;
58
38
  }
59
- const headersSerializer = fetchRequest.headersSerializer || getHeadersObj;
60
- const nodeHeaders = headersSerializer(fetchRequest.headers);
61
- if (nodeHeaders['accept-encoding'] == null) {
62
- nodeHeaders['accept-encoding'] = 'gzip, deflate, br';
39
+ }
40
+ function setPassthrough(contentEncoding) {
41
+ switch (contentEncoding) {
42
+ case 'x-gzip':
43
+ case 'gzip':
44
+ passthrough = createGunzip();
45
+ break;
46
+ case 'x-deflate':
47
+ case 'deflate':
48
+ passthrough = createInflate();
49
+ break;
50
+ case 'x-deflate-raw':
51
+ case 'deflate-raw':
52
+ passthrough = createInflateRaw();
53
+ break;
54
+ case 'br':
55
+ passthrough = createBrotliDecompress();
56
+ break;
57
+ default:
58
+ passthrough = new PassThrough();
63
59
  }
64
- (fetchRequest.dispatcher || getGlobalDispatcher()).dispatch({
65
- origin: fetchRequest.parsedUrl.origin,
66
- path: fetchRequest.parsedUrl.pathname,
67
- query: Object.fromEntries(fetchRequest.parsedUrl.searchParams),
68
- method: fetchRequest.method,
69
- headers: nodeHeaders,
70
- body,
71
- }, {
72
- onRequestStart(controller) {
73
- abortListener = function abortListener() {
74
- controller.abort(fetchRequest['_signal']?.reason);
75
- };
76
- fetchRequest['_signal']?.addEventListener('abort', abortListener, { once: true });
77
- },
78
- onRequestUpgrade(_controller, statusCode, headers, socket) {
79
- response = new PonyfillResponse(socket, {
80
- status: statusCode,
81
- headers: headers,
82
- url: fetchRequest.url,
83
- });
84
- resolve(response);
85
- },
86
- onResponseStart(controller, statusCode, headers, statusMessage) {
87
- if (headers.location) {
88
- if (fetchRequest.redirect === 'error') {
89
- const redirectError = new Error('Redirects are not allowed');
90
- reject(redirectError);
91
- controller.resume();
92
- return;
93
- }
94
- if (fetchRequest.redirect === 'follow') {
95
- const redirectedUrl = new PonyfillURL(headers.location, fetchRequest.parsedUrl || fetchRequest.url);
96
- const redirectResponse$ = fetchUndici(new PonyfillRequest(redirectedUrl, fetchRequest));
97
- resolve(redirectResponse$.then(redirectResponse => {
98
- redirectResponse.redirected = true;
99
- return redirectResponse;
100
- }));
101
- controller.resume();
102
- return;
103
- }
104
- }
105
- passthrough = setPassthrough(headers['content-encoding']);
106
- resolve(new PonyfillResponse(passthrough, {
107
- status: statusCode,
108
- statusText: statusMessage,
109
- headers: headers,
110
- url: fetchRequest.url,
111
- }));
112
- },
113
- onResponseData(_controller, chunk) {
114
- passthrough.write(chunk);
115
- },
116
- onResponseEnd(_controller, _trailers) {
117
- passthrough.end();
118
- fetchRequest['_signal']?.removeEventListener('abort', abortListener);
119
- },
120
- onResponseError(_controller, error) {
121
- if (passthrough) {
122
- passthrough.destroy(error);
123
- }
124
- else {
125
- reject(error);
126
- }
127
- fetchRequest['_signal']?.removeEventListener('abort', abortListener);
128
- },
129
- // Old Undici support
130
- onConnect(abort) {
131
- abortListener = function abortListener() {
132
- abort(fetchRequest['_signal']?.reason);
133
- };
134
- fetchRequest['_signal']?.addEventListener('abort', abortListener, { once: true });
135
- },
136
- onError(error) {
137
- if (passthrough) {
138
- passthrough.destroy(error);
60
+ return passthrough;
61
+ }
62
+ function onAbort(e) {
63
+ fetchRequest['_signal']?.removeEventListener('abort', abortListener);
64
+ passthrough?.destroy(e);
65
+ deferred.reject(e);
66
+ }
67
+ const headersSerializer = fetchRequest.headersSerializer || getHeadersObj;
68
+ const nodeHeaders = headersSerializer(fetchRequest.headers);
69
+ if (nodeHeaders['accept-encoding'] == null) {
70
+ nodeHeaders['accept-encoding'] = 'gzip, deflate, br';
71
+ }
72
+ const dispatcherReturn = dispatcher.dispatch({
73
+ origin: fetchRequest.parsedUrl.origin,
74
+ path: fetchRequest.parsedUrl.pathname,
75
+ query: Object.fromEntries(fetchRequest.parsedUrl.searchParams),
76
+ method: fetchRequest.method,
77
+ headers: nodeHeaders,
78
+ body,
79
+ }, {
80
+ onRequestStart(controller) {
81
+ abortListener = function abortListener() {
82
+ onAbort(fetchRequest['_signal']?.reason);
83
+ controller.abort(fetchRequest['_signal']?.reason);
84
+ };
85
+ fetchRequest['_signal']?.addEventListener('abort', abortListener, { once: true });
86
+ },
87
+ onRequestUpgrade(_controller, statusCode, headers, socket) {
88
+ response = new PonyfillResponse(socket, {
89
+ status: statusCode,
90
+ headers: headers,
91
+ url: fetchRequest.url,
92
+ });
93
+ deferred.resolve(response);
94
+ fetchRequest['_signal']?.removeEventListener('abort', abortListener);
95
+ },
96
+ onResponseStart(controller, statusCode, headers, statusMessage) {
97
+ if (headers.location) {
98
+ if (fetchRequest.redirect === 'error') {
99
+ const redirectError = new Error('Redirects are not allowed');
100
+ deferred.reject(redirectError);
101
+ controller.resume();
102
+ return;
139
103
  }
140
- else {
141
- reject(error);
104
+ if (fetchRequest.redirect === 'follow') {
105
+ const redirectedUrl = new PonyfillURL(headers.location, fetchRequest.parsedUrl || fetchRequest.url);
106
+ const redirectResponse$ = fetchUndici(new PonyfillRequest(redirectedUrl, fetchRequest));
107
+ deferred.resolve(redirectResponse$.then(redirectResponse => {
108
+ redirectResponse.redirected = true;
109
+ return redirectResponse;
110
+ }));
111
+ controller.resume();
112
+ return;
142
113
  }
143
- fetchRequest['_signal']?.removeEventListener('abort', abortListener);
144
- },
145
- // TODO: onUpgrade
146
- onHeaders(statusCode, headersBuf, _resume, statusText) {
147
- const headers = headersBuf.map(headerBuf => {
148
- const header = headerBuf
149
- .toString('utf-8')
150
- .split(/:\s(.+)/)
151
- .slice(0, 2);
152
- if (header[0] === 'content-encoding') {
153
- const contentEncoding = header[1];
154
- setPassthrough(contentEncoding);
155
- }
156
- return header;
157
- });
158
- passthrough ||= new PassThrough();
159
- resolve(new PonyfillResponse(passthrough, {
160
- status: statusCode,
161
- statusText,
162
- headers,
163
- url: fetchRequest.url,
164
- }));
165
- return true;
166
- },
167
- onData(chunk) {
168
- return passthrough.write(chunk);
169
- },
170
- onComplete() {
114
+ }
115
+ passthrough = setPassthrough(headers['content-encoding']);
116
+ deferred.resolve(new PonyfillResponse(passthrough, {
117
+ status: statusCode,
118
+ statusText: statusMessage,
119
+ headers: headers,
120
+ url: fetchRequest.url,
121
+ }));
122
+ },
123
+ onResponseData(controller, chunk) {
124
+ passthrough.write(chunk);
125
+ if (controller.reason) {
126
+ onAbort(controller.reason);
127
+ }
128
+ },
129
+ onResponseEnd(controller, _trailers) {
130
+ if (controller.reason) {
131
+ onAbort(controller.reason);
132
+ }
133
+ else {
171
134
  passthrough.end();
172
135
  fetchRequest['_signal']?.removeEventListener('abort', abortListener);
173
- },
174
- });
136
+ }
137
+ },
138
+ onResponseError(controller, error) {
139
+ onAbort(error || controller.reason);
140
+ },
141
+ // Old Undici support
142
+ onConnect(abort) {
143
+ abortListener = function abortListener() {
144
+ abort(fetchRequest['_signal']?.reason);
145
+ onAbort(fetchRequest['_signal']?.reason);
146
+ };
147
+ fetchRequest['_signal']?.addEventListener('abort', abortListener, { once: true });
148
+ },
149
+ onError(error) {
150
+ onAbort(error);
151
+ },
152
+ // TODO: onUpgrade
153
+ onHeaders(statusCode, headersBuf, _resume, statusText) {
154
+ const headers = headersBuf.map(headerBuf => {
155
+ const header = headerBuf
156
+ .toString('utf-8')
157
+ .split(/:\s(.+)/)
158
+ .slice(0, 2);
159
+ if (header[0] === 'content-encoding') {
160
+ const contentEncoding = header[1];
161
+ setPassthrough(contentEncoding);
162
+ }
163
+ return header;
164
+ });
165
+ passthrough ||= new PassThrough();
166
+ deferred.resolve(new PonyfillResponse(passthrough, {
167
+ status: statusCode,
168
+ statusText,
169
+ headers,
170
+ url: fetchRequest.url,
171
+ }));
172
+ return true;
173
+ },
174
+ onData(chunk) {
175
+ return passthrough.write(chunk);
176
+ },
177
+ onComplete() {
178
+ passthrough.end();
179
+ fetchRequest['_signal']?.removeEventListener('abort', abortListener);
180
+ },
175
181
  });
182
+ if (!dispatcherReturn) {
183
+ console.warn('Undici dispatcher returned false');
184
+ }
185
+ return deferred.promise;
176
186
  };
177
187
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whatwg-node/node-fetch",
3
- "version": "0.7.8-alpha-20250122135958-d7c45737356867271ee584ba6eb3446d0bfa504b",
3
+ "version": "0.7.8-alpha-20250122150621-99aa3b02dabf84434a687202da321ea8807e453d",
4
4
  "description": "Fetch API implementation for Node",
5
5
  "sideEffects": false,
6
6
  "dependencies": {
@@ -6,7 +6,7 @@ export declare function isArrayBufferView(obj: any): obj is ArrayBufferView;
6
6
  export declare function isNodeReadable(obj: any): obj is Readable;
7
7
  export interface DeferredPromise<T = void> {
8
8
  promise: Promise<T>;
9
- resolve: (value: T) => void;
9
+ resolve: (value: T | PromiseLike<T>) => void;
10
10
  reject: (reason: any) => void;
11
11
  }
12
12
  export declare function createDeferredPromise<T = void>(): DeferredPromise<T>;
@@ -6,7 +6,7 @@ export declare function isArrayBufferView(obj: any): obj is ArrayBufferView;
6
6
  export declare function isNodeReadable(obj: any): obj is Readable;
7
7
  export interface DeferredPromise<T = void> {
8
8
  promise: Promise<T>;
9
- resolve: (value: T) => void;
9
+ resolve: (value: T | PromiseLike<T>) => void;
10
10
  reject: (reason: any) => void;
11
11
  }
12
12
  export declare function createDeferredPromise<T = void>(): DeferredPromise<T>;