@whatwg-node/node-fetch 0.7.22-alpha-20250526163200-dc90c3024c7fa99ad5eb4e46eeee8988f7e003df → 0.7.22-alpha-20250527014600-33a0363f582926116cdd12dd455c7db8f571dbfe

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/Body.js CHANGED
@@ -4,6 +4,7 @@ exports.PonyfillBody = void 0;
4
4
  /* eslint-disable @typescript-eslint/ban-ts-comment */
5
5
  const node_buffer_1 = require("node:buffer");
6
6
  const node_stream_1 = require("node:stream");
7
+ const promises_1 = require("node:stream/promises");
7
8
  const busboy_1 = require("@fastify/busboy");
8
9
  const promise_helpers_1 = require("@whatwg-node/promise-helpers");
9
10
  const Blob_js_1 = require("./Blob.js");
@@ -208,93 +209,57 @@ class PonyfillBody {
208
209
  ...this.options.formDataLimits,
209
210
  ...opts?.formDataLimits,
210
211
  };
211
- return new Promise((resolve, reject) => {
212
- const stream = this.body?.readable;
213
- if (!stream) {
214
- return reject(new Error('No stream available'));
212
+ const stream = this.body?.readable;
213
+ if (!stream) {
214
+ return (0, promise_helpers_1.fakeRejectPromise)(new Error('No stream available'));
215
+ }
216
+ const bb = new busboy_1.Busboy({
217
+ headers: {
218
+ 'content-length': typeof this.contentLength === 'number'
219
+ ? this.contentLength.toString()
220
+ : this.contentLength || '',
221
+ 'content-type': this.contentType || '',
222
+ },
223
+ limits: formDataLimits,
224
+ defCharset: 'utf-8',
225
+ });
226
+ bb.on('field', (name, value, fieldnameTruncated, valueTruncated) => {
227
+ if (fieldnameTruncated) {
228
+ bb.destroy(new Error(`Field name size exceeded: ${formDataLimits?.fieldNameSize} bytes`));
215
229
  }
216
- // form data file that is currently being processed, it's
217
- // important to keep track of it in case the stream ends early
218
- let currFile = null;
219
- const bb = new busboy_1.Busboy({
220
- headers: {
221
- 'content-length': typeof this.contentLength === 'number'
222
- ? this.contentLength.toString()
223
- : this.contentLength || '',
224
- 'content-type': this.contentType || '',
225
- },
226
- limits: formDataLimits,
227
- defCharset: 'utf-8',
228
- });
229
- if (this._signal) {
230
- (0, node_stream_1.addAbortSignal)(this._signal, bb);
230
+ if (valueTruncated) {
231
+ bb.destroy(new Error(`Field value size exceeded: ${formDataLimits?.fieldSize} bytes`));
231
232
  }
232
- let completed = false;
233
- const complete = (err) => {
234
- if (completed)
235
- return;
236
- completed = true;
237
- stream.unpipe(bb);
238
- bb.destroy();
239
- if (currFile) {
240
- currFile.destroy();
241
- currFile = null;
242
- }
243
- if (err) {
244
- reject(err);
245
- }
246
- else {
247
- // no error occured, this is a successful end/complete/finish
248
- resolve(this._formData);
249
- }
250
- };
251
- // we dont need to listen to the stream close event because bb will close or error when necessary
252
- // stream.on('close', complete);
253
- // stream can be aborted, for example
254
- stream.on('error', complete);
255
- bb.on('field', (name, value, fieldnameTruncated, valueTruncated) => {
256
- if (fieldnameTruncated) {
257
- return complete(new Error(`Field name size exceeded: ${formDataLimits?.fieldNameSize} bytes`));
258
- }
259
- if (valueTruncated) {
260
- return complete(new Error(`Field value size exceeded: ${formDataLimits?.fieldSize} bytes`));
261
- }
262
- this._formData.set(name, value);
263
- });
264
- bb.on('file', (name, fileStream, filename, _transferEncoding, mimeType) => {
265
- currFile = fileStream;
266
- const chunks = [];
267
- fileStream.on('data', chunk => {
268
- chunks.push(chunk);
269
- });
270
- fileStream.on('error', complete);
271
- fileStream.on('limit', () => {
272
- complete(new Error(`File size limit exceeded: ${formDataLimits?.fileSize} bytes`));
273
- });
274
- fileStream.on('close', () => {
275
- if (fileStream.truncated) {
276
- complete(new Error(`File size limit exceeded: ${formDataLimits?.fileSize} bytes`));
277
- }
278
- currFile = null;
279
- const file = new File_js_1.PonyfillFile(chunks, filename, { type: mimeType });
280
- this._formData.set(name, file);
281
- });
282
- });
283
- bb.on('fieldsLimit', () => {
284
- complete(new Error(`Fields limit exceeded: ${formDataLimits?.fields}`));
233
+ this._formData.set(name, value);
234
+ });
235
+ bb.on('file', (name, fileStream, filename, _transferEncoding, mimeType) => {
236
+ const chunks = [];
237
+ fileStream.on('data', chunk => {
238
+ chunks.push(chunk);
285
239
  });
286
- bb.on('filesLimit', () => {
287
- complete(new Error(`Files limit exceeded: ${formDataLimits?.files}`));
240
+ fileStream.on('limit', () => {
241
+ bb.destroy(new Error(`File size limit exceeded: ${formDataLimits?.fileSize} bytes`));
288
242
  });
289
- bb.on('partsLimit', () => {
290
- complete(new Error(`Parts limit exceeded: ${formDataLimits?.parts}`));
243
+ fileStream.on('close', () => {
244
+ if (fileStream.truncated) {
245
+ bb.destroy(new Error(`File size limit exceeded: ${formDataLimits?.fileSize} bytes`));
246
+ }
247
+ const file = new File_js_1.PonyfillFile(chunks, filename, { type: mimeType });
248
+ this._formData.set(name, file);
291
249
  });
292
- bb.on('end', complete);
293
- bb.on('finish', complete);
294
- bb.on('close', complete);
295
- bb.on('error', complete);
296
- stream.pipe(bb);
297
250
  });
251
+ bb.on('fieldsLimit', () => {
252
+ bb.destroy(new Error(`Fields limit exceeded: ${formDataLimits?.fields}`));
253
+ });
254
+ bb.on('filesLimit', () => {
255
+ bb.destroy(new Error(`Files limit exceeded: ${formDataLimits?.files}`));
256
+ });
257
+ bb.on('partsLimit', () => {
258
+ bb.destroy(new Error(`Parts limit exceeded: ${formDataLimits?.parts}`));
259
+ });
260
+ return (0, promises_1.pipeline)(stream, bb, {
261
+ signal: this._signal || undefined,
262
+ }).then(() => this._formData);
298
263
  }
299
264
  buffer() {
300
265
  if (this._buffer) {
@@ -95,14 +95,12 @@ function fetchNodeHttp(fetchRequest) {
95
95
  return;
96
96
  }
97
97
  }
98
- if (outputStream != null) {
99
- outputStream = (0, utils_js_1.wrapIncomingMessageWithPassthrough)({
100
- incomingMessage: nodeResponse,
101
- passThrough: outputStream,
102
- signal,
103
- onError: reject,
104
- });
105
- }
98
+ outputStream = (0, utils_js_1.wrapIncomingMessageWithPassthrough)({
99
+ incomingMessage: nodeResponse,
100
+ passThrough: outputStream,
101
+ signal,
102
+ onError: reject,
103
+ });
106
104
  const statusCode = nodeResponse.statusCode || 200;
107
105
  let statusText = nodeResponse.statusMessage || node_http_1.STATUS_CODES[statusCode];
108
106
  if (statusText == null) {
package/esm/Body.js CHANGED
@@ -1,8 +1,9 @@
1
1
  /* eslint-disable @typescript-eslint/ban-ts-comment */
2
2
  import { Buffer } from 'node:buffer';
3
- import { addAbortSignal, Readable } from 'node:stream';
3
+ import { Readable } from 'node:stream';
4
+ import { pipeline } from 'node:stream/promises';
4
5
  import { Busboy } from '@fastify/busboy';
5
- import { createDeferredPromise } from '@whatwg-node/promise-helpers';
6
+ import { createDeferredPromise, fakeRejectPromise, } from '@whatwg-node/promise-helpers';
6
7
  import { hasArrayBufferMethod, hasBufferMethod, hasBytesMethod, PonyfillBlob } from './Blob.js';
7
8
  import { PonyfillFile } from './File.js';
8
9
  import { getStreamFromFormData, PonyfillFormData } from './FormData.js';
@@ -205,93 +206,57 @@ export class PonyfillBody {
205
206
  ...this.options.formDataLimits,
206
207
  ...opts?.formDataLimits,
207
208
  };
208
- return new Promise((resolve, reject) => {
209
- const stream = this.body?.readable;
210
- if (!stream) {
211
- return reject(new Error('No stream available'));
209
+ const stream = this.body?.readable;
210
+ if (!stream) {
211
+ return fakeRejectPromise(new Error('No stream available'));
212
+ }
213
+ const bb = new Busboy({
214
+ headers: {
215
+ 'content-length': typeof this.contentLength === 'number'
216
+ ? this.contentLength.toString()
217
+ : this.contentLength || '',
218
+ 'content-type': this.contentType || '',
219
+ },
220
+ limits: formDataLimits,
221
+ defCharset: 'utf-8',
222
+ });
223
+ bb.on('field', (name, value, fieldnameTruncated, valueTruncated) => {
224
+ if (fieldnameTruncated) {
225
+ bb.destroy(new Error(`Field name size exceeded: ${formDataLimits?.fieldNameSize} bytes`));
212
226
  }
213
- // form data file that is currently being processed, it's
214
- // important to keep track of it in case the stream ends early
215
- let currFile = null;
216
- const bb = new Busboy({
217
- headers: {
218
- 'content-length': typeof this.contentLength === 'number'
219
- ? this.contentLength.toString()
220
- : this.contentLength || '',
221
- 'content-type': this.contentType || '',
222
- },
223
- limits: formDataLimits,
224
- defCharset: 'utf-8',
225
- });
226
- if (this._signal) {
227
- addAbortSignal(this._signal, bb);
227
+ if (valueTruncated) {
228
+ bb.destroy(new Error(`Field value size exceeded: ${formDataLimits?.fieldSize} bytes`));
228
229
  }
229
- let completed = false;
230
- const complete = (err) => {
231
- if (completed)
232
- return;
233
- completed = true;
234
- stream.unpipe(bb);
235
- bb.destroy();
236
- if (currFile) {
237
- currFile.destroy();
238
- currFile = null;
239
- }
240
- if (err) {
241
- reject(err);
242
- }
243
- else {
244
- // no error occured, this is a successful end/complete/finish
245
- resolve(this._formData);
246
- }
247
- };
248
- // we dont need to listen to the stream close event because bb will close or error when necessary
249
- // stream.on('close', complete);
250
- // stream can be aborted, for example
251
- stream.on('error', complete);
252
- bb.on('field', (name, value, fieldnameTruncated, valueTruncated) => {
253
- if (fieldnameTruncated) {
254
- return complete(new Error(`Field name size exceeded: ${formDataLimits?.fieldNameSize} bytes`));
255
- }
256
- if (valueTruncated) {
257
- return complete(new Error(`Field value size exceeded: ${formDataLimits?.fieldSize} bytes`));
258
- }
259
- this._formData.set(name, value);
260
- });
261
- bb.on('file', (name, fileStream, filename, _transferEncoding, mimeType) => {
262
- currFile = fileStream;
263
- const chunks = [];
264
- fileStream.on('data', chunk => {
265
- chunks.push(chunk);
266
- });
267
- fileStream.on('error', complete);
268
- fileStream.on('limit', () => {
269
- complete(new Error(`File size limit exceeded: ${formDataLimits?.fileSize} bytes`));
270
- });
271
- fileStream.on('close', () => {
272
- if (fileStream.truncated) {
273
- complete(new Error(`File size limit exceeded: ${formDataLimits?.fileSize} bytes`));
274
- }
275
- currFile = null;
276
- const file = new PonyfillFile(chunks, filename, { type: mimeType });
277
- this._formData.set(name, file);
278
- });
279
- });
280
- bb.on('fieldsLimit', () => {
281
- complete(new Error(`Fields limit exceeded: ${formDataLimits?.fields}`));
230
+ this._formData.set(name, value);
231
+ });
232
+ bb.on('file', (name, fileStream, filename, _transferEncoding, mimeType) => {
233
+ const chunks = [];
234
+ fileStream.on('data', chunk => {
235
+ chunks.push(chunk);
282
236
  });
283
- bb.on('filesLimit', () => {
284
- complete(new Error(`Files limit exceeded: ${formDataLimits?.files}`));
237
+ fileStream.on('limit', () => {
238
+ bb.destroy(new Error(`File size limit exceeded: ${formDataLimits?.fileSize} bytes`));
285
239
  });
286
- bb.on('partsLimit', () => {
287
- complete(new Error(`Parts limit exceeded: ${formDataLimits?.parts}`));
240
+ fileStream.on('close', () => {
241
+ if (fileStream.truncated) {
242
+ bb.destroy(new Error(`File size limit exceeded: ${formDataLimits?.fileSize} bytes`));
243
+ }
244
+ const file = new PonyfillFile(chunks, filename, { type: mimeType });
245
+ this._formData.set(name, file);
288
246
  });
289
- bb.on('end', complete);
290
- bb.on('finish', complete);
291
- bb.on('close', complete);
292
- bb.on('error', complete);
293
- stream.pipe(bb);
294
247
  });
248
+ bb.on('fieldsLimit', () => {
249
+ bb.destroy(new Error(`Fields limit exceeded: ${formDataLimits?.fields}`));
250
+ });
251
+ bb.on('filesLimit', () => {
252
+ bb.destroy(new Error(`Files limit exceeded: ${formDataLimits?.files}`));
253
+ });
254
+ bb.on('partsLimit', () => {
255
+ bb.destroy(new Error(`Parts limit exceeded: ${formDataLimits?.parts}`));
256
+ });
257
+ return pipeline(stream, bb, {
258
+ signal: this._signal || undefined,
259
+ }).then(() => this._formData);
295
260
  }
296
261
  buffer() {
297
262
  if (this._buffer) {
@@ -92,14 +92,12 @@ export function fetchNodeHttp(fetchRequest) {
92
92
  return;
93
93
  }
94
94
  }
95
- if (outputStream != null) {
96
- outputStream = wrapIncomingMessageWithPassthrough({
97
- incomingMessage: nodeResponse,
98
- passThrough: outputStream,
99
- signal,
100
- onError: reject,
101
- });
102
- }
95
+ outputStream = wrapIncomingMessageWithPassthrough({
96
+ incomingMessage: nodeResponse,
97
+ passThrough: outputStream,
98
+ signal,
99
+ onError: reject,
100
+ });
103
101
  const statusCode = nodeResponse.statusCode || 200;
104
102
  let statusText = nodeResponse.statusMessage || STATUS_CODES[statusCode];
105
103
  if (statusText == null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whatwg-node/node-fetch",
3
- "version": "0.7.22-alpha-20250526163200-dc90c3024c7fa99ad5eb4e46eeee8988f7e003df",
3
+ "version": "0.7.22-alpha-20250527014600-33a0363f582926116cdd12dd455c7db8f571dbfe",
4
4
  "description": "Fetch API implementation for Node",
5
5
  "sideEffects": false,
6
6
  "dependencies": {