BigQuery MCP Server
by takuya0206
Verified
---
description: bun
globs: *.ts
alwaysApply: false
---
<!-- **Note** — The `Bun.file` and `Bun.write` APIs documented on this page are heavily optimized and represent the recommended way to perform file-system tasks using Bun. Existing Node.js projects may use Bun's [nearly complete](mdc:https:/bun.sh/docs/runtime/nodejs-apis#node-fs) implementation of the [`node:fs`](mdc:https:/nodejs.org/api/fs.html) module. -->
**Note** — The `Bun.file` and `Bun.write` APIs documented on this page are heavily optimized and represent the recommended way to perform file-system tasks using Bun. For operations that are not yet available with `Bun.file`, such as `mkdir` or `readdir`, you can use Bun's [nearly complete](mdc:https:/bun.sh/docs/runtime/nodejs-apis#node-fs) implementation of the [`node:fs`](mdc:https:/nodejs.org/api/fs.html) module.
{% /callout %}
Bun provides a set of optimized APIs for reading and writing files.
## Reading files (`Bun.file()`)
`Bun.file(path): BunFile`
Create a `BunFile` instance with the `Bun.file(path)` function. A `BunFile` represents a lazily-loaded file; initializing it does not actually read the file from disk.
```ts
const foo = Bun.file("foo.txt"); // relative to cwd
foo.size; // number of bytes
foo.type; // MIME type
```
The reference conforms to the [`Blob`](mdc:https:/developer.mozilla.org/en-US/docs/Web/API/Blob) interface, so the contents can be read in various formats.
```ts
const foo = Bun.file("foo.txt");
await foo.text(); // contents as a string
await foo.stream(); // contents as ReadableStream
await foo.arrayBuffer(); // contents as ArrayBuffer
await foo.bytes(); // contents as Uint8Array
```
File references can also be created using numerical [file descriptors](mdc:https:/en.wikipedia.org/wiki/File_descriptor) or `file://` URLs.
```ts
Bun.file(1234);
Bun.file(new URL(import.meta.url)); // reference to the current file
```
A `BunFile` can point to a location on disk where a file does not exist.
```ts
const notreal = Bun.file("notreal.txt");
notreal.size; // 0
notreal.type; // "text/plain;charset=utf-8"
const exists = await notreal.exists(); // false
```
The default MIME type is `text/plain;charset=utf-8`, but it can be overridden by passing a second argument to `Bun.file`.
```ts
const notreal = Bun.file("notreal.json", { type: "application/json" });
notreal.type; // => "application/json;charset=utf-8"
```
For convenience, Bun exposes `stdin`, `stdout` and `stderr` as instances of `BunFile`.
```ts
Bun.stdin; // readonly
Bun.stdout;
Bun.stderr;
```
### Deleting files (`file.delete()`)
You can delete a file by calling the `.delete()` function.
```ts
await Bun.file("logs.json").delete()
```
## Writing files (`Bun.write()`)
`Bun.write(destination, data): Promise<number>`
The `Bun.write` function is a multi-tool for writing payloads of all kinds to disk.
The first argument is the `destination` which can have any of the following types:
- `string`: A path to a location on the file system. Use the `"path"` module to manipulate paths.
- `URL`: A `file://` descriptor.
- `BunFile`: A file reference.
The second argument is the data to be written. It can be any of the following:
- `string`
- `Blob` (including `BunFile`)
- `ArrayBuffer` or `SharedArrayBuffer`
- `TypedArray` (`Uint8Array`, et. al.)
- `Response`
All possible permutations are handled using the fastest available system calls on the current platform.
{% details summary="See syscalls" %}
{% table %}
- Output
- Input
- System call
- Platform
---
- file
- file
- copy_file_range
- Linux
---
- file
- pipe
- sendfile
- Linux
---
- pipe
- pipe
- splice
- Linux
---
- terminal
- file
- sendfile
- Linux
---
- terminal
- terminal
- sendfile
- Linux
---
- socket
- file or pipe
- sendfile (if http, not https)
- Linux
---
- file (doesn't exist)
- file (path)
- clonefile
- macOS
---
- file (exists)
- file
- fcopyfile
- macOS
---
- file
- Blob or string
- write
- macOS
---
- file
- Blob or string
- write
- Linux
{% /table %}
{% /details %}
To write a string to disk:
```ts
const data = `It was the best of times, it was the worst of times.`;
await Bun.write("output.txt", data);
```
To copy a file to another location on disk:
```js
const input = Bun.file("input.txt");
const output = Bun.file("output.txt"); // doesn't exist yet!
await Bun.write(output, input);
```
To write a byte array to disk:
```ts
const encoder = new TextEncoder();
const data = encoder.encode("datadatadata"); // Uint8Array
await Bun.write("output.txt", data);
```
To write a file to `stdout`:
```ts
const input = Bun.file("input.txt");
await Bun.write(Bun.stdout, input);
```
To write the body of an HTTP response to disk:
```ts
const response = await fetch("https://bun.sh");
await Bun.write("index.html", response);
```
## Incremental writing with `FileSink`
Bun provides a native incremental file writing API called `FileSink`. To retrieve a `FileSink` instance from a `BunFile`:
```ts
const file = Bun.file("output.txt");
const writer = file.writer();
```
To incrementally write to the file, call `.write()`.
```ts
const file = Bun.file("output.txt");
const writer = file.writer();
writer.write("it was the best of times\n");
writer.write("it was the worst of times\n");
```
These chunks will be buffered internally. To flush the buffer to disk, use `.flush()`. This returns the number of flushed bytes.
```ts
writer.flush(); // write buffer to disk
```
The buffer will also auto-flush when the `FileSink`'s _high water mark_ is reached; that is, when its internal buffer is full. This value can be configured.
```ts
const file = Bun.file("output.txt");
const writer = file.writer({ highWaterMark: 1024 * 1024 }); // 1MB
```
To flush the buffer and close the file:
```ts
writer.end();
```
Note that, by default, the `bun` process will stay alive until this `FileSink` is explicitly closed with `.end()`. To opt out of this behavior, you can "unref" the instance.
```ts
writer.unref();
// to "re-ref" it later
writer.ref();
```
## Directories
Bun's implementation of `node:fs` is fast, and we haven't implemented a Bun-specific API for reading directories just yet. For now, you should use `node:fs` for working with directories in Bun.
### Reading directories (readdir)
To read a directory in Bun, use `readdir` from `node:fs`.
```ts
import { readdir } from "node:fs/promises";
// read all the files in the current directory
const files = await readdir(import.meta.dir);
```
#### Reading directories recursively
To recursively read a directory in Bun, use `readdir` with `recursive: true`.
```ts
import { readdir } from "node:fs/promises";
// read all the files in the current directory, recursively
const files = await readdir("../", { recursive: true });
```
### Creating directories (mkdir)
To recursively create a directory, use `mkdir` in `node:fs`:
```ts
import { mkdir } from "node:fs/promises";
await mkdir("path/to/dir", { recursive: true });
```
## Benchmarks
The following is a 3-line implementation of the Linux `cat` command.
```ts#cat.ts
// Usage
// $ bun ./cat.ts ./path-to-file
import { resolve } from "path";
const path = resolve(process.argv.at(-1));
await Bun.write(Bun.stdout, Bun.file(path));
```
To run the file:
```bash
$ bun ./cat.ts ./path-to-file
```
It runs 2x faster than GNU `cat` for large files on Linux.
{% image src="/images/cat.jpg" /%}
## Reference
```ts
interface Bun {
stdin: BunFile;
stdout: BunFile;
stderr: BunFile;
file(path: string | number | URL, options?: { type?: string }): BunFile;
write(
destination: string | number | BunFile | URL,
input:
| string
| Blob
| ArrayBuffer
| SharedArrayBuffer
| TypedArray
| Response,
): Promise<number>;
}
interface BunFile {
readonly size: number;
readonly type: string;
text(): Promise<string>;
stream(): ReadableStream;
arrayBuffer(): Promise<ArrayBuffer>;
json(): Promise<any>;
writer(params: { highWaterMark?: number }): FileSink;
exists(): Promise<boolean>;
}
export interface FileSink {
write(
chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
): number;
flush(): number | Promise<number>;
end(error?: Error): number | Promise<number>;
start(options?: { highWaterMark?: number }): void;
ref(): void;
unref(): void;
}
```