@whatwg-node/node-fetch 0.0.2-alpha-20230202192735-c9da64f → 0.0.3-alpha-20230205160101-d3a1033

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 (4) hide show
  1. package/Body.d.ts +5 -1
  2. package/index.js +213 -100
  3. package/index.mjs +213 -100
  4. package/package.json +1 -1
package/Body.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="node" />
2
3
  import { Readable } from 'stream';
3
4
  import { PonyfillBlob } from './Blob';
4
5
  import { PonyfillFormData } from './FormData';
@@ -20,17 +21,20 @@ export declare class PonyfillBody<TJSON = any> implements Body {
20
21
  private bodyInit;
21
22
  private options;
22
23
  bodyUsed: boolean;
23
- private _body;
24
24
  contentType: string | null;
25
25
  contentLength: number | null;
26
26
  constructor(bodyInit: BodyPonyfillInit | null, options?: PonyfillBodyOptions);
27
27
  private bodyType?;
28
+ private _bodyFactory;
29
+ private _generatedBody;
30
+ private generateBody;
28
31
  get body(): PonyfillReadableStream<Uint8Array> | null;
29
32
  arrayBuffer(): Promise<ArrayBuffer>;
30
33
  blob(): Promise<PonyfillBlob>;
31
34
  formData(opts?: {
32
35
  formDataLimits: FormDataLimits;
33
36
  }): Promise<PonyfillFormData>;
37
+ buffer(): Promise<Buffer>;
34
38
  json(): Promise<TJSON>;
35
39
  text(): Promise<string>;
36
40
  }
package/index.js CHANGED
@@ -9,9 +9,9 @@ const http = require('http');
9
9
  const https = require('https');
10
10
  const stream = require('stream');
11
11
  const url = require('url');
12
+ const buffer = require('buffer');
12
13
  const events = require('@whatwg-node/events');
13
14
  const busboy = _interopDefault(require('busboy'));
14
- const buffer = require('buffer');
15
15
 
16
16
  // Will be removed after v14 reaches EOL
17
17
  class PonyfillAbortError extends Error {
@@ -30,48 +30,6 @@ class PonyfillAbortError extends Error {
30
30
  }
31
31
  }
32
32
 
33
- // Will be removed after v14 reaches EOL
34
- class PonyfillAbortSignal extends events.EventTarget {
35
- constructor() {
36
- super(...arguments);
37
- this.aborted = false;
38
- this._onabort = null;
39
- }
40
- throwIfAborted() {
41
- if (this.aborted) {
42
- throw new PonyfillAbortError();
43
- }
44
- }
45
- get onabort() {
46
- return this._onabort;
47
- }
48
- set onabort(value) {
49
- if (this._onabort) {
50
- this.removeEventListener('abort', this._onabort);
51
- }
52
- this.addEventListener('abort', value);
53
- }
54
- abort(reason) {
55
- const abortEvent = new events.CustomEvent('abort', { detail: reason });
56
- this.dispatchEvent(abortEvent);
57
- }
58
- static timeout(milliseconds) {
59
- const signal = new PonyfillAbortSignal();
60
- setTimeout(() => signal.abort(`timeout in ${milliseconds} ms`), milliseconds);
61
- return signal;
62
- }
63
- }
64
-
65
- // Will be removed after v14 reaches EOL
66
- class PonyfillAbortController {
67
- constructor() {
68
- this.signal = new PonyfillAbortSignal();
69
- }
70
- abort(reason) {
71
- this.signal.abort(reason);
72
- }
73
- }
74
-
75
33
  function createController(desiredSize, readable) {
76
34
  let chunks = [];
77
35
  return {
@@ -232,6 +190,48 @@ class PonyfillBlob extends buffer.Blob {
232
190
  }
233
191
  }
234
192
 
193
+ // Will be removed after v14 reaches EOL
194
+ class PonyfillAbortSignal extends events.EventTarget {
195
+ constructor() {
196
+ super(...arguments);
197
+ this.aborted = false;
198
+ this._onabort = null;
199
+ }
200
+ throwIfAborted() {
201
+ if (this.aborted) {
202
+ throw new PonyfillAbortError();
203
+ }
204
+ }
205
+ get onabort() {
206
+ return this._onabort;
207
+ }
208
+ set onabort(value) {
209
+ if (this._onabort) {
210
+ this.removeEventListener('abort', this._onabort);
211
+ }
212
+ this.addEventListener('abort', value);
213
+ }
214
+ abort(reason) {
215
+ const abortEvent = new events.CustomEvent('abort', { detail: reason });
216
+ this.dispatchEvent(abortEvent);
217
+ }
218
+ static timeout(milliseconds) {
219
+ const signal = new PonyfillAbortSignal();
220
+ setTimeout(() => signal.abort(`timeout in ${milliseconds} ms`), milliseconds);
221
+ return signal;
222
+ }
223
+ }
224
+
225
+ // Will be removed after v14 reaches EOL
226
+ class PonyfillAbortController {
227
+ constructor() {
228
+ this.signal = new PonyfillAbortSignal();
229
+ }
230
+ abort(reason) {
231
+ this.signal.abort(reason);
232
+ }
233
+ }
234
+
235
235
  class PonyfillFile extends PonyfillBlob {
236
236
  constructor(fileBits, name, options) {
237
237
  super(fileBits, options);
@@ -251,7 +251,9 @@ class PonyfillFormData {
251
251
  values = [];
252
252
  this.map.set(name, values);
253
253
  }
254
- const entry = value instanceof PonyfillBlob ? getNormalizedFile(name, value, fileName) : value;
254
+ const entry = isBlob(value)
255
+ ? getNormalizedFile(name, value, fileName)
256
+ : value;
255
257
  values.push(entry);
256
258
  }
257
259
  delete(name) {
@@ -268,7 +270,9 @@ class PonyfillFormData {
268
270
  return this.map.has(name);
269
271
  }
270
272
  set(name, value, fileName) {
271
- const entry = value instanceof PonyfillBlob ? getNormalizedFile(name, value, fileName) : value;
273
+ const entry = isBlob(value)
274
+ ? getNormalizedFile(name, value, fileName)
275
+ : value;
272
276
  this.map.set(name, [entry]);
273
277
  }
274
278
  *[Symbol.iterator]() {
@@ -296,11 +300,7 @@ class PonyfillFormData {
296
300
  const entry = entries.shift();
297
301
  if (entry) {
298
302
  const [key, value] = entry;
299
- if (typeof value === 'string') {
300
- controller.enqueue(Buffer.from(`Content-Disposition: form-data; name="${key}"\r\n\r\n`));
301
- controller.enqueue(Buffer.from(value));
302
- }
303
- else {
303
+ if (value instanceof PonyfillFile) {
304
304
  let filenamePart = '';
305
305
  if (value.name) {
306
306
  filenamePart = `; filename="${value.name}"`;
@@ -309,6 +309,10 @@ class PonyfillFormData {
309
309
  controller.enqueue(Buffer.from(`Content-Type: ${value.type || 'application/octet-stream'}\r\n\r\n`));
310
310
  controller.enqueue(Buffer.from(await value.arrayBuffer()));
311
311
  }
312
+ else {
313
+ controller.enqueue(Buffer.from(`Content-Disposition: form-data; name="${key}"\r\n\r\n`));
314
+ controller.enqueue(Buffer.from(value));
315
+ }
312
316
  if (entries.length === 0) {
313
317
  controller.enqueue(Buffer.from(`\r\n--${boundary}--\r\n`));
314
318
  controller.close();
@@ -337,6 +341,9 @@ function getNormalizedFile(name, blob, fileName) {
337
341
  }
338
342
  return new PonyfillFile([blob], fileName || name, { type: blob.type });
339
343
  }
344
+ function isBlob(value) {
345
+ return value != null && typeof value === 'object' && typeof value.arrayBuffer === 'function';
346
+ }
340
347
 
341
348
  var BodyInitType;
342
349
  (function (BodyInitType) {
@@ -346,26 +353,38 @@ var BodyInitType;
346
353
  BodyInitType["ArrayBuffer"] = "ArrayBuffer";
347
354
  BodyInitType["String"] = "String";
348
355
  BodyInitType["Readable"] = "Readable";
356
+ BodyInitType["Buffer"] = "Buffer";
357
+ BodyInitType["Uint8Array"] = "Uint8Array";
349
358
  })(BodyInitType || (BodyInitType = {}));
350
359
  class PonyfillBody {
351
360
  constructor(bodyInit, options = {}) {
352
361
  this.bodyInit = bodyInit;
353
362
  this.options = options;
354
363
  this.bodyUsed = false;
355
- this._body = null;
356
364
  this.contentType = null;
357
365
  this.contentLength = null;
358
- const { body, contentType, contentLength, bodyType } = processBodyInit(bodyInit);
359
- this._body = body;
366
+ this._bodyFactory = () => null;
367
+ this._generatedBody = null;
368
+ const { bodyFactory, contentType, contentLength, bodyType } = processBodyInit(bodyInit);
369
+ this._bodyFactory = bodyFactory;
360
370
  this.contentType = contentType;
361
371
  this.contentLength = contentLength;
362
372
  this.bodyType = bodyType;
363
373
  }
374
+ generateBody() {
375
+ if (this._generatedBody) {
376
+ return this._generatedBody;
377
+ }
378
+ const body = this._bodyFactory();
379
+ this._generatedBody = body;
380
+ return body;
381
+ }
364
382
  get body() {
365
- if (this._body != null) {
366
- const ponyfillReadableStream = this._body;
367
- const readable = this._body.readable;
368
- return new Proxy(this._body.readable, {
383
+ const _body = this.generateBody();
384
+ if (_body != null) {
385
+ const ponyfillReadableStream = _body;
386
+ const readable = _body.readable;
387
+ return new Proxy(_body.readable, {
369
388
  get(_, prop) {
370
389
  if (prop in ponyfillReadableStream) {
371
390
  const ponyfillReadableStreamProp = ponyfillReadableStream[prop];
@@ -390,6 +409,9 @@ class PonyfillBody {
390
409
  if (this.bodyType === BodyInitType.ArrayBuffer) {
391
410
  return this.bodyInit;
392
411
  }
412
+ if (this.bodyType === BodyInitType.Uint8Array || this.bodyType === BodyInitType.Buffer) {
413
+ return this.bodyInit.buffer;
414
+ }
393
415
  const blob = await this.blob();
394
416
  return blob.arrayBuffer();
395
417
  }
@@ -397,20 +419,37 @@ class PonyfillBody {
397
419
  if (this.bodyType === BodyInitType.Blob) {
398
420
  return this.bodyInit;
399
421
  }
422
+ if (this.bodyType === BodyInitType.String || this.bodyType === BodyInitType.Buffer || this.bodyType === BodyInitType.Uint8Array) {
423
+ const bodyInitTyped = this.bodyInit;
424
+ return new PonyfillBlob([bodyInitTyped], {
425
+ type: this.contentType || '',
426
+ });
427
+ }
428
+ if (this.bodyType === BodyInitType.ArrayBuffer) {
429
+ const bodyInitTyped = this.bodyInit;
430
+ const buf = Buffer.from(bodyInitTyped, undefined, bodyInitTyped.byteLength);
431
+ return new PonyfillBlob([buf], {
432
+ type: this.contentType || '',
433
+ });
434
+ }
400
435
  const chunks = [];
401
- if (this._body) {
402
- for await (const chunk of this._body.readable) {
436
+ const _body = this.generateBody();
437
+ if (_body) {
438
+ for await (const chunk of _body.readable) {
403
439
  chunks.push(chunk);
404
440
  }
405
441
  }
406
- return new PonyfillBlob(chunks);
442
+ return new PonyfillBlob(chunks, {
443
+ type: this.contentType || '',
444
+ });
407
445
  }
408
446
  formData(opts) {
409
447
  if (this.bodyType === BodyInitType.FormData) {
410
448
  return Promise.resolve(this.bodyInit);
411
449
  }
412
450
  const formData = new PonyfillFormData();
413
- if (this._body == null) {
451
+ const _body = this.generateBody();
452
+ if (_body == null) {
414
453
  return Promise.resolve(formData);
415
454
  }
416
455
  const formDataLimits = {
@@ -418,7 +457,6 @@ class PonyfillBody {
418
457
  ...opts === null || opts === void 0 ? void 0 : opts.formDataLimits,
419
458
  };
420
459
  return new Promise((resolve, reject) => {
421
- var _a;
422
460
  const bb = busboy({
423
461
  headers: {
424
462
  'content-type': this.contentType || '',
@@ -466,9 +504,22 @@ class PonyfillBody {
466
504
  bb.on('error', err => {
467
505
  reject(err);
468
506
  });
469
- (_a = this._body) === null || _a === void 0 ? void 0 : _a.readable.pipe(bb);
507
+ _body === null || _body === void 0 ? void 0 : _body.readable.pipe(bb);
470
508
  });
471
509
  }
510
+ async buffer() {
511
+ if (this.bodyType === BodyInitType.Buffer) {
512
+ return this.bodyInit;
513
+ }
514
+ if (this.bodyType === BodyInitType.Uint8Array || this.bodyType === BodyInitType.ArrayBuffer) {
515
+ const bodyInitTyped = this.bodyInit;
516
+ const buffer = Buffer.from(bodyInitTyped, 'byteOffset' in bodyInitTyped ? bodyInitTyped.byteOffset : undefined, bodyInitTyped.byteLength);
517
+ return buffer;
518
+ }
519
+ const blob = await this.blob();
520
+ const arrayBuffer = await blob.arrayBuffer();
521
+ return Buffer.from(arrayBuffer, undefined, arrayBuffer.byteLength);
522
+ }
472
523
  async json() {
473
524
  const text = await this.text();
474
525
  return JSON.parse(text);
@@ -477,6 +528,14 @@ class PonyfillBody {
477
528
  if (this.bodyType === BodyInitType.String) {
478
529
  return this.bodyInit;
479
530
  }
531
+ if (this.bodyType === BodyInitType.Buffer) {
532
+ return this.bodyInit.toString('utf-8');
533
+ }
534
+ if (this.bodyType === BodyInitType.ArrayBuffer || this.bodyType === BodyInitType.Uint8Array) {
535
+ const bodyInitTyped = this.bodyInit;
536
+ const buffer = Buffer.from(bodyInitTyped, 'byteOffset' in bodyInitTyped ? bodyInitTyped.byteOffset : undefined, bodyInitTyped.byteLength);
537
+ return buffer.toString('utf-8');
538
+ }
480
539
  const blob = await this.blob();
481
540
  return blob.text();
482
541
  }
@@ -484,114 +543,152 @@ class PonyfillBody {
484
543
  function processBodyInit(bodyInit) {
485
544
  if (bodyInit == null) {
486
545
  return {
487
- body: null,
546
+ bodyFactory: () => null,
488
547
  contentType: null,
489
548
  contentLength: null,
490
549
  };
491
550
  }
492
551
  if (typeof bodyInit === 'string') {
493
- const buffer = Buffer.from(bodyInit);
494
- const readable = stream.Readable.from(buffer);
495
- const body = new PonyfillReadableStream(readable);
496
552
  return {
497
553
  bodyType: BodyInitType.String,
498
554
  contentType: 'text/plain;charset=UTF-8',
499
- contentLength: buffer.length,
500
- body,
555
+ contentLength: bodyInit.length,
556
+ bodyFactory() {
557
+ const buffer = Buffer.from(bodyInit);
558
+ const readable = stream.Readable.from(buffer);
559
+ return new PonyfillReadableStream(readable);
560
+ },
501
561
  };
502
562
  }
503
563
  if (bodyInit instanceof PonyfillReadableStream) {
504
564
  return {
505
565
  bodyType: BodyInitType.ReadableStream,
506
- body: bodyInit,
566
+ bodyFactory: () => bodyInit,
507
567
  contentType: null,
508
568
  contentLength: null,
509
569
  };
510
570
  }
511
571
  if (bodyInit instanceof PonyfillBlob) {
512
- const readable = bodyInit.stream();
513
- const body = new PonyfillReadableStream(readable);
514
572
  return {
515
573
  bodyType: BodyInitType.Blob,
516
574
  contentType: bodyInit.type,
517
575
  contentLength: bodyInit.size,
518
- body,
576
+ bodyFactory() {
577
+ return bodyInit.stream();
578
+ },
519
579
  };
520
580
  }
521
581
  if (bodyInit instanceof PonyfillFormData) {
522
582
  const boundary = Math.random().toString(36).substr(2);
523
583
  const contentType = `multipart/form-data; boundary=${boundary}`;
524
- const body = bodyInit.stream(boundary);
525
584
  return {
526
585
  bodyType: BodyInitType.FormData,
527
586
  contentType,
528
587
  contentLength: null,
529
- body,
588
+ bodyFactory: () => bodyInit.stream(boundary),
589
+ };
590
+ }
591
+ if (bodyInit instanceof Buffer) {
592
+ const contentLength = bodyInit.length;
593
+ return {
594
+ bodyType: BodyInitType.Buffer,
595
+ contentLength,
596
+ contentType: null,
597
+ bodyFactory() {
598
+ const readable = stream.Readable.from(bodyInit);
599
+ const body = new PonyfillReadableStream(readable);
600
+ return body;
601
+ },
602
+ };
603
+ }
604
+ if (bodyInit instanceof Uint8Array) {
605
+ const contentLength = bodyInit.byteLength;
606
+ return {
607
+ bodyType: BodyInitType.Uint8Array,
608
+ contentLength,
609
+ contentType: null,
610
+ bodyFactory() {
611
+ const readable = stream.Readable.from(bodyInit);
612
+ const body = new PonyfillReadableStream(readable);
613
+ return body;
614
+ }
530
615
  };
531
616
  }
532
617
  if ('buffer' in bodyInit) {
533
618
  const contentLength = bodyInit.byteLength;
534
- const buffer = Buffer.from(bodyInit.buffer, bodyInit.byteOffset, bodyInit.byteLength);
535
- const readable = stream.Readable.from(buffer);
536
- const body = new PonyfillReadableStream(readable);
537
619
  return {
538
620
  contentLength,
539
621
  contentType: null,
540
- body,
622
+ bodyFactory() {
623
+ const buffer = Buffer.from(bodyInit.buffer, bodyInit.byteOffset, bodyInit.byteLength);
624
+ const readable = stream.Readable.from(buffer);
625
+ const body = new PonyfillReadableStream(readable);
626
+ return body;
627
+ }
541
628
  };
542
629
  }
543
630
  if (bodyInit instanceof ArrayBuffer) {
544
631
  const contentLength = bodyInit.byteLength;
545
- const buffer = Buffer.from(bodyInit, undefined, bodyInit.byteLength);
546
- const readable = stream.Readable.from(buffer);
547
- const body = new PonyfillReadableStream(readable);
548
632
  return {
549
633
  bodyType: BodyInitType.ArrayBuffer,
550
634
  contentType: null,
551
635
  contentLength,
552
- body,
636
+ bodyFactory() {
637
+ const buffer = Buffer.from(bodyInit, undefined, bodyInit.byteLength);
638
+ const readable = stream.Readable.from(buffer);
639
+ const body = new PonyfillReadableStream(readable);
640
+ return body;
641
+ }
553
642
  };
554
643
  }
555
644
  if (bodyInit instanceof stream.Readable) {
556
- const body = new PonyfillReadableStream(bodyInit);
557
645
  return {
558
646
  bodyType: BodyInitType.Readable,
559
647
  contentType: null,
560
648
  contentLength: null,
561
- body,
649
+ bodyFactory() {
650
+ const body = new PonyfillReadableStream(bodyInit);
651
+ return body;
652
+ }
562
653
  };
563
654
  }
564
655
  if ('stream' in bodyInit) {
565
- const bodyStream = bodyInit.stream();
566
- const body = new PonyfillReadableStream(bodyStream);
567
656
  return {
568
657
  contentType: bodyInit.type,
569
658
  contentLength: bodyInit.size,
570
- body,
659
+ bodyFactory() {
660
+ const bodyStream = bodyInit.stream();
661
+ const body = new PonyfillReadableStream(bodyStream);
662
+ return body;
663
+ }
571
664
  };
572
665
  }
573
666
  if (bodyInit instanceof URLSearchParams) {
574
667
  const contentType = 'application/x-www-form-urlencoded;charset=UTF-8';
575
- const body = new PonyfillReadableStream(stream.Readable.from(bodyInit.toString()));
576
668
  return {
577
669
  bodyType: BodyInitType.String,
578
670
  contentType,
579
671
  contentLength: null,
580
- body,
672
+ bodyFactory() {
673
+ const body = new PonyfillReadableStream(stream.Readable.from(bodyInit.toString()));
674
+ return body;
675
+ }
581
676
  };
582
677
  }
583
678
  if ('forEach' in bodyInit) {
584
- const formData = new PonyfillFormData();
585
- bodyInit.forEach((value, key) => {
586
- formData.append(key, value);
587
- });
588
679
  const boundary = Math.random().toString(36).substr(2);
589
680
  const contentType = `multipart/form-data; boundary=${boundary}`;
590
- const body = formData.stream(boundary);
591
681
  return {
592
682
  contentType,
593
683
  contentLength: null,
594
- body,
684
+ bodyFactory() {
685
+ const formData = new PonyfillFormData();
686
+ bodyInit.forEach((value, key) => {
687
+ formData.append(key, value);
688
+ });
689
+ const body = formData.stream(boundary);
690
+ return body;
691
+ },
595
692
  };
596
693
  }
597
694
  throw new Error('Unknown body type');
@@ -749,6 +846,24 @@ class PonyfillResponse extends PonyfillBody {
749
846
  this.redirected = init.redirected || false;
750
847
  this.type = init.type || 'default';
751
848
  }
849
+ const contentTypeInHeaders = this.headers.get('content-type');
850
+ if (!contentTypeInHeaders) {
851
+ if (this.contentType) {
852
+ this.headers.set('content-type', this.contentType);
853
+ }
854
+ }
855
+ else {
856
+ this.contentType = contentTypeInHeaders;
857
+ }
858
+ const contentLengthInHeaders = this.headers.get('content-length');
859
+ if (!contentLengthInHeaders) {
860
+ if (this.contentLength) {
861
+ this.headers.set('content-length', this.contentLength.toString());
862
+ }
863
+ }
864
+ else {
865
+ this.contentLength = parseInt(contentLengthInHeaders, 10);
866
+ }
752
867
  }
753
868
  get ok() {
754
869
  return this.status >= 200 && this.status < 300;
@@ -825,12 +940,10 @@ function fetchPonyfill(info, init) {
825
940
  if (mimeType.endsWith(BASE64_SUFFIX)) {
826
941
  const buffer = Buffer.from(data, 'base64');
827
942
  const realMimeType = mimeType.slice(0, -BASE64_SUFFIX.length);
828
- const response = new PonyfillResponse(buffer, {
943
+ const file = new PonyfillBlob([buffer], { type: realMimeType });
944
+ const response = new PonyfillResponse(file, {
829
945
  status: 200,
830
946
  statusText: 'OK',
831
- headers: {
832
- 'content-type': realMimeType,
833
- },
834
947
  });
835
948
  resolve(response);
836
949
  return;
package/index.mjs CHANGED
@@ -3,9 +3,9 @@ import { request as request$1 } from 'http';
3
3
  import { request } from 'https';
4
4
  import { Readable } from 'stream';
5
5
  import { fileURLToPath } from 'url';
6
+ import { Blob } from 'buffer';
6
7
  import { EventTarget, CustomEvent } from '@whatwg-node/events';
7
8
  import busboy from 'busboy';
8
- import { Blob } from 'buffer';
9
9
 
10
10
  // Will be removed after v14 reaches EOL
11
11
  class PonyfillAbortError extends Error {
@@ -24,48 +24,6 @@ class PonyfillAbortError extends Error {
24
24
  }
25
25
  }
26
26
 
27
- // Will be removed after v14 reaches EOL
28
- class PonyfillAbortSignal extends EventTarget {
29
- constructor() {
30
- super(...arguments);
31
- this.aborted = false;
32
- this._onabort = null;
33
- }
34
- throwIfAborted() {
35
- if (this.aborted) {
36
- throw new PonyfillAbortError();
37
- }
38
- }
39
- get onabort() {
40
- return this._onabort;
41
- }
42
- set onabort(value) {
43
- if (this._onabort) {
44
- this.removeEventListener('abort', this._onabort);
45
- }
46
- this.addEventListener('abort', value);
47
- }
48
- abort(reason) {
49
- const abortEvent = new CustomEvent('abort', { detail: reason });
50
- this.dispatchEvent(abortEvent);
51
- }
52
- static timeout(milliseconds) {
53
- const signal = new PonyfillAbortSignal();
54
- setTimeout(() => signal.abort(`timeout in ${milliseconds} ms`), milliseconds);
55
- return signal;
56
- }
57
- }
58
-
59
- // Will be removed after v14 reaches EOL
60
- class PonyfillAbortController {
61
- constructor() {
62
- this.signal = new PonyfillAbortSignal();
63
- }
64
- abort(reason) {
65
- this.signal.abort(reason);
66
- }
67
- }
68
-
69
27
  function createController(desiredSize, readable) {
70
28
  let chunks = [];
71
29
  return {
@@ -226,6 +184,48 @@ class PonyfillBlob extends Blob {
226
184
  }
227
185
  }
228
186
 
187
+ // Will be removed after v14 reaches EOL
188
+ class PonyfillAbortSignal extends EventTarget {
189
+ constructor() {
190
+ super(...arguments);
191
+ this.aborted = false;
192
+ this._onabort = null;
193
+ }
194
+ throwIfAborted() {
195
+ if (this.aborted) {
196
+ throw new PonyfillAbortError();
197
+ }
198
+ }
199
+ get onabort() {
200
+ return this._onabort;
201
+ }
202
+ set onabort(value) {
203
+ if (this._onabort) {
204
+ this.removeEventListener('abort', this._onabort);
205
+ }
206
+ this.addEventListener('abort', value);
207
+ }
208
+ abort(reason) {
209
+ const abortEvent = new CustomEvent('abort', { detail: reason });
210
+ this.dispatchEvent(abortEvent);
211
+ }
212
+ static timeout(milliseconds) {
213
+ const signal = new PonyfillAbortSignal();
214
+ setTimeout(() => signal.abort(`timeout in ${milliseconds} ms`), milliseconds);
215
+ return signal;
216
+ }
217
+ }
218
+
219
+ // Will be removed after v14 reaches EOL
220
+ class PonyfillAbortController {
221
+ constructor() {
222
+ this.signal = new PonyfillAbortSignal();
223
+ }
224
+ abort(reason) {
225
+ this.signal.abort(reason);
226
+ }
227
+ }
228
+
229
229
  class PonyfillFile extends PonyfillBlob {
230
230
  constructor(fileBits, name, options) {
231
231
  super(fileBits, options);
@@ -245,7 +245,9 @@ class PonyfillFormData {
245
245
  values = [];
246
246
  this.map.set(name, values);
247
247
  }
248
- const entry = value instanceof PonyfillBlob ? getNormalizedFile(name, value, fileName) : value;
248
+ const entry = isBlob(value)
249
+ ? getNormalizedFile(name, value, fileName)
250
+ : value;
249
251
  values.push(entry);
250
252
  }
251
253
  delete(name) {
@@ -262,7 +264,9 @@ class PonyfillFormData {
262
264
  return this.map.has(name);
263
265
  }
264
266
  set(name, value, fileName) {
265
- const entry = value instanceof PonyfillBlob ? getNormalizedFile(name, value, fileName) : value;
267
+ const entry = isBlob(value)
268
+ ? getNormalizedFile(name, value, fileName)
269
+ : value;
266
270
  this.map.set(name, [entry]);
267
271
  }
268
272
  *[Symbol.iterator]() {
@@ -290,11 +294,7 @@ class PonyfillFormData {
290
294
  const entry = entries.shift();
291
295
  if (entry) {
292
296
  const [key, value] = entry;
293
- if (typeof value === 'string') {
294
- controller.enqueue(Buffer.from(`Content-Disposition: form-data; name="${key}"\r\n\r\n`));
295
- controller.enqueue(Buffer.from(value));
296
- }
297
- else {
297
+ if (value instanceof PonyfillFile) {
298
298
  let filenamePart = '';
299
299
  if (value.name) {
300
300
  filenamePart = `; filename="${value.name}"`;
@@ -303,6 +303,10 @@ class PonyfillFormData {
303
303
  controller.enqueue(Buffer.from(`Content-Type: ${value.type || 'application/octet-stream'}\r\n\r\n`));
304
304
  controller.enqueue(Buffer.from(await value.arrayBuffer()));
305
305
  }
306
+ else {
307
+ controller.enqueue(Buffer.from(`Content-Disposition: form-data; name="${key}"\r\n\r\n`));
308
+ controller.enqueue(Buffer.from(value));
309
+ }
306
310
  if (entries.length === 0) {
307
311
  controller.enqueue(Buffer.from(`\r\n--${boundary}--\r\n`));
308
312
  controller.close();
@@ -331,6 +335,9 @@ function getNormalizedFile(name, blob, fileName) {
331
335
  }
332
336
  return new PonyfillFile([blob], fileName || name, { type: blob.type });
333
337
  }
338
+ function isBlob(value) {
339
+ return value != null && typeof value === 'object' && typeof value.arrayBuffer === 'function';
340
+ }
334
341
 
335
342
  var BodyInitType;
336
343
  (function (BodyInitType) {
@@ -340,26 +347,38 @@ var BodyInitType;
340
347
  BodyInitType["ArrayBuffer"] = "ArrayBuffer";
341
348
  BodyInitType["String"] = "String";
342
349
  BodyInitType["Readable"] = "Readable";
350
+ BodyInitType["Buffer"] = "Buffer";
351
+ BodyInitType["Uint8Array"] = "Uint8Array";
343
352
  })(BodyInitType || (BodyInitType = {}));
344
353
  class PonyfillBody {
345
354
  constructor(bodyInit, options = {}) {
346
355
  this.bodyInit = bodyInit;
347
356
  this.options = options;
348
357
  this.bodyUsed = false;
349
- this._body = null;
350
358
  this.contentType = null;
351
359
  this.contentLength = null;
352
- const { body, contentType, contentLength, bodyType } = processBodyInit(bodyInit);
353
- this._body = body;
360
+ this._bodyFactory = () => null;
361
+ this._generatedBody = null;
362
+ const { bodyFactory, contentType, contentLength, bodyType } = processBodyInit(bodyInit);
363
+ this._bodyFactory = bodyFactory;
354
364
  this.contentType = contentType;
355
365
  this.contentLength = contentLength;
356
366
  this.bodyType = bodyType;
357
367
  }
368
+ generateBody() {
369
+ if (this._generatedBody) {
370
+ return this._generatedBody;
371
+ }
372
+ const body = this._bodyFactory();
373
+ this._generatedBody = body;
374
+ return body;
375
+ }
358
376
  get body() {
359
- if (this._body != null) {
360
- const ponyfillReadableStream = this._body;
361
- const readable = this._body.readable;
362
- return new Proxy(this._body.readable, {
377
+ const _body = this.generateBody();
378
+ if (_body != null) {
379
+ const ponyfillReadableStream = _body;
380
+ const readable = _body.readable;
381
+ return new Proxy(_body.readable, {
363
382
  get(_, prop) {
364
383
  if (prop in ponyfillReadableStream) {
365
384
  const ponyfillReadableStreamProp = ponyfillReadableStream[prop];
@@ -384,6 +403,9 @@ class PonyfillBody {
384
403
  if (this.bodyType === BodyInitType.ArrayBuffer) {
385
404
  return this.bodyInit;
386
405
  }
406
+ if (this.bodyType === BodyInitType.Uint8Array || this.bodyType === BodyInitType.Buffer) {
407
+ return this.bodyInit.buffer;
408
+ }
387
409
  const blob = await this.blob();
388
410
  return blob.arrayBuffer();
389
411
  }
@@ -391,20 +413,37 @@ class PonyfillBody {
391
413
  if (this.bodyType === BodyInitType.Blob) {
392
414
  return this.bodyInit;
393
415
  }
416
+ if (this.bodyType === BodyInitType.String || this.bodyType === BodyInitType.Buffer || this.bodyType === BodyInitType.Uint8Array) {
417
+ const bodyInitTyped = this.bodyInit;
418
+ return new PonyfillBlob([bodyInitTyped], {
419
+ type: this.contentType || '',
420
+ });
421
+ }
422
+ if (this.bodyType === BodyInitType.ArrayBuffer) {
423
+ const bodyInitTyped = this.bodyInit;
424
+ const buf = Buffer.from(bodyInitTyped, undefined, bodyInitTyped.byteLength);
425
+ return new PonyfillBlob([buf], {
426
+ type: this.contentType || '',
427
+ });
428
+ }
394
429
  const chunks = [];
395
- if (this._body) {
396
- for await (const chunk of this._body.readable) {
430
+ const _body = this.generateBody();
431
+ if (_body) {
432
+ for await (const chunk of _body.readable) {
397
433
  chunks.push(chunk);
398
434
  }
399
435
  }
400
- return new PonyfillBlob(chunks);
436
+ return new PonyfillBlob(chunks, {
437
+ type: this.contentType || '',
438
+ });
401
439
  }
402
440
  formData(opts) {
403
441
  if (this.bodyType === BodyInitType.FormData) {
404
442
  return Promise.resolve(this.bodyInit);
405
443
  }
406
444
  const formData = new PonyfillFormData();
407
- if (this._body == null) {
445
+ const _body = this.generateBody();
446
+ if (_body == null) {
408
447
  return Promise.resolve(formData);
409
448
  }
410
449
  const formDataLimits = {
@@ -412,7 +451,6 @@ class PonyfillBody {
412
451
  ...opts === null || opts === void 0 ? void 0 : opts.formDataLimits,
413
452
  };
414
453
  return new Promise((resolve, reject) => {
415
- var _a;
416
454
  const bb = busboy({
417
455
  headers: {
418
456
  'content-type': this.contentType || '',
@@ -460,9 +498,22 @@ class PonyfillBody {
460
498
  bb.on('error', err => {
461
499
  reject(err);
462
500
  });
463
- (_a = this._body) === null || _a === void 0 ? void 0 : _a.readable.pipe(bb);
501
+ _body === null || _body === void 0 ? void 0 : _body.readable.pipe(bb);
464
502
  });
465
503
  }
504
+ async buffer() {
505
+ if (this.bodyType === BodyInitType.Buffer) {
506
+ return this.bodyInit;
507
+ }
508
+ if (this.bodyType === BodyInitType.Uint8Array || this.bodyType === BodyInitType.ArrayBuffer) {
509
+ const bodyInitTyped = this.bodyInit;
510
+ const buffer = Buffer.from(bodyInitTyped, 'byteOffset' in bodyInitTyped ? bodyInitTyped.byteOffset : undefined, bodyInitTyped.byteLength);
511
+ return buffer;
512
+ }
513
+ const blob = await this.blob();
514
+ const arrayBuffer = await blob.arrayBuffer();
515
+ return Buffer.from(arrayBuffer, undefined, arrayBuffer.byteLength);
516
+ }
466
517
  async json() {
467
518
  const text = await this.text();
468
519
  return JSON.parse(text);
@@ -471,6 +522,14 @@ class PonyfillBody {
471
522
  if (this.bodyType === BodyInitType.String) {
472
523
  return this.bodyInit;
473
524
  }
525
+ if (this.bodyType === BodyInitType.Buffer) {
526
+ return this.bodyInit.toString('utf-8');
527
+ }
528
+ if (this.bodyType === BodyInitType.ArrayBuffer || this.bodyType === BodyInitType.Uint8Array) {
529
+ const bodyInitTyped = this.bodyInit;
530
+ const buffer = Buffer.from(bodyInitTyped, 'byteOffset' in bodyInitTyped ? bodyInitTyped.byteOffset : undefined, bodyInitTyped.byteLength);
531
+ return buffer.toString('utf-8');
532
+ }
474
533
  const blob = await this.blob();
475
534
  return blob.text();
476
535
  }
@@ -478,114 +537,152 @@ class PonyfillBody {
478
537
  function processBodyInit(bodyInit) {
479
538
  if (bodyInit == null) {
480
539
  return {
481
- body: null,
540
+ bodyFactory: () => null,
482
541
  contentType: null,
483
542
  contentLength: null,
484
543
  };
485
544
  }
486
545
  if (typeof bodyInit === 'string') {
487
- const buffer = Buffer.from(bodyInit);
488
- const readable = Readable.from(buffer);
489
- const body = new PonyfillReadableStream(readable);
490
546
  return {
491
547
  bodyType: BodyInitType.String,
492
548
  contentType: 'text/plain;charset=UTF-8',
493
- contentLength: buffer.length,
494
- body,
549
+ contentLength: bodyInit.length,
550
+ bodyFactory() {
551
+ const buffer = Buffer.from(bodyInit);
552
+ const readable = Readable.from(buffer);
553
+ return new PonyfillReadableStream(readable);
554
+ },
495
555
  };
496
556
  }
497
557
  if (bodyInit instanceof PonyfillReadableStream) {
498
558
  return {
499
559
  bodyType: BodyInitType.ReadableStream,
500
- body: bodyInit,
560
+ bodyFactory: () => bodyInit,
501
561
  contentType: null,
502
562
  contentLength: null,
503
563
  };
504
564
  }
505
565
  if (bodyInit instanceof PonyfillBlob) {
506
- const readable = bodyInit.stream();
507
- const body = new PonyfillReadableStream(readable);
508
566
  return {
509
567
  bodyType: BodyInitType.Blob,
510
568
  contentType: bodyInit.type,
511
569
  contentLength: bodyInit.size,
512
- body,
570
+ bodyFactory() {
571
+ return bodyInit.stream();
572
+ },
513
573
  };
514
574
  }
515
575
  if (bodyInit instanceof PonyfillFormData) {
516
576
  const boundary = Math.random().toString(36).substr(2);
517
577
  const contentType = `multipart/form-data; boundary=${boundary}`;
518
- const body = bodyInit.stream(boundary);
519
578
  return {
520
579
  bodyType: BodyInitType.FormData,
521
580
  contentType,
522
581
  contentLength: null,
523
- body,
582
+ bodyFactory: () => bodyInit.stream(boundary),
583
+ };
584
+ }
585
+ if (bodyInit instanceof Buffer) {
586
+ const contentLength = bodyInit.length;
587
+ return {
588
+ bodyType: BodyInitType.Buffer,
589
+ contentLength,
590
+ contentType: null,
591
+ bodyFactory() {
592
+ const readable = Readable.from(bodyInit);
593
+ const body = new PonyfillReadableStream(readable);
594
+ return body;
595
+ },
596
+ };
597
+ }
598
+ if (bodyInit instanceof Uint8Array) {
599
+ const contentLength = bodyInit.byteLength;
600
+ return {
601
+ bodyType: BodyInitType.Uint8Array,
602
+ contentLength,
603
+ contentType: null,
604
+ bodyFactory() {
605
+ const readable = Readable.from(bodyInit);
606
+ const body = new PonyfillReadableStream(readable);
607
+ return body;
608
+ }
524
609
  };
525
610
  }
526
611
  if ('buffer' in bodyInit) {
527
612
  const contentLength = bodyInit.byteLength;
528
- const buffer = Buffer.from(bodyInit.buffer, bodyInit.byteOffset, bodyInit.byteLength);
529
- const readable = Readable.from(buffer);
530
- const body = new PonyfillReadableStream(readable);
531
613
  return {
532
614
  contentLength,
533
615
  contentType: null,
534
- body,
616
+ bodyFactory() {
617
+ const buffer = Buffer.from(bodyInit.buffer, bodyInit.byteOffset, bodyInit.byteLength);
618
+ const readable = Readable.from(buffer);
619
+ const body = new PonyfillReadableStream(readable);
620
+ return body;
621
+ }
535
622
  };
536
623
  }
537
624
  if (bodyInit instanceof ArrayBuffer) {
538
625
  const contentLength = bodyInit.byteLength;
539
- const buffer = Buffer.from(bodyInit, undefined, bodyInit.byteLength);
540
- const readable = Readable.from(buffer);
541
- const body = new PonyfillReadableStream(readable);
542
626
  return {
543
627
  bodyType: BodyInitType.ArrayBuffer,
544
628
  contentType: null,
545
629
  contentLength,
546
- body,
630
+ bodyFactory() {
631
+ const buffer = Buffer.from(bodyInit, undefined, bodyInit.byteLength);
632
+ const readable = Readable.from(buffer);
633
+ const body = new PonyfillReadableStream(readable);
634
+ return body;
635
+ }
547
636
  };
548
637
  }
549
638
  if (bodyInit instanceof Readable) {
550
- const body = new PonyfillReadableStream(bodyInit);
551
639
  return {
552
640
  bodyType: BodyInitType.Readable,
553
641
  contentType: null,
554
642
  contentLength: null,
555
- body,
643
+ bodyFactory() {
644
+ const body = new PonyfillReadableStream(bodyInit);
645
+ return body;
646
+ }
556
647
  };
557
648
  }
558
649
  if ('stream' in bodyInit) {
559
- const bodyStream = bodyInit.stream();
560
- const body = new PonyfillReadableStream(bodyStream);
561
650
  return {
562
651
  contentType: bodyInit.type,
563
652
  contentLength: bodyInit.size,
564
- body,
653
+ bodyFactory() {
654
+ const bodyStream = bodyInit.stream();
655
+ const body = new PonyfillReadableStream(bodyStream);
656
+ return body;
657
+ }
565
658
  };
566
659
  }
567
660
  if (bodyInit instanceof URLSearchParams) {
568
661
  const contentType = 'application/x-www-form-urlencoded;charset=UTF-8';
569
- const body = new PonyfillReadableStream(Readable.from(bodyInit.toString()));
570
662
  return {
571
663
  bodyType: BodyInitType.String,
572
664
  contentType,
573
665
  contentLength: null,
574
- body,
666
+ bodyFactory() {
667
+ const body = new PonyfillReadableStream(Readable.from(bodyInit.toString()));
668
+ return body;
669
+ }
575
670
  };
576
671
  }
577
672
  if ('forEach' in bodyInit) {
578
- const formData = new PonyfillFormData();
579
- bodyInit.forEach((value, key) => {
580
- formData.append(key, value);
581
- });
582
673
  const boundary = Math.random().toString(36).substr(2);
583
674
  const contentType = `multipart/form-data; boundary=${boundary}`;
584
- const body = formData.stream(boundary);
585
675
  return {
586
676
  contentType,
587
677
  contentLength: null,
588
- body,
678
+ bodyFactory() {
679
+ const formData = new PonyfillFormData();
680
+ bodyInit.forEach((value, key) => {
681
+ formData.append(key, value);
682
+ });
683
+ const body = formData.stream(boundary);
684
+ return body;
685
+ },
589
686
  };
590
687
  }
591
688
  throw new Error('Unknown body type');
@@ -743,6 +840,24 @@ class PonyfillResponse extends PonyfillBody {
743
840
  this.redirected = init.redirected || false;
744
841
  this.type = init.type || 'default';
745
842
  }
843
+ const contentTypeInHeaders = this.headers.get('content-type');
844
+ if (!contentTypeInHeaders) {
845
+ if (this.contentType) {
846
+ this.headers.set('content-type', this.contentType);
847
+ }
848
+ }
849
+ else {
850
+ this.contentType = contentTypeInHeaders;
851
+ }
852
+ const contentLengthInHeaders = this.headers.get('content-length');
853
+ if (!contentLengthInHeaders) {
854
+ if (this.contentLength) {
855
+ this.headers.set('content-length', this.contentLength.toString());
856
+ }
857
+ }
858
+ else {
859
+ this.contentLength = parseInt(contentLengthInHeaders, 10);
860
+ }
746
861
  }
747
862
  get ok() {
748
863
  return this.status >= 200 && this.status < 300;
@@ -819,12 +934,10 @@ function fetchPonyfill(info, init) {
819
934
  if (mimeType.endsWith(BASE64_SUFFIX)) {
820
935
  const buffer = Buffer.from(data, 'base64');
821
936
  const realMimeType = mimeType.slice(0, -BASE64_SUFFIX.length);
822
- const response = new PonyfillResponse(buffer, {
937
+ const file = new PonyfillBlob([buffer], { type: realMimeType });
938
+ const response = new PonyfillResponse(file, {
823
939
  status: 200,
824
940
  statusText: 'OK',
825
- headers: {
826
- 'content-type': realMimeType,
827
- },
828
941
  });
829
942
  resolve(response);
830
943
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whatwg-node/node-fetch",
3
- "version": "0.0.2-alpha-20230202192735-c9da64f",
3
+ "version": "0.0.3-alpha-20230205160101-d3a1033",
4
4
  "description": "Fetch API implementation for Node",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {