Use Bun.write for zero-dependency file output
Published August 6, 2027
import { write } from "bun";
export const saveJsonReport = (path: string, report: Record<string, unknown>) =>
write(path, JSON.stringify(report, null, 2) + "\n");
export const mirrorResponseToDisk = async (url: string, path: string) => {
const response = await fetch(url);
return write(path, response);
};
export const overwriteExistingConfig = (path: string, contents: string) =>
write(path, contents, { createPath: false });What
Bun.write(destination, data) is Bun's single function for writing a string, a Blob/BunFile, a TypedArray, an ArrayBuffer, or a fetch Response body straight to a file — no node:fs boilerplate, no third-party file-writing package.
Why it matters
In Node, writing a file means picking the right function for what you're writing — writeFile for a buffer or string, manual stream piping for a fetch response body — and importing node:fs/promises to get there. Bun.write collapses that into one function that inspects what you handed it and picks the fastest way to write it, choosing platform-specific system calls (like copy_file_range on Linux or clonefile on macOS) when the source is itself a file. mirrorResponseToDisk below is the clearest example: handing write a Response directly streams the body to disk as it arrives, without a single line of manual stream-piping code.
How it works
saveJsonReportwrites a string — the simplest case, and the onenode:fs'swriteFilealso covers, included here as the baseline.mirrorResponseToDiskawaits afetch()call and passes the resultingResponsestraight towrite. Bun reads the response body and writes it to disk incrementally, which matters once the response is larger than you'd want to hold fully in memory first.overwriteExistingConfigpasses{ createPath: false }— the options object everywritecall accepts as a third argument alongside destination and data.- Every
write()call returnsPromise<number>— the byte count actually written, useful for verifying a write matched the expected size or just for logging.
Gotchas
write()creates missing parent directories by default (createPath: true, since Bun v1.0.16) — a typo'd path silently creates a new directory tree instead of failing loudly. Pass{ createPath: false }wherever a missing directory should be an error, not a silentmkdir -p, asoverwriteExistingConfigdoes.- Passing a
Responsefrom a failed request still writes whatever body came back —write()doesn't checkresponse.ok. Check the status before writing if a 404 error page shouldn't end up saved as your file. write()overwrites the destination with no confirmation by default — there's no separate "fail if exists" flag the waynode:fs/promises'cphas witherrorOnExist. Check for existence first, via aBunFile's.exists(), if that matters.
Related
Bun.file()— the read-side counterpart; returns a lazily-openedBunFilethat can be passed right back intowrite()as a source.node:fs/promises'cp— for directory-level copies rather than single-file or stream writes; a different tool for an adjacent problem.