@whatwg-node/node-fetch 0.1.0 → 0.2.0-alpha-20230210093840-06aaaf0

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/URL.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ import FastUrl from "fast-url-parser";
2
+ import { PonyfillURLSearchParams } from "./URLSearchParams";
3
+ export declare class PonyfillURL extends FastUrl implements URL {
4
+ constructor(url: string, base?: string | URL);
5
+ get origin(): string;
6
+ private _searchParams?;
7
+ get searchParams(): PonyfillURLSearchParams;
8
+ get username(): string;
9
+ set username(value: string);
10
+ get password(): string;
11
+ set password(value: string);
12
+ toString(): string;
13
+ toJSON(): string;
14
+ }
@@ -0,0 +1,17 @@
1
+ export declare class PonyfillURLSearchParams implements URLSearchParams {
2
+ private params;
3
+ constructor(init?: string | string[][] | Record<string, string> | URLSearchParams);
4
+ append(name: string, value: string): void;
5
+ delete(name: string): void;
6
+ get(name: string): string | null;
7
+ getAll(name: string): string[];
8
+ has(name: string): boolean;
9
+ set(name: string, value: string): void;
10
+ sort(): void;
11
+ toString(): string;
12
+ keys(): IterableIterator<string>;
13
+ entries(): IterableIterator<[string, string]>;
14
+ values(): IterableIterator<string>;
15
+ [Symbol.iterator](): IterableIterator<[string, string]>;
16
+ forEach(callback: (value: string, key: string, parent: URLSearchParams) => void): void;
17
+ }
package/index.d.ts CHANGED
@@ -11,3 +11,5 @@ export { PonyfillAbortSignal as AbortSignal } from './AbortSignal';
11
11
  export { PonyfillAbortError as AbortError } from './AbortError';
12
12
  export { PonyfillBlob as Blob } from './Blob';
13
13
  export { PonyfillTextEncoder as TextEncoder, PonyfillTextDecoder as TextDecoder, PonyfillBtoa as btoa, } from './TextEncoderDecoder';
14
+ export { PonyfillURL as URL } from './URL';
15
+ export { PonyfillURLSearchParams as URLSearchParams } from './URLSearchParams';
package/index.js CHANGED
@@ -11,6 +11,8 @@ const stream = require('stream');
11
11
  const url = require('url');
12
12
  const events = require('@whatwg-node/events');
13
13
  const busboy = _interopDefault(require('busboy'));
14
+ const FastUrl = _interopDefault(require('fast-url-parser'));
15
+ const FastQuerystring = _interopDefault(require('fast-querystring'));
14
16
 
15
17
  // Will be removed after v14 reaches EOL
16
18
  class PonyfillAbortError extends Error {
@@ -797,7 +799,7 @@ function processBodyInit(bodyInit) {
797
799
  },
798
800
  };
799
801
  }
800
- if (bodyInit instanceof URLSearchParams) {
802
+ if ('sort' in bodyInit) {
801
803
  const contentType = 'application/x-www-form-urlencoded;charset=UTF-8';
802
804
  return {
803
805
  bodyType: BodyInitType.String,
@@ -907,7 +909,7 @@ class PonyfillRequest extends PonyfillBody {
907
909
  if (typeof input === 'string') {
908
910
  url = input;
909
911
  }
910
- else if (input instanceof URL) {
912
+ else if ('href' in input) {
911
913
  url = input.toString();
912
914
  }
913
915
  else if (isRequest(input)) {
@@ -1028,6 +1030,150 @@ class PonyfillResponse extends PonyfillBody {
1028
1030
  }
1029
1031
  }
1030
1032
 
1033
+ class PonyfillURLSearchParams {
1034
+ constructor(init) {
1035
+ if (init) {
1036
+ if (typeof init === 'string') {
1037
+ this.params = FastQuerystring.parse(init);
1038
+ }
1039
+ else if (Array.isArray(init)) {
1040
+ this.params = {};
1041
+ for (const [key, value] of init) {
1042
+ this.params[key] = value;
1043
+ }
1044
+ }
1045
+ else if ('entries' in init) {
1046
+ this.params = {};
1047
+ for (const [key, value] of init.entries()) {
1048
+ this.params[key] = value;
1049
+ }
1050
+ }
1051
+ else {
1052
+ this.params = init;
1053
+ }
1054
+ }
1055
+ else {
1056
+ this.params = {};
1057
+ }
1058
+ }
1059
+ append(name, value) {
1060
+ const existingValue = this.params[name];
1061
+ const finalValue = existingValue ? `${existingValue},${value}` : value;
1062
+ this.params[name] = finalValue;
1063
+ }
1064
+ delete(name) {
1065
+ delete this.params[name];
1066
+ }
1067
+ get(name) {
1068
+ const value = this.params[name];
1069
+ if (Array.isArray(value)) {
1070
+ return value[0] || null;
1071
+ }
1072
+ return value || null;
1073
+ }
1074
+ getAll(name) {
1075
+ const value = this.params[name];
1076
+ if (!Array.isArray(value)) {
1077
+ return value ? [value] : [];
1078
+ }
1079
+ return value;
1080
+ }
1081
+ has(name) {
1082
+ return name in this.params;
1083
+ }
1084
+ set(name, value) {
1085
+ this.params[name] = value;
1086
+ }
1087
+ sort() {
1088
+ const sortedKeys = Object.keys(this.params).sort();
1089
+ const sortedParams = {};
1090
+ for (const key of sortedKeys) {
1091
+ sortedParams[key] = this.params[key];
1092
+ }
1093
+ this.params = sortedParams;
1094
+ }
1095
+ toString() {
1096
+ return FastQuerystring.stringify(this.params);
1097
+ }
1098
+ *keys() {
1099
+ for (const key in this.params) {
1100
+ yield key;
1101
+ }
1102
+ }
1103
+ *entries() {
1104
+ for (const key in this.keys()) {
1105
+ const value = this.params[key];
1106
+ if (Array.isArray(value)) {
1107
+ for (const item of value) {
1108
+ yield [key, item];
1109
+ }
1110
+ }
1111
+ yield [key, value];
1112
+ }
1113
+ }
1114
+ *values() {
1115
+ for (const [, value] of this) {
1116
+ yield value;
1117
+ }
1118
+ }
1119
+ [Symbol.iterator]() {
1120
+ return this.entries();
1121
+ }
1122
+ forEach(callback) {
1123
+ for (const [key, value] of this) {
1124
+ callback(value, key, this);
1125
+ }
1126
+ }
1127
+ }
1128
+
1129
+ FastUrl.queryString = FastQuerystring;
1130
+ class PonyfillURL extends FastUrl {
1131
+ constructor(url, base) {
1132
+ super();
1133
+ if (url.startsWith('data:')) {
1134
+ this.protocol = 'data:';
1135
+ this.pathname = url.slice('data:'.length);
1136
+ return;
1137
+ }
1138
+ this.parse(url, false);
1139
+ if (base) {
1140
+ const baseParsed = typeof base === 'string' ? new PonyfillURL(base) : base;
1141
+ this.protocol = this.protocol || baseParsed.protocol;
1142
+ this.host = this.host || baseParsed.host;
1143
+ this.pathname = this.pathname || baseParsed.pathname;
1144
+ }
1145
+ }
1146
+ get origin() {
1147
+ return `${this.protocol}//${this.host}`;
1148
+ }
1149
+ get searchParams() {
1150
+ if (!this._searchParams) {
1151
+ this._searchParams = new PonyfillURLSearchParams(this.query);
1152
+ }
1153
+ return this._searchParams;
1154
+ }
1155
+ get username() {
1156
+ var _a;
1157
+ return ((_a = this.auth) === null || _a === void 0 ? void 0 : _a.split(':')[0]) || '';
1158
+ }
1159
+ set username(value) {
1160
+ this.auth = `${value}:${this.password}`;
1161
+ }
1162
+ get password() {
1163
+ var _a;
1164
+ return ((_a = this.auth) === null || _a === void 0 ? void 0 : _a.split(':')[1]) || '';
1165
+ }
1166
+ set password(value) {
1167
+ this.auth = `${this.username}:${value}`;
1168
+ }
1169
+ toString() {
1170
+ return this.format();
1171
+ }
1172
+ toJSON() {
1173
+ return this.toString();
1174
+ }
1175
+ }
1176
+
1031
1177
  function getResponseForFile(url$1) {
1032
1178
  const path = url.fileURLToPath(url$1);
1033
1179
  const readable = fs.createReadStream(path);
@@ -1044,14 +1190,14 @@ function getRequestFnForProtocol(protocol) {
1044
1190
  }
1045
1191
  const BASE64_SUFFIX = ';base64';
1046
1192
  function fetchPonyfill(info, init) {
1047
- if (typeof info === 'string' || info instanceof URL) {
1193
+ if (typeof info === 'string' || 'href' in info) {
1048
1194
  const ponyfillRequest = new PonyfillRequest(info, init);
1049
1195
  return fetchPonyfill(ponyfillRequest);
1050
1196
  }
1051
1197
  const fetchRequest = info;
1052
1198
  return new Promise((resolve, reject) => {
1053
1199
  try {
1054
- const url = new URL(fetchRequest.url, 'http://localhost');
1200
+ const url = new PonyfillURL(fetchRequest.url, 'http://localhost');
1055
1201
  if (url.protocol === 'data:') {
1056
1202
  const [mimeType = 'text/plain', ...datas] = url.pathname.split(',');
1057
1203
  const data = decodeURIComponent(datas.join(','));
@@ -1077,7 +1223,7 @@ function fetchPonyfill(info, init) {
1077
1223
  return;
1078
1224
  }
1079
1225
  if (url.protocol === 'file:') {
1080
- const response = getResponseForFile(url);
1226
+ const response = getResponseForFile(fetchRequest.url);
1081
1227
  resolve(response);
1082
1228
  return;
1083
1229
  }
@@ -1094,7 +1240,7 @@ function fetchPonyfill(info, init) {
1094
1240
  reject(new PonyfillAbortError(reason));
1095
1241
  };
1096
1242
  fetchRequest.signal.addEventListener('abort', abortListener);
1097
- const nodeRequest = requestFn(url, {
1243
+ const nodeRequest = requestFn(fetchRequest.url, {
1098
1244
  // signal: fetchRequest.signal will be added when v14 reaches EOL
1099
1245
  method: fetchRequest.method,
1100
1246
  headers: nodeHeaders,
@@ -1108,7 +1254,7 @@ function fetchPonyfill(info, init) {
1108
1254
  return;
1109
1255
  }
1110
1256
  if (fetchRequest.redirect === 'follow') {
1111
- const redirectedUrl = new URL(nodeResponse.headers.location, url);
1257
+ const redirectedUrl = new PonyfillURL(nodeResponse.headers.location, url);
1112
1258
  const redirectResponse$ = fetchPonyfill(redirectedUrl, info);
1113
1259
  resolve(redirectResponse$.then(redirectResponse => {
1114
1260
  redirectResponse.redirected = true;
@@ -1188,5 +1334,7 @@ exports.Request = PonyfillRequest;
1188
1334
  exports.Response = PonyfillResponse;
1189
1335
  exports.TextDecoder = PonyfillTextDecoder;
1190
1336
  exports.TextEncoder = PonyfillTextEncoder;
1337
+ exports.URL = PonyfillURL;
1338
+ exports.URLSearchParams = PonyfillURLSearchParams;
1191
1339
  exports.btoa = PonyfillBtoa;
1192
1340
  exports.fetch = fetchPonyfill;
package/index.mjs CHANGED
@@ -5,6 +5,8 @@ import { Readable } from 'stream';
5
5
  import { fileURLToPath } from 'url';
6
6
  import { EventTarget, CustomEvent } from '@whatwg-node/events';
7
7
  import busboy from 'busboy';
8
+ import FastUrl from 'fast-url-parser';
9
+ import FastQuerystring from 'fast-querystring';
8
10
 
9
11
  // Will be removed after v14 reaches EOL
10
12
  class PonyfillAbortError extends Error {
@@ -791,7 +793,7 @@ function processBodyInit(bodyInit) {
791
793
  },
792
794
  };
793
795
  }
794
- if (bodyInit instanceof URLSearchParams) {
796
+ if ('sort' in bodyInit) {
795
797
  const contentType = 'application/x-www-form-urlencoded;charset=UTF-8';
796
798
  return {
797
799
  bodyType: BodyInitType.String,
@@ -901,7 +903,7 @@ class PonyfillRequest extends PonyfillBody {
901
903
  if (typeof input === 'string') {
902
904
  url = input;
903
905
  }
904
- else if (input instanceof URL) {
906
+ else if ('href' in input) {
905
907
  url = input.toString();
906
908
  }
907
909
  else if (isRequest(input)) {
@@ -1022,6 +1024,150 @@ class PonyfillResponse extends PonyfillBody {
1022
1024
  }
1023
1025
  }
1024
1026
 
1027
+ class PonyfillURLSearchParams {
1028
+ constructor(init) {
1029
+ if (init) {
1030
+ if (typeof init === 'string') {
1031
+ this.params = FastQuerystring.parse(init);
1032
+ }
1033
+ else if (Array.isArray(init)) {
1034
+ this.params = {};
1035
+ for (const [key, value] of init) {
1036
+ this.params[key] = value;
1037
+ }
1038
+ }
1039
+ else if ('entries' in init) {
1040
+ this.params = {};
1041
+ for (const [key, value] of init.entries()) {
1042
+ this.params[key] = value;
1043
+ }
1044
+ }
1045
+ else {
1046
+ this.params = init;
1047
+ }
1048
+ }
1049
+ else {
1050
+ this.params = {};
1051
+ }
1052
+ }
1053
+ append(name, value) {
1054
+ const existingValue = this.params[name];
1055
+ const finalValue = existingValue ? `${existingValue},${value}` : value;
1056
+ this.params[name] = finalValue;
1057
+ }
1058
+ delete(name) {
1059
+ delete this.params[name];
1060
+ }
1061
+ get(name) {
1062
+ const value = this.params[name];
1063
+ if (Array.isArray(value)) {
1064
+ return value[0] || null;
1065
+ }
1066
+ return value || null;
1067
+ }
1068
+ getAll(name) {
1069
+ const value = this.params[name];
1070
+ if (!Array.isArray(value)) {
1071
+ return value ? [value] : [];
1072
+ }
1073
+ return value;
1074
+ }
1075
+ has(name) {
1076
+ return name in this.params;
1077
+ }
1078
+ set(name, value) {
1079
+ this.params[name] = value;
1080
+ }
1081
+ sort() {
1082
+ const sortedKeys = Object.keys(this.params).sort();
1083
+ const sortedParams = {};
1084
+ for (const key of sortedKeys) {
1085
+ sortedParams[key] = this.params[key];
1086
+ }
1087
+ this.params = sortedParams;
1088
+ }
1089
+ toString() {
1090
+ return FastQuerystring.stringify(this.params);
1091
+ }
1092
+ *keys() {
1093
+ for (const key in this.params) {
1094
+ yield key;
1095
+ }
1096
+ }
1097
+ *entries() {
1098
+ for (const key in this.keys()) {
1099
+ const value = this.params[key];
1100
+ if (Array.isArray(value)) {
1101
+ for (const item of value) {
1102
+ yield [key, item];
1103
+ }
1104
+ }
1105
+ yield [key, value];
1106
+ }
1107
+ }
1108
+ *values() {
1109
+ for (const [, value] of this) {
1110
+ yield value;
1111
+ }
1112
+ }
1113
+ [Symbol.iterator]() {
1114
+ return this.entries();
1115
+ }
1116
+ forEach(callback) {
1117
+ for (const [key, value] of this) {
1118
+ callback(value, key, this);
1119
+ }
1120
+ }
1121
+ }
1122
+
1123
+ FastUrl.queryString = FastQuerystring;
1124
+ class PonyfillURL extends FastUrl {
1125
+ constructor(url, base) {
1126
+ super();
1127
+ if (url.startsWith('data:')) {
1128
+ this.protocol = 'data:';
1129
+ this.pathname = url.slice('data:'.length);
1130
+ return;
1131
+ }
1132
+ this.parse(url, false);
1133
+ if (base) {
1134
+ const baseParsed = typeof base === 'string' ? new PonyfillURL(base) : base;
1135
+ this.protocol = this.protocol || baseParsed.protocol;
1136
+ this.host = this.host || baseParsed.host;
1137
+ this.pathname = this.pathname || baseParsed.pathname;
1138
+ }
1139
+ }
1140
+ get origin() {
1141
+ return `${this.protocol}//${this.host}`;
1142
+ }
1143
+ get searchParams() {
1144
+ if (!this._searchParams) {
1145
+ this._searchParams = new PonyfillURLSearchParams(this.query);
1146
+ }
1147
+ return this._searchParams;
1148
+ }
1149
+ get username() {
1150
+ var _a;
1151
+ return ((_a = this.auth) === null || _a === void 0 ? void 0 : _a.split(':')[0]) || '';
1152
+ }
1153
+ set username(value) {
1154
+ this.auth = `${value}:${this.password}`;
1155
+ }
1156
+ get password() {
1157
+ var _a;
1158
+ return ((_a = this.auth) === null || _a === void 0 ? void 0 : _a.split(':')[1]) || '';
1159
+ }
1160
+ set password(value) {
1161
+ this.auth = `${this.username}:${value}`;
1162
+ }
1163
+ toString() {
1164
+ return this.format();
1165
+ }
1166
+ toJSON() {
1167
+ return this.toString();
1168
+ }
1169
+ }
1170
+
1025
1171
  function getResponseForFile(url) {
1026
1172
  const path = fileURLToPath(url);
1027
1173
  const readable = createReadStream(path);
@@ -1038,14 +1184,14 @@ function getRequestFnForProtocol(protocol) {
1038
1184
  }
1039
1185
  const BASE64_SUFFIX = ';base64';
1040
1186
  function fetchPonyfill(info, init) {
1041
- if (typeof info === 'string' || info instanceof URL) {
1187
+ if (typeof info === 'string' || 'href' in info) {
1042
1188
  const ponyfillRequest = new PonyfillRequest(info, init);
1043
1189
  return fetchPonyfill(ponyfillRequest);
1044
1190
  }
1045
1191
  const fetchRequest = info;
1046
1192
  return new Promise((resolve, reject) => {
1047
1193
  try {
1048
- const url = new URL(fetchRequest.url, 'http://localhost');
1194
+ const url = new PonyfillURL(fetchRequest.url, 'http://localhost');
1049
1195
  if (url.protocol === 'data:') {
1050
1196
  const [mimeType = 'text/plain', ...datas] = url.pathname.split(',');
1051
1197
  const data = decodeURIComponent(datas.join(','));
@@ -1071,7 +1217,7 @@ function fetchPonyfill(info, init) {
1071
1217
  return;
1072
1218
  }
1073
1219
  if (url.protocol === 'file:') {
1074
- const response = getResponseForFile(url);
1220
+ const response = getResponseForFile(fetchRequest.url);
1075
1221
  resolve(response);
1076
1222
  return;
1077
1223
  }
@@ -1088,7 +1234,7 @@ function fetchPonyfill(info, init) {
1088
1234
  reject(new PonyfillAbortError(reason));
1089
1235
  };
1090
1236
  fetchRequest.signal.addEventListener('abort', abortListener);
1091
- const nodeRequest = requestFn(url, {
1237
+ const nodeRequest = requestFn(fetchRequest.url, {
1092
1238
  // signal: fetchRequest.signal will be added when v14 reaches EOL
1093
1239
  method: fetchRequest.method,
1094
1240
  headers: nodeHeaders,
@@ -1102,7 +1248,7 @@ function fetchPonyfill(info, init) {
1102
1248
  return;
1103
1249
  }
1104
1250
  if (fetchRequest.redirect === 'follow') {
1105
- const redirectedUrl = new URL(nodeResponse.headers.location, url);
1251
+ const redirectedUrl = new PonyfillURL(nodeResponse.headers.location, url);
1106
1252
  const redirectResponse$ = fetchPonyfill(redirectedUrl, info);
1107
1253
  resolve(redirectResponse$.then(redirectResponse => {
1108
1254
  redirectResponse.redirected = true;
@@ -1169,4 +1315,4 @@ function PonyfillBtoa(input) {
1169
1315
  return Buffer.from(input, 'binary').toString('base64');
1170
1316
  }
1171
1317
 
1172
- export { PonyfillAbortController as AbortController, PonyfillAbortError as AbortError, PonyfillAbortSignal as AbortSignal, PonyfillBlob as Blob, PonyfillBody as Body, PonyfillFile as File, PonyfillFormData as FormData, PonyfillHeaders as Headers, PonyfillReadableStream as ReadableStream, PonyfillRequest as Request, PonyfillResponse as Response, PonyfillTextDecoder as TextDecoder, PonyfillTextEncoder as TextEncoder, PonyfillBtoa as btoa, fetchPonyfill as fetch };
1318
+ export { PonyfillAbortController as AbortController, PonyfillAbortError as AbortError, PonyfillAbortSignal as AbortSignal, PonyfillBlob as Blob, PonyfillBody as Body, PonyfillFile as File, PonyfillFormData as FormData, PonyfillHeaders as Headers, PonyfillReadableStream as ReadableStream, PonyfillRequest as Request, PonyfillResponse as Response, PonyfillTextDecoder as TextDecoder, PonyfillTextEncoder as TextEncoder, PonyfillURL as URL, PonyfillURLSearchParams as URLSearchParams, PonyfillBtoa as btoa, fetchPonyfill as fetch };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whatwg-node/node-fetch",
3
- "version": "0.1.0",
3
+ "version": "0.2.0-alpha-20230210093840-06aaaf0",
4
4
  "description": "Fetch API implementation for Node",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
@@ -9,6 +9,8 @@
9
9
  "dependencies": {
10
10
  "@whatwg-node/events": "^0.0.2",
11
11
  "busboy": "^1.6.0",
12
+ "fast-querystring": "^1.1.1",
13
+ "fast-url-parser": "^1.1.3",
12
14
  "tslib": "^2.3.1"
13
15
  },
14
16
  "repository": {