@whatwg-node/fetch 0.3.2 → 0.4.0
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 +8 -0
- package/dist/create-node-ponyfill.js +5 -0
- package/dist/getFormDataMethod.js +75 -16
- package/dist/index.d.ts +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @whatwg-node/fetch
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`005937c`](https://github.com/ardatan/whatwg-node/commit/005937c72749dfa3914c8b6193a88c772a522275) Thanks [@ardatan](https://github.com/ardatan)! - feat(fetch): new `fieldsFirst` option to allow async stream consumption for multipart forms
|
|
8
|
+
|
|
9
|
+
- [`effc03d`](https://github.com/ardatan/whatwg-node/commit/effc03d58793328595183ac7cd5c9abab95dec17) Thanks [@ardatan](https://github.com/ardatan)! - Bun Support
|
|
10
|
+
|
|
3
11
|
## 0.3.2
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
|
@@ -2,6 +2,11 @@ const handleFileRequest = require("./handle-file-request");
|
|
|
2
2
|
|
|
3
3
|
module.exports = function createNodePonyfill(opts = {}) {
|
|
4
4
|
|
|
5
|
+
// Bun already has a Fetch API
|
|
6
|
+
if (process.versions.bun) {
|
|
7
|
+
return globalThis;
|
|
8
|
+
}
|
|
9
|
+
|
|
5
10
|
const ponyfills = {};
|
|
6
11
|
|
|
7
12
|
if (!opts.useNodeFetch) {
|
|
@@ -1,7 +1,35 @@
|
|
|
1
1
|
const busboy = require('busboy');
|
|
2
|
+
const { resolve } = require('path');
|
|
2
3
|
const streams = require("stream");
|
|
3
4
|
|
|
4
5
|
module.exports = function getFormDataMethod(File, limits) {
|
|
6
|
+
function consumeStreamAsFile({
|
|
7
|
+
name,
|
|
8
|
+
filename,
|
|
9
|
+
mimeType,
|
|
10
|
+
fileStream,
|
|
11
|
+
formData,
|
|
12
|
+
}) {
|
|
13
|
+
if (fileStream._consumedAsFile) {
|
|
14
|
+
return Promise.resolve(formData.get(name));
|
|
15
|
+
}
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const chunks = [];
|
|
18
|
+
fileStream.on('limit', () => {
|
|
19
|
+
reject(new Error(`File size limit exceeded: ${limits.fileSize} bytes`));
|
|
20
|
+
})
|
|
21
|
+
fileStream.on('data', (chunk) => {
|
|
22
|
+
chunks.push(chunk);
|
|
23
|
+
})
|
|
24
|
+
fileStream.on('close', () => {
|
|
25
|
+
const file = new File(chunks, filename, { type: mimeType });
|
|
26
|
+
formData.set(name, file);
|
|
27
|
+
fileStream._consumedAsFile = true;
|
|
28
|
+
resolve(file);
|
|
29
|
+
});
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
|
|
5
33
|
return function formData() {
|
|
6
34
|
if (this.body == null) {
|
|
7
35
|
return null;
|
|
@@ -17,18 +45,6 @@ module.exports = function getFormDataMethod(File, limits) {
|
|
|
17
45
|
});
|
|
18
46
|
return new Promise((resolve, reject) => {
|
|
19
47
|
const formData = new Map();
|
|
20
|
-
bb.on('file', (name, fileStream, { filename, mimeType }) => {
|
|
21
|
-
const chunks = [];
|
|
22
|
-
fileStream.on('limit', () => {
|
|
23
|
-
reject(new Error(`File size limit exceeded: ${limits.fileSize} bytes`));
|
|
24
|
-
})
|
|
25
|
-
fileStream.on('data', (chunk) => {
|
|
26
|
-
chunks.push(chunk);
|
|
27
|
-
})
|
|
28
|
-
fileStream.on('close', () => {
|
|
29
|
-
formData.set(name, new File(chunks, filename, { type: mimeType }));
|
|
30
|
-
});
|
|
31
|
-
})
|
|
32
48
|
bb.on('field', (name, value, { nameTruncated, valueTruncated }) => {
|
|
33
49
|
if (nameTruncated) {
|
|
34
50
|
reject(new Error(`Field name size exceeded: ${limits.fieldNameSize} bytes`));
|
|
@@ -38,14 +54,57 @@ module.exports = function getFormDataMethod(File, limits) {
|
|
|
38
54
|
}
|
|
39
55
|
formData.set(name, value)
|
|
40
56
|
})
|
|
41
|
-
bb.on('
|
|
42
|
-
reject(new Error(`
|
|
57
|
+
bb.on('fieldsLimit', () => {
|
|
58
|
+
reject(new Error(`Fields limit exceeded: ${limits.fields}`));
|
|
59
|
+
})
|
|
60
|
+
bb.on('file', (name, fileStream, { filename, mimeType }) => {
|
|
61
|
+
if (limits.fieldsFirst) {
|
|
62
|
+
resolve(formData);
|
|
63
|
+
const fakeFileObj = {
|
|
64
|
+
name: filename,
|
|
65
|
+
type: mimeType,
|
|
66
|
+
}
|
|
67
|
+
Object.setPrototypeOf(fakeFileObj, File.prototype);
|
|
68
|
+
formData.set(name, new Proxy(fakeFileObj, {
|
|
69
|
+
get: (target, prop) => {
|
|
70
|
+
switch(prop) {
|
|
71
|
+
case 'name':
|
|
72
|
+
return filename;
|
|
73
|
+
case 'type':
|
|
74
|
+
return mimeType;
|
|
75
|
+
case 'stream':
|
|
76
|
+
return () => fileStream;
|
|
77
|
+
case 'size':
|
|
78
|
+
throw new Error(`Cannot access file size before consuming the stream.`);
|
|
79
|
+
case 'slice':
|
|
80
|
+
throw new Error(`Cannot slice file before consuming the stream.`);
|
|
81
|
+
case 'text':
|
|
82
|
+
case 'arrayBuffer':
|
|
83
|
+
return () => consumeStreamAsFile({
|
|
84
|
+
name,
|
|
85
|
+
filename,
|
|
86
|
+
mimeType,
|
|
87
|
+
fileStream,
|
|
88
|
+
formData,
|
|
89
|
+
}).then(file => file[prop]())
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
}))
|
|
93
|
+
} else {
|
|
94
|
+
consumeStreamAsFile({
|
|
95
|
+
name,
|
|
96
|
+
filename,
|
|
97
|
+
mimeType,
|
|
98
|
+
fileStream,
|
|
99
|
+
formData,
|
|
100
|
+
}).catch(err => reject(err));
|
|
101
|
+
}
|
|
43
102
|
})
|
|
44
103
|
bb.on('filesLimit', () => {
|
|
45
104
|
reject(new Error(`Files limit exceeded: ${limits.files}`));
|
|
46
105
|
})
|
|
47
|
-
bb.on('
|
|
48
|
-
reject(new Error(`
|
|
106
|
+
bb.on('partsLimit', () => {
|
|
107
|
+
reject(new Error(`Parts limit exceeded: ${limits.parts}`));
|
|
49
108
|
})
|
|
50
109
|
bb.on('close', () => {
|
|
51
110
|
resolve(formData);
|
package/dist/index.d.ts
CHANGED
|
@@ -51,6 +51,8 @@ declare module "@whatwg-node/fetch" {
|
|
|
51
51
|
parts?: number;
|
|
52
52
|
/* For multipart forms, the max number of header key-value pairs to parse. Default: 2000. */
|
|
53
53
|
headerSize?: number;
|
|
54
|
+
/* For multipart forms, enable this if your data has fields first, then files. Default: false. */
|
|
55
|
+
fieldsFirst?: boolean;
|
|
54
56
|
}
|
|
55
57
|
export const createFetch: (opts?: { useNodeFetch?: boolean; formDataLimits?: FormDataLimits }) => ({
|
|
56
58
|
fetch: typeof _fetch,
|