1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
import type * as s from "stream";
const { Headers, Request, Response: WebResponse, Blob, File = Blob, FormData } = globalThis as any;
const nativeFetch = Bun.fetch;
const { Readable } = require("node:stream");
class Response extends WebResponse {
_body: any;
get body() {
return this._body ?? (this._body = Readable.fromWeb(super.body));
}
}
/**
* `node-fetch` works like the browser-fetch API, except it's a little more strict on some features,
* and uses node streams instead of web streams.
*
* It's overall a positive on speed to override the implementation, since most people will use something
* like `.json()` or `.text()`, which is faster in Bun's native fetch, vs `node-fetch` going
* through `node:http`, a node stream, then processing the data.
*/
async function fetch(url: any, init?: RequestInit & { body?: any }) {
// input node stream -> web stream
let body: s.Readable | undefined = init?.body;
if (body) {
const chunks: any = [];
if (body instanceof Readable) {
// TODO: Bun fetch() doesn't support ReadableStream at all.
for await (const chunk of body) {
chunks.push(chunk);
}
init = { ...init, body: new Blob(chunks) };
}
}
const response = await nativeFetch(url, init);
Object.setPrototypeOf(response, Response.prototype);
return response;
}
class AbortError extends DOMException {
constructor(message) {
super(message, "AbortError");
}
}
class FetchBaseError extends Error {
type: string;
constructor(message, type) {
super(message);
this.type = type;
}
}
class FetchError extends FetchBaseError {
constructor(message, type, systemError) {
super(message, type);
this.code = systemError?.code;
}
}
function blobFrom(path, options) {
return Promise.resolve(Bun.file(path, options));
}
function blobFromSync(path, options) {
return Bun.file(path, options);
}
var fileFrom = blobFrom;
var fileFromSync = blobFromSync;
function isRedirect(code) {
return code === 301 || code === 302 || code === 303 || code === 307 || code === 308;
}
export default Object.assign(fetch, {
AbortError,
Blob,
FetchBaseError,
FetchError,
File,
FormData,
Headers,
Request,
Response,
blobFrom,
blobFromSync,
fileFrom,
fileFromSync,
isRedirect,
fetch,
default: fetch,
});
|