@whatwg-node/node-fetch 0.0.1-alpha-20230117081522-969e299 → 0.0.1-alpha-20230117095738-14df726

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/AbortSignal.d.ts CHANGED
@@ -6,4 +6,6 @@ export declare class PonyfillAbortSignal extends EventTarget implements AbortSig
6
6
  throwIfAborted(): void;
7
7
  get onabort(): ((this: AbortSignal, ev: Event) => any) | null;
8
8
  set onabort(value: ((this: AbortSignal, ev: Event) => any) | null);
9
+ abort(reason?: any): void;
10
+ static timeout(milliseconds: number): PonyfillAbortSignal;
9
11
  }
package/index.js CHANGED
@@ -10,14 +10,13 @@ const events = require('@whatwg-node/events');
10
10
  const buffer = require('buffer');
11
11
  const stream = require('stream');
12
12
  const busboy = _interopDefault(require('busboy'));
13
- const headerCase = require('header-case');
14
13
  const url = require('url');
15
14
  const fs = require('fs');
16
15
 
17
16
  // Will be removed after v14 reaches EOL
18
17
  class PonyfillAbortError extends Error {
19
18
  constructor(reason) {
20
- super('The operation was aborted.', {
19
+ super('The operation was aborted' + reason || '', {
21
20
  cause: reason,
22
21
  });
23
22
  this.name = 'AbortError';
@@ -47,6 +46,14 @@ class PonyfillAbortSignal extends events.EventTarget {
47
46
  }
48
47
  this.addEventListener('abort', value);
49
48
  }
49
+ abort(reason) {
50
+ this.dispatchEvent(new CustomEvent('abort', { detail: reason }));
51
+ }
52
+ static timeout(milliseconds) {
53
+ const signal = new PonyfillAbortSignal();
54
+ setTimeout(() => signal.abort(`Operation timed out`), milliseconds);
55
+ return signal;
56
+ }
50
57
  }
51
58
 
52
59
  // Will be removed after v14 reaches EOL
@@ -304,6 +311,10 @@ class PonyfillFormData {
304
311
  controller.enqueue(Buffer.from(`\r\n--${boundary}\r\n`));
305
312
  }
306
313
  }
314
+ else {
315
+ controller.enqueue(Buffer.from(`\r\n--${boundary}--\r\n`));
316
+ controller.close();
317
+ }
307
318
  },
308
319
  });
309
320
  }
@@ -541,6 +552,39 @@ function processBodyInit(bodyInit) {
541
552
  body,
542
553
  };
543
554
  }
555
+ if ('stream' in bodyInit) {
556
+ const bodyStream = bodyInit.stream();
557
+ const body = new PonyfillReadableStream(bodyStream);
558
+ return {
559
+ contentType: bodyInit.type,
560
+ contentLength: bodyInit.size,
561
+ body,
562
+ };
563
+ }
564
+ if (bodyInit instanceof URLSearchParams) {
565
+ const contentType = 'application/x-www-form-urlencoded;charset=UTF-8';
566
+ const body = new PonyfillReadableStream(stream.Readable.from(bodyInit.toString()));
567
+ return {
568
+ bodyType: BodyInitType.String,
569
+ contentType,
570
+ contentLength: null,
571
+ body,
572
+ };
573
+ }
574
+ if ('forEach' in bodyInit) {
575
+ const formData = new PonyfillFormData();
576
+ bodyInit.forEach((value, key) => {
577
+ formData.append(key, value);
578
+ });
579
+ const boundary = Math.random().toString(36).substr(2);
580
+ const contentType = `multipart/form-data; boundary=${boundary}`;
581
+ const body = formData.stream(boundary);
582
+ return {
583
+ contentType,
584
+ contentLength: null,
585
+ body,
586
+ };
587
+ }
544
588
  throw new Error('Unknown body type');
545
589
  }
546
590
 
@@ -581,26 +625,26 @@ class PonyfillHeaders {
581
625
  }
582
626
  }
583
627
  append(name, value) {
584
- const key = headerCase.headerCase(name);
628
+ const key = name.toLowerCase();
585
629
  if (this.map.has(key)) {
586
630
  value = this.map.get(key) + ', ' + value;
587
631
  }
588
632
  this.map.set(key, value);
589
633
  }
590
634
  get(name) {
591
- const key = headerCase.headerCase(name);
635
+ const key = name.toLowerCase();
592
636
  return this.map.get(key) || null;
593
637
  }
594
638
  has(name) {
595
- const key = headerCase.headerCase(name);
639
+ const key = name.toLowerCase();
596
640
  return this.map.has(key);
597
641
  }
598
642
  set(name, value) {
599
- const key = headerCase.headerCase(name);
643
+ const key = name.toLowerCase();
600
644
  this.map.set(key, value);
601
645
  }
602
646
  delete(name) {
603
- const key = headerCase.headerCase(name);
647
+ const key = name.toLowerCase();
604
648
  this.map.delete(key);
605
649
  }
606
650
  forEach(callback) {
@@ -621,6 +665,7 @@ function isRequest(input) {
621
665
  }
622
666
  class PonyfillRequest extends PonyfillBody {
623
667
  constructor(input, options) {
668
+ var _a;
624
669
  let url;
625
670
  let bodyInit = null;
626
671
  let requestInit;
@@ -647,7 +692,7 @@ class PonyfillRequest extends PonyfillBody {
647
692
  this.headers = new PonyfillHeaders(requestInit === null || requestInit === void 0 ? void 0 : requestInit.headers);
648
693
  this.integrity = (requestInit === null || requestInit === void 0 ? void 0 : requestInit.integrity) || '';
649
694
  this.keepalive = (requestInit === null || requestInit === void 0 ? void 0 : requestInit.keepalive) || true;
650
- this.method = (requestInit === null || requestInit === void 0 ? void 0 : requestInit.method) || 'GET';
695
+ this.method = ((_a = requestInit === null || requestInit === void 0 ? void 0 : requestInit.method) === null || _a === void 0 ? void 0 : _a.toUpperCase()) || 'GET';
651
696
  this.mode = (requestInit === null || requestInit === void 0 ? void 0 : requestInit.mode) || 'cors';
652
697
  this.redirect = (requestInit === null || requestInit === void 0 ? void 0 : requestInit.redirect) || 'follow';
653
698
  this.referrer = (requestInit === null || requestInit === void 0 ? void 0 : requestInit.referrer) || 'about:client';
@@ -753,9 +798,9 @@ function getResponseForFile(url$1) {
753
798
  }
754
799
  function getRequestFnForProtocol(protocol) {
755
800
  switch (protocol) {
756
- case 'http':
801
+ case 'http:':
757
802
  return http.request;
758
- case 'https':
803
+ case 'https:':
759
804
  return https.request;
760
805
  }
761
806
  throw new Error(`Unsupported protocol: ${protocol}`);
@@ -768,13 +813,39 @@ function fetchPonyfill(info, init) {
768
813
  const fetchRequest = info;
769
814
  return new Promise((resolve, reject) => {
770
815
  try {
771
- const protocol = fetchRequest.url.split('://')[0];
772
- if (protocol === 'file') {
773
- const response = getResponseForFile(fetchRequest.url);
816
+ const url = new URL(fetchRequest.url, 'http://localhost');
817
+ if (url.protocol === 'data:') {
818
+ const [mimeType = 'text/plain', base64FlagOrText, base64String] = url.pathname.split(',');
819
+ if (base64FlagOrText === 'base64' && base64String) {
820
+ const buffer = Buffer.from(base64String, 'base64');
821
+ const response = new PonyfillResponse(buffer, {
822
+ status: 200,
823
+ statusText: 'OK',
824
+ headers: {
825
+ 'content-type': mimeType,
826
+ },
827
+ });
828
+ resolve(response);
829
+ return;
830
+ }
831
+ if (base64FlagOrText) {
832
+ const response = new PonyfillResponse(base64FlagOrText, {
833
+ status: 200,
834
+ statusText: 'OK',
835
+ headers: {
836
+ 'content-type': mimeType,
837
+ },
838
+ });
839
+ resolve(response);
840
+ return;
841
+ }
842
+ }
843
+ if (url.protocol === 'file:') {
844
+ const response = getResponseForFile(url);
774
845
  resolve(response);
775
846
  return;
776
847
  }
777
- const requestFn = getRequestFnForProtocol(protocol);
848
+ const requestFn = getRequestFnForProtocol(url.protocol);
778
849
  const nodeReadable = (fetchRequest.body != null
779
850
  ? 'pipe' in fetchRequest.body
780
851
  ? fetchRequest.body
@@ -783,10 +854,16 @@ function fetchPonyfill(info, init) {
783
854
  const nodeHeaders = getHeadersObj(fetchRequest.headers);
784
855
  const abortListener = function abortListener(event) {
785
856
  nodeRequest.destroy();
786
- reject(new PonyfillAbortError(event.detail));
857
+ const reason = event.detail;
858
+ if (reason instanceof Error) {
859
+ reject(reason);
860
+ }
861
+ else {
862
+ reject(new PonyfillAbortError(reason));
863
+ }
787
864
  };
788
865
  fetchRequest.signal.addEventListener('abort', abortListener);
789
- const nodeRequest = requestFn(fetchRequest.url, {
866
+ const nodeRequest = requestFn(url, {
790
867
  // signal: fetchRequest.signal will be added when v14 reaches EOL
791
868
  method: fetchRequest.method,
792
869
  headers: nodeHeaders,
@@ -800,7 +877,7 @@ function fetchPonyfill(info, init) {
800
877
  return;
801
878
  }
802
879
  if (fetchRequest.redirect === 'follow') {
803
- const redirectedUrl = new URL(nodeResponse.headers.location, fetchRequest.url);
880
+ const redirectedUrl = new URL(nodeResponse.headers.location, url);
804
881
  const redirectResponse$ = fetchPonyfill(redirectedUrl, info);
805
882
  resolve(redirectResponse$.then(redirectResponse => {
806
883
  redirectResponse.redirected = true;
package/index.mjs CHANGED
@@ -1,17 +1,16 @@
1
1
  import { request as request$1 } from 'http';
2
2
  import { request } from 'https';
3
- import { EventTarget, CustomEvent } from '@whatwg-node/events';
3
+ import { EventTarget, CustomEvent as CustomEvent$1 } from '@whatwg-node/events';
4
4
  import { Blob } from 'buffer';
5
5
  import { Readable } from 'stream';
6
6
  import busboy from 'busboy';
7
- import { headerCase } from 'header-case';
8
7
  import { fileURLToPath } from 'url';
9
8
  import { createReadStream } from 'fs';
10
9
 
11
10
  // Will be removed after v14 reaches EOL
12
11
  class PonyfillAbortError extends Error {
13
12
  constructor(reason) {
14
- super('The operation was aborted.', {
13
+ super('The operation was aborted' + reason || '', {
15
14
  cause: reason,
16
15
  });
17
16
  this.name = 'AbortError';
@@ -41,6 +40,14 @@ class PonyfillAbortSignal extends EventTarget {
41
40
  }
42
41
  this.addEventListener('abort', value);
43
42
  }
43
+ abort(reason) {
44
+ this.dispatchEvent(new CustomEvent('abort', { detail: reason }));
45
+ }
46
+ static timeout(milliseconds) {
47
+ const signal = new PonyfillAbortSignal();
48
+ setTimeout(() => signal.abort(`Operation timed out`), milliseconds);
49
+ return signal;
50
+ }
44
51
  }
45
52
 
46
53
  // Will be removed after v14 reaches EOL
@@ -49,7 +56,7 @@ class PonyfillAbortController {
49
56
  this.signal = new PonyfillAbortSignal();
50
57
  }
51
58
  abort(reason) {
52
- this.signal.dispatchEvent(new CustomEvent('abort', { detail: reason }));
59
+ this.signal.dispatchEvent(new CustomEvent$1('abort', { detail: reason }));
53
60
  }
54
61
  }
55
62
 
@@ -298,6 +305,10 @@ class PonyfillFormData {
298
305
  controller.enqueue(Buffer.from(`\r\n--${boundary}\r\n`));
299
306
  }
300
307
  }
308
+ else {
309
+ controller.enqueue(Buffer.from(`\r\n--${boundary}--\r\n`));
310
+ controller.close();
311
+ }
301
312
  },
302
313
  });
303
314
  }
@@ -535,6 +546,39 @@ function processBodyInit(bodyInit) {
535
546
  body,
536
547
  };
537
548
  }
549
+ if ('stream' in bodyInit) {
550
+ const bodyStream = bodyInit.stream();
551
+ const body = new PonyfillReadableStream(bodyStream);
552
+ return {
553
+ contentType: bodyInit.type,
554
+ contentLength: bodyInit.size,
555
+ body,
556
+ };
557
+ }
558
+ if (bodyInit instanceof URLSearchParams) {
559
+ const contentType = 'application/x-www-form-urlencoded;charset=UTF-8';
560
+ const body = new PonyfillReadableStream(Readable.from(bodyInit.toString()));
561
+ return {
562
+ bodyType: BodyInitType.String,
563
+ contentType,
564
+ contentLength: null,
565
+ body,
566
+ };
567
+ }
568
+ if ('forEach' in bodyInit) {
569
+ const formData = new PonyfillFormData();
570
+ bodyInit.forEach((value, key) => {
571
+ formData.append(key, value);
572
+ });
573
+ const boundary = Math.random().toString(36).substr(2);
574
+ const contentType = `multipart/form-data; boundary=${boundary}`;
575
+ const body = formData.stream(boundary);
576
+ return {
577
+ contentType,
578
+ contentLength: null,
579
+ body,
580
+ };
581
+ }
538
582
  throw new Error('Unknown body type');
539
583
  }
540
584
 
@@ -575,26 +619,26 @@ class PonyfillHeaders {
575
619
  }
576
620
  }
577
621
  append(name, value) {
578
- const key = headerCase(name);
622
+ const key = name.toLowerCase();
579
623
  if (this.map.has(key)) {
580
624
  value = this.map.get(key) + ', ' + value;
581
625
  }
582
626
  this.map.set(key, value);
583
627
  }
584
628
  get(name) {
585
- const key = headerCase(name);
629
+ const key = name.toLowerCase();
586
630
  return this.map.get(key) || null;
587
631
  }
588
632
  has(name) {
589
- const key = headerCase(name);
633
+ const key = name.toLowerCase();
590
634
  return this.map.has(key);
591
635
  }
592
636
  set(name, value) {
593
- const key = headerCase(name);
637
+ const key = name.toLowerCase();
594
638
  this.map.set(key, value);
595
639
  }
596
640
  delete(name) {
597
- const key = headerCase(name);
641
+ const key = name.toLowerCase();
598
642
  this.map.delete(key);
599
643
  }
600
644
  forEach(callback) {
@@ -615,6 +659,7 @@ function isRequest(input) {
615
659
  }
616
660
  class PonyfillRequest extends PonyfillBody {
617
661
  constructor(input, options) {
662
+ var _a;
618
663
  let url;
619
664
  let bodyInit = null;
620
665
  let requestInit;
@@ -641,7 +686,7 @@ class PonyfillRequest extends PonyfillBody {
641
686
  this.headers = new PonyfillHeaders(requestInit === null || requestInit === void 0 ? void 0 : requestInit.headers);
642
687
  this.integrity = (requestInit === null || requestInit === void 0 ? void 0 : requestInit.integrity) || '';
643
688
  this.keepalive = (requestInit === null || requestInit === void 0 ? void 0 : requestInit.keepalive) || true;
644
- this.method = (requestInit === null || requestInit === void 0 ? void 0 : requestInit.method) || 'GET';
689
+ this.method = ((_a = requestInit === null || requestInit === void 0 ? void 0 : requestInit.method) === null || _a === void 0 ? void 0 : _a.toUpperCase()) || 'GET';
645
690
  this.mode = (requestInit === null || requestInit === void 0 ? void 0 : requestInit.mode) || 'cors';
646
691
  this.redirect = (requestInit === null || requestInit === void 0 ? void 0 : requestInit.redirect) || 'follow';
647
692
  this.referrer = (requestInit === null || requestInit === void 0 ? void 0 : requestInit.referrer) || 'about:client';
@@ -747,9 +792,9 @@ function getResponseForFile(url) {
747
792
  }
748
793
  function getRequestFnForProtocol(protocol) {
749
794
  switch (protocol) {
750
- case 'http':
795
+ case 'http:':
751
796
  return request$1;
752
- case 'https':
797
+ case 'https:':
753
798
  return request;
754
799
  }
755
800
  throw new Error(`Unsupported protocol: ${protocol}`);
@@ -762,13 +807,39 @@ function fetchPonyfill(info, init) {
762
807
  const fetchRequest = info;
763
808
  return new Promise((resolve, reject) => {
764
809
  try {
765
- const protocol = fetchRequest.url.split('://')[0];
766
- if (protocol === 'file') {
767
- const response = getResponseForFile(fetchRequest.url);
810
+ const url = new URL(fetchRequest.url, 'http://localhost');
811
+ if (url.protocol === 'data:') {
812
+ const [mimeType = 'text/plain', base64FlagOrText, base64String] = url.pathname.split(',');
813
+ if (base64FlagOrText === 'base64' && base64String) {
814
+ const buffer = Buffer.from(base64String, 'base64');
815
+ const response = new PonyfillResponse(buffer, {
816
+ status: 200,
817
+ statusText: 'OK',
818
+ headers: {
819
+ 'content-type': mimeType,
820
+ },
821
+ });
822
+ resolve(response);
823
+ return;
824
+ }
825
+ if (base64FlagOrText) {
826
+ const response = new PonyfillResponse(base64FlagOrText, {
827
+ status: 200,
828
+ statusText: 'OK',
829
+ headers: {
830
+ 'content-type': mimeType,
831
+ },
832
+ });
833
+ resolve(response);
834
+ return;
835
+ }
836
+ }
837
+ if (url.protocol === 'file:') {
838
+ const response = getResponseForFile(url);
768
839
  resolve(response);
769
840
  return;
770
841
  }
771
- const requestFn = getRequestFnForProtocol(protocol);
842
+ const requestFn = getRequestFnForProtocol(url.protocol);
772
843
  const nodeReadable = (fetchRequest.body != null
773
844
  ? 'pipe' in fetchRequest.body
774
845
  ? fetchRequest.body
@@ -777,10 +848,16 @@ function fetchPonyfill(info, init) {
777
848
  const nodeHeaders = getHeadersObj(fetchRequest.headers);
778
849
  const abortListener = function abortListener(event) {
779
850
  nodeRequest.destroy();
780
- reject(new PonyfillAbortError(event.detail));
851
+ const reason = event.detail;
852
+ if (reason instanceof Error) {
853
+ reject(reason);
854
+ }
855
+ else {
856
+ reject(new PonyfillAbortError(reason));
857
+ }
781
858
  };
782
859
  fetchRequest.signal.addEventListener('abort', abortListener);
783
- const nodeRequest = requestFn(fetchRequest.url, {
860
+ const nodeRequest = requestFn(url, {
784
861
  // signal: fetchRequest.signal will be added when v14 reaches EOL
785
862
  method: fetchRequest.method,
786
863
  headers: nodeHeaders,
@@ -794,7 +871,7 @@ function fetchPonyfill(info, init) {
794
871
  return;
795
872
  }
796
873
  if (fetchRequest.redirect === 'follow') {
797
- const redirectedUrl = new URL(nodeResponse.headers.location, fetchRequest.url);
874
+ const redirectedUrl = new URL(nodeResponse.headers.location, url);
798
875
  const redirectResponse$ = fetchPonyfill(redirectedUrl, info);
799
876
  resolve(redirectResponse$.then(redirectResponse => {
800
877
  redirectResponse.redirected = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whatwg-node/node-fetch",
3
- "version": "0.0.1-alpha-20230117081522-969e299",
3
+ "version": "0.0.1-alpha-20230117095738-14df726",
4
4
  "description": "Fetch API implementation for Node",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
@@ -9,7 +9,6 @@
9
9
  "dependencies": {
10
10
  "@whatwg-node/events": "0.0.2",
11
11
  "busboy": "1.6.0",
12
- "header-case": "^2.0.4",
13
12
  "tslib": "^2.3.1"
14
13
  },
15
14
  "repository": {