@whatwg-node/fetch 0.5.4 → 0.5.5-alpha-20221230080146-72104f6

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/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @whatwg-node/fetch
2
2
 
3
+ ## 0.5.5-alpha-20221230080146-72104f6
4
+
5
+ ### Patch Changes
6
+
7
+ - [#154](https://github.com/ardatan/whatwg-node/pull/154) [`d7ef0c8`](https://github.com/ardatan/whatwg-node/commit/d7ef0c8fdf806f168e2814c596ad7b7b5653318f) Thanks [@ardatan](https://github.com/ardatan)! - dependencies updates:
8
+
9
+ - Added dependency [`@whatwg-node/node-fetch@0.0.0` ↗︎](https://www.npmjs.com/package/@whatwg-node/node-fetch/v/0.0.0) (to `dependencies`)
10
+ - Removed dependency [`abort-controller@^3.0.0` ↗︎](https://www.npmjs.com/package/abort-controller/v/3.0.0) (from `dependencies`)
11
+ - Removed dependency [`form-data-encoder@^1.7.1` ↗︎](https://www.npmjs.com/package/form-data-encoder/v/1.7.1) (from `dependencies`)
12
+ - Removed dependency [`formdata-node@^4.3.1` ↗︎](https://www.npmjs.com/package/formdata-node/v/4.3.1) (from `dependencies`)
13
+ - Removed dependency [`node-fetch@^2.6.7` ↗︎](https://www.npmjs.com/package/node-fetch/v/2.6.7) (from `dependencies`)
14
+ - Removed dependency [`undici@^5.12.0` ↗︎](https://www.npmjs.com/package/undici/v/5.12.0) (from `dependencies`)
15
+ - Removed dependency [`web-streams-polyfill@^3.2.0` ↗︎](https://www.npmjs.com/package/web-streams-polyfill/v/3.2.0) (from `dependencies`)
16
+
17
+ - [#154](https://github.com/ardatan/whatwg-node/pull/154) [`d7ef0c8`](https://github.com/ardatan/whatwg-node/commit/d7ef0c8fdf806f168e2814c596ad7b7b5653318f) Thanks [@ardatan](https://github.com/ardatan)! - New Fetch API implementation for Node
18
+
19
+ - Updated dependencies [[`d7ef0c8`](https://github.com/ardatan/whatwg-node/commit/d7ef0c8fdf806f168e2814c596ad7b7b5653318f)]:
20
+ - @whatwg-node/node-fetch@0.0.1-alpha-20221230080146-72104f6
21
+
3
22
  ## 0.5.4
4
23
 
5
24
  ### Patch Changes
@@ -1,7 +1,3 @@
1
- const http2 = require('http2')
2
- const handleFileRequest = require("./handle-file-request");
3
- const readableStreamToReadable = require("./readableStreamToReadable");
4
-
5
1
  module.exports = function createNodePonyfill(opts = {}) {
6
2
 
7
3
  // Bun already has a Fetch API
@@ -9,74 +5,49 @@ module.exports = function createNodePonyfill(opts = {}) {
9
5
  return globalThis;
10
6
  }
11
7
 
12
- const ponyfills = {};
13
-
14
- if (!opts.useNodeFetch) {
15
- ponyfills.fetch = globalThis.fetch;
16
- ponyfills.Headers = globalThis.Headers;
17
- ponyfills.Request = globalThis.Request;
18
- ponyfills.Response = globalThis.Response;
19
- ponyfills.FormData = globalThis.FormData;
20
- ponyfills.File = globalThis.File;
21
- }
22
-
23
- ponyfills.AbortController = globalThis.AbortController;
24
- ponyfills.ReadableStream = globalThis.ReadableStream;
25
- ponyfills.WritableStream = globalThis.WritableStream;
26
- ponyfills.TransformStream = globalThis.TransformStream;
27
- ponyfills.Blob = globalThis.Blob;
28
- ponyfills.crypto = globalThis.crypto;
29
-
30
- if (!ponyfills.AbortController) {
31
- const abortControllerModule = require("abort-controller");
32
- ponyfills.AbortController =
33
- abortControllerModule.default || abortControllerModule;
34
- }
8
+ const newNodeFetch = require('@whatwg-node/node-fetch');
35
9
 
36
- if (!ponyfills.Blob) {
37
- const bufferModule = require('buffer')
38
- ponyfills.Blob = bufferModule.Blob;
39
- }
40
-
41
- if (!ponyfills.Blob) {
42
- const formDataModule = require("formdata-node");
43
- ponyfills.Blob = formDataModule.Blob
44
- }
45
-
46
- if (!ponyfills.ReadableStream) {
47
- try {
48
- const streamsWeb = require("stream/web");
10
+ const ponyfills = {};
49
11
 
50
- ponyfills.ReadableStream = streamsWeb.ReadableStream;
51
- ponyfills.WritableStream = streamsWeb.WritableStream;
52
- ponyfills.TransformStream = streamsWeb.TransformStream;
53
- } catch (e) {
54
- const streamsWeb = require("web-streams-polyfill/ponyfill");
55
- ponyfills.ReadableStream = streamsWeb.ReadableStream;
56
- ponyfills.WritableStream = streamsWeb.WritableStream;
57
- ponyfills.TransformStream = streamsWeb.TransformStream;
12
+ ponyfills.AbortController = newNodeFetch.AbortController;
13
+ ponyfills.AbortError = newNodeFetch.AbortError;
14
+ ponyfills.AbortSignal = newNodeFetch.AbortSignal;
15
+ ponyfills.Blob = newNodeFetch.Blob;
16
+ ponyfills.Body = newNodeFetch.Body;
17
+ ponyfills.fetch = newNodeFetch.fetch;
18
+ ponyfills.File = newNodeFetch.File;
19
+ ponyfills.FormData = newNodeFetch.FormData;
20
+ ponyfills.Headers = newNodeFetch.Headers;
21
+ ponyfills.ReadableStream = newNodeFetch.ReadableStream;
22
+ ponyfills.Request = newNodeFetch.Request;
23
+ ponyfills.Response = newNodeFetch.Response;
24
+ ponyfills.TextEncoder = newNodeFetch.TextEncoder;
25
+ ponyfills.TextDecoder = newNodeFetch.TextDecoder;
26
+ ponyfills.btoa = newNodeFetch.btoa;
27
+
28
+ if (opts.formDataLimits) {
29
+ ponyfills.Body = class Body extends newNodeFetch.Body {
30
+ constructor(body, userOpts) {
31
+ super(body, {
32
+ formDataLimits: opts.formDataLimits,
33
+ ...userOpts,
34
+ });
35
+ }
58
36
  }
59
- }
60
-
61
- ponyfills.btoa = globalThis.btoa
62
- if (!ponyfills.btoa) {
63
- ponyfills.btoa = function btoa(data) {
64
- return Buffer.from(data, 'binary').toString('base64');
65
- };
66
- }
67
-
68
- ponyfills.TextEncoder = function TextEncoder(encoding = 'utf-8') {
69
- return {
70
- encode(str) {
71
- return Buffer.from(str, encoding);
37
+ ponyfills.Request = class Request extends newNodeFetch.Request {
38
+ constructor(input, userOpts) {
39
+ super(input, {
40
+ formDataLimits: opts.formDataLimits,
41
+ ...userOpts,
42
+ });
72
43
  }
73
44
  }
74
- }
75
-
76
- ponyfills.TextDecoder = function TextDecoder(encoding = 'utf-8') {
77
- return {
78
- decode(buf) {
79
- return Buffer.from(buf).toString(encoding);
45
+ ponyfills.Response = class Response extends newNodeFetch.Response {
46
+ constructor(body, userOpts) {
47
+ super(body, {
48
+ formDataLimits: opts.formDataLimits,
49
+ ...userOpts,
50
+ });
80
51
  }
81
52
  }
82
53
  }
@@ -91,255 +62,5 @@ module.exports = function createNodePonyfill(opts = {}) {
91
62
  ponyfills.crypto = new cryptoPonyfill.Crypto();
92
63
  }
93
64
 
94
- // If any of classes of Fetch API is missing, we need to ponyfill them.
95
- if (!ponyfills.fetch ||
96
- !ponyfills.Request ||
97
- !ponyfills.Headers ||
98
- !ponyfills.Response ||
99
- !ponyfills.FormData ||
100
- !ponyfills.File ||
101
- opts.useNodeFetch) {
102
-
103
- const [
104
- nodeMajorStr,
105
- nodeMinorStr
106
- ] = process.versions.node.split('.');
107
-
108
- const nodeMajor = parseInt(nodeMajorStr);
109
- const nodeMinor = parseInt(nodeMinorStr);
110
- const getFormDataMethod = require('./getFormDataMethod');
111
-
112
- if (!opts.useNodeFetch && (nodeMajor > 16 || (nodeMajor === 16 && nodeMinor >= 5))) {
113
- const undici = require("undici");
114
-
115
- if (!ponyfills.Headers) {
116
- ponyfills.Headers = undici.Headers;
117
- }
118
-
119
- const streams = require("stream");
120
-
121
- const OriginalRequest = ponyfills.Request || undici.Request;
122
-
123
- class Request extends OriginalRequest {
124
- constructor(requestOrUrl, options) {
125
- if (typeof requestOrUrl === "string" || requestOrUrl instanceof URL) {
126
- if (options != null && typeof options === "object" && !options.duplex) {
127
- options.duplex = 'half';
128
- }
129
- super(requestOrUrl, options);
130
- const contentType = this.headers.get("content-type");
131
- if (contentType && contentType.startsWith("multipart/form-data")) {
132
- this.headers.set("content-type", contentType.split(', ')[0]);
133
- }
134
- } else {
135
- super(requestOrUrl);
136
- }
137
- this.formData = getFormDataMethod(undici.File, opts.formDataLimits);
138
- }
139
- }
140
-
141
- ponyfills.Request = Request;
142
-
143
- const originalFetch = ponyfills.fetch || undici.fetch;
144
-
145
- const fetch = function (requestOrUrl, options) {
146
- if (typeof requestOrUrl === "string" || requestOrUrl instanceof URL) {
147
- if (options != null && typeof options === "object" && !options.duplex) {
148
- options.duplex = 'half';
149
- }
150
- // We cannot use our ctor because it leaks on Node 18's global fetch
151
- return originalFetch(requestOrUrl, options);
152
- }
153
- if (requestOrUrl.url.startsWith('file:')) {
154
- return handleFileRequest(requestOrUrl.url, ponyfills.Response);
155
- }
156
- return originalFetch(requestOrUrl);
157
- };
158
-
159
- ponyfills.fetch = fetch;
160
-
161
- if (!ponyfills.Response) {
162
- ponyfills.Response = undici.Response;
163
- }
164
-
165
- if (!ponyfills.FormData) {
166
- ponyfills.FormData = undici.FormData;
167
- }
168
-
169
- if (!ponyfills.File) {
170
- ponyfills.File = undici.File
171
- }
172
- } else {
173
- const nodeFetch = require("node-fetch");
174
- const realFetch = ponyfills.fetch || nodeFetch.default || nodeFetch;
175
- if (!ponyfills.Headers) {
176
- ponyfills.Headers = nodeFetch.Headers;
177
- // Sveltekit
178
- if (globalThis.Headers && nodeMajor < 18) {
179
- Object.defineProperty(globalThis.Headers, Symbol.hasInstance, {
180
- value(obj) {
181
- return obj && obj.get && obj.set && obj.delete && obj.has && obj.append;
182
- },
183
- configurable: true,
184
- })
185
- }
186
- }
187
- const formDataEncoderModule = require("form-data-encoder");
188
- const streams = require("stream");
189
- const formDataModule = require("formdata-node");
190
- if (!ponyfills.FormData) {
191
- ponyfills.FormData = formDataModule.FormData
192
- }
193
- if (!ponyfills.File) {
194
- ponyfills.File = formDataModule.File
195
- }
196
-
197
- const OriginalRequest = ponyfills.Request || nodeFetch.Request;
198
-
199
- class Request extends OriginalRequest {
200
- constructor(requestOrUrl, options) {
201
- if (typeof requestOrUrl === "string" || requestOrUrl instanceof URL) {
202
- // Support schemaless URIs on the server for parity with the browser.
203
- // Ex: //github.com/ -> https://github.com/
204
- if (/^\/\//.test(requestOrUrl.toString())) {
205
- requestOrUrl = "https:" + requestOrUrl.toString();
206
- }
207
- let method = (options || {}).method;
208
- const headers = {};
209
- if ('headers' in (options || {})) {
210
- let isHttp2 = false;
211
- for (const [key, value] of Object.entries(options.headers)) {
212
- if (key.startsWith(':')) {
213
- // omit http2 headers
214
- isHttp2 = true;
215
- } else {
216
- headers[key] = value
217
- }
218
- }
219
- if (isHttp2) {
220
- // translate http2 if applicable
221
- method = options.headers[http2.constants.HTTP2_HEADER_METHOD];
222
- const scheme = options.headers[http2.constants.HTTP2_HEADER_SCHEME];
223
- const authority = options.headers[http2.constants.HTTP2_HEADER_AUTHORITY];
224
- const path = options.headers[http2.constants.HTTP2_HEADER_PATH];
225
- headers.host = authority;
226
- requestOrUrl = `${scheme}://${authority}${path}`
227
- }
228
- }
229
- const fixedOptions = {
230
- ...options,
231
- method,
232
- headers,
233
- };
234
- fixedOptions.headers = new ponyfills.Headers(fixedOptions.headers || {});
235
- fixedOptions.headers.set('Connection', 'keep-alive');
236
- if (fixedOptions.body != null) {
237
- if (fixedOptions.body[Symbol.toStringTag] === 'FormData') {
238
- const encoder = new formDataEncoderModule.FormDataEncoder(fixedOptions.body)
239
- for (const headerKey in encoder.headers) {
240
- fixedOptions.headers.set(headerKey, encoder.headers[headerKey])
241
- }
242
- fixedOptions.body = streams.Readable.from(encoder);
243
- } else if (fixedOptions.body[Symbol.toStringTag] === 'ReadableStream') {
244
- fixedOptions.body = readableStreamToReadable(fixedOptions.body);
245
- }
246
- }
247
- super(requestOrUrl, fixedOptions);
248
- } else {
249
- super(requestOrUrl);
250
- }
251
- this.formData = getFormDataMethod(formDataModule.File, opts.formDataLimits);
252
- }
253
- }
254
- ponyfills.Request = Request;
255
- const fetch = function (requestOrUrl, options) {
256
- if (typeof requestOrUrl === "string" || requestOrUrl instanceof URL) {
257
- return fetch(new Request(requestOrUrl, options));
258
- }
259
- if (requestOrUrl.url.startsWith('file:')) {
260
- return handleFileRequest(requestOrUrl.url, ponyfills.Response);
261
- }
262
- const abortCtrl = new ponyfills.AbortController();
263
-
264
- return realFetch(requestOrUrl, {
265
- ...options,
266
- signal: abortCtrl.signal
267
- }).then(res => {
268
- return new Proxy(res, {
269
- get(target, prop, receiver) {
270
- if (prop === 'body') {
271
- return new Proxy(res.body, {
272
- get(target, prop, receiver) {
273
- if (prop === Symbol.asyncIterator) {
274
- return () => {
275
- const originalAsyncIterator = target[Symbol.asyncIterator]();
276
- return {
277
- next() {
278
- return originalAsyncIterator.next();
279
- },
280
- return() {
281
- abortCtrl.abort();
282
- return originalAsyncIterator.return();
283
- },
284
- throw(error) {
285
- abortCtrl.abort(error);
286
- return originalAsyncIterator.throw(error);
287
- }
288
- }
289
- }
290
- }
291
- return Reflect.get(target, prop, receiver);
292
- }
293
- })
294
- }
295
- return Reflect.get(target, prop, receiver);
296
- }
297
- })
298
- });
299
- };
300
-
301
- ponyfills.fetch = fetch;
302
-
303
- const OriginalResponse = ponyfills.Response || nodeFetch.Response;
304
- ponyfills.Response = function Response(body, init) {
305
- if (body != null && body[Symbol.toStringTag] === 'ReadableStream') {
306
- const actualBody = readableStreamToReadable(body);
307
- // Polyfill ReadableStream is not working well with node-fetch's Response
308
- return new OriginalResponse(actualBody, init);
309
- }
310
- return new OriginalResponse(body, init);
311
- };
312
-
313
- }
314
- }
315
-
316
- if (!ponyfills.Response.redirect) {
317
- ponyfills.Response.redirect = function (url, status = 302) {
318
- return new ponyfills.Response(null, {
319
- status,
320
- headers: {
321
- Location: url,
322
- },
323
- });
324
- };
325
- }
326
- if (!ponyfills.Response.json) {
327
- ponyfills.Response.json = function (data, init = {}) {
328
- return new ponyfills.Response(JSON.stringify(data), {
329
- ...init,
330
- headers: {
331
- "Content-Type": "application/json",
332
- ...init.headers,
333
- },
334
- });
335
- };
336
- }
337
- if (!ponyfills.Response.error) {
338
- ponyfills.Response.error = function () {
339
- return new ponyfills.Response(null, {
340
- status: 500,
341
- });
342
- };
343
- }
344
65
  return ponyfills;
345
66
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whatwg-node/fetch",
3
- "version": "0.5.4",
3
+ "version": "0.5.5-alpha-20221230080146-72104f6",
4
4
  "description": "Cross Platform Smart Fetch Ponyfill",
5
5
  "author": "Arda TANRIKULU <ardatanrikulu@gmail.com>",
6
6
  "repository": {
@@ -19,13 +19,8 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "@peculiar/webcrypto": "^1.4.0",
22
- "abort-controller": "^3.0.0",
23
- "busboy": "^1.6.0",
24
- "form-data-encoder": "^1.7.1",
25
- "formdata-node": "^4.3.1",
26
- "node-fetch": "^2.6.7",
27
- "undici": "^5.12.0",
28
- "web-streams-polyfill": "^3.2.0"
22
+ "@whatwg-node/node-fetch": "0.0.1-alpha-20221230080146-72104f6",
23
+ "busboy": "^1.6.0"
29
24
  },
30
25
  "publishConfig": {
31
26
  "access": "public"
@@ -1,36 +1,58 @@
1
- import { createTestContainer } from '../../server/test/create-test-container';
1
+ import * as fetchAPI from '@whatwg-node/fetch';
2
2
 
3
3
  describe('getFormDataMethod', () => {
4
- createTestContainer(fetchAPI => {
5
- it('should parse fields correctly', async () => {
6
- const formData = new fetchAPI.FormData();
7
- formData.append('greetings', 'Hello world!');
8
- formData.append('bye', 'Goodbye world!');
9
- const request = new fetchAPI.Request('http://localhost:8080', {
10
- method: 'POST',
11
- body: formData,
12
- });
13
- const formdata = await request.formData();
14
- expect(formdata.get('greetings')).toBe('Hello world!');
15
- expect(formdata.get('bye')).toBe('Goodbye world!');
4
+ it('should parse fields correctly', async () => {
5
+ const formData = new fetchAPI.FormData();
6
+ formData.append('greetings', 'Hello world!');
7
+ formData.append('bye', 'Goodbye world!');
8
+ const request = new fetchAPI.Request('http://localhost:8080', {
9
+ method: 'POST',
10
+ body: formData,
16
11
  });
17
- it('should parse and receive text files correctly', async () => {
18
- const formData = new fetchAPI.FormData();
19
- const greetingsFile = new fetchAPI.File(['Hello world!'], 'greetings.txt', { type: 'text/plain' });
20
- const byeFile = new fetchAPI.File(['Goodbye world!'], 'bye.txt', { type: 'text/plain' });
21
- formData.append('greetings', greetingsFile);
22
- formData.append('bye', byeFile);
23
- const request = new fetchAPI.Request('http://localhost:8080', {
24
- method: 'POST',
25
- body: formData,
26
- });
27
- const formdata = await request.formData();
28
- const receivedGreetingsFile = formdata.get('greetings') as File;
29
- const receivedGreetingsText = await receivedGreetingsFile.text();
30
- expect(receivedGreetingsText).toBe('Hello world!');
31
- const receivedByeFile = formdata.get('bye') as File;
32
- const receivedByeText = await receivedByeFile.text();
33
- expect(receivedByeText).toBe('Goodbye world!');
12
+ const formdata = await request.formData();
13
+ expect(formdata.get('greetings')).toBe('Hello world!');
14
+ expect(formdata.get('bye')).toBe('Goodbye world!');
15
+ });
16
+ it('should parse and receive text files correctly', async () => {
17
+ const formData = new fetchAPI.FormData();
18
+ const greetingsFile = new fetchAPI.File(['Hello world!'], 'greetings.txt', { type: 'text/plain' });
19
+ const byeFile = new fetchAPI.File(['Goodbye world!'], 'bye.txt', { type: 'text/plain' });
20
+ formData.append('greetings', greetingsFile);
21
+ formData.append('bye', byeFile);
22
+ const request = new fetchAPI.Request('http://localhost:8080', {
23
+ method: 'POST',
24
+ body: formData,
25
+ });
26
+ const formdata = await request.formData();
27
+ const receivedGreetingsFile = formdata.get('greetings') as File;
28
+ const receivedGreetingsText = await receivedGreetingsFile.text();
29
+ expect(receivedGreetingsText).toBe('Hello world!');
30
+ const receivedByeFile = formdata.get('bye') as File;
31
+ const receivedByeText = await receivedByeFile.text();
32
+ expect(receivedByeText).toBe('Goodbye world!');
33
+ });
34
+ it('should handle file limits', async () => {
35
+ const limitedFetchAPI = fetchAPI.createFetch({
36
+ formDataLimits: {
37
+ fileSize: 1,
38
+ },
39
+ });
40
+ const formData = new limitedFetchAPI.FormData();
41
+ const greetingsFile = new limitedFetchAPI.File(['Hello world!'], 'greetings.txt', { type: 'text/plain' });
42
+ formData.append('greetings', greetingsFile);
43
+ const proxyRequest = new limitedFetchAPI.Request('http://localhost:8080', {
44
+ method: 'POST',
45
+ body: formData,
46
+ });
47
+ const formDataInText = await proxyRequest.text();
48
+ const contentType = proxyRequest.headers.get('content-type')!;
49
+ const requestWillParse = new limitedFetchAPI.Request('http://localhost:8080', {
50
+ method: 'POST',
51
+ body: formDataInText,
52
+ headers: {
53
+ 'content-type': contentType,
54
+ },
34
55
  });
56
+ await expect(() => requestWillParse.formData()).rejects.toThrowError('File size limit exceeded: 1 bytes');
35
57
  });
36
58
  });
@@ -1,65 +0,0 @@
1
- const busboy = require('busboy');
2
- const { resolve } = require('path');
3
- const streams = require("stream");
4
-
5
- module.exports = function getFormDataMethod(File, limits) {
6
-
7
- return function formData() {
8
- if (this.body == null) {
9
- return null;
10
- }
11
- const contentType = this.headers.get('Content-Type');
12
- const nodeReadable = this.body.on ? this.body : streams.Readable.from(this.body);
13
- const bb = busboy({
14
- headers: {
15
- 'content-type': contentType
16
- },
17
- limits,
18
- defParamCharset: 'utf-8'
19
- });
20
- return new Promise((resolve, reject) => {
21
- const formData = new Map();
22
- bb.on('field', (name, value, { nameTruncated, valueTruncated }) => {
23
- if (nameTruncated) {
24
- reject(new Error(`Field name size exceeded: ${limits.fieldNameSize} bytes`));
25
- }
26
- if (valueTruncated) {
27
- reject(new Error(`Field value size exceeded: ${limits.fieldSize} bytes`));
28
- }
29
- formData.set(name, value)
30
- })
31
- bb.on('fieldsLimit', () => {
32
- reject(new Error(`Fields limit exceeded: ${limits.fields}`));
33
- })
34
- bb.on('file', (name, fileStream, { filename, mimeType }) => {
35
- const chunks = [];
36
- fileStream.on('limit', () => {
37
- reject(new Error(`File size limit exceeded: ${limits.fileSize} bytes`));
38
- })
39
- fileStream.on('data', (chunk) => {
40
- chunks.push(Buffer.from(chunk));
41
- })
42
- fileStream.on('close', () => {
43
- if (fileStream.truncated) {
44
- reject(new Error(`File size limit exceeded: ${limits.fileSize} bytes`));
45
- }
46
- const file = new File(chunks, filename, { type: mimeType });
47
- formData.set(name, file);
48
- });
49
- })
50
- bb.on('filesLimit', () => {
51
- reject(new Error(`Files limit exceeded: ${limits.files}`));
52
- })
53
- bb.on('partsLimit', () => {
54
- reject(new Error(`Parts limit exceeded: ${limits.parts}`));
55
- })
56
- bb.on('close', () => {
57
- resolve(formData);
58
- });
59
- bb.on('error', err => {
60
- reject(err);
61
- })
62
- nodeReadable.pipe(bb);
63
- })
64
- }
65
- }
@@ -1,7 +0,0 @@
1
- const { fileURLToPath } = require('url');
2
- const { createReadStream } = require('fs');
3
- module.exports = function handleFileRequest(url, Response) {
4
- return new Response(
5
- createReadStream(fileURLToPath(url)),
6
- )
7
- }
@@ -1,26 +0,0 @@
1
- const streams = require('stream');
2
-
3
- module.exports = function readableStreamToReadable(readableStream) {
4
- const reader = readableStream.getReader();
5
- return new streams.Readable({
6
- read() {
7
- reader.read().then(({ done, value }) => {
8
- if (done) {
9
- this.push(null);
10
- } else {
11
- this.push(value);
12
- }
13
- })
14
- },
15
- async destroy(err, callback) {
16
- try {
17
- reader.cancel();
18
- reader.releaseLock();
19
- await readableStream.cancel();
20
- callback();
21
- } catch (error) {
22
- callback(error);
23
- }
24
- }
25
- })
26
- }