@whatwg-node/node-fetch 0.0.6-alpha-20230207114030-349e836 → 0.0.7-alpha-20230208145746-08ecb64

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/Blob.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  import { Blob as NodeBlob } from 'buffer';
3
- declare const PonyfillBlob_base: typeof NodeBlob;
4
- export declare class PonyfillBlob extends PonyfillBlob_base implements Blob {
3
+ declare const BaseBlob: typeof NodeBlob;
4
+ export declare class PonyfillBlob extends BaseBlob implements Blob {
5
5
  stream(): any;
6
6
  slice(...args: any[]): any;
7
7
  }
package/Headers.d.ts CHANGED
@@ -1,7 +1,12 @@
1
1
  export type PonyfillHeadersInit = [string, string][] | Record<string, string | string[] | undefined> | Headers;
2
2
  export declare class PonyfillHeaders implements Headers {
3
+ private headersInit?;
3
4
  private map;
4
- constructor(headersInit?: PonyfillHeadersInit);
5
+ private mapIsBuilt;
6
+ private objectKeysOfeadersInit;
7
+ constructor(headersInit?: PonyfillHeadersInit | undefined);
8
+ private _get;
9
+ private getMap;
5
10
  append(name: string, value: string): void;
6
11
  get(name: string): string | null;
7
12
  has(name: string): boolean;
package/index.js CHANGED
@@ -184,9 +184,10 @@ class DummyBlob {
184
184
  throw new Error('Blob is not supported in this environment, if you are using an older version of Node v14, please upgrade to v14.17.0 or higher');
185
185
  }
186
186
  }
187
+ const BaseBlob = buffer.Blob || DummyBlob;
187
188
  // Will be removed after v14 reaches EOL
188
189
  // Needed because v14 doesn't have .stream() implemented
189
- class PonyfillBlob extends (buffer.Blob || DummyBlob) {
190
+ class PonyfillBlob extends BaseBlob {
190
191
  stream() {
191
192
  return new PonyfillReadableStream({
192
193
  start: async (controller) => {
@@ -561,6 +562,15 @@ class PonyfillBody {
561
562
  const buffer = Buffer.from(bodyInitTyped, 'byteOffset' in bodyInitTyped ? bodyInitTyped.byteOffset : undefined, bodyInitTyped.byteLength);
562
563
  return buffer.toString('utf-8');
563
564
  }
565
+ // perf: avoid reading the stream twice (we read from Readable to create Blob and then we read from Blob to create a string)
566
+ const _body = this.generateBody();
567
+ if (_body) {
568
+ const chunks = [];
569
+ for await (const chunk of _body.readable) {
570
+ chunks.push(chunk);
571
+ }
572
+ return Buffer.concat(chunks).toString(this.contentType || 'utf-8');
573
+ }
564
574
  const blob = await this.blob();
565
575
  return blob.text();
566
576
  }
@@ -718,19 +728,61 @@ function isHeadersLike(headers) {
718
728
  }
719
729
  class PonyfillHeaders {
720
730
  constructor(headersInit) {
731
+ this.headersInit = headersInit;
721
732
  this.map = new Map();
722
- if (headersInit != null) {
723
- if (Array.isArray(headersInit)) {
724
- this.map = new Map(headersInit);
733
+ this.mapIsBuilt = false;
734
+ this.objectKeysOfeadersInit = [];
735
+ }
736
+ // perf: we don't need to build `this.map` for Requests, as we can access the headers directly
737
+ _get(key) {
738
+ // If the map is built, reuse it
739
+ if (this.mapIsBuilt) {
740
+ return this.map.get(key.toLowerCase()) || null;
741
+ }
742
+ // If the map is not built, try to get the value from the this.headersInit
743
+ if (this.headersInit == null) {
744
+ return null;
745
+ }
746
+ const normalized = key.toLowerCase();
747
+ if (Array.isArray(this.headersInit)) {
748
+ return this.headersInit.find(header => header[0] === normalized);
749
+ }
750
+ else if (isHeadersLike(this.headersInit)) {
751
+ return this.headersInit.get(normalized);
752
+ }
753
+ else {
754
+ const initValue = this.headersInit[key] || this.headersInit[normalized];
755
+ if (initValue != null) {
756
+ return initValue;
757
+ }
758
+ if (!this.objectKeysOfeadersInit.length) {
759
+ this.objectKeysOfeadersInit = Object.keys(this.headersInit).map(k => k.toLowerCase());
760
+ }
761
+ const index = this.objectKeysOfeadersInit.indexOf(normalized);
762
+ if (index === -1) {
763
+ return null;
725
764
  }
726
- else if (isHeadersLike(headersInit)) {
727
- headersInit.forEach((value, key) => {
765
+ return this.headersInit[index];
766
+ }
767
+ }
768
+ // perf: Build the map of headers lazily, only when we need to access all headers or write to it.
769
+ // I could do a getter here, but I'm too lazy to type `getter`.
770
+ getMap() {
771
+ if (this.mapIsBuilt) {
772
+ return this.map;
773
+ }
774
+ if (this.headersInit != null) {
775
+ if (Array.isArray(this.headersInit)) {
776
+ this.map = new Map(this.headersInit);
777
+ }
778
+ else if (isHeadersLike(this.headersInit)) {
779
+ this.headersInit.forEach((value, key) => {
728
780
  this.map.set(key, value);
729
781
  });
730
782
  }
731
783
  else {
732
- for (const initKey in headersInit) {
733
- const initValue = headersInit[initKey];
784
+ for (const initKey in this.headersInit) {
785
+ const initValue = this.headersInit[initKey];
734
786
  if (initValue != null) {
735
787
  const normalizedValue = Array.isArray(initValue) ? initValue.join(', ') : initValue;
736
788
  const normalizedKey = initKey.toLowerCase();
@@ -739,39 +791,48 @@ class PonyfillHeaders {
739
791
  }
740
792
  }
741
793
  }
794
+ this.mapIsBuilt = true;
795
+ return this.map;
742
796
  }
743
797
  append(name, value) {
744
798
  const key = name.toLowerCase();
745
- const existingValue = this.map.get(key);
799
+ const existingValue = this.getMap().get(key);
746
800
  const finalValue = existingValue ? `${existingValue}, ${value}` : value;
747
- this.map.set(key, finalValue);
801
+ this.getMap().set(key, finalValue);
748
802
  }
749
803
  get(name) {
750
804
  const key = name.toLowerCase();
751
- return this.map.get(key) || null;
805
+ const value = this._get(key);
806
+ if (value == null) {
807
+ return null;
808
+ }
809
+ if (Array.isArray(value)) {
810
+ return value.join(', ');
811
+ }
812
+ return value;
752
813
  }
753
814
  has(name) {
754
815
  const key = name.toLowerCase();
755
- return this.map.has(key);
816
+ return !!this._get(key); // we might need to check if header exists and not just check if it's not nullable
756
817
  }
757
818
  set(name, value) {
758
819
  const key = name.toLowerCase();
759
- this.map.set(key, value);
820
+ this.getMap().set(key, value);
760
821
  }
761
822
  delete(name) {
762
823
  const key = name.toLowerCase();
763
- this.map.delete(key);
824
+ this.getMap().delete(key);
764
825
  }
765
826
  forEach(callback) {
766
- this.map.forEach((value, key) => {
827
+ this.getMap().forEach((value, key) => {
767
828
  callback(value, key, this);
768
829
  });
769
830
  }
770
831
  entries() {
771
- return this.map.entries();
832
+ return this.getMap().entries();
772
833
  }
773
834
  [Symbol.iterator]() {
774
- return this.map.entries();
835
+ return this.getMap().entries();
775
836
  }
776
837
  }
777
838
 
package/index.mjs CHANGED
@@ -178,9 +178,10 @@ class DummyBlob {
178
178
  throw new Error('Blob is not supported in this environment, if you are using an older version of Node v14, please upgrade to v14.17.0 or higher');
179
179
  }
180
180
  }
181
+ const BaseBlob = Blob || DummyBlob;
181
182
  // Will be removed after v14 reaches EOL
182
183
  // Needed because v14 doesn't have .stream() implemented
183
- class PonyfillBlob extends (Blob || DummyBlob) {
184
+ class PonyfillBlob extends BaseBlob {
184
185
  stream() {
185
186
  return new PonyfillReadableStream({
186
187
  start: async (controller) => {
@@ -555,6 +556,15 @@ class PonyfillBody {
555
556
  const buffer = Buffer.from(bodyInitTyped, 'byteOffset' in bodyInitTyped ? bodyInitTyped.byteOffset : undefined, bodyInitTyped.byteLength);
556
557
  return buffer.toString('utf-8');
557
558
  }
559
+ // perf: avoid reading the stream twice (we read from Readable to create Blob and then we read from Blob to create a string)
560
+ const _body = this.generateBody();
561
+ if (_body) {
562
+ const chunks = [];
563
+ for await (const chunk of _body.readable) {
564
+ chunks.push(chunk);
565
+ }
566
+ return Buffer.concat(chunks).toString(this.contentType || 'utf-8');
567
+ }
558
568
  const blob = await this.blob();
559
569
  return blob.text();
560
570
  }
@@ -712,19 +722,61 @@ function isHeadersLike(headers) {
712
722
  }
713
723
  class PonyfillHeaders {
714
724
  constructor(headersInit) {
725
+ this.headersInit = headersInit;
715
726
  this.map = new Map();
716
- if (headersInit != null) {
717
- if (Array.isArray(headersInit)) {
718
- this.map = new Map(headersInit);
727
+ this.mapIsBuilt = false;
728
+ this.objectKeysOfeadersInit = [];
729
+ }
730
+ // perf: we don't need to build `this.map` for Requests, as we can access the headers directly
731
+ _get(key) {
732
+ // If the map is built, reuse it
733
+ if (this.mapIsBuilt) {
734
+ return this.map.get(key.toLowerCase()) || null;
735
+ }
736
+ // If the map is not built, try to get the value from the this.headersInit
737
+ if (this.headersInit == null) {
738
+ return null;
739
+ }
740
+ const normalized = key.toLowerCase();
741
+ if (Array.isArray(this.headersInit)) {
742
+ return this.headersInit.find(header => header[0] === normalized);
743
+ }
744
+ else if (isHeadersLike(this.headersInit)) {
745
+ return this.headersInit.get(normalized);
746
+ }
747
+ else {
748
+ const initValue = this.headersInit[key] || this.headersInit[normalized];
749
+ if (initValue != null) {
750
+ return initValue;
751
+ }
752
+ if (!this.objectKeysOfeadersInit.length) {
753
+ this.objectKeysOfeadersInit = Object.keys(this.headersInit).map(k => k.toLowerCase());
754
+ }
755
+ const index = this.objectKeysOfeadersInit.indexOf(normalized);
756
+ if (index === -1) {
757
+ return null;
719
758
  }
720
- else if (isHeadersLike(headersInit)) {
721
- headersInit.forEach((value, key) => {
759
+ return this.headersInit[index];
760
+ }
761
+ }
762
+ // perf: Build the map of headers lazily, only when we need to access all headers or write to it.
763
+ // I could do a getter here, but I'm too lazy to type `getter`.
764
+ getMap() {
765
+ if (this.mapIsBuilt) {
766
+ return this.map;
767
+ }
768
+ if (this.headersInit != null) {
769
+ if (Array.isArray(this.headersInit)) {
770
+ this.map = new Map(this.headersInit);
771
+ }
772
+ else if (isHeadersLike(this.headersInit)) {
773
+ this.headersInit.forEach((value, key) => {
722
774
  this.map.set(key, value);
723
775
  });
724
776
  }
725
777
  else {
726
- for (const initKey in headersInit) {
727
- const initValue = headersInit[initKey];
778
+ for (const initKey in this.headersInit) {
779
+ const initValue = this.headersInit[initKey];
728
780
  if (initValue != null) {
729
781
  const normalizedValue = Array.isArray(initValue) ? initValue.join(', ') : initValue;
730
782
  const normalizedKey = initKey.toLowerCase();
@@ -733,39 +785,48 @@ class PonyfillHeaders {
733
785
  }
734
786
  }
735
787
  }
788
+ this.mapIsBuilt = true;
789
+ return this.map;
736
790
  }
737
791
  append(name, value) {
738
792
  const key = name.toLowerCase();
739
- const existingValue = this.map.get(key);
793
+ const existingValue = this.getMap().get(key);
740
794
  const finalValue = existingValue ? `${existingValue}, ${value}` : value;
741
- this.map.set(key, finalValue);
795
+ this.getMap().set(key, finalValue);
742
796
  }
743
797
  get(name) {
744
798
  const key = name.toLowerCase();
745
- return this.map.get(key) || null;
799
+ const value = this._get(key);
800
+ if (value == null) {
801
+ return null;
802
+ }
803
+ if (Array.isArray(value)) {
804
+ return value.join(', ');
805
+ }
806
+ return value;
746
807
  }
747
808
  has(name) {
748
809
  const key = name.toLowerCase();
749
- return this.map.has(key);
810
+ return !!this._get(key); // we might need to check if header exists and not just check if it's not nullable
750
811
  }
751
812
  set(name, value) {
752
813
  const key = name.toLowerCase();
753
- this.map.set(key, value);
814
+ this.getMap().set(key, value);
754
815
  }
755
816
  delete(name) {
756
817
  const key = name.toLowerCase();
757
- this.map.delete(key);
818
+ this.getMap().delete(key);
758
819
  }
759
820
  forEach(callback) {
760
- this.map.forEach((value, key) => {
821
+ this.getMap().forEach((value, key) => {
761
822
  callback(value, key, this);
762
823
  });
763
824
  }
764
825
  entries() {
765
- return this.map.entries();
826
+ return this.getMap().entries();
766
827
  }
767
828
  [Symbol.iterator]() {
768
- return this.map.entries();
829
+ return this.getMap().entries();
769
830
  }
770
831
  }
771
832
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whatwg-node/node-fetch",
3
- "version": "0.0.6-alpha-20230207114030-349e836",
3
+ "version": "0.0.7-alpha-20230208145746-08ecb64",
4
4
  "description": "Fetch API implementation for Node",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {