# Bun > ## Documentation Index --- # Source: https://bun.com/docs/guides/install/add-dev.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Add a development dependency To add an npm package as a development dependency, use `bun add --development`. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun add zod --dev bun add zod -d # shorthand ``` *** This will add the package to `devDependencies` in `package.json`. ```json theme={"theme":{"light":"github-light","dark":"dracula"}} { "devDependencies": { "zod": "^3.0.0" // [!code ++] } } ``` *** See [Docs > Package manager](/pm/cli/install) for complete documentation of Bun's package manager. --- # Source: https://bun.com/docs/guides/install/add-git.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Add a Git dependency Bun supports directly adding GitHub repositories as dependencies of your project. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun add github:lodash/lodash ``` *** This will add the following line to your `package.json`: ```json package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} { "dependencies": { "lodash": "github:lodash/lodash" } } ``` *** Bun supports a number of protocols for specifying Git dependencies. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun add git+https://github.com/lodash/lodash.git bun add git+ssh://github.com/lodash/lodash.git#4.17.21 bun add git@github.com:lodash/lodash.git bun add github:colinhacks/zod ``` **Note:** GitHub dependencies download via HTTP tarball when possible for faster installation. *** See [Docs > Package manager](/pm/cli/install) for complete documentation of Bun's package manager. --- # Source: https://bun.com/docs/guides/install/add-optional.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Add an optional dependency To add an npm package as an optional dependency, use the `--optional` flag. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun add zod --optional ``` *** This will add the package to `optionalDependencies` in `package.json`. ```json package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} { "optionalDependencies": { "zod": "^3.0.0" // [!code ++] } } ``` *** See [Docs > Package manager](/pm/cli/install) for complete documentation of Bun's package manager. --- # Source: https://bun.com/docs/guides/install/add-peer.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Add a peer dependency To add an npm package as a peer dependency, use the `--peer` flag. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun add @types/bun --peer ``` *** This will add the package to `peerDependencies` in `package.json`. ```json package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} { "peerDependencies": { "@types/bun": "^1.3.3" // [!code ++] } } ``` *** Running `bun install` will install peer dependencies by default, unless marked optional in `peerDependenciesMeta`. ```json package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} { "peerDependencies": { "@types/bun": "^1.3.3" }, "peerDependenciesMeta": { "@types/bun": { // [!code ++] "optional": true // [!code ++] } // [!code ++] } } ``` *** See [Docs > Package manager](/pm/cli/install) for complete documentation of Bun's package manager. --- # Source: https://bun.com/docs/guides/install/add-tarball.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Add a tarball dependency Bun's package manager can install any publicly available tarball URL as a dependency of your project. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun add zod@https://registry.npmjs.org/zod/-/zod-3.21.4.tgz ``` *** Running this command will download, extract, and install the tarball to your project's `node_modules` directory. It will also add the following line to your `package.json`: ```json package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} { "dependencies": { "zod": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz" // [!code ++] } } ``` *** The package `"zod"` can now be imported as usual. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} import { z } from "zod"; ``` *** See [Docs > Package manager](/pm/cli/install) for complete documentation of Bun's package manager. --- # Source: https://bun.com/docs/pm/cli/add.md # Source: https://bun.com/docs/guides/install/add.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Add a dependency To add an npm package as a dependency, use `bun add`. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun add zod ``` *** This will add the package to `dependencies` in `package.json`. By default, the `^` range specifier will be used, to indicate that any future minor or patch versions are acceptable. ```json package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} { "dependencies": { "zod": "^3.0.0" // [!code ++] } } ``` *** To "pin" to an exact version of the package, use `--exact`. This will add the package to `dependencies` without the `^`, pinning your project to the exact version you installed. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun add zod --exact ``` *** To specify an exact version or a tag: ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun add zod@3.0.0 bun add zod@next ``` *** See [Docs > Package manager](/pm/cli/install) for complete documentation of Bun's package manager. --- # Source: https://bun.com/docs/guides/write-file/append.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Append content to a file Bun implements the `node:fs` module, which includes the `fs.appendFile` and `fs.appendFileSync` functions for appending content to files. *** You can use `fs.appendFile` to asynchronously append data to a file, creating the file if it does not yet exist. The content can be a string or a `Buffer`. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} import { appendFile } from "node:fs/promises"; await appendFile("message.txt", "data to append"); ``` *** To use the non-`Promise` API: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} import { appendFile } from "node:fs"; appendFile("message.txt", "data to append", err => { if (err) throw err; console.log('The "data to append" was appended to file!'); }); ``` *** To specify the encoding of the content: ```js theme={"theme":{"light":"github-light","dark":"dracula"}} import { appendFile } from "node:fs"; appendFile("message.txt", "data to append", "utf8", callback); ``` *** To append the data synchronously, use `fs.appendFileSync`: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} import { appendFileSync } from "node:fs"; appendFileSync("message.txt", "data to append", "utf8"); ``` *** See the [Node.js documentation](https://nodejs.org/api/fs.html#fspromisesappendfilepath-data-options) for more information. --- # Source: https://bun.com/docs/runtime/archive.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Archive > Create and extract tar archives with Bun's fast native implementation Bun provides a fast, native implementation for working with tar archives through `Bun.Archive`. It supports creating archives from in-memory data, extracting archives to disk, and reading archive contents without extraction. ## Quickstart **Create an archive from files:** ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const archive = new Bun.Archive({ "hello.txt": "Hello, World!", "data.json": JSON.stringify({ foo: "bar" }), "nested/file.txt": "Nested content", }); // Write to disk await Bun.write("bundle.tar", archive); ``` **Extract an archive:** ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const tarball = await Bun.file("package.tar.gz").bytes(); const archive = new Bun.Archive(tarball); const entryCount = await archive.extract("./output"); console.log(`Extracted ${entryCount} entries`); ``` **Read archive contents without extracting:** ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const tarball = await Bun.file("package.tar.gz").bytes(); const archive = new Bun.Archive(tarball); const files = await archive.files(); for (const [path, file] of files) { console.log(`${path}: ${await file.text()}`); } ``` ## Creating Archives Use `new Bun.Archive()` to create an archive from an object where keys are file paths and values are file contents. By default, archives are uncompressed: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // Creates an uncompressed tar archive (default) const archive = new Bun.Archive({ "README.md": "# My Project", "src/index.ts": "console.log('Hello');", "package.json": JSON.stringify({ name: "my-project" }), }); ``` File contents can be: * **Strings** - Text content * **Blobs** - Binary data * **ArrayBufferViews** (e.g., `Uint8Array`) - Raw bytes * **ArrayBuffers** - Raw binary data ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const data = "binary data"; const arrayBuffer = new ArrayBuffer(8); const archive = new Bun.Archive({ "text.txt": "Plain text", "blob.bin": new Blob([data]), "bytes.bin": new Uint8Array([1, 2, 3, 4]), "buffer.bin": arrayBuffer, }); ``` ### Writing Archives to Disk Use `Bun.write()` to write an archive to disk: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // Write uncompressed tar (default) const archive = new Bun.Archive({ "file1.txt": "content1", "file2.txt": "content2", }); await Bun.write("output.tar", archive); // Write gzipped tar const compressed = new Bun.Archive({ "src/index.ts": "console.log('Hello');" }, { compress: "gzip" }); await Bun.write("output.tar.gz", compressed); ``` ### Getting Archive Bytes Get the archive data as bytes or a Blob: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const archive = new Bun.Archive({ "hello.txt": "Hello, World!" }); // As Uint8Array const bytes = await archive.bytes(); // As Blob const blob = await archive.blob(); // With gzip compression (set at construction) const gzipped = new Bun.Archive({ "hello.txt": "Hello, World!" }, { compress: "gzip" }); const gzippedBytes = await gzipped.bytes(); const gzippedBlob = await gzipped.blob(); ``` ## Extracting Archives ### From Existing Archive Data Create an archive from existing tar/tar.gz data: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // From a file const tarball = await Bun.file("package.tar.gz").bytes(); const archiveFromFile = new Bun.Archive(tarball); ``` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // From a fetch response const response = await fetch("https://example.com/archive.tar.gz"); const archiveFromFetch = new Bun.Archive(await response.blob()); ``` ### Extracting to Disk Use `.extract()` to write all files to a directory: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const tarball = await Bun.file("package.tar.gz").bytes(); const archive = new Bun.Archive(tarball); const count = await archive.extract("./extracted"); console.log(`Extracted ${count} entries`); ``` The target directory is created automatically if it doesn't exist. Existing files are overwritten. The returned count includes files, directories, and symlinks (on POSIX systems). **Note**: On Windows, symbolic links in archives are always skipped during extraction. Bun does not attempt to create them regardless of privilege level. On Linux and macOS, symlinks are extracted normally. **Security note**: Bun.Archive validates paths during extraction, rejecting absolute paths (POSIX `/`, Windows drive letters like `C:\` or `C:/`, and UNC paths like `\\server\share`). Path traversal components (`..`) are normalized away (e.g., `dir/sub/../file` becomes `dir/file`) to prevent directory escape attacks. ### Filtering Extracted Files Use glob patterns to extract only specific files. Patterns are matched against archive entry paths normalized to use forward slashes (`/`). Positive patterns specify what to include, and negative patterns (prefixed with `!`) specify what to exclude. Negative patterns are applied after positive patterns, so **using only negative patterns will match nothing** (you must include a positive pattern like `**` first): ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const tarball = await Bun.file("package.tar.gz").bytes(); const archive = new Bun.Archive(tarball); // Extract only TypeScript files const tsCount = await archive.extract("./extracted", { glob: "**/*.ts" }); // Extract files from multiple directories const multiCount = await archive.extract("./extracted", { glob: ["src/**", "lib/**"], }); ``` Use negative patterns (prefixed with `!`) to exclude files. When mixing positive and negative patterns, entries must match at least one positive pattern and not match any negative pattern: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // Extract everything except node_modules const distCount = await archive.extract("./extracted", { glob: ["**", "!node_modules/**"], }); // Extract source files but exclude tests const srcCount = await archive.extract("./extracted", { glob: ["src/**", "!**/*.test.ts", "!**/__tests__/**"], }); ``` ## Reading Archive Contents ### Get All Files Use `.files()` to get archive contents as a `Map` of `File` objects without extracting to disk. Unlike `extract()` which processes all entry types, `files()` returns only regular files (no directories): ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const tarball = await Bun.file("package.tar.gz").bytes(); const archive = new Bun.Archive(tarball); const files = await archive.files(); for (const [path, file] of files) { console.log(`${path}: ${file.size} bytes`); console.log(await file.text()); } ``` Each `File` object includes: * `name` - The file path within the archive (always uses forward slashes `/` as separators) * `size` - File size in bytes * `lastModified` - Modification timestamp * Standard `Blob` methods: `text()`, `arrayBuffer()`, `stream()`, etc. **Note**: `files()` loads file contents into memory. For large archives, consider using `extract()` to write directly to disk instead. ### Error Handling Archive operations can fail due to corrupted data, I/O errors, or invalid paths. Use try/catch to handle these cases: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} try { const tarball = await Bun.file("package.tar.gz").bytes(); const archive = new Bun.Archive(tarball); const count = await archive.extract("./output"); console.log(`Extracted ${count} entries`); } catch (e: unknown) { if (e instanceof Error) { const error = e as Error & { code?: string }; if (error.code === "EACCES") { console.error("Permission denied"); } else if (error.code === "ENOSPC") { console.error("Disk full"); } else { console.error("Archive error:", error.message); } } else { console.error("Archive error:", String(e)); } } ``` Common error scenarios: * **Corrupted/truncated archives** - `new Archive()` loads the archive data; errors may be deferred until read/extract operations * **Permission denied** - `extract()` throws if the target directory is not writable * **Disk full** - `extract()` throws if there's insufficient space * **Invalid paths** - Operations throw for malformed file paths The count returned by `extract()` includes all successfully written entries (files, directories, and symlinks on POSIX systems). **Security note**: Bun.Archive automatically validates paths during extraction. Absolute paths (POSIX `/`, Windows drive letters, UNC paths) and unsafe symlink targets are rejected. Path traversal components (`..`) are normalized away to prevent directory escape. For additional security with untrusted archives, you can enumerate and validate paths before extraction: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const archive = new Bun.Archive(untrustedData); const files = await archive.files(); // Optional: Custom validation for additional checks for (const [path] of files) { // Example: Reject hidden files if (path.startsWith(".") || path.includes("/.")) { throw new Error(`Hidden file rejected: ${path}`); } // Example: Whitelist specific directories if (!path.startsWith("src/") && !path.startsWith("lib/")) { throw new Error(`Unexpected path: ${path}`); } } // Extract to a controlled destination await archive.extract("./safe-output"); ``` When using `files()` with a glob pattern, an empty `Map` is returned if no files match: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const matches = await archive.files("*.nonexistent"); if (matches.size === 0) { console.log("No matching files found"); } ``` ### Filtering with Glob Patterns Pass a glob pattern to filter which files are returned: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // Get only TypeScript files const tsFiles = await archive.files("**/*.ts"); // Get files in src directory const srcFiles = await archive.files("src/*"); // Get all JSON files (recursive) const jsonFiles = await archive.files("**/*.json"); // Get multiple file types with array of patterns const codeFiles = await archive.files(["**/*.ts", "**/*.js"]); ``` Supported glob patterns (subset of [Bun.Glob](/docs/api/glob) syntax): * `*` - Match any characters except `/` * `**` - Match any characters including `/` * `?` - Match single character * `[abc]` - Match character set * `{a,b}` - Match alternatives * `!pattern` - Exclude files matching pattern (negation). Must be combined with positive patterns; using only negative patterns matches nothing. See [Bun.Glob](/docs/api/glob) for the full glob syntax including escaping and advanced patterns. ## Compression Bun.Archive creates uncompressed tar archives by default. Use `{ compress: "gzip" }` to enable gzip compression: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // Default: uncompressed tar const archive = new Bun.Archive({ "hello.txt": "Hello, World!" }); // Reading: automatically detects gzip const gzippedTarball = await Bun.file("archive.tar.gz").bytes(); const readArchive = new Bun.Archive(gzippedTarball); // Enable gzip compression const compressed = new Bun.Archive({ "hello.txt": "Hello, World!" }, { compress: "gzip" }); // Gzip with custom level (1-12) const maxCompression = new Bun.Archive({ "hello.txt": "Hello, World!" }, { compress: "gzip", level: 12 }); ``` The options accept: * No options or `undefined` - Uncompressed tar (default) * `{ compress: "gzip" }` - Enable gzip compression at level 6 * `{ compress: "gzip", level: number }` - Gzip with custom level 1-12 (1 = fastest, 12 = smallest) ## Examples ### Bundle Project Files ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} import { Glob } from "bun"; // Collect source files const files: Record = {}; const glob = new Glob("src/**/*.ts"); for await (const path of glob.scan(".")) { // Normalize path separators to forward slashes for cross-platform compatibility const archivePath = path.replaceAll("\\", "/"); files[archivePath] = await Bun.file(path).text(); } // Add package.json files["package.json"] = await Bun.file("package.json").text(); // Create compressed archive and write to disk const archive = new Bun.Archive(files, { compress: "gzip" }); await Bun.write("bundle.tar.gz", archive); ``` ### Extract and Process npm Package ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const response = await fetch("https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"); const archive = new Bun.Archive(await response.blob()); // Get package.json const files = await archive.files("package/package.json"); const packageJson = files.get("package/package.json"); if (packageJson) { const pkg = JSON.parse(await packageJson.text()); console.log(`Package: ${pkg.name}@${pkg.version}`); } ``` ### Create Archive from Directory ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} import { readdir } from "node:fs/promises"; import { join } from "node:path"; async function archiveDirectory(dir: string, compress = false): Promise { const files: Record = {}; async function walk(currentDir: string, prefix: string = "") { const entries = await readdir(currentDir, { withFileTypes: true }); for (const entry of entries) { const fullPath = join(currentDir, entry.name); const archivePath = prefix ? `${prefix}/${entry.name}` : entry.name; if (entry.isDirectory()) { await walk(fullPath, archivePath); } else { files[archivePath] = Bun.file(fullPath); } } } await walk(dir); return new Bun.Archive(files, compress ? { compress: "gzip" } : undefined); } const archive = await archiveDirectory("./my-project", true); await Bun.write("my-project.tar.gz", archive); ``` ## Reference > **Note**: The following type signatures are simplified for documentation purposes. See [`packages/bun-types/bun.d.ts`](https://github.com/oven-sh/bun/blob/main/packages/bun-types/bun.d.ts) for the full type definitions. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} type ArchiveInput = | Record | Blob | Bun.ArrayBufferView | ArrayBufferLike; type ArchiveOptions = { /** Compression algorithm. Currently only "gzip" is supported. */ compress?: "gzip"; /** Compression level 1-12 (default 6 when gzip is enabled). */ level?: number; }; interface ArchiveExtractOptions { /** Glob pattern(s) to filter extraction. Supports negative patterns with "!" prefix. */ glob?: string | readonly string[]; } class Archive { /** * Create an Archive from input data * @param data - Files to archive (as object) or existing archive data (as bytes/blob) * @param options - Compression options. Uncompressed by default. * Pass { compress: "gzip" } to enable compression. */ constructor(data: ArchiveInput, options?: ArchiveOptions); /** * Extract archive to a directory * @returns Number of entries extracted (files, directories, and symlinks) */ extract(path: string, options?: ArchiveExtractOptions): Promise; /** * Get archive as a Blob (uses compression setting from constructor) */ blob(): Promise; /** * Get archive as a Uint8Array (uses compression setting from constructor) */ bytes(): Promise>; /** * Get archive contents as File objects (regular files only, no directories) */ files(glob?: string | readonly string[]): Promise>; } ``` --- # Source: https://bun.com/docs/guides/process/argv.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Parse command-line arguments The *argument vector* is the list of arguments passed to the program when it is run. It is available as `Bun.argv`. ```ts cli.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} console.log(Bun.argv); ``` *** Running this file with arguments results in the following: ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun run cli.ts --flag1 --flag2 value ``` ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} [ '/path/to/bun', '/path/to/cli.ts', '--flag1', '--flag2', 'value' ] ``` *** To parse `argv` into a more useful format, `util.parseArgs` would be helpful. Example: ```ts cli.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} import { parseArgs } from "util"; const { values, positionals } = parseArgs({ args: Bun.argv, options: { flag1: { type: "boolean", }, flag2: { type: "string", }, }, strict: true, allowPositionals: true, }); console.log(values); console.log(positionals); ``` *** then it outputs ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun run cli.ts --flag1 --flag2 value ``` ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} { flag1: true, flag2: "value", } [ "/path/to/bun", "/path/to/cli.ts" ] ``` --- # Source: https://bun.com/docs/guides/binary/arraybuffer-to-array.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Convert an ArrayBuffer to an array of numbers To retrieve the contents of an `ArrayBuffer` as an array of numbers, create a [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) over of the buffer. and use the [`Array.from()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from) method to convert it to an array. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buf = new ArrayBuffer(64); const arr = new Uint8Array(buf); arr.length; // 64 arr[0]; // 0 (instantiated with all zeros) ``` *** The `Uint8Array` class supports array indexing and iteration. However if you wish to convert the instance to a regular `Array`, use `Array.from()`. (This will likely be slower than using the `Uint8Array` directly.) ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buf = new ArrayBuffer(64); const uintArr = new Uint8Array(buf); const regularArr = Array.from(uintArr); // number[] ``` *** See [Docs > API > Binary Data](/runtime/binary-data#conversion) for complete documentation on manipulating binary data with Bun. --- # Source: https://bun.com/docs/guides/binary/arraybuffer-to-blob.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Convert an ArrayBuffer to a Blob A [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) can be constructed from an array of "chunks", where each chunk is a string, binary data structure, or another `Blob`. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buf = new ArrayBuffer(64); const blob = new Blob([buf]); ``` *** By default the `type` of the resulting `Blob` will be unset. This can be set manually. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buf = new ArrayBuffer(64); const blob = new Blob([buf], { type: "application/octet-stream" }); blob.type; // => "application/octet-stream" ``` *** See [Docs > API > Binary Data](/runtime/binary-data#conversion) for complete documentation on manipulating binary data with Bun. --- # Source: https://bun.com/docs/guides/binary/arraybuffer-to-buffer.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Convert an ArrayBuffer to a Buffer The Node.js [`Buffer`](https://nodejs.org/api/buffer.html) API predates the introduction of `ArrayBuffer` into the JavaScript language. Bun implements both. Use the static `Buffer.from()` method to create a `Buffer` from an `ArrayBuffer`. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const arrBuffer = new ArrayBuffer(64); const nodeBuffer = Buffer.from(arrBuffer); ``` *** To create a `Buffer` that only views a portion of the underlying buffer, pass the offset and length to the constructor. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const arrBuffer = new ArrayBuffer(64); const nodeBuffer = Buffer.from(arrBuffer, 0, 16); // view first 16 bytes ``` *** See [Docs > API > Binary Data](/runtime/binary-data#conversion) for complete documentation on manipulating binary data with Bun. --- # Source: https://bun.com/docs/guides/binary/arraybuffer-to-string.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Convert an ArrayBuffer to a string Bun implements the Web-standard [`TextDecoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder) class for converting between binary data types and strings. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buf = new ArrayBuffer(64); const decoder = new TextDecoder(); const str = decoder.decode(buf); ``` *** See [Docs > API > Binary Data](/runtime/binary-data#conversion) for complete documentation on manipulating binary data with Bun. --- # Source: https://bun.com/docs/guides/binary/arraybuffer-to-typedarray.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Convert an ArrayBuffer to a Uint8Array A `Uint8Array` is a *typed array*, meaning it is a mechanism for viewing the data in an underlying `ArrayBuffer`. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buffer = new ArrayBuffer(64); const arr = new Uint8Array(buffer); ``` *** Instances of other typed arrays can be created similarly. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buffer = new ArrayBuffer(64); const arr1 = new Uint8Array(buffer); const arr2 = new Uint16Array(buffer); const arr3 = new Uint32Array(buffer); const arr4 = new Float32Array(buffer); const arr5 = new Float64Array(buffer); const arr6 = new BigInt64Array(buffer); const arr7 = new BigUint64Array(buffer); ``` *** To create a typed array that only views a portion of the underlying buffer, pass the offset and length to the constructor. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buffer = new ArrayBuffer(64); const arr = new Uint8Array(buffer, 0, 16); // view first 16 bytes ``` *** See [Docs > API > Utils](/runtime/utils) for more useful utilities. --- # Source: https://bun.com/docs/guides/read-file/arraybuffer.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Read a file to an ArrayBuffer The `Bun.file()` function accepts a path and returns a `BunFile` instance. The `BunFile` class extends `Blob` and allows you to lazily read the file in a variety of formats. Use `.arrayBuffer()` to read the file as an `ArrayBuffer`. ```ts index.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const path = "/path/to/package.json"; const file = Bun.file(path); const buffer = await file.arrayBuffer(); ``` *** The binary content in the `ArrayBuffer` can then be read as a typed array, such as `Int8Array`. For `Uint8Array`, use [`.bytes()`](/guides/read-file/uint8array). ```ts index.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const buffer = await file.arrayBuffer(); const bytes = new Int8Array(buffer); bytes[0]; bytes.length; ``` *** Refer to the [Typed arrays](/runtime/binary-data#typedarray) docs for more information on working with typed arrays in Bun. --- # Source: https://bun.com/docs/guides/ecosystem/astro.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Build an app with Astro and Bun Initialize a fresh Astro app with `bun create astro`. The `create-astro` package detects when you are using `bunx` and will automatically install dependencies using `bun`. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun create astro ``` ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} ╭─────╮ Houston: │ ◠ ◡ ◠ We're glad to have you on board. ╰─────╯ astro v3.1.4 Launch sequence initiated. dir Where should we create your new project? ./fumbling-field tmpl How would you like to start your new project? Use blog template ✔ Template copied deps Install dependencies? Yes ✔ Dependencies installed ts Do you plan to write TypeScript? Yes use How strict should TypeScript be? Strict ✔ TypeScript customized git Initialize a new git repository? Yes ✔ Git initialized next Liftoff confirmed. Explore your project! Enter your project directory using cd ./fumbling-field Run `bun run dev` to start the dev server. CTRL+C to stop. Add frameworks like react or tailwind using astro add. Stuck? Join us at https://astro.build/chat ╭─────╮ Houston: │ ◠ ◡ ◠ Good luck out there, astronaut! 🚀 ╰─────╯ ``` *** Start the dev server with `bunx`. By default, Bun will run the dev server with Node.js. To use the Bun runtime instead, use the `--bun` flag. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bunx --bun astro dev ``` ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} 🚀 astro v3.1.4 started in 200ms ┃ Local http://localhost:4321/ ┃ Network use --host to expose ``` *** Open [http://localhost:4321](http://localhost:4321) with your browser to see the result. Astro will hot-reload your app as you edit your source files. *** Refer to the [Astro docs](https://docs.astro.build/en/getting-started/) for complete documentation. --- # Source: https://bun.com/docs/pm/cli/audit.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # bun audit > Check your installed packages for known security vulnerabilities Run the command in a project with a `bun.lock` file: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun audit ``` Bun sends the list of installed packages and versions to NPM, and prints a report of any vulnerabilities that were found. Packages installed from registries other than the default registry are skipped. If no vulnerabilities are found, the command prints: ``` No vulnerabilities found ``` When vulnerabilities are detected, each affected package is listed along with the severity, a short description and a link to the advisory. At the end of the report Bun prints a summary and hints for updating: ``` 3 vulnerabilities (1 high, 2 moderate) To update all dependencies to the latest compatible versions: bun update To update all dependencies to the latest versions (including breaking changes): bun update --latest ``` ### Filtering options **`--audit-level=`** - Only show vulnerabilities at this severity level or higher: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun audit --audit-level=high ``` **`--prod`** - Audit only production dependencies (excludes devDependencies): ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun audit --prod ``` **`--ignore `** - Ignore specific CVEs (can be used multiple times): ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun audit --ignore CVE-2022-25883 --ignore CVE-2023-26136 ``` ### `--json` Use the `--json` flag to print the raw JSON response from the registry instead of the formatted report: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun audit --json ``` ### Exit code `bun audit` will exit with code `0` if no vulnerabilities are found and `1` if the report lists any vulnerabilities. This will still happen even if `--json` is passed. --- # Source: https://bun.com/docs/runtime/auto-install.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Auto-install > Bun's automatic package installation feature for standalone script execution If no `node_modules` directory is found in the working directory or higher, Bun will abandon Node.js-style module resolution in favor of the **Bun module resolution algorithm**. Under Bun-style module resolution, all imported packages are auto-installed on the fly into a [global module cache](/pm/global-cache) during execution (the same cache used by [`bun install`](/pm/cli/install)). ```ts index.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} import { foo } from "foo"; // install `latest` version foo(); ``` The first time you run this script, Bun will auto-install `"foo"` and cache it. The next time you run the script, it will use the cached version. *** ## Version resolution To determine which version to install, Bun follows the following algorithm: 1. Check for a `bun.lock` file in the project root. If it exists, use the version specified in the lockfile. 2. Otherwise, scan up the tree for a `package.json` that includes `"foo"` as a dependency. If found, use the specified semver version or version range. 3. Otherwise, use `latest`. *** ## Cache behavior Once a version or version range has been determined, Bun will: 1. Check the module cache for a compatible version. If one exists, use it. 2. When resolving `latest`, Bun will check if `package@latest` has been downloaded and cached in the last *24 hours*. If so, use it. 3. Otherwise, download and install the appropriate version from the `npm` registry. *** ## Installation Packages are installed and cached into `/@`, so multiple versions of the same package can be cached at once. Additionally, a symlink is created under `//` to make it faster to look up all versions of a package that exist in the cache. *** ## Version specifiers This entire resolution algorithm can be short-circuited by specifying a version or version range directly in your import statement. ```ts index.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} import { z } from "zod@3.0.0"; // specific version import { z } from "zod@next"; // npm tag import { z } from "zod@^3.20.0"; // semver range ``` *** ## Benefits This auto-installation approach is useful for a few reasons: * **Space efficiency** — Each version of a dependency only exists in one place on disk. This is a huge space and time savings compared to redundant per-project installations. * **Portability** — To share simple scripts and gists, your source file is *self-contained*. No need to `zip` together a directory containing your code and config files. With version specifiers in `import` statements, even a `package.json` isn't necessary. * **Convenience** — There's no need to run `npm install` or `bun install` before running a file or script. Just `bun run` it. * **Backwards compatibility** — Because Bun still respects the versions specified in `package.json` if one exists, you can switch to Bun-style resolution with a single command: `rm -rf node_modules`. *** ## Limitations * No Intellisense. TypeScript auto-completion in IDEs relies on the existence of type declaration files inside `node_modules`. We are investigating various solutions to this. * No [patch-package](https://github.com/ds300/patch-package) support *** ## FAQ With pnpm, you have to run `pnpm install`, which creates a `node_modules` folder of symlinks for the runtime to resolve. By contrast, Bun resolves dependencies on the fly when you run a file; there's no need to run any `install` command ahead of time. Bun also doesn't create a `node_modules` folder. With Yarn, you must run `yarn install` before you run a script. By contrast, Bun resolves dependencies on the fly when you run a file; there's no need to run any `install` command ahead of time. Yarn Plug'N'Play also uses zip files to store dependencies. This makes dependency loading [slower at runtime](https://twitter.com/jarredsumner/status/1458207919636287490), as random access reads on zip files tend to be slower than the equivalent disk lookup. Deno requires an `npm:` specifier before each npm `import`, lacks support for import maps via `compilerOptions.paths` in `tsconfig.json`, and has incomplete support for `package.json` settings. Unlike Deno, Bun does not currently support URL imports. --- # Source: https://bun.com/docs/guides/deployment/aws-lambda.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Deploy a Bun application on AWS Lambda [AWS Lambda](https://aws.amazon.com/lambda/) is a serverless compute service that lets you run code without provisioning or managing servers. In this guide, we will deploy a Bun HTTP server to AWS Lambda using a `Dockerfile`. Before continuing, make sure you have: * A Bun application ready for deployment * An [AWS account](https://aws.amazon.com/) * [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html) installed and configured * [Docker](https://docs.docker.com/get-started/get-docker/) installed and added to your `PATH` *** Make sure you're in the directory containing your project, then create a new `Dockerfile` in the root of your project. This file contains the instructions to initialize the container, copy your local project files into it, install dependencies, and start the application. ```docker Dockerfile icon="docker" theme={"theme":{"light":"github-light","dark":"dracula"}} # Use the official AWS Lambda adapter image to handle the Lambda runtime FROM public.ecr.aws/awsguru/aws-lambda-adapter:0.9.0 AS aws-lambda-adapter # Use the official Bun image to run the application FROM oven/bun:debian AS bun_latest # Copy the Lambda adapter into the container COPY --from=aws-lambda-adapter /lambda-adapter /opt/extensions/lambda-adapter # Set the port to 8080. This is required for the AWS Lambda adapter. ENV PORT=8080 # Set the work directory to `/var/task`. This is the default work directory for Lambda. WORKDIR "/var/task" # Copy the package.json and bun.lock into the container COPY package.json bun.lock ./ # Install the dependencies RUN bun install --production --frozen-lockfile # Copy the rest of the application into the container COPY . /var/task # Run the application. CMD ["bun", "index.ts"] ``` Make sure that the start command corresponds to your application's entry point. This can also be `CMD ["bun", "run", "start"]` if you have a start script in your `package.json`. This image installs dependencies and runs your app with Bun inside a container. If your app doesn't have dependencies, you can omit the `RUN bun install --production --frozen-lockfile` line. Create a new `.dockerignore` file in the root of your project. This file contains the files and directories that should be *excluded* from the container image, such as `node_modules`. This makes your builds faster and smaller: ```docker .dockerignore icon="Docker" theme={"theme":{"light":"github-light","dark":"dracula"}} node_modules Dockerfile* .dockerignore .git .gitignore README.md LICENSE .vscode .env # Any other files or directories you want to exclude ``` Make sure you're in the directory containing your `Dockerfile`, then build the Docker image. In this case, we'll call the image `bun-lambda-demo` and tag it as `latest`. ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} # cd /path/to/your/app docker build --provenance=false --platform linux/amd64 -t bun-lambda-demo:latest . ``` To push the image to AWS Lambda, we first need to create an [ECR repository](https://aws.amazon.com/ecr/) to push the image to. By running the following command, we: * Create an ECR repository named `bun-lambda-demo` in the `us-east-1` region * Get the repository URI, and export the repository URI as an environment variable. This is optional, but make the next steps easier. ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} export ECR_URI=$(aws ecr create-repository --repository-name bun-lambda-demo --region us-east-1 --query 'repository.repositoryUri' --output text) echo $ECR_URI ``` ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} [id].dkr.ecr.us-east-1.amazonaws.com/bun-lambda-demo ``` If you're using IAM Identity Center (SSO) or have configured AWS CLI with profiles, you'll need to add the `--profile` flag to your AWS CLI commands. For example, if your profile is named `my-sso-app`, use `--profile my-sso-app`. Check your AWS CLI configuration with `aws configure list-profiles` to see available profiles. ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} export ECR_URI=$(aws ecr create-repository --repository-name bun-lambda-demo --region us-east-1 --profile my-sso-app --query 'repository.repositoryUri' --output text) echo $ECR_URI ``` Log in to the ECR repository: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin $ECR_URI ``` ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} Login Succeeded ``` If using a profile, use the `--profile` flag: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} aws ecr get-login-password --region us-east-1 --profile my-sso-app | docker login --username AWS --password-stdin $ECR_URI ``` Make sure you're in the directory containing your `Dockerfile`, then tag the docker image with the ECR repository URI. ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} docker tag bun-lambda-demo:latest ${ECR_URI}:latest ``` Then, push the image to the ECR repository. ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} docker push ${ECR_URI}:latest ``` Go to **AWS Console** > **Lambda** > [**Create Function**](https://us-east-1.console.aws.amazon.com/lambda/home?region=us-east-1#/create/function?intent=authorFromImage) > Select **Container image** Make sure you've selected the right region, this URL defaults to `us-east-1`. Create Function Give the function a name, like `my-bun-function`. Then, go to the **Container image URI** section, click on **Browse images**. Select the image we just pushed to the ECR repository. Select Container Repository Then, select the `latest` image, and click on **Select image**. Select Container Image To get a public URL for the function, we need to go to **Additional configurations** > **Networking** > **Function URL**. Set this to **Enable**, with Auth Type **NONE**. Set the Function URL Click on **Create function** at the bottom of the page, this will create the function. Create Function Once the function has been created you'll be redirected to the function's page, where you can see the function URL in the **"Function URL"** section. Function URL 🥳 Your app is now live! To test the function, you can either go to the **Test** tab, or call the function URL directly. ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} curl -X GET https://[your-function-id].lambda-url.us-east-1.on.aws/ ``` ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} Hello from Bun on Lambda! ``` --- # Source: https://bun.com/docs/guides/install/azure-artifacts.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Using bun install with an Azure Artifacts npm registry In [Azure Artifact's](https://learn.microsoft.com/en-us/azure/devops/artifacts/npm/npmrc?view=azure-devops\&tabs=windows%2Cclassic) instructions for `.npmrc`, they say to base64 encode the password. Do not do this for `bun install`. Bun will automatically base64 encode the password for you if needed. [Azure Artifacts](https://azure.microsoft.com/en-us/products/devops/artifacts) is a package management system for Azure DevOps. It allows you to host your own private npm registry, npm packages, and other types of packages as well. *** ### Configure with bunfig.toml *** To use it with `bun install`, add a `bunfig.toml` file to your project with the following contents. Make sure to replace `my-azure-artifacts-user` with your Azure Artifacts username, such as `jarred1234`. ```toml bunfig.toml icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install.registry] url = "https://pkgs.dev.azure.com/my-azure-artifacts-user/_packaging/my-azure-artifacts-user/npm/registry" username = "my-azure-artifacts-user" # You can use an environment variable here password = "$NPM_PASSWORD" ``` *** Then assign your Azure Personal Access Token to the `NPM_PASSWORD` environment variable. Bun [automatically reads](/runtime/environment-variables) `.env` files, so create a file called `.env` in your project root. There is no need to base-64 encode this token! Bun will do this for you. ```ini .env icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} NPM_PASSWORD= ``` *** ### Configure with environment variables *** To configure Azure Artifacts without `bunfig.toml`, you can set the `NPM_CONFIG_REGISTRY` environment variable. The URL should include `:username` and `:_password` as query parameters. Replace `` and `` with the appropriate values. ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} NPM_CONFIG_REGISTRY=https://pkgs.dev.azure.com/my-azure-artifacts-user/_packaging/my-azure-artifacts-user/npm/registry/:username=:_password= ``` *** ### Don't base64 encode the password *** In [Azure Artifact's](https://learn.microsoft.com/en-us/azure/devops/artifacts/npm/npmrc?view=azure-devops\&tabs=windows%2Cclassic) instructions for `.npmrc`, they say to base64 encode the password. Do not do this for `bun install`. Bun will automatically base64 encode the password for you if needed. **Tip** — If it ends with `==`, it probably is base64 encoded. *** To decode a base64-encoded password, open your browser console and run: ```js browser icon="computer" theme={"theme":{"light":"github-light","dark":"dracula"}} atob(""); ``` *** Alternatively, use the `base64` command line tool, but doing so means it may be saved in your terminal history which is not recommended: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} echo "base64-encoded-password" | base64 --decode ``` --- # Source: https://bun.com/docs/guides/test/bail.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Bail early with the Bun test runner Use the `--bail` flag to bail on a test run after a single failure. This is useful for aborting as soon as possible in a continuous integration environment. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun test --bail ``` *** To bail after a certain threshold of failures, optionally specify a number after the flag. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} # bail after 10 failures bun test --bail=10 ``` *** See [Docs > Test runner](/test) for complete documentation of `bun test`. --- # Source: https://bun.com/docs/guides/util/base64.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Encode and decode base64 strings Bun implements the Web-standard [`atob`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/atob) and [`btoa`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/btoa) functions for encoding and decoding base64 strings. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const data = "hello world"; const encoded = btoa(data); // => "aGVsbG8gd29ybGQ=" const decoded = atob(encoded); // => "hello world" ``` *** See [Docs > Web APIs](/runtime/web-apis) for a complete breakdown of the Web APIs implemented in Bun. --- # Source: https://bun.com/docs/guides/write-file/basic.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Write a string to a file This code snippet writes a string to disk at a particular *absolute path*. It uses the fast [`Bun.write()`](/runtime/file-io#writing-files-bun-write) API to efficiently write data to disk. The first argument is a *destination*; the second is the *data* to write. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const path = "/path/to/file.txt"; await Bun.write(path, "Lorem ipsum"); ``` *** Any relative paths will be resolved relative to the project root (the nearest directory containing a `package.json` file). ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const path = "./file.txt"; await Bun.write(path, "Lorem ipsum"); ``` *** You can pass a `BunFile` as the destination. `Bun.write()` will write the data to its associated path. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const path = Bun.file("./file.txt"); await Bun.write(path, "Lorem ipsum"); ``` *** `Bun.write()` returns the number of bytes written to disk. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const path = "./file.txt"; const bytes = await Bun.write(path, "Lorem ipsum"); // => 11 ``` *** See [Docs > API > File I/O](/runtime/file-io#writing-files-bun-write) for complete documentation of `Bun.write()`. --- # Source: https://bun.com/docs/project/benchmarking.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Benchmarking > How to benchmark Bun Bun is designed for speed. Hot paths are extensively profiled and benchmarked. The source code for all of Bun's public benchmarks can be found in the [`/bench`](https://github.com/oven-sh/bun/tree/main/bench) directory of the Bun repo. ## Measuring time To precisely measure time, Bun offers two runtime APIs functions: 1. The Web-standard [`performance.now()`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now) function 2. `Bun.nanoseconds()` which is similar to `performance.now()` except it returns the current time since the application started in nanoseconds. You can use `performance.timeOrigin` to convert this to a Unix timestamp. ## Benchmarking tools When writing your own benchmarks, it's important to choose the right tool. * For microbenchmarks, a great general-purpose tool is [`mitata`](https://github.com/evanwashere/mitata). * For load testing, you *must use* an HTTP benchmarking tool that is at least as fast as `Bun.serve()`, or your results will be skewed. Some popular Node.js-based benchmarking tools like [`autocannon`](https://github.com/mcollina/autocannon) are not fast enough. We recommend one of the following: * [`bombardier`](https://github.com/codesenberg/bombardier) * [`oha`](https://github.com/hatoo/oha) * [`http_load_test`](https://github.com/uNetworking/uSockets/blob/master/examples/http_load_test.c) * For benchmarking scripts or CLI commands, we recommend [`hyperfine`](https://github.com/sharkdp/hyperfine). ## Measuring memory usage Bun has two heaps. One heap is for the JavaScript runtime and the other heap is for everything else. ### JavaScript heap stats The `bun:jsc` module exposes a few functions for measuring memory usage: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} import { heapStats } from "bun:jsc"; console.log(heapStats()); ``` ```ts expandable icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} { heapSize: 1657575, heapCapacity: 2872775, extraMemorySize: 598199, objectCount: 13790, protectedObjectCount: 62, globalObjectCount: 1, protectedGlobalObjectCount: 1, // A count of every object type in the heap objectTypeCounts: { CallbackObject: 25, FunctionExecutable: 2078, AsyncGeneratorFunction: 2, 'RegExp String Iterator': 1, FunctionCodeBlock: 188, ModuleProgramExecutable: 13, String: 1, UnlinkedModuleProgramCodeBlock: 13, JSON: 1, AsyncGenerator: 1, Symbol: 1, GetterSetter: 68, ImportMeta: 10, DOMAttributeGetterSetter: 1, UnlinkedFunctionCodeBlock: 174, RegExp: 52, ModuleLoader: 1, Intl: 1, WeakMap: 4, Generator: 2, PropertyTable: 95, 'Array Iterator': 1, JSLexicalEnvironment: 75, UnlinkedFunctionExecutable: 2067, WeakSet: 1, console: 1, Map: 23, SparseArrayValueMap: 14, StructureChain: 19, Set: 18, 'String Iterator': 1, FunctionRareData: 3, JSGlobalLexicalEnvironment: 1, Object: 481, BigInt: 2, StructureRareData: 55, Array: 179, AbortController: 2, ModuleNamespaceObject: 11, ShadowRealm: 1, 'Immutable Butterfly': 103, Primordials: 1, 'Set Iterator': 1, JSGlobalProxy: 1, AsyncFromSyncIterator: 1, ModuleRecord: 13, FinalizationRegistry: 1, AsyncIterator: 1, InternalPromise: 22, Iterator: 1, CustomGetterSetter: 65, Promise: 19, WeakRef: 1, InternalPromisePrototype: 1, Function: 2381, AsyncFunction: 2, GlobalObject: 1, ArrayBuffer: 2, Boolean: 1, Math: 1, CallbackConstructor: 1, Error: 2, JSModuleEnvironment: 13, WebAssembly: 1, HashMapBucket: 300, Callee: 3, symbol: 37, string: 2484, Performance: 1, ModuleProgramCodeBlock: 12, JSSourceCode: 13, JSPropertyNameEnumerator: 3, NativeExecutable: 290, Number: 1, Structure: 1550, SymbolTable: 108, GeneratorFunction: 2, 'Map Iterator': 1 }, protectedObjectTypeCounts: { CallbackConstructor: 1, BigInt: 1, RegExp: 2, GlobalObject: 1, UnlinkedModuleProgramCodeBlock: 13, HashMapBucket: 2, Structure: 41, JSPropertyNameEnumerator: 1 } } ``` JavaScript is a garbage-collected language, not reference counted. It's normal and correct for objects to not be freed immediately in all cases, though it's not normal for objects to never be freed. To force garbage collection to run manually: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Bun.gc(true); // synchronous Bun.gc(false); // asynchronous ``` Heap snapshots let you inspect what objects are not being freed. You can use the `bun:jsc` module to take a heap snapshot and then view it with Safari or WebKit GTK developer tools. To generate a heap snapshot: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} import { generateHeapSnapshot } from "bun"; const snapshot = generateHeapSnapshot(); await Bun.write("heap.json", JSON.stringify(snapshot, null, 2)); ``` To view the snapshot, open the `heap.json` file in Safari's Developer Tools (or WebKit GTK) 1. Open the Developer Tools 2. Click "Timeline" 3. Click "JavaScript Allocations" in the menu on the left. It might not be visible until you click the pencil icon to show all the timelines 4. Click "Import" and select your heap snapshot JSON Importing a heap snapshot Once imported, you should see something like this: Viewing heap snapshot in Safari > The [web debugger](/runtime/debugger#inspect) also offers the timeline feature which allows you to track and examine the memory usage of the running debug session. ### Native heap stats Bun uses mimalloc for the other heap. To report a summary of non-JavaScript memory usage, set the `MIMALLOC_SHOW_STATS=1` environment variable. and stats will print on exit. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} MIMALLOC_SHOW_STATS=1 bun script.js ``` ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} heap stats: peak total freed current unit count reserved: 64.0 MiB 64.0 MiB 0 64.0 MiB not all freed! committed: 64.0 MiB 64.0 MiB 0 64.0 MiB not all freed! reset: 0 0 0 0 ok touched: 128.5 KiB 128.5 KiB 5.4 MiB -5.3 MiB ok segments: 1 1 0 1 not all freed! -abandoned: 0 0 0 0 ok -cached: 0 0 0 0 ok pages: 0 0 53 -53 ok -abandoned: 0 0 0 0 ok -extended: 0 -noretire: 0 mmaps: 0 commits: 0 threads: 0 0 0 0 ok searches: 0.0 avg numa nodes: 1 elapsed: 0.068 s process: user: 0.061 s, system: 0.014 s, faults: 0, rss: 57.4 MiB, commit: 64.0 MiB ``` ## CPU profiling Profile JavaScript execution to identify performance bottlenecks with the `--cpu-prof` flag. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun --cpu-prof script.js ``` This generates a `.cpuprofile` file you can open in Chrome DevTools (Performance tab → Load profile) or VS Code's CPU profiler. ### Markdown output Use `--cpu-prof-md` to generate a markdown CPU profile, which is grep-friendly and designed for LLM analysis: ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun --cpu-prof-md script.js ``` Both `--cpu-prof` and `--cpu-prof-md` can be used together to generate both formats at once: ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun --cpu-prof --cpu-prof-md script.js ``` You can also trigger profiling via the `BUN_OPTIONS` environment variable: ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} BUN_OPTIONS="--cpu-prof-md" bun script.js ``` ### Options ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun --cpu-prof --cpu-prof-name my-profile.cpuprofile script.js bun --cpu-prof --cpu-prof-dir ./profiles script.js ``` | Flag | Description | | ---------------------------- | ----------------------------------------------------------- | | `--cpu-prof` | Generate a `.cpuprofile` JSON file (Chrome DevTools format) | | `--cpu-prof-md` | Generate a markdown CPU profile (grep/LLM-friendly) | | `--cpu-prof-name ` | Set output filename | | `--cpu-prof-dir ` | Set output directory | ## Heap profiling Generate heap snapshots on exit to analyze memory usage and find memory leaks. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun --heap-prof script.js ``` This generates a V8 `.heapsnapshot` file that can be loaded in Chrome DevTools (Memory tab → Load). ### Markdown output Use `--heap-prof-md` to generate a markdown heap profile for CLI analysis: ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun --heap-prof-md script.js ``` If both `--heap-prof` and `--heap-prof-md` are specified, the markdown format is used. ### Options ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun --heap-prof --heap-prof-name my-snapshot.heapsnapshot script.js bun --heap-prof --heap-prof-dir ./profiles script.js ``` | Flag | Description | | ----------------------------- | ------------------------------------------ | | `--heap-prof` | Generate a V8 `.heapsnapshot` file on exit | | `--heap-prof-md` | Generate a markdown heap profile on exit | | `--heap-prof-name ` | Set output filename | | `--heap-prof-dir ` | Set output directory | --- # Source: https://bun.com/docs/runtime/binary-data.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Binary Data > Working with binary data in JavaScript This page is intended as an introduction to working with binary data in JavaScript. Bun implements a number of data types and utilities for working with binary data, most of which are Web-standard. Any Bun-specific APIs will be noted as such. Below is a quick "cheat sheet" that doubles as a table of contents. Click an item in the left column to jump to that section. | Class | Description | | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [`TypedArray`](#typedarray) | A family of classes that provide an `Array`-like interface for interacting with binary data. Includes `Uint8Array`, `Uint16Array`, `Int8Array`, and more. | | [`Buffer`](#buffer) | A subclass of `Uint8Array` that implements a wide range of convenience methods. Unlike the other elements in this table, this is a Node.js API (which Bun implements). It can't be used in the browser. | | [`DataView`](#dataview) | A class that provides a `get/set` API for writing some number of bytes to an `ArrayBuffer` at a particular byte offset. Often used reading or writing binary protocols. | | [`Blob`](#blob) | A readonly blob of binary data usually representing a file. Has a MIME `type`, a `size`, and methods for converting to `ArrayBuffer`, `ReadableStream`, and string. | | [`File`](#file) | A subclass of `Blob` that represents a file. Has a `name` and `lastModified` timestamp. There is experimental support in Node.js v20. | | [`BunFile`](#bunfile) | *Bun only*. A subclass of `Blob` that represents a lazily-loaded file on disk. Created with `Bun.file(path)`. | *** ## `ArrayBuffer` and views Until 2009, there was no language-native way to store and manipulate binary data in JavaScript. ECMAScript v5 introduced a range of new mechanisms for this. The most fundamental building block is `ArrayBuffer`, a simple data structure that represents a sequence of bytes in memory. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // this buffer can store 8 bytes const buf = new ArrayBuffer(8); ``` Despite the name, it isn't an array and supports none of the array methods and operators one might expect. In fact, there is no way to directly read or write values from an `ArrayBuffer`. There's very little you can do with one except check its size and create "slices" from it. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buf = new ArrayBuffer(8); buf.byteLength; // => 8 const slice = buf.slice(0, 4); // returns new ArrayBuffer slice.byteLength; // => 4 ``` To do anything interesting we need a construct known as a "view". A view is a class that *wraps* an `ArrayBuffer` instance and lets you read and manipulate the underlying data. There are two types of views: *typed arrays* and `DataView`. ### `DataView` The `DataView` class is a lower-level interface for reading and manipulating the data in an `ArrayBuffer`. Below we create a new `DataView` and set the first byte to 3. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buf = new ArrayBuffer(4); // [0b00000000, 0b00000000, 0b00000000, 0b00000000] const dv = new DataView(buf); dv.setUint8(0, 3); // write value 3 at byte offset 0 dv.getUint8(0); // => 3 // [0b00000011, 0b00000000, 0b00000000, 0b00000000] ``` Now let's write a `Uint16` at byte offset `1`. This requires two bytes. We're using the value `513`, which is `2 * 256 + 1`; in bytes, that's `00000010 00000001`. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} dv.setUint16(1, 513); // [0b00000011, 0b00000010, 0b00000001, 0b00000000] console.log(dv.getUint16(1)); // => 513 ``` We've now assigned a value to the first three bytes in our underlying `ArrayBuffer`. Even though the second and third bytes were created using `setUint16()`, we can still read each of its component bytes using `getUint8()`. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} console.log(dv.getUint8(1)); // => 2 console.log(dv.getUint8(2)); // => 1 ``` Attempting to write a value that requires more space than is available in the underlying `ArrayBuffer` will cause an error. Below we attempt to write a `Float64` (which requires 8 bytes) at byte offset `0`, but there are only four total bytes in the buffer. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} dv.setFloat64(0, 3.1415); // ^ RangeError: Out of bounds access ``` The following methods are available on `DataView`: | Getters | Setters | | -------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | | [`getBigInt64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getBigInt64) | [`setBigInt64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setBigInt64) | | [`getBigUint64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getBigUint64) | [`setBigUint64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setBigUint64) | | [`getFloat32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getFloat32) | [`setFloat32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setFloat32) | | [`getFloat64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getFloat64) | [`setFloat64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setFloat64) | | [`getInt16()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getInt16) | [`setInt16()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setInt16) | | [`getInt32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getInt32) | [`setInt32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setInt32) | | [`getInt8()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getInt8) | [`setInt8()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setInt8) | | [`getUint16()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getUint16) | [`setUint16()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setUint16) | | [`getUint32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getUint32) | [`setUint32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setUint32) | | [`getUint8()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getUint8) | [`setUint8()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setUint8) | ### `TypedArray` Typed arrays are a family of classes that provide an `Array`-like interface for interacting with data in an `ArrayBuffer`. Whereas a `DataView` lets you write numbers of varying size at a particular offset, a `TypedArray` interprets the underlying bytes as an array of numbers, each of a fixed size. It's common to refer to this family of classes collectively by their shared superclass `TypedArray`. This class as *internal* to JavaScript; you can't directly create instances of it, and `TypedArray` is not defined in the global scope. Think of it as an `interface` or an abstract class. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buffer = new ArrayBuffer(3); const arr = new Uint8Array(buffer); // contents are initialized to zero console.log(arr); // Uint8Array(3) [0, 0, 0] // assign values like an array arr[0] = 0; arr[1] = 10; arr[2] = 255; arr[3] = 255; // no-op, out of bounds ``` While an `ArrayBuffer` is a generic sequence of bytes, these typed array classes interpret the bytes as an array of numbers of a given byte size. The top row contains the raw bytes, and the later rows contain how these bytes will be interpreted when *viewed* using different typed array classes. The following classes are typed arrays, along with a description of how they interpret the bytes in an `ArrayBuffer`: Here's the first table formatted as a markdown table: | Class | Description | | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) | Every one (1) byte is interpreted as an unsigned 8-bit integer. Range 0 to 255. | | [`Uint16Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint16Array) | Every two (2) bytes are interpreted as an unsigned 16-bit integer. Range 0 to 65535. | | [`Uint32Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint32Array) | Every four (4) bytes are interpreted as an unsigned 32-bit integer. Range 0 to 4294967295. | | [`Int8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int8Array) | Every one (1) byte is interpreted as a signed 8-bit integer. Range -128 to 127. | | [`Int16Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int16Array) | Every two (2) bytes are interpreted as a signed 16-bit integer. Range -32768 to 32767. | | [`Int32Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int32Array) | Every four (4) bytes are interpreted as a signed 32-bit integer. Range -2147483648 to 2147483647. | | [`Float16Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float16Array) | Every two (2) bytes are interpreted as a 16-bit floating point number. Range -6.104e5 to 6.55e4. | | [`Float32Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array) | Every four (4) bytes are interpreted as a 32-bit floating point number. Range -3.4e38 to 3.4e38. | | [`Float64Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float64Array) | Every eight (8) bytes are interpreted as a 64-bit floating point number. Range -1.7e308 to 1.7e308. | | [`BigInt64Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array) | Every eight (8) bytes are interpreted as a signed `BigInt`. Range -9223372036854775808 to 9223372036854775807 (though `BigInt` is capable of representing larger numbers). | | [`BigUint64Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigUint64Array) | Every eight (8) bytes are interpreted as an unsigned `BigInt`. Range 0 to 18446744073709551615 (though `BigInt` is capable of representing larger numbers). | | [`Uint8ClampedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray) | Same as `Uint8Array`, but automatically "clamps" to the range 0-255 when assigning a value to an element. | The table below demonstrates how the bytes in an `ArrayBuffer` are interpreted when viewed using different typed array classes. | | Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 | | ---------------- | ------------------- | ---------- | ------------------- | ---------- | -------------------- | ---------- | -------------------- | ---------- | | `ArrayBuffer` | `00000000` | `00000001` | `00000010` | `00000011` | `00000100` | `00000101` | `00000110` | `00000111` | | `Uint8Array` | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | `Uint16Array` | 256 (`1 * 256 + 0`) | | 770 (`3 * 256 + 2`) | | 1284 (`5 * 256 + 4`) | | 1798 (`7 * 256 + 6`) | | | `Uint32Array` | 50462976 | | | | 117835012 | | | | | `BigUint64Array` | 506097522914230528n | | | | | | | | To create a typed array from a pre-defined `ArrayBuffer`: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // create typed array from ArrayBuffer const buf = new ArrayBuffer(10); const arr = new Uint8Array(buf); arr[0] = 30; arr[1] = 60; // all elements are initialized to zero console.log(arr); // => Uint8Array(10) [ 30, 60, 0, 0, 0, 0, 0, 0, 0, 0 ]; ``` If we tried to instantiate a `Uint32Array` from this same `ArrayBuffer`, we'd get an error. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buf = new ArrayBuffer(10); const arr = new Uint32Array(buf); // ^ RangeError: ArrayBuffer length minus the byteOffset // is not a multiple of the element size ``` A `Uint32` value requires four bytes (16 bits). Because the `ArrayBuffer` is 10 bytes long, there's no way to cleanly divide its contents into 4-byte chunks. To fix this, we can create a typed array over a particular "slice" of an `ArrayBuffer`. The `Uint16Array` below only "views" the *first* 8 bytes of the underlying `ArrayBuffer`. To achieve these, we specify a `byteOffset` of `0` and a `length` of `2`, which indicates the number of `Uint32` numbers we want our array to hold. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // create typed array from ArrayBuffer slice const buf = new ArrayBuffer(10); const arr = new Uint32Array(buf, 0, 2); /* buf _ _ _ _ _ _ _ _ _ _ 10 bytes arr [_______,_______] 2 4-byte elements */ arr.byteOffset; // 0 arr.length; // 2 ``` You don't need to explicitly create an `ArrayBuffer` instance; you can instead directly specify a length in the typed array constructor: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const arr2 = new Uint8Array(5); // all elements are initialized to zero // => Uint8Array(5) [0, 0, 0, 0, 0] ``` Typed arrays can also be instantiated directly from an array of numbers, or another typed array: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // from an array of numbers const arr1 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7]); arr1[0]; // => 0; arr1[7]; // => 7; // from another typed array const arr2 = new Uint8Array(arr); ``` Broadly speaking, typed arrays provide the same methods as regular arrays, with a few exceptions. For example, `push` and `pop` are not available on typed arrays, because they would require resizing the underlying `ArrayBuffer`. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const arr = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7]); // supports common array methods arr.filter(n => n > 128); // Uint8Array(1) [255] arr.map(n => n * 2); // Uint8Array(8) [0, 2, 4, 6, 8, 10, 12, 14] arr.reduce((acc, n) => acc + n, 0); // 28 arr.forEach(n => console.log(n)); // 0 1 2 3 4 5 6 7 arr.every(n => n < 10); // true arr.find(n => n > 5); // 6 arr.includes(5); // true arr.indexOf(5); // 5 ``` Refer to the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) for more information on the properties and methods of typed arrays. ### `Uint8Array` It's worth specifically highlighting `Uint8Array`, as it represents a classic "byte array"—a sequence of 8-bit unsigned integers between 0 and 255. This is the most common typed array you'll encounter in JavaScript. In Bun, and someday in other JavaScript engines, it has methods available for converting between byte arrays and serialized representations of those arrays as base64 or hex strings. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new Uint8Array([1, 2, 3, 4, 5]).toBase64(); // "AQIDBA==" Uint8Array.fromBase64("AQIDBA=="); // Uint8Array(4) [1, 2, 3, 4, 5] new Uint8Array([255, 254, 253, 252, 251]).toHex(); // "fffefdfcfb==" Uint8Array.fromHex("fffefdfcfb"); // Uint8Array(5) [255, 254, 253, 252, 251] ``` It is the return value of [`TextEncoder#encode`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder), and the input type of [`TextDecoder#decode`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder), two utility classes designed to translate strings and various binary encodings, most notably `"utf-8"`. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const encoder = new TextEncoder(); const bytes = encoder.encode("hello world"); // => Uint8Array(11) [ 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100 ] const decoder = new TextDecoder(); const text = decoder.decode(bytes); // => hello world ``` ### `Buffer` Bun implements `Buffer`, a Node.js API for working with binary data that pre-dates the introduction of typed arrays in the JavaScript spec. It has since been re-implemented as a subclass of `Uint8Array`. It provides a wide range of methods, including several Array-like and `DataView`-like methods. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buf = Buffer.from("hello world"); // => Buffer(11) [ 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100 ] buf.length; // => 11 buf[0]; // => 104, ascii for 'h' buf.writeUInt8(72, 0); // => ascii for 'H' console.log(buf.toString()); // => Hello world ``` For complete documentation, refer to the [Node.js documentation](https://nodejs.org/api/buffer.html). ## `Blob` `Blob` is a Web API commonly used for representing files. `Blob` was initially implemented in browsers (unlike `ArrayBuffer` which is part of JavaScript itself), but it is now supported in Node and Bun. It isn't common to directly create `Blob` instances. More often, you'll receive instances of `Blob` from an external source (like an `` element in the browser) or library. That said, it is possible to create a `Blob` from one or more string or binary "blob parts". ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const blob = new Blob(["Hello"], { type: "text/html", }); blob.type; // => text/html blob.size; // => 19 ``` These parts can be `string`, `ArrayBuffer`, `TypedArray`, `DataView`, or other `Blob` instances. The blob parts are concatenated together in the order they are provided. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const blob = new Blob([ "", new Blob([""]), new Uint8Array([104, 101, 108, 108, 111]), // "hello" in binary "", ]); ``` The contents of a `Blob` can be asynchronously read in various formats. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} await blob.text(); // => hello await blob.bytes(); // => Uint8Array (copies contents) await blob.arrayBuffer(); // => ArrayBuffer (copies contents) await blob.stream(); // => ReadableStream ``` ### `BunFile` `BunFile` is a subclass of `Blob` used to represent a lazily-loaded file on disk. Like `File`, it adds a `name` and `lastModified` property. Unlike `File`, it does not require the file to be loaded into memory. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const file = Bun.file("index.txt"); // => BunFile ``` ### `File` Browser only. Experimental support in Node.js 20. [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) is a subclass of `Blob` that adds a `name` and `lastModified` property. It's commonly used in the browser to represent files uploaded via a `` element. Node.js and Bun implement `File`. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // on browser! // const files = document.getElementById("file").files; // => File[] ``` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const file = new File(["Hello"], "index.html", { type: "text/html", }); ``` Refer to the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/Blob) for complete docs information. *** ## Streams Streams are an important abstraction for working with binary data without loading it all into memory at once. They are commonly used for reading and writing files, sending and receiving network requests, and processing large amounts of data. Bun implements the Web APIs [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) and [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream). Bun also implements the `node:stream` module, including [`Readable`](https://nodejs.org/api/stream.html#stream_readable_streams), [`Writable`](https://nodejs.org/api/stream.html#stream_writable_streams), and [`Duplex`](https://nodejs.org/api/stream.html#stream_duplex_and_transform_streams). For complete documentation, refer to the Node.js docs. To create a simple readable stream: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const stream = new ReadableStream({ start(controller) { controller.enqueue("hello"); controller.enqueue("world"); controller.close(); }, }); ``` The contents of this stream can be read chunk-by-chunk with `for await` syntax. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} for await (const chunk of stream) { console.log(chunk); } // => "hello" // => "world" ``` For a more complete discussion of streams in Bun, see [API > Streams](/runtime/streams). *** ## Conversion Converting from one binary format to another is a common task. This section is intended as a reference. ### From `ArrayBuffer` Since `ArrayBuffer` stores the data that underlies other binary structures like `TypedArray`, the snippets below are not *converting* from `ArrayBuffer` to another format. Instead, they are *creating* a new instance using the data stored underlying data. #### To `TypedArray` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new Uint8Array(buf); ``` #### To `DataView` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new DataView(buf); ``` #### To `Buffer` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // create Buffer over entire ArrayBuffer Buffer.from(buf); // create Buffer over a slice of the ArrayBuffer Buffer.from(buf, 0, 10); ``` #### To `string` As UTF-8: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new TextDecoder().decode(buf); ``` #### To `number[]` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Array.from(new Uint8Array(buf)); ``` #### To `Blob` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new Blob([buf], { type: "text/plain" }); ``` #### To `ReadableStream` The following snippet creates a `ReadableStream` and enqueues the entire `ArrayBuffer` as a single chunk. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new ReadableStream({ start(controller) { controller.enqueue(buf); controller.close(); }, }); ``` To stream the `ArrayBuffer` in chunks, use a `Uint8Array` view and enqueue each chunk. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const view = new Uint8Array(buf); const chunkSize = 1024; new ReadableStream({ start(controller) { for (let i = 0; i < view.length; i += chunkSize) { controller.enqueue(view.slice(i, i + chunkSize)); } controller.close(); }, }); ``` ### From `TypedArray` #### To `ArrayBuffer` This retrieves the underlying `ArrayBuffer`. Note that a `TypedArray` can be a view of a *slice* of the underlying buffer, so the sizes may differ. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} arr.buffer; ``` #### To `DataView` To creates a `DataView` over the same byte range as the TypedArray. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new DataView(arr.buffer, arr.byteOffset, arr.byteLength); ``` #### To `Buffer` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Buffer.from(arr); ``` #### To `string` As UTF-8: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new TextDecoder().decode(arr); ``` #### To `number[]` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Array.from(arr); ``` #### To `Blob` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // only if arr is a view of its entire backing TypedArray new Blob([arr.buffer], { type: "text/plain" }); ``` #### To `ReadableStream` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new ReadableStream({ start(controller) { controller.enqueue(arr); controller.close(); }, }); ``` To stream the `ArrayBuffer` in chunks, split the `TypedArray` into chunks and enqueue each one individually. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new ReadableStream({ start(controller) { for (let i = 0; i < arr.length; i += chunkSize) { controller.enqueue(arr.slice(i, i + chunkSize)); } controller.close(); }, }); ``` ### From `DataView` #### To `ArrayBuffer` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} view.buffer; ``` #### To `TypedArray` Only works if the `byteLength` of the `DataView` is a multiple of the `BYTES_PER_ELEMENT` of the `TypedArray` subclass. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new Uint8Array(view.buffer, view.byteOffset, view.byteLength); new Uint16Array(view.buffer, view.byteOffset, view.byteLength / 2); new Uint32Array(view.buffer, view.byteOffset, view.byteLength / 4); // etc... ``` #### To `Buffer` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Buffer.from(view.buffer, view.byteOffset, view.byteLength); ``` #### To `string` As UTF-8: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new TextDecoder().decode(view); ``` #### To `number[]` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Array.from(view); ``` #### To `Blob` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new Blob([view.buffer], { type: "text/plain" }); ``` #### To `ReadableStream` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new ReadableStream({ start(controller) { controller.enqueue(view.buffer); controller.close(); }, }); ``` To stream the `ArrayBuffer` in chunks, split the `DataView` into chunks and enqueue each one individually. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new ReadableStream({ start(controller) { for (let i = 0; i < view.byteLength; i += chunkSize) { controller.enqueue(view.buffer.slice(i, i + chunkSize)); } controller.close(); }, }); ``` ### From `Buffer` #### To `ArrayBuffer` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} buf.buffer; ``` #### To `TypedArray` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new Uint8Array(buf); ``` #### To `DataView` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new DataView(buf.buffer, buf.byteOffset, buf.byteLength); ``` #### To `string` As UTF-8: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} buf.toString(); ``` As base64: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} buf.toString("base64"); ``` As hex: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} buf.toString("hex"); ``` #### To `number[]` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Array.from(buf); ``` #### To `Blob` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new Blob([buf], { type: "text/plain" }); ``` #### To `ReadableStream` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new ReadableStream({ start(controller) { controller.enqueue(buf); controller.close(); }, }); ``` To stream the `ArrayBuffer` in chunks, split the `Buffer` into chunks and enqueue each one individually. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new ReadableStream({ start(controller) { for (let i = 0; i < buf.length; i += chunkSize) { controller.enqueue(buf.slice(i, i + chunkSize)); } controller.close(); }, }); ``` ### From `Blob` #### To `ArrayBuffer` The `Blob` class provides a convenience method for this purpose. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} await blob.arrayBuffer(); ``` #### To `TypedArray` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} await blob.bytes(); ``` #### To `DataView` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new DataView(await blob.arrayBuffer()); ``` #### To `Buffer` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Buffer.from(await blob.arrayBuffer()); ``` #### To `string` As UTF-8: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} await blob.text(); ``` #### To `number[]` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Array.from(await blob.bytes()); ``` #### To `ReadableStream` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} blob.stream(); ``` ### From `ReadableStream` It's common to use [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) as a convenient intermediate representation to make it easier to convert `ReadableStream` to other formats. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} stream; // ReadableStream const buffer = new Response(stream).arrayBuffer(); ``` However this approach is verbose and adds overhead that slows down overall performance unnecessarily. Bun implements a set of optimized convenience functions for converting `ReadableStream` various binary formats. #### To `ArrayBuffer` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // with Response new Response(stream).arrayBuffer(); // with Bun function Bun.readableStreamToArrayBuffer(stream); ``` #### To `Uint8Array` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // with Response new Response(stream).bytes(); // with Bun function Bun.readableStreamToBytes(stream); ``` #### To `TypedArray` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // with Response const buf = await new Response(stream).arrayBuffer(); new Int8Array(buf); // with Bun function new Int8Array(Bun.readableStreamToArrayBuffer(stream)); ``` #### To `DataView` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // with Response const buf = await new Response(stream).arrayBuffer(); new DataView(buf); // with Bun function new DataView(Bun.readableStreamToArrayBuffer(stream)); ``` #### To `Buffer` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // with Response const buf = await new Response(stream).arrayBuffer(); Buffer.from(buf); // with Bun function Buffer.from(Bun.readableStreamToArrayBuffer(stream)); ``` #### To `string` As UTF-8: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // with Response await new Response(stream).text(); // with Bun function await Bun.readableStreamToText(stream); ``` #### To `number[]` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // with Response const arr = await new Response(stream).bytes(); Array.from(arr); // with Bun function Array.from(new Uint8Array(Bun.readableStreamToArrayBuffer(stream))); ``` Bun provides a utility for resolving a `ReadableStream` to an array of its chunks. Each chunk may be a string, typed array, or `ArrayBuffer`. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // with Bun function Bun.readableStreamToArray(stream); ``` #### To `Blob` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} new Response(stream).blob(); ``` #### To `ReadableStream` To split a `ReadableStream` into two streams that can be consumed independently: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const [a, b] = stream.tee(); ``` --- # Source: https://bun.com/docs/project/bindgen.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Bindgen > Bindgen for Bun This document is for maintainers and contributors to Bun, and describes internal implementation details. The new bindings generator, introduced to the codebase in Dec 2024, scans for `*.bind.ts` to find function and class definition, and generates glue code to interop between JavaScript and native code. There are currently other code generators and systems that achieve similar purposes. The following will all eventually be completely phased out in favor of this one: * "Classes generator", converting `*.classes.ts` for custom classes. * "JS2Native", allowing ad-hoc calls from `src/js` to native code. ## Creating JS Functions in Zig Given a file implementing a simple function, such as `add` ```zig src/bun.js/math.zig theme={"theme":{"light":"github-light","dark":"dracula"}} pub fn add(global: *jsc.JSGlobalObject, a: i32, b: i32) !i32 { return std.math.add(i32, a, b) catch { // Binding functions can return `error.OutOfMemory` and `error.JSError`. // Others like `error.Overflow` from `std.math.add` must be converted. // Remember to be descriptive. return global.throwPretty("Integer overflow while adding", .{}); }; } const gen = bun.gen.math; // "math" being this file's basename const std = @import("std"); const bun = @import("bun"); const jsc = bun.jsc; ``` Then describe the API schema using a `.bind.ts` function. The binding file goes next to the Zig file. ```ts src/bun.js/math.bind.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} import { t, fn } from "bindgen"; export const add = fn({ args: { global: t.globalObject, a: t.i32, b: t.i32.default(1), }, ret: t.i32, }); ``` This function declaration is equivalent to: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} /** * Throws if zero arguments are provided. * Wraps out of range numbers using modulo. */ declare function add(a: number, b: number = 1): number; ``` The code generator will provide `bun.gen.math.jsAdd`, which is the native function implementation. To pass to JavaScript, use `bun.gen.math.createAddCallback(global)`. JS files in `src/js/` may use `$bindgenFn("math.bind.ts", "add")` to get a handle to the implementation. ## Strings The type for receiving strings is one of [`t.DOMString`](https://webidl.spec.whatwg.org/#idl-DOMString), [`t.ByteString`](https://webidl.spec.whatwg.org/#idl-ByteString), and [`t.USVString`](https://webidl.spec.whatwg.org/#idl-USVString). These map directly to their WebIDL counterparts, and have slightly different conversion logic. Bindgen will pass BunString to native code in all cases. When in doubt, use DOMString. `t.UTF8String` can be used in place of `t.DOMString`, but will call `bun.String.toUTF8`. The native callback gets `[]const u8` (WTF-8 data) passed to native code, freeing it after the function returns. TLDRs from WebIDL spec: * ByteString can only contain valid latin1 characters. It is not safe to assume bun.String is already in 8-bit format, but it is extremely likely. * USVString will not contain invalid surrogate pairs, aka text that can be represented correctly in UTF-8. * DOMString is the loosest but also most recommended strategy. ## Function Variants A `variants` can specify multiple variants (also known as overloads). ```ts src/bun.js/math.bind.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} import { t, fn } from "bindgen"; export const action = fn({ variants: [ { args: { a: t.i32, }, ret: t.i32, }, { args: { a: t.DOMString, }, ret: t.DOMString, }, ], }); ``` In Zig, each variant gets a number, based on the order the schema defines. ```zig theme={"theme":{"light":"github-light","dark":"dracula"}} fn action1(a: i32) i32 { return a; } fn action2(a: bun.String) bun.String { return a; } ``` ## `t.dictionary` A `dictionary` is a definition for a JavaScript object, typically as a function inputs. For function outputs, it is usually a smarter idea to declare a class type to add functions and destructuring. ## Enumerations To use [WebIDL's enumeration](https://webidl.spec.whatwg.org/#idl-enums) type, use either: * `t.stringEnum`: Create and codegen a new enum type. * `t.zigEnum`: Derive a bindgen type off of an existing enum in the codebase. An example of `stringEnum` as used in `fmt.zig` / `bun:internal-for-testing` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} export const Formatter = t.stringEnum("highlight-javascript", "escape-powershell"); export const fmtString = fn({ args: { global: t.globalObject, code: t.UTF8String, formatter: Formatter, }, ret: t.DOMString, }); ``` WebIDL strongly encourages using kebab case for enumeration values, to be consistent with existing Web APIs. ### Deriving enums from Zig code TODO: zigEnum ## `t.oneOf` A `oneOf` is a union between two or more types. It is represented by `union(enum)` in Zig. TODO: ## Attributes There are set of attributes that can be chained onto `t.*` types. On all types there are: * `.required`, in dictionary parameters only * `.optional`, in function arguments only * `.default(T)` When a value is optional, it is lowered to a Zig optional. Depending on the type, there are more attributes available. See the type definitions in auto-complete for more details. Note that one of the above three can only be applied, and they must be applied at the end. ### Integer Attributes Integer types allow customizing the overflow behavior with `clamp` or `enforceRange` ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} import { t, fn } from "bindgen"; export const add = fn({ args: { global: t.globalObject, // enforce in i32 range a: t.i32.enforceRange(), // clamp to u16 range b: t.u16, // enforce in arbitrary range, with a default if not provided c: t.i32.enforceRange(0, 1000).default(5), // clamp to arbitrary range, or null d: t.u16.clamp(0, 10).optional, }, ret: t.i32, }); ``` Various Node.js validator functions such as `validateInteger`, `validateNumber`, and more are available. Use these when implementing Node.js APIs, so the error messages match 1:1 what Node would do. Unlike `enforceRange`, which is taken from WebIDL, `validate*` functions are much more strict on the input they accept. For example, Node's numerical validator check `typeof value === 'number'`, while WebIDL uses `ToNumber` for lossy conversion. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} import { t, fn } from "bindgen"; export const add = fn({ args: { global: t.globalObject, // throw if not given a number a: t.f64.validateNumber(), // valid in i32 range a: t.i32.validateInt32(), // f64 within safe integer range b: t.f64.validateInteger(), // f64 in given range c: t.f64.validateNumber(-10000, 10000), }, ret: t.i32, }); ``` ## Callbacks TODO ## Classes TODO --- # Source: https://bun.com/docs/guides/binary/blob-to-arraybuffer.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Convert a Blob to an ArrayBuffer The [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) class provides a number of methods for consuming its contents in different formats, including `.arrayBuffer()`. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const blob = new Blob(["hello world"]); const buf = await blob.arrayBuffer(); ``` *** See [Docs > API > Binary Data](/runtime/binary-data#conversion) for complete documentation on manipulating binary data with Bun. --- # Source: https://bun.com/docs/guides/binary/blob-to-dataview.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Convert a Blob to a DataView The [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) class provides a number of methods for consuming its contents in different formats. This snippets reads the contents to an `ArrayBuffer`, then creates a `DataView` from the buffer. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const blob = new Blob(["hello world"]); const arr = new DataView(await blob.arrayBuffer()); ``` *** See [Docs > API > Binary Data](/runtime/binary-data#conversion) for complete documentation on manipulating binary data with Bun. --- # Source: https://bun.com/docs/guides/binary/blob-to-stream.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Convert a Blob to a ReadableStream The [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) class provides a number of methods for consuming its contents in different formats, including `.stream()`. This returns `Promise`. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const blob = new Blob(["hello world"]); const stream = await blob.stream(); ``` *** See [Docs > API > Binary Data](/runtime/binary-data#conversion) for complete documentation on manipulating binary data with Bun. --- # Source: https://bun.com/docs/guides/binary/blob-to-string.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Convert a Blob to a string The [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) class provides a number of methods for consuming its contents in different formats, including `.text()`. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const blob = new Blob(["hello world"]); const str = await blob.text(); // => "hello world" ``` *** See [Docs > API > Binary Data](/runtime/binary-data#conversion) for complete documentation on manipulating binary data with Bun. --- # Source: https://bun.com/docs/guides/binary/blob-to-typedarray.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Convert a Blob to a Uint8Array The [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) class provides a number of methods for consuming its contents in different formats. This snippets reads the contents to an `ArrayBuffer`, then creates a `Uint8Array` from the buffer. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const blob = new Blob(["hello world"]); const arr = new Uint8Array(await blob.arrayBuffer()); ``` *** See [Docs > API > Binary Data](/runtime/binary-data#conversion) for complete documentation on manipulating binary data with Bun. --- # Source: https://bun.com/docs/guides/write-file/blob.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Write a Blob to a file This code snippet writes a `Blob` to disk at a particular path. It uses the fast [`Bun.write()`](/runtime/file-io#writing-files-bun-write) API to efficiently write data to disk. The first argument is a *destination*, like an absolute path or `BunFile` instance. The second argument is the *data* to write. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const path = "/path/to/file.txt"; await Bun.write(path, "Lorem ipsum"); ``` *** The `BunFile` class extends `Blob`, so you can pass a `BunFile` directly into `Bun.write()` as well. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const path = "./out.txt"; const data = Bun.file("./in.txt"); // write the contents of ./in.txt to ./out.txt await Bun.write(path, data); ``` *** See [Docs > API > File I/O](/runtime/file-io#writing-files-bun-write) for complete documentation of `Bun.write()`. --- # Source: https://bun.com/docs/guides/binary/buffer-to-arraybuffer.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Convert a Buffer to an ArrayBuffer The Node.js [`Buffer`](https://nodejs.org/api/buffer.html) class provides a way to view and manipulate data in an underlying `ArrayBuffer`, which is available via the `buffer` property. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const nodeBuf = Buffer.alloc(64); const arrBuf = nodeBuf.buffer; ``` *** See [Docs > API > Binary Data](/runtime/binary-data#conversion) for complete documentation on manipulating binary data with Bun. --- # Source: https://bun.com/docs/guides/binary/buffer-to-blob.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Convert a Buffer to a blob A [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) can be constructed from an array of "chunks", where each chunk is a string, binary data structure (including `Buffer`), or another `Blob`. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buf = Buffer.from("hello"); const blob = new Blob([buf]); ``` *** See [Docs > API > Binary Data](/runtime/binary-data#conversion) for complete documentation on manipulating binary data with Bun. --- # Source: https://bun.com/docs/guides/binary/buffer-to-readablestream.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Convert a Buffer to a ReadableStream The naive approach to creating a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) from a [`Buffer`](https://nodejs.org/api/buffer.html) is to use the `ReadableStream` constructor and enqueue the entire array as a single chunk. For a large buffer, this may be undesirable as this approach does not "streaming" the data in smaller chunks. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buf = Buffer.from("hello world"); const stream = new ReadableStream({ start(controller) { controller.enqueue(buf); controller.close(); }, }); ``` *** To stream the data in smaller chunks, first create a `Blob` instance from the `Buffer`. Then use the [`Blob.stream()`](https://developer.mozilla.org/en-US/docs/Web/API/Blob/stream) method to create a `ReadableStream` that streams the data in chunks of a specified size. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buf = Buffer.from("hello world"); const blob = new Blob([buf]); const stream = blob.stream(); ``` *** The chunk size can be set by passing a number to the `.stream()` method. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buf = Buffer.from("hello world"); const blob = new Blob([buf]); // set chunk size of 1024 bytes const stream = blob.stream(1024); ``` *** See [Docs > API > Binary Data](/runtime/binary-data#conversion) for complete documentation on manipulating binary data with Bun. --- # Source: https://bun.com/docs/guides/binary/buffer-to-string.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Convert a Buffer to a string The [`Buffer`](https://nodejs.org/api/buffer.html) class provides a built-in `.toString()` method that converts a `Buffer` to a string. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buf = Buffer.from("hello"); const str = buf.toString(); // => "hello" ``` *** You can optionally specify an encoding and byte range. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buf = Buffer.from("hello world!"); const str = buf.toString("utf8", 0, 5); // => "hello" ``` *** See [Docs > API > Binary Data](/runtime/binary-data#conversion) for complete documentation on manipulating binary data with Bun. --- # Source: https://bun.com/docs/guides/binary/buffer-to-typedarray.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Convert a Buffer to a Uint8Array The Node.js [`Buffer`](https://nodejs.org/api/buffer.html) class extends [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array), so no conversion is needed. All properties and methods on `Uint8Array` are available on `Buffer`. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const buf = Buffer.alloc(64); buf instanceof Uint8Array; // => true ``` *** See [Docs > API > Binary Data](/runtime/binary-data#conversion) for complete documentation on manipulating binary data with Bun. --- # Source: https://bun.com/docs/guides/read-file/buffer.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Read a file to a Buffer The `Bun.file()` function accepts a path and returns a `BunFile` instance. The `BunFile` class extends `Blob` and allows you to lazily read the file in a variety of formats. To read the file into a `Buffer` instance, first use `.arrayBuffer()` to consume the file as an `ArrayBuffer`, then use `Buffer.from()` to create a `Buffer` from the `ArrayBuffer`. ```ts index.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const path = "/path/to/package.json"; const file = Bun.file(path); const arrbuf = await file.arrayBuffer(); const buffer = Buffer.from(arrbuf); ``` *** Refer to [Binary data > Buffer](/runtime/binary-data#buffer) for more information on working with `Buffer` and other binary data formats in Bun. --- # Source: https://bun.com/docs/guides/runtime/build-time-constants.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Build-time constants with --define The `--define` flag can be used with `bun build` and `bun build --compile` to inject build-time constants into your application. This is especially useful for embedding metadata like build versions, timestamps, or configuration flags directly into your compiled executables. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun build --compile --define BUILD_VERSION='"1.2.3"' --define BUILD_TIME='"2024-01-15T10:30:00Z"' src/index.ts --outfile myapp ``` *** ## Why use build-time constants? Build-time constants are embedded directly into your compiled code, making them: * **Zero runtime overhead** - No environment variable lookups or file reads * **Immutable** - Values are baked into the binary at compile time * **Optimizable** - Dead code elimination can remove unused branches * **Secure** - No external dependencies or configuration files to manage This is similar to `gcc -D` or `#define` in C/C++, but for JavaScript/TypeScript. *** ## Basic usage ### With `bun build` ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} # Bundle with build-time constants bun build --define BUILD_VERSION='"1.0.0"' --define NODE_ENV='"production"' src/index.ts --outdir ./dist ``` ### With `bun build --compile` ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} # Compile to executable with build-time constants bun build --compile --define BUILD_VERSION='"1.0.0"' --define BUILD_TIME='"2024-01-15T10:30:00Z"' src/cli.ts --outfile mycli ``` ### JavaScript API ```ts build.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} await Bun.build({ entrypoints: ["./src/index.ts"], outdir: "./dist", define: { BUILD_VERSION: '"1.0.0"', BUILD_TIME: '"2024-01-15T10:30:00Z"', DEBUG: "false", }, }); ``` *** ## Common use cases ### Version information Embed version and build metadata directly into your executable: ```ts src/version.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // These constants are replaced at build time declare const BUILD_VERSION: string; declare const BUILD_TIME: string; declare const GIT_COMMIT: string; export function getVersion() { return { version: BUILD_VERSION, buildTime: BUILD_TIME, commit: GIT_COMMIT, }; } ``` ```sh Build command theme={"theme":{"light":"github-light","dark":"dracula"}} bun build --compile \ --define BUILD_VERSION='"1.2.3"' \ --define BUILD_TIME='"2024-01-15T10:30:00Z"' \ --define GIT_COMMIT='"abc123"' \ src/cli.ts --outfile mycli ``` ### Feature flags Use build-time constants to enable/disable features: ```ts src/version.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // Replaced at build time declare const ENABLE_ANALYTICS: boolean; declare const ENABLE_DEBUG: boolean; function trackEvent(event: string) { if (ENABLE_ANALYTICS) { // This entire block is removed if ENABLE_ANALYTICS is false console.log("Tracking:", event); } } if (ENABLE_DEBUG) { console.log("Debug mode enabled"); } ``` ```sh theme={"theme":{"light":"github-light","dark":"dracula"}} # Production build - analytics enabled, debug disabled bun build --compile --define ENABLE_ANALYTICS=true --define ENABLE_DEBUG=false src/app.ts --outfile app-prod # Development build - both enabled bun build --compile --define ENABLE_ANALYTICS=false --define ENABLE_DEBUG=true src/app.ts --outfile app-dev ``` ### Configuration Replace configuration objects at build time: ```ts src/version.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} declare const CONFIG: { apiUrl: string; timeout: number; retries: number; }; // CONFIG is replaced with the actual object at build time const response = await fetch(CONFIG.apiUrl, { timeout: CONFIG.timeout, }); ``` ```sh theme={"theme":{"light":"github-light","dark":"dracula"}} bun build --compile --define 'CONFIG={"apiUrl":"https://api.example.com","timeout":5000,"retries":3}' src/app.ts --outfile app ``` *** ## Advanced patterns ### Environment-specific builds Create different executables for different environments: ```json theme={"theme":{"light":"github-light","dark":"dracula"}} { "scripts": { "build:dev": "bun build --compile --define NODE_ENV='\"development\"' --define API_URL='\"http://localhost:3000\"' src/app.ts --outfile app-dev", "build:staging": "bun build --compile --define NODE_ENV='\"staging\"' --define API_URL='\"https://staging.example.com\"' src/app.ts --outfile app-staging", "build:prod": "bun build --compile --define NODE_ENV='\"production\"' --define API_URL='\"https://api.example.com\"' src/app.ts --outfile app-prod" } } ``` ### Using shell commands for dynamic values Generate build-time constants from shell commands: ```sh theme={"theme":{"light":"github-light","dark":"dracula"}} # Use git to get current commit and timestamp bun build --compile \ --define BUILD_VERSION="\"$(git describe --tags --always)\"" \ --define BUILD_TIME="\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"" \ --define GIT_COMMIT="\"$(git rev-parse HEAD)\"" \ src/cli.ts --outfile mycli ``` ### Build automation script Create a build script that automatically injects build metadata: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // build.ts import { $ } from "bun"; const version = await $`git describe --tags --always`.text(); const buildTime = new Date().toISOString(); const gitCommit = await $`git rev-parse HEAD`.text(); await Bun.build({ entrypoints: ["./src/cli.ts"], outdir: "./dist", define: { BUILD_VERSION: JSON.stringify(version.trim()), BUILD_TIME: JSON.stringify(buildTime), GIT_COMMIT: JSON.stringify(gitCommit.trim()), }, }); console.log(`Built with version ${version.trim()}`); ``` *** ## Important considerations ### Value format Values must be valid JSON that will be parsed and inlined as JavaScript expressions: ```sh theme={"theme":{"light":"github-light","dark":"dracula"}} # ✅ Strings must be JSON-quoted --define VERSION='"1.0.0"' # ✅ Numbers are JSON literals --define PORT=3000 # ✅ Booleans are JSON literals --define DEBUG=true # ✅ Objects and arrays (use single quotes to wrap the JSON) --define 'CONFIG={"host":"localhost","port":3000}' # ✅ Arrays work too --define 'FEATURES=["auth","billing","analytics"]' # ❌ This won't work - missing quotes around string --define VERSION=1.0.0 ``` ### Property keys You can use property access patterns as keys, not just simple identifiers: ```sh theme={"theme":{"light":"github-light","dark":"dracula"}} # ✅ Replace process.env.NODE_ENV with "production" --define 'process.env.NODE_ENV="production"' # ✅ Replace process.env.API_KEY with the actual key --define 'process.env.API_KEY="abc123"' # ✅ Replace nested properties --define 'window.myApp.version="1.0.0"' # ✅ Replace array access --define 'process.argv[2]="--production"' ``` This is particularly useful for environment variables: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // Before compilation if (process.env.NODE_ENV === "production") { console.log("Production mode"); } // After compilation with --define 'process.env.NODE_ENV="production"' if ("production" === "production") { console.log("Production mode"); } // After optimization console.log("Production mode"); ``` ### TypeScript declarations For TypeScript projects, declare your constants to avoid type errors: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // types/build-constants.d.ts declare const BUILD_VERSION: string; declare const BUILD_TIME: string; declare const NODE_ENV: "development" | "staging" | "production"; declare const DEBUG: boolean; ``` ### Cross-platform compatibility When building for multiple platforms, constants work the same way: ```sh theme={"theme":{"light":"github-light","dark":"dracula"}} # Linux bun build --compile --target=bun-linux-x64 --define PLATFORM='"linux"' src/app.ts --outfile app-linux # macOS bun build --compile --target=bun-darwin-x64 --define PLATFORM='"darwin"' src/app.ts --outfile app-macos # Windows bun build --compile --target=bun-windows-x64 --define PLATFORM='"windows"' src/app.ts --outfile app-windows.exe ``` *** ## Related * [Define constants at runtime](/guides/runtime/define-constant) - Using `--define` with `bun run` * [Building executables](/bundler/executables) - Complete guide to `bun build --compile` * [Bundler API](/bundler) - Full bundler documentation including `define` option --- # Source: https://bun.com/docs/project/building-windows.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Building Windows > Building Bun on Windows This document describes the build process for Windows. If you run into problems, please join the [#contributing channel on our Discord](http://bun.com/discord) for help. It is strongly recommended to use [PowerShell 7 (`pwsh.exe`)](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.4) instead of the default `powershell.exe`. ## Prerequisites ### Enable Scripts By default, running unverified scripts are blocked. ```ps1 theme={"theme":{"light":"github-light","dark":"dracula"}} Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted ``` ### System Dependencies Bun v1.1 or later. We use Bun to run it's own code generators. ```ps1 theme={"theme":{"light":"github-light","dark":"dracula"}} irm bun.sh/install.ps1 | iex ``` [Visual Studio](https://visualstudio.microsoft.com) with the "Desktop Development with C++" workload. While installing, make sure to install Git as well, if Git for Windows is not already installed. Visual Studio can be installed graphically using the wizard or through WinGet: ```ps1 theme={"theme":{"light":"github-light","dark":"dracula"}} winget install "Visual Studio Community 2022" --override "--add Microsoft.VisualStudio.Workload.NativeDesktop Microsoft.VisualStudio.Component.Git " -s msstore ``` After Visual Studio, you need the following: * LLVM (19.1.7 for x64, 21.1.8 for ARM64) * Go * Rust * NASM * Perl * Ruby * Node.js The Zig compiler is automatically downloaded, installed, and updated by the building process. [Scoop](https://scoop.sh) can be used to install these remaining tools easily. ```ps1 Scoop (x64) theme={"theme":{"light":"github-light","dark":"dracula"}} irm https://get.scoop.sh | iex scoop install nodejs-lts go rust nasm ruby perl ccache # scoop seems to be buggy if you install llvm and the rest at the same time scoop install llvm@19.1.7 ``` For Windows ARM64, download LLVM 21.1.8 directly from GitHub releases (first version with ARM64 Windows builds): ```ps1 ARM64 theme={"theme":{"light":"github-light","dark":"dracula"}} # Download and install LLVM for ARM64 Invoke-WebRequest -Uri "https://github.com/llvm/llvm-project/releases/download/llvmorg-21.1.8/LLVM-21.1.8-woa64.exe" -OutFile "$env:TEMP\LLVM-21.1.8-woa64.exe" Start-Process -FilePath "$env:TEMP\LLVM-21.1.8-woa64.exe" -ArgumentList "/S" -Wait ``` Please do not use WinGet/other package manager for these, as you will likely install Strawberry Perl instead of a more minimal installation of Perl. Strawberry Perl includes many other utilities that get installed into `$Env:PATH` that will conflict with MSVC and break the build. If you intend on building WebKit locally (optional, x64 only), you should install these packages: ```ps1 Scoop theme={"theme":{"light":"github-light","dark":"dracula"}} scoop install make cygwin python ``` Cygwin is not required for ARM64 builds as WebKit is provided as a pre-built binary. From here on out, it is **expected you use a PowerShell Terminal with `.\scripts\vs-shell.ps1` sourced**. This script is available in the Bun repository and can be loaded by executing it: ```ps1 theme={"theme":{"light":"github-light","dark":"dracula"}} .\scripts\vs-shell.ps1 ``` To verify, you can check for an MSVC-only command line such as `mt.exe` ```ps1 theme={"theme":{"light":"github-light","dark":"dracula"}} Get-Command mt ``` It is not recommended to install `ninja` / `cmake` into your global path, because you may run into a situation where you try to build bun without .\scripts\vs-shell.ps1 sourced. ## Building ```ps1 theme={"theme":{"light":"github-light","dark":"dracula"}} bun run build # after the initial `bun run build` you can use the following to build ninja -Cbuild/debug ``` If this was successful, you should have a `bun-debug.exe` in the `build/debug` folder. ```ps1 theme={"theme":{"light":"github-light","dark":"dracula"}} .\build\debug\bun-debug.exe --revision ``` You should add this to `$Env:PATH`. The simplest way to do so is to open the start menu, type "Path", and then navigate the environment variables menu to add `C:\.....\bun\build\debug` to the user environment variable `PATH`. You should then restart your editor (if it does not update still, log out and log back in). ## Extra paths * WebKit is extracted to `build/debug/cache/webkit/` * Zig is extracted to `build/debug/cache/zig/bin/zig.exe` ## Tests You can run the test suite either using `bun test ` or by using the wrapper script `bun node:test `. The `bun node:test` command runs every test file in a separate instance of bun.exe, to prevent a crash in the test runner from stopping the entire suite. ```ps1 theme={"theme":{"light":"github-light","dark":"dracula"}} # Setup bun i --cwd packages\bun-internal-test # Run the entire test suite with reporter # the package.json script "test" uses "build/debug/bun-debug.exe" by default bun run test # Run an individual test file: bun-debug test node\fs bun-debug test "C:\bun\test\js\bun\resolve\import-meta.test.js" ``` ## Troubleshooting ### .rc file fails to build `llvm-rc.exe` is odd. don't use it. use `rc.exe`, to do this make sure you are in a visual studio dev terminal, check `rc /?` to ensure it is `Microsoft Resource Compiler` ### failed to write output 'bun-debug.exe': permission denied you cannot overwrite `bun-debug.exe` if it is already open. you likely have a running instance, maybe in the vscode debugger? --- # Source: https://bun.com/docs/runtime/bun-apis.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Bun APIs > Overview of Bun's native APIs available on the Bun global object and built-in modules Bun implements a set of native APIs on the `Bun` global object and through a number of built-in modules. These APIs are heavily optimized and represent the canonical "Bun-native" way to implement some common functionality. Bun strives to implement standard Web APIs wherever possible. Bun introduces new APIs primarily for server-side tasks where no standard exists, such as file I/O and starting an HTTP server. In these cases, Bun's approach still builds atop standard APIs like `Blob`, `URL`, and `Request`. ```ts server.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} Bun.serve({ fetch(req: Request) { return new Response("Success!"); }, }); ``` Click the link in the right column to jump to the associated documentation. | Topic | APIs | | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | HTTP Server | [`Bun.serve`](/runtime/http/server) | | Shell | [`$`](/runtime/shell) | | Bundler | [`Bun.build`](/bundler) | | File I/O | [`Bun.file`](/runtime/file-io#reading-files-bun-file), [`Bun.write`](/runtime/file-io#writing-files-bun-write), `Bun.stdin`, `Bun.stdout`, `Bun.stderr` | | Child Processes | [`Bun.spawn`](/runtime/child-process#spawn-a-process-bun-spawn), [`Bun.spawnSync`](/runtime/child-process#blocking-api-bun-spawnsync) | | TCP Sockets | [`Bun.listen`](/runtime/networking/tcp#start-a-server-bun-listen), [`Bun.connect`](/runtime/networking/tcp#start-a-server-bun-listen) | | UDP Sockets | [`Bun.udpSocket`](/runtime/networking/udp) | | WebSockets | `new WebSocket()` (client), [`Bun.serve`](/runtime/http/websockets) (server) | | Transpiler | [`Bun.Transpiler`](/runtime/transpiler) | | Routing | [`Bun.FileSystemRouter`](/runtime/file-system-router) | | Streaming HTML | [`HTMLRewriter`](/runtime/html-rewriter) | | Hashing | [`Bun.password`](/runtime/hashing#bun-password), [`Bun.hash`](/runtime/hashing#bun-hash), [`Bun.CryptoHasher`](/runtime/hashing#bun-cryptohasher), `Bun.sha` | | SQLite | [`bun:sqlite`](/runtime/sqlite) | | PostgreSQL Client | [`Bun.SQL`](/runtime/sql), `Bun.sql` | | Redis (Valkey) Client | [`Bun.RedisClient`](/runtime/redis), `Bun.redis` | | FFI (Foreign Function Interface) | [`bun:ffi`](/runtime/ffi) | | DNS | [`Bun.dns.lookup`](/runtime/networking/dns), `Bun.dns.prefetch`, `Bun.dns.getCacheStats` | | Testing | [`bun:test`](/test) | | Workers | [`new Worker()`](/runtime/workers) | | Module Loaders | [`Bun.plugin`](/bundler/plugins) | | Glob | [`Bun.Glob`](/runtime/glob) | | Cookies | [`Bun.Cookie`](/runtime/cookies), [`Bun.CookieMap`](/runtime/cookies) | | Node-API | [`Node-API`](/runtime/node-api) | | `import.meta` | [`import.meta`](/runtime/module-resolution#import-meta) | | Utilities | [`Bun.version`](/runtime/utils#bun-version), [`Bun.revision`](/runtime/utils#bun-revision), [`Bun.env`](/runtime/utils#bun-env), [`Bun.main`](/runtime/utils#bun-main) | | Sleep & Timing | [`Bun.sleep()`](/runtime/utils#bun-sleep), [`Bun.sleepSync()`](/runtime/utils#bun-sleepsync), [`Bun.nanoseconds()`](/runtime/utils#bun-nanoseconds) | | Random & UUID | [`Bun.randomUUIDv7()`](/runtime/utils#bun-randomuuidv7) | | System & Environment | [`Bun.which()`](/runtime/utils#bun-which) | | Comparison & Inspection | [`Bun.peek()`](/runtime/utils#bun-peek), [`Bun.deepEquals()`](/runtime/utils#bun-deepequals), `Bun.deepMatch`, [`Bun.inspect()`](/runtime/utils#bun-inspect) | | String & Text Processing | [`Bun.escapeHTML()`](/runtime/utils#bun-escapehtml), [`Bun.stringWidth()`](/runtime/utils#bun-stringwidth), `Bun.indexOfLine` | | URL & Path Utilities | [`Bun.fileURLToPath()`](/runtime/utils#bun-fileurltopath), [`Bun.pathToFileURL()`](/runtime/utils#bun-pathtofileurl) | | Compression | [`Bun.gzipSync()`](/runtime/utils#bun-gzipsync), [`Bun.gunzipSync()`](/runtime/utils#bun-gunzipsync), [`Bun.deflateSync()`](/runtime/utils#bun-deflatesync), [`Bun.inflateSync()`](/runtime/utils#bun-inflatesync), `Bun.zstdCompressSync()`, `Bun.zstdDecompressSync()`, `Bun.zstdCompress()`, `Bun.zstdDecompress()` | | Stream Processing | [`Bun.readableStreamTo*()`](/runtime/utils#bun-readablestreamto), `Bun.readableStreamToBytes()`, `Bun.readableStreamToBlob()`, `Bun.readableStreamToFormData()`, `Bun.readableStreamToJSON()`, `Bun.readableStreamToArray()` | | Memory & Buffer Management | `Bun.ArrayBufferSink`, `Bun.allocUnsafe`, `Bun.concatArrayBuffers` | | Module Resolution | [`Bun.resolveSync()`](/runtime/utils#bun-resolvesync) | | Parsing & Formatting | [`Bun.semver`](/runtime/semver), `Bun.TOML.parse`, [`Bun.markdown`](/runtime/markdown), [`Bun.color`](/runtime/color) | | Low-level / Internals | `Bun.mmap`, `Bun.gc`, `Bun.generateHeapSnapshot`, [`bun:jsc`](https://bun.com/reference/bun/jsc) | --- # Source: https://bun.com/docs/runtime/bunfig.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # bunfig.toml > Configure Bun's behavior using its configuration file bunfig.toml Bun's behavior can be configured using its configuration file, `bunfig.toml`. In general, Bun relies on pre-existing configuration files like `package.json` and `tsconfig.json` to configure its behavior. `bunfig.toml` is only necessary for configuring Bun-specific things. This file is optional, and Bun will work out of the box without it. ## Global vs. local In general, it's recommended to add a `bunfig.toml` file to your project root, alongside your `package.json`. To configure Bun globally, you can also create a `.bunfig.toml` file at one of the following paths: * `$HOME/.bunfig.toml` * `$XDG_CONFIG_HOME/.bunfig.toml` If both a global and local `bunfig` are detected, the results are shallow-merged, with local overriding global. CLI flags will override `bunfig` setting where applicable. ## Runtime Bun's runtime behavior is configured using top-level fields in the `bunfig.toml` file. ### `preload` An array of scripts/plugins to execute before running a file or script. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} # scripts to run before `bun run`-ing a file or script # register plugins by adding them to this list preload = ["./preload.ts"] ``` ### `jsx` Configure how Bun handles JSX. You can also set these fields in the `compilerOptions` of your `tsconfig.json`, but they are supported here as well for non-TypeScript projects. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} jsx = "react" jsxFactory = "h" jsxFragment = "Fragment" jsxImportSource = "react" ``` Refer to the tsconfig docs for more information on these fields. * [`jsx`](https://www.typescriptlang.org/tsconfig#jsx) * [`jsxFactory`](https://www.typescriptlang.org/tsconfig#jsxFactory) * [`jsxFragment`](https://www.typescriptlang.org/tsconfig#jsxFragment) * [`jsxImportSource`](https://www.typescriptlang.org/tsconfig#jsxImportSource) ### `smol` Enable `smol` mode. This reduces memory usage at the cost of performance. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} # Reduce memory usage at the cost of performance smol = true ``` ### `logLevel` Set the log level. This can be one of `"debug"`, `"warn"`, or `"error"`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} logLevel = "debug" # "debug" | "warn" | "error" ``` ### `define` The `define` field allows you to replace certain global identifiers with constant expressions. Bun will replace any usage of the identifier with the expression. The expression should be a JSON string. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [define] # Replace any usage of "process.env.bagel" with the string `lox`. # The values are parsed as JSON, except single-quoted strings are supported and `'undefined'` becomes `undefined` in JS. # This will probably change in a future release to be just regular TOML instead. It is a holdover from the CLI argument parsing. "process.env.bagel" = "'lox'" ``` ### `loader` Configure how Bun maps file extensions to loaders. This is useful for loading files that aren't natively supported by Bun. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [loader] # when a .bagel file is imported, treat it like a tsx file ".bagel" = "tsx" ``` Bun supports the following loaders: * `jsx` * `js` * `ts` * `tsx` * `css` * `file` * `json` * `toml` * `wasm` * `napi` * `base64` * `dataurl` * `text` ### `telemetry` The `telemetry` field is used to enable/disable analytics. By default, telemetry is enabled. This is equivalent to the `DO_NOT_TRACK` environment variable. Currently we do not collect telemetry and this setting is only used for enabling/disabling anonymous crash reports, but in the future we plan to collect information like which Bun APIs are used most or how long `bun build` takes. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} telemetry = false ``` ### `env` Configure automatic `.env` file loading. By default, Bun automatically loads `.env` files. To disable this behavior: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} # Disable automatic .env file loading env = false ``` You can also use object syntax with the `file` property: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [env] file = false ``` This is useful in production environments or CI/CD pipelines where you want to rely solely on system environment variables. Note: Explicitly provided environment files via `--env-file` will still be loaded even when default loading is disabled. ### `console` Configure console output behavior. #### `console.depth` Set the default depth for `console.log()` object inspection. Default `2`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [console] depth = 3 ``` This controls how deeply nested objects are displayed in console output. Higher values show more nested properties but may produce verbose output for complex objects. This setting can be overridden by the `--console-depth` CLI flag. ## Test runner The test runner is configured under the `[test]` section of your bunfig.toml. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # configuration goes here ``` ### `test.root` The root directory to run tests from. Default `.`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] root = "./__tests__" ``` ### `test.preload` Same as the top-level `preload` field, but only applies to `bun test`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] preload = ["./setup.ts"] ``` ### `test.smol` Same as the top-level `smol` field, but only applies to `bun test`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] smol = true ``` ### `test.coverage` Enables coverage reporting. Default `false`. Use `--coverage` to override. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] coverage = false ``` ### `test.coverageThreshold` To specify a coverage threshold. By default, no threshold is set. If your test suite does not meet or exceed this threshold, `bun test` will exit with a non-zero exit code to indicate the failure. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # to require 90% line-level and function-level coverage coverageThreshold = 0.9 ``` Different thresholds can be specified for line-wise, function-wise, and statement-wise coverage. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] coverageThreshold = { line = 0.7, function = 0.8, statement = 0.9 } ``` ### `test.coverageSkipTestFiles` Whether to skip test files when computing coverage statistics. Default `false`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] coverageSkipTestFiles = false ``` ### `test.coveragePathIgnorePatterns` Exclude specific files or file patterns from coverage reports using glob patterns. Can be a single string pattern or an array of patterns. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # Single pattern coveragePathIgnorePatterns = "**/*.spec.ts" # Multiple patterns coveragePathIgnorePatterns = [ "**/*.spec.ts", "**/*.test.ts", "src/utils/**", "*.config.js" ] ``` ### `test.coverageReporter` By default, coverage reports will be printed to the console. For persistent code coverage reports in CI environments and for other tools use `lcov`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] coverageReporter = ["text", "lcov"] # default ["text"] ``` ### `test.coverageDir` Set path where coverage reports will be saved. Please notice, that it works only for persistent `coverageReporter` like `lcov`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] coverageDir = "path/to/somewhere" # default "coverage" ``` ### `test.randomize` Run tests in random order. Default `false`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] randomize = true ``` This helps catch bugs related to test interdependencies by running tests in a different order each time. When combined with `seed`, the random order becomes reproducible. The `--randomize` CLI flag will override this setting when specified. ### `test.seed` Set the random seed for test randomization. This option requires `randomize` to be `true`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] randomize = true seed = 2444615283 ``` Using a seed makes the randomized test order reproducible across runs, which is useful for debugging flaky tests. When you encounter a test failure with randomization enabled, you can use the same seed to reproduce the exact test order. The `--seed` CLI flag will override this setting when specified. ### `test.rerunEach` Re-run each test file a specified number of times. Default `0` (run once). ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] rerunEach = 3 ``` This is useful for catching flaky tests or non-deterministic behavior. Each test file will be executed the specified number of times. The `--rerun-each` CLI flag will override this setting when specified. ### `test.concurrentTestGlob` Specify a glob pattern to automatically run matching test files with concurrent test execution enabled. Test files matching this pattern will behave as if the `--concurrent` flag was passed, running all tests within those files concurrently. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] concurrentTestGlob = "**/concurrent-*.test.ts" ``` This is useful for: * Gradually migrating test suites to concurrent execution * Running integration tests concurrently while keeping unit tests sequential * Separating fast concurrent tests from tests that require sequential execution The `--concurrent` CLI flag will override this setting when specified. ### `test.onlyFailures` When enabled, only failed tests are displayed in the output. This helps reduce noise in large test suites by hiding passing tests. Default `false`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] onlyFailures = true ``` This is equivalent to using the `--only-failures` flag when running `bun test`. ### `test.reporter` Configure the test reporter settings. #### `test.reporter.dots` Enable the dots reporter, which displays a compact output showing a dot for each test. Default `false`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test.reporter] dots = true ``` #### `test.reporter.junit` Enable JUnit XML reporting and specify the output file path. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test.reporter] junit = "test-results.xml" ``` This generates a JUnit XML report that can be consumed by CI systems and other tools. ## Package manager Package management is a complex issue; to support a range of use cases, the behavior of `bun install` can be configured under the `[install]` section. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] # configuration here ``` ### `install.optional` Whether to install optional dependencies. Default `true`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] optional = true ``` ### `install.dev` Whether to install development dependencies. Default `true`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] dev = true ``` ### `install.peer` Whether to install peer dependencies. Default `true`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] peer = true ``` ### `install.production` Whether `bun install` will run in "production mode". Default `false`. In production mode, `"devDependencies"` are not installed. You can use `--production` in the CLI to override this setting. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] production = false ``` ### `install.exact` Whether to set an exact version in `package.json`. Default `false`. By default Bun uses caret ranges; if the `latest` version of a package is `2.4.1`, the version range in your `package.json` will be `^2.4.1`. This indicates that any version from `2.4.1` up to (but not including) `3.0.0` is acceptable. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] exact = false ``` ### `install.saveTextLockfile` If false, generate a binary `bun.lockb` instead of a text-based `bun.lock` file when running `bun install` and no lockfile is present. Default `true` (since Bun v1.2). ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] saveTextLockfile = false ``` ### `install.auto` To configure Bun's package auto-install behavior. Default `"auto"` — when no `node_modules` folder is found, Bun will automatically install dependencies on the fly during execution. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] auto = "auto" ``` Valid values are: | Value | Description | | ------------ | ----------------------------------------------------------------------------------------------------------------------------------- | | `"auto"` | Resolve modules from local `node_modules` if it exists. Otherwise, auto-install dependencies on the fly. | | `"force"` | Always auto-install dependencies, even if `node_modules` exists. | | `"disable"` | Never auto-install dependencies. | | `"fallback"` | Check local `node_modules` first, then auto-install any packages that aren't found. You can enable this from the CLI with `bun -i`. | ### `install.frozenLockfile` When true, `bun install` will not update `bun.lock`. Default `false`. If `package.json` and the existing `bun.lock` are not in agreement, this will error. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] frozenLockfile = false ``` ### `install.dryRun` Whether `bun install` will actually install dependencies. Default `false`. When true, it's equivalent to setting `--dry-run` on all `bun install` commands. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] dryRun = false ``` ### `install.globalDir` To configure the directory where Bun puts globally installed packages. Environment variable: `BUN_INSTALL_GLOBAL_DIR` ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] # where `bun install --global` installs packages globalDir = "~/.bun/install/global" ``` ### `install.globalBinDir` To configure the directory where Bun installs globally installed binaries and CLIs. Environment variable: `BUN_INSTALL_BIN` ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] # where globally-installed package bins are linked globalBinDir = "~/.bun/bin" ``` ### `install.registry` The default registry is `https://registry.npmjs.org/`. This can be globally configured in `bunfig.toml`: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] # set default registry as a string registry = "https://registry.npmjs.org" # set a token registry = { url = "https://registry.npmjs.org", token = "123456" } # set a username/password registry = "https://username:password@registry.npmjs.org" ``` ### `install.linkWorkspacePackages` To configure how workspace packages are linked, use the `install.linkWorkspacePackages` option. Whether to link workspace packages from the monorepo root to their respective `node_modules` directories. Default `true`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] linkWorkspacePackages = true ``` ### `install.scopes` To configure a registry for a particular scope (e.g. `@myorg/`) use `install.scopes`. You can reference environment variables with `$variable` notation. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install.scopes] # registry as string myorg = "https://username:password@registry.myorg.com/" # registry with username/password # you can reference environment variables myorg = { username = "myusername", password = "$npm_password", url = "https://registry.myorg.com/" } # registry with token myorg = { token = "$npm_token", url = "https://registry.myorg.com/" } ``` ### `install.ca` and `install.cafile` To configure a CA certificate, use `install.ca` or `install.cafile` to specify a path to a CA certificate file. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] # The CA certificate as a string ca = "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----" # A path to a CA certificate file. The file can contain multiple certificates. cafile = "path/to/cafile" ``` ### `install.cache` To configure the cache behavior: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install.cache] # the directory to use for the cache dir = "~/.bun/install/cache" # when true, don't load from the global cache. # Bun may still write to node_modules/.cache disable = false # when true, always resolve the latest versions from the registry disableManifest = false ``` ### `install.lockfile` To configure lockfile behavior, use the `install.lockfile` section. Whether to generate a lockfile on `bun install`. Default `true`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install.lockfile] save = true ``` Whether to generate a non-Bun lockfile alongside `bun.lock`. (A `bun.lock` will always be created.) Currently `"yarn"` is the only supported value. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install.lockfile] print = "yarn" ``` ### `install.linker` Configure the linker strategy for installing dependencies. Defaults to `"isolated"` for new workspaces, `"hoisted"` for new single-package projects and existing projects (made pre-v1.3.2). For complete documentation refer to [Package manager > Isolated installs](/pm/isolated-installs). ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] linker = "hoisted" ``` Valid values are: | Value | Description | | ------------ | ------------------------------------------------------- | | `"hoisted"` | Link dependencies in a shared `node_modules` directory. | | `"isolated"` | Link dependencies inside each package installation. | ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [debug] # When navigating to a blob: or src: link, open the file in your editor # If not, it tries $EDITOR or $VISUAL # If that still fails, it will try Visual Studio Code, then Sublime Text, then a few others # This is used by Bun.openInEditor() editor = "code" # List of editors: # - "subl", "sublime" # - "vscode", "code" # - "textmate", "mate" # - "idea" # - "webstorm" # - "nvim", "neovim" # - "vim","vi" # - "emacs" ``` ### `install.security.scanner` Configure a security scanner to scan packages for vulnerabilities before installation. First, install a security scanner from npm: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun add -d @acme/bun-security-scanner ``` Then configure it in your `bunfig.toml`: ```toml bunfig.toml icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install.security] scanner = "@acme/bun-security-scanner" ``` When a security scanner is configured: * Auto-install is automatically disabled for security * Packages are scanned before installation * Installation is cancelled if fatal issues are found * Security warnings are displayed during installation Learn more about [using and writing security scanners](/pm/security-scanner-api). ### `install.minimumReleaseAge` Configure a minimum age (in seconds) for npm package versions. Package versions published more recently than this threshold will be filtered out during installation. Default is `null` (disabled). ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] # Only install package versions published at least 3 days ago minimumReleaseAge = 259200 # These packages will bypass the 3-day minimum age requirement minimumReleaseAgeExcludes = ["@types/bun", "typescript"] ``` For more details see [Minimum release age](/pm/cli/install#minimum-release-age) in the install documentation. ## `bun run` The `bun run` command can be configured under the `[run]` section. These apply to the `bun run` command and the `bun` command when running a file or executable or script. Currently, `bunfig.toml` is only automatically loaded for `bun run` in a local project (it doesn't check for a global `.bunfig.toml`). ### `run.shell` - use the system shell or Bun's shell The shell to use when running package.json scripts via `bun run` or `bun`. On Windows, this defaults to `"bun"` and on other platforms it defaults to `"system"`. To always use the system shell instead of Bun's shell (default behavior unless Windows): ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [run] # default outside of Windows shell = "system" ``` To always use Bun's shell instead of the system shell: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [run] # default on Windows shell = "bun" ``` ### `run.bun` - auto alias `node` to `bun` When `true`, this prepends `$PATH` with a `node` symlink that points to the `bun` binary for all scripts or executables invoked by `bun run` or `bun`. This means that if you have a script that runs `node`, it will actually run `bun` instead, without needing to change your script. This works recursively, so if your script runs another script that runs `node`, it will also run `bun` instead. This applies to shebangs as well, so if you have a script with a shebang that points to `node`, it will actually run `bun` instead. By default, this is enabled if `node` is not already in your `$PATH`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [run] # equivalent to `bun --bun` for all `bun run` commands bun = true ``` You can test this by running: ```sh theme={"theme":{"light":"github-light","dark":"dracula"}} bun --bun which node # /path/to/bun bun which node # /path/to/node ``` This option is equivalent to prefixing all `bun run` commands with `--bun`: ```sh theme={"theme":{"light":"github-light","dark":"dracula"}} bun --bun run dev bun --bun dev bun run --bun dev ``` If set to `false`, this will disable the `node` symlink. ### `run.silent` - suppress reporting the command being run When `true`, suppresses the output of the command being run by `bun run` or `bun`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [run] silent = true ``` Without this option, the command being run will be printed to the console: ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun run dev echo "Running \"dev\"..." ``` ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} Running "dev"... ``` With this option, the command being run will not be printed to the console: ```sh theme={"theme":{"light":"github-light","dark":"dracula"}} bun run dev ``` ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} Running "dev"... ``` This is equivalent to passing `--silent` to all `bun run` commands: ```sh theme={"theme":{"light":"github-light","dark":"dracula"}} bun --silent run dev bun --silent dev bun run --silent dev ``` --- # Source: https://bun.com/docs/pm/bunx.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # bunx > Run packages from npm `bunx` is an alias for `bun x`. The `bunx` CLI will be auto-installed when you install `bun`. Use `bunx` to auto-install and run packages from `npm`. It's Bun's equivalent of `npx` or `yarn dlx`. ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bunx cowsay "Hello world!" ``` ⚡️ **Speed** — With Bun's fast startup times, `bunx` is [roughly 100x faster](https://twitter.com/jarredsumner/status/1606163655527059458) than `npx` for locally installed packages. Packages can declare executables in the `"bin"` field of their `package.json`. These are known as *package executables* or *package binaries*. ```json package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} { // ... other fields "name": "my-cli", "bin": { "my-cli": "dist/index.js" } } ``` These executables are commonly plain JavaScript files marked with a [shebang line](https://en.wikipedia.org/wiki/Shebang_\(Unix\)) to indicate which program should be used to execute them. The following file indicates that it should be executed with `node`. ```js dist/index.js icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/javascript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=81efd0ad0d779debfa163bfd906ef6a6" theme={"theme":{"light":"github-light","dark":"dracula"}} #!/usr/bin/env node console.log("Hello world!"); ``` These executables can be run with `bunx`, ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bunx my-cli ``` As with `npx`, `bunx` will check for a locally installed package first, then fall back to auto-installing the package from `npm`. Installed packages will be stored in Bun's global cache for future use. ## Arguments and flags To pass additional command-line flags and arguments through to the executable, place them after the executable name. ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bunx my-cli --foo bar ``` *** ## Shebangs By default, Bun respects shebangs. If an executable is marked with `#!/usr/bin/env node`, Bun will spin up a `node` process to execute the file. However, in some cases it may be desirable to run executables using Bun's runtime, even if the executable indicates otherwise. To do so, include the `--bun` flag. ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bunx --bun my-cli ``` The `--bun` flag must occur *before* the executable name. Flags that appear *after* the name are passed through to the executable. ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bunx --bun my-cli # good bunx my-cli --bun # bad ``` ## Package flag **`--package ` or `-p `** - Run binary from specific package. Useful when binary name differs from package name: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bunx -p renovate renovate-config-validator bunx --package @angular/cli ng ``` To force bun to always be used with a script, use a shebang. ```js dist/index.js icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/javascript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=81efd0ad0d779debfa163bfd906ef6a6" theme={"theme":{"light":"github-light","dark":"dracula"}} #!/usr/bin/env bun ``` *** ## Usage ```bash theme={"theme":{"light":"github-light","dark":"dracula"}} bunx [flags] [@version] [flags and arguments for the package] ``` Execute an npm package executable (CLI), automatically installing into a global shared cache if not installed in `node_modules`. ### Flags Force the command to run with Bun instead of Node.js, even if the executable contains a Node shebang (`#!/usr/bin/env node`) Specify package to install when binary name differs from package name Skip installation if package is not already installed Enable verbose output during installation Suppress output during installation ### Examples ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} # Run Prisma migrations bunx prisma migrate # Format a file with Prettier bunx prettier foo.js # Run a specific version of a package bunx uglify-js@3.14.0 app.js # Use --package when binary name differs from package name bunx -p @angular/cli ng new my-app # Force running with Bun instead of Node.js, even if the executable contains a Node shebang bunx --bun vite dev foo.js ``` --- # Source: https://bun.com/docs/bundler/bytecode.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Bytecode Caching > Speed up JavaScript execution with bytecode caching in Bun's bundler Bytecode caching is a build-time optimization that dramatically improves application startup time by pre-compiling your JavaScript to bytecode. For example, when compiling TypeScript's `tsc` with bytecode enabled, startup time improves by **2x**. ## Usage ### Basic usage (CommonJS) Enable bytecode caching with the `--bytecode` flag. Without `--format`, this defaults to CommonJS: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun build ./index.ts --target=bun --bytecode --outdir=./dist ``` This generates two files: * `dist/index.js` - Your bundled JavaScript (CommonJS) * `dist/index.jsc` - The bytecode cache file At runtime, Bun automatically detects and uses the `.jsc` file: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun ./dist/index.js # Automatically uses index.jsc ``` ### With standalone executables When creating executables with `--compile`, bytecode is embedded into the binary. Both ESM and CommonJS formats are supported: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} # ESM (requires --compile) bun build ./cli.ts --compile --bytecode --format=esm --outfile=mycli # CommonJS (works with or without --compile) bun build ./cli.ts --compile --bytecode --outfile=mycli ``` The resulting executable contains both the code and bytecode, giving you maximum performance in a single file. ### ESM bytecode ESM bytecode requires `--compile` because Bun embeds module metadata (import/export information) in the compiled binary. This metadata allows the JavaScript engine to skip parsing entirely at runtime. Without `--compile`, ESM bytecode would still require parsing the source to analyze module dependencies—defeating the purpose of bytecode caching. ### Combining with other optimizations Bytecode works great with minification and source maps: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun build --compile --bytecode --minify --sourcemap ./cli.ts --outfile=mycli ``` * `--minify` reduces code size before generating bytecode (less code -> less bytecode) * `--sourcemap` preserves error reporting (errors still point to original source) * `--bytecode` eliminates parsing overhead ## Performance impact The performance improvement scales with your codebase size: | Application size | Typical startup improvement | | ------------------------- | --------------------------- | | Small CLI (\< 100 KB) | 1.5-2x faster | | Medium-large app (> 5 MB) | 2.5x-4x faster | Larger applications benefit more because they have more code to parse. ## When to use bytecode ### Great for: #### CLI tools * Invoked frequently (linters, formatters, git hooks) * Startup time is the entire user experience * Users notice the difference between 90ms and 45ms startup * Example: TypeScript compiler, Prettier, ESLint #### Build tools and task runners * Run hundreds or thousands of times during development * Milliseconds saved per run compound quickly * Developer experience improvement * Example: Build scripts, test runners, code generators #### Standalone executables * Distributed to users who care about snappy performance * Single-file distribution is convenient * File size less important than startup time * Example: CLIs distributed via npm or as binaries ### Skip it for: * ❌ **Small scripts** * ❌ **Code that runs once** * ❌ **Development builds** * ❌ **Size-constrained environments** ## Limitations ### Version compatibility Bytecode is **not portable across Bun versions**. The bytecode format is tied to JavaScriptCore's internal representation, which changes between versions. When you update Bun, you must regenerate bytecode: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} # After updating Bun bun build --bytecode ./index.ts --outdir=./dist ``` If bytecode doesn't match the current Bun version, it's automatically ignored and your code falls back to parsing the JavaScript source. Your app still runs - you just lose the performance optimization. **Best practice**: Generate bytecode as part of your CI/CD build process. Don't commit `.jsc` files to git. Regenerate them whenever you update Bun. ### Source code still required * The `.js` file (your bundled source code) * The `.jsc` file (the bytecode cache) At runtime: 1. Bun loads the `.js` file, sees a `@bytecode` pragma, and checks the `.jsc` file 2. Bun loads the `.jsc` file 3. Bun validates the bytecode hash matches the source 4. If valid, Bun uses the bytecode 5. If invalid, Bun falls back to parsing the source ### Bytecode is not obfuscation Bytecode **does not obscure your source code**. It's an optimization, not a security measure. ## Production deployment ### Docker Include bytecode generation in your Dockerfile: ```dockerfile Dockerfile icon="docker" theme={"theme":{"light":"github-light","dark":"dracula"}} FROM oven/bun:1 AS builder WORKDIR /app COPY package.json bun.lock ./ RUN bun install --frozen-lockfile COPY . . RUN bun build --bytecode --minify --sourcemap \ --target=bun \ --outdir=./dist \ --compile \ ./src/server.ts --outfile=./dist/server FROM oven/bun:1 AS runner WORKDIR /app COPY --from=builder /dist/server /app/server CMD ["./server"] ``` The bytecode is architecture-independent. ### CI/CD Generate bytecode during your build pipeline: ```yaml workflow.yml icon="file-code" theme={"theme":{"light":"github-light","dark":"dracula"}} # GitHub Actions - name: Build with bytecode run: | bun install bun build --bytecode --minify \ --outdir=./dist \ --target=bun \ ./src/index.ts ``` ## Debugging ### Verify bytecode is being used Check that the `.jsc` file exists: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} ls -lh dist/ ``` ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} -rw-r--r-- 1 user staff 245K index.js -rw-r--r-- 1 user staff 1.1M index.jsc ``` The `.jsc` file should be 2-8x larger than the `.js` file. To log if bytecode is being used, set `BUN_JSC_verboseDiskCache=1` in your environment. On success, it will log something like: ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} [Disk cache] cache hit for sourceCode ``` If you see a cache miss, it will log something like: ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} [Disk cache] cache miss for sourceCode ``` It's normal for it it to log a cache miss multiple times since Bun doesn't currently bytecode cache JavaScript code used in builtin modules. ### Common issues **Bytecode silently ignored**: Usually caused by a Bun version update. The cache version doesn't match, so bytecode is rejected. Regenerate to fix. **File size too large**: This is expected. Consider: * Using `--minify` to reduce code size before bytecode generation * Compressing `.jsc` files for network transfer (gzip/brotli) * Evaluating if the startup performance gain is worth the size increase ## What is bytecode? When you run JavaScript, the JavaScript engine doesn't execute your source code directly. Instead, it goes through several steps: 1. **Parsing**: The engine reads your JavaScript source code and converts it into an Abstract Syntax Tree (AST) 2. **Bytecode compilation**: The AST is compiled into bytecode - a lower-level representation that's faster to execute 3. **Execution**: The bytecode is executed by the engine's interpreter or JIT compiler Bytecode is an intermediate representation - it's lower-level than JavaScript source code, but higher-level than machine code. Think of it as assembly language for a virtual machine. Each bytecode instruction represents a single operation like "load this variable," "add two numbers," or "call this function." This happens **every single time** you run your code. If you have a CLI tool that runs 100 times a day, your code gets parsed 100 times. If you have a serverless function with frequent cold starts, parsing happens on every cold start. With bytecode caching, Bun moves steps 1 and 2 to the build step. At runtime, the engine loads the pre-compiled bytecode and jumps straight to execution. ### Why lazy parsing makes this even better Modern JavaScript engines use a clever optimization called **lazy parsing**. They don't parse all your code upfront - instead, functions are only parsed when they're first called: ```js theme={"theme":{"light":"github-light","dark":"dracula"}} // Without bytecode caching: function rarely_used() { // This 500-line function is only parsed // when it's actually called } function main() { console.log("Starting app"); // rarely_used() is never called, so it's never parsed } ``` This means parsing overhead isn't just a startup cost - it happens throughout your application's lifetime as different code paths execute. With bytecode caching, **all functions are pre-compiled**, even the ones that are lazily parsed. The parsing work happens once at build time instead of being distributed throughout your application's execution. ## The bytecode format ### Inside a .jsc file A `.jsc` file contains a serialized bytecode structure. Understanding what's inside helps explain both the performance benefits and the file size tradeoff. **Header section** (validated on every load): * **Cache version**: A hash tied to the JavaScriptCore framework version. This ensures bytecode generated with one version of Bun only runs with that exact version. * **Code block type tag**: Identifies whether this is a Program, Module, Eval, or Function code block. **SourceCodeKey** (validates bytecode matches source): * **Source code hash**: A hash of the original JavaScript source code. Bun verifies this matches before using the bytecode. * **Source code length**: The exact length of the source, for additional validation. * **Compilation flags**: Critical compilation context like strict mode, whether it's a script vs module, eval context type, etc. The same source code compiled with different flags produces different bytecode. **Bytecode instructions**: * **Instruction stream**: The actual bytecode opcodes - the compiled representation of your JavaScript. This is a variable-length sequence of bytecode instructions. * **Metadata table**: Each opcode has associated metadata - things like profiling counters, type hints, and execution counts (even if not yet populated). * **Jump targets**: Pre-computed addresses for control flow (if/else, loops, switch statements). * **Switch tables**: Optimized lookup tables for switch statements. **Constants and identifiers**: * **Constant pool**: All literal values in your code - numbers, strings, booleans, null, undefined. These are stored as actual JavaScript values (JSValues) so they don't need to be parsed from source at runtime. * **Identifier table**: All variable and function names used in the code. Stored as deduplicated strings. * **Source code representation markers**: Flags indicating how constants should be represented (as integers, doubles, big ints, etc.). **Function metadata** (for each function in your code): * **Register allocation**: How many registers (local variables) the function needs - `thisRegister`, `scopeRegister`, `numVars`, `numCalleeLocals`, `numParameters`. * **Code features**: A bitmask of function characteristics: is it a constructor? an arrow function? does it use `super`? does it have tail calls? These affect how the function is executed. * **Lexically scoped features**: Strict mode and other lexical context. * **Parse mode**: The mode in which the function was parsed (normal, async, generator, async generator). **Nested structures**: * **Function declarations and expressions**: Each nested function gets its own bytecode block, recursively. A file with 100 functions has 100 separate bytecode blocks, all nested in the structure. * **Exception handlers**: Try/catch/finally blocks with their boundaries and handler addresses pre-computed. * **Expression info**: Maps bytecode positions back to source code locations for error reporting and debugging. ### What bytecode does NOT contain Importantly, **bytecode does not embed your source code**. Instead: * The JavaScript source is stored separately (in the `.js` file) * The bytecode only stores a hash and length of the source * At load time, Bun validates the bytecode matches the current source code This is why you need to deploy both the `.js` and `.jsc` files. The `.jsc` file is useless without its corresponding `.js` file. ## The tradeoff: file size Bytecode files are significantly larger than source code - typically 2-8x larger. ### Why is bytecode so much larger? **Bytecode instructions are verbose**: A single line of minified JavaScript might compile to dozens of bytecode instructions. For example: ```js theme={"theme":{"light":"github-light","dark":"dracula"}} const sum = arr.reduce((a, b) => a + b, 0); ``` Compiles to bytecode that: * Loads the `arr` variable * Gets the `reduce` property * Creates the arrow function (which itself has bytecode) * Loads the initial value `0` * Sets up the call with the right number of arguments * Actually performs the call * Stores the result in `sum` Each of these steps is a separate bytecode instruction with its own metadata. **Constant pools store everything**: Every string literal, number, property name - everything gets stored in the constant pool. Even if your source code has `"hello"` a hundred times, the constant pool stores it once, but the identifier table and constant references add overhead. **Per-function metadata**: Each function - even small one-line functions - gets its own complete metadata: * Register allocation info * Code features bitmask * Parse mode * Exception handlers * Expression info for debugging A file with 1,000 small functions has 1,000 sets of metadata. **Profiling data structures**: Even though profiling data isn't populated yet, the *structures* to hold profiling data are allocated. This includes: * Value profile slots (tracking what types flow through each operation) * Array profile slots (tracking array access patterns) * Binary arithmetic profile slots (tracking number types in math operations) * Unary arithmetic profile slots These take up space even when empty. **Pre-computed control flow**: Jump targets, switch tables, and exception handler boundaries are all pre-computed and stored. This makes execution faster but increases file size. ### Mitigation strategies **Compression**: Bytecode compresses extremely well with gzip/brotli (60-70% compression). The repetitive structure and metadata compress efficiently. **Minification first**: Using `--minify` before bytecode generation helps: * Shorter identifiers → smaller identifier table * Dead code elimination → less bytecode generated * Constant folding → fewer constants in the pool **The tradeoff**: You're trading 2-4x larger files for 2-4x faster startup. For CLIs, this is usually worth it. For long-running servers where a few megabytes of disk space don't matter, it's even less of an issue. ## Versioning and portability ### Cross-architecture portability: ✅ Bytecode is **architecture-independent**. You can: * Build on macOS ARM64, deploy to Linux x64 * Build on Linux x64, deploy to AWS Lambda ARM64 * Build on Windows x64, deploy to macOS ARM64 The bytecode contains abstract instructions that work on any architecture. Architecture-specific optimizations happen during JIT compilation at runtime, not in the cached bytecode. ### Cross-version portability: ❌ Bytecode is **not stable across Bun versions**. Here's why: **Bytecode format changes**: JavaScriptCore's bytecode format evolves. New opcodes get added, old ones get removed or changed, metadata structures change. Each version of JavaScriptCore has a different bytecode format. **Version validation**: The cache version in the `.jsc` file header is a hash of the JavaScriptCore framework. When Bun loads bytecode: 1. It extracts the cache version from the `.jsc` file 2. It computes the current JavaScriptCore version 3. If they don't match, the bytecode is **silently rejected** 4. Bun falls back to parsing the `.js` source code Your application still runs - you just lose the performance optimization. **Graceful degradation**: This design means bytecode caching "fails open" - if anything goes wrong (version mismatch, corrupted file, missing file), your code still runs normally. You might see slower startup, but you won't see errors. ## Unlinked vs. linked bytecode JavaScriptCore makes a crucial distinction between "unlinked" and "linked" bytecode. This separation is what makes bytecode caching possible: ### Unlinked bytecode (what's cached) The bytecode saved in `.jsc` files is **unlinked bytecode**. It contains: * The compiled bytecode instructions * Structural information about the code * Constants and identifiers * Control flow information But it **doesn't** contain: * Pointers to actual runtime objects * JIT-compiled machine code * Profiling data from previous runs * Call link information (which functions call which) Unlinked bytecode is **immutable and shareable**. Multiple executions of the same code can all reference the same unlinked bytecode. ### Linked bytecode (runtime execution) When Bun runs bytecode, it "links" it - creating a runtime wrapper that adds: * **Call link information**: As your code runs, the engine learns which functions call which and optimizes those call sites. * **Profiling data**: The engine tracks how many times each instruction executes, what types of values flow through the code, array access patterns, etc. * **JIT compilation state**: References to baseline JIT or optimizing JIT (DFG/FTL) compiled versions of hot code. * **Runtime objects**: Pointers to actual JavaScript objects, prototypes, scopes, etc. This linked representation is created fresh every time you run your code. This allows: 1. **Caching the expensive work** (parsing and compilation to unlinked bytecode) 2. **Still collecting runtime profiling data** to guide optimizations 3. **Still applying JIT optimizations** based on actual execution patterns Bytecode caching moves expensive work (parsing and compiling to bytecode) from runtime to build time. For applications that start frequently, this can halve your startup time at the cost of larger files on disk. For production CLIs and serverless deployments, the combination of `--bytecode --minify --sourcemap` gives you the best performance while maintaining debuggability. --- # Source: https://bun.com/docs/runtime/c-compiler.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # C Compiler > Compile and run C from JavaScript with low overhead `bun:ffi` has experimental support for compiling and running C from JavaScript with low overhead. *** ## Usage (cc in `bun:ffi`) See the [introduction blog post](https://bun.com/blog/compile-and-run-c-in-js) for more information. JavaScript: ```ts hello.ts icon="file-code" theme={"theme":{"light":"github-light","dark":"dracula"}} import { cc } from "bun:ffi"; import source from "./hello.c" with { type: "file" }; const { symbols: { hello }, } = cc({ source, symbols: { hello: { args: [], returns: "int", }, }, }); console.log("What is the answer to the universe?", hello()); ``` C source: ```c hello.c theme={"theme":{"light":"github-light","dark":"dracula"}} int hello() { return 42; } ``` When you run `hello.js`, it will print: ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun hello.js What is the answer to the universe? 42 ``` Under the hood, `cc` uses [TinyCC](https://bellard.org/tcc/) to compile the C code and then link it with the JavaScript runtime, efficiently converting types in-place. ### Primitive types The same `FFIType` values in [`dlopen`](/runtime/ffi) are supported in `cc`. | `FFIType` | C Type | Aliases | | ----------- | -------------- | --------------------------- | | cstring | `char*` | | | function | `(void*)(*)()` | `fn`, `callback` | | ptr | `void*` | `pointer`, `void*`, `char*` | | i8 | `int8_t` | `int8_t` | | i16 | `int16_t` | `int16_t` | | i32 | `int32_t` | `int32_t`, `int` | | i64 | `int64_t` | `int64_t` | | i64\_fast | `int64_t` | | | u8 | `uint8_t` | `uint8_t` | | u16 | `uint16_t` | `uint16_t` | | u32 | `uint32_t` | `uint32_t` | | u64 | `uint64_t` | `uint64_t` | | u64\_fast | `uint64_t` | | | f32 | `float` | `float` | | f64 | `double` | `double` | | bool | `bool` | | | char | `char` | | | napi\_env | `napi_env` | | | napi\_value | `napi_value` | | ### Strings, objects, and non-primitive types To make it easier to work with strings, objects, and other non-primitive types that don't map 1:1 to C types, `cc` supports N-API. To pass or receive a JavaScript values without any type conversions from a C function, you can use `napi_value`. You can also pass a `napi_env` to receive the N-API environment used to call the JavaScript function. #### Returning a C string to JavaScript For example, if you have a string in C, you can return it to JavaScript like this: ```ts hello.ts theme={"theme":{"light":"github-light","dark":"dracula"}} import { cc } from "bun:ffi"; import source from "./hello.c" with { type: "file" }; const { symbols: { hello }, } = cc({ source, symbols: { hello: { args: ["napi_env"], returns: "napi_value", }, }, }); const result = hello(); ``` And in C: ```c hello.c theme={"theme":{"light":"github-light","dark":"dracula"}} #include napi_value hello(napi_env env) { napi_value result; napi_create_string_utf8(env, "Hello, Napi!", NAPI_AUTO_LENGTH, &result); return result; } ``` You can also use this to return other types like objects and arrays: ```c hello.c theme={"theme":{"light":"github-light","dark":"dracula"}} #include napi_value hello(napi_env env) { napi_value result; napi_create_object(env, &result); return result; } ``` ### `cc` Reference #### `library: string[]` The `library` array is used to specify the libraries that should be linked with the C code. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} type Library = string[]; cc({ source: "hello.c", library: ["sqlite3"], }); ``` #### `symbols` The `symbols` object is used to specify the functions and variables that should be exposed to JavaScript. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} type Symbols = { [key: string]: { args: FFIType[]; returns: FFIType; }; }; ``` #### `source` The `source` is a file path to the C code that should be compiled and linked with the JavaScript runtime. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} type Source = string | URL | BunFile; cc({ source: "hello.c", symbols: { hello: { args: [], returns: "int", }, }, }); ``` #### `flags: string | string[]` The `flags` is an optional array of strings that should be passed to the TinyCC compiler. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} type Flags = string | string[]; ``` These are flags like `-I` for include directories and `-D` for preprocessor definitions. #### `define: Record` The `define` is an optional object that should be passed to the TinyCC compiler. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} type Defines = Record; cc({ source: "hello.c", define: { NDEBUG: "1", }, }); ``` These are preprocessor definitions passed to the TinyCC compiler. --- # Source: https://bun.com/docs/guides/write-file/cat.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Write a file to stdout Bun exposes `stdout` as a `BunFile` with the `Bun.stdout` property. This can be used as a destination for [`Bun.write()`](/runtime/file-io#writing-files-bun-write). This code writes a file to `stdout` similar to the `cat` command in Unix. ```ts cat.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const path = "/path/to/file.txt"; const file = Bun.file(path); await Bun.write(Bun.stdout, file); ``` *** See [Docs > API > File I/O](/runtime/file-io#writing-files-bun-write) for complete documentation of `Bun.write()`. --- # Source: https://bun.com/docs/pm/catalogs.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Catalogs > Share common dependency versions across multiple packages in a monorepo Catalogs in Bun provide a straightforward way to share common dependency versions across multiple packages in a monorepo. Rather than specifying the same versions repeatedly in each workspace package, you define them once in the root package.json and reference them consistently throughout your project. ## Overview Unlike traditional dependency management where each workspace package needs to independently specify versions, catalogs let you: 1. Define version catalogs in the root package.json 2. Reference these versions with a simple `catalog:` protocol 3. Update all packages simultaneously by changing the version in just one place This is especially useful in large monorepos where dozens of packages need to use the same version of key dependencies. ## How to Use Catalogs ### Directory Structure Example Consider a monorepo with the following structure: ``` my-monorepo/ ├── package.json ├── bun.lock └── packages/ ├── app/ │ └── package.json ├── ui/ │ └── package.json └── utils/ └── package.json ``` ### 1. Define Catalogs in Root package.json In your root-level `package.json`, add a `catalog` or `catalogs` field within the `workspaces` object: ```json package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} { "name": "my-monorepo", "workspaces": { "packages": ["packages/*"], "catalog": { "react": "^19.0.0", "react-dom": "^19.0.0" }, "catalogs": { "testing": { "jest": "30.0.0", "testing-library": "14.0.0" } } } } ``` If you put `catalog` or `catalogs` at the top level of the `package.json` file, that will work too. ### 2. Reference Catalog Versions in Workspace Packages In your workspace packages, use the `catalog:` protocol to reference versions: ```json packages/app/package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} { "name": "app", "dependencies": { "react": "catalog:", "react-dom": "catalog:", "jest": "catalog:testing" } } ``` ```json packages/ui/package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} { "name": "ui", "dependencies": { "react": "catalog:", "react-dom": "catalog:" }, "devDependencies": { "jest": "catalog:testing", "testing-library": "catalog:testing" } } ``` ### 3. Run Bun Install Run `bun install` to install all dependencies according to the catalog versions. ## Catalog vs Catalogs Bun supports two ways to define catalogs: 1. **`catalog`** (singular): A single default catalog for commonly used dependencies ```json package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} "catalog": { "react": "^19.0.0", "react-dom": "^19.0.0" } ``` Reference with simply `catalog:`: ```json packages/app/package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} "dependencies": { "react": "catalog:" } ``` 2. **`catalogs`** (plural): Multiple named catalogs for grouping dependencies ```json package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} "catalogs": { "testing": { "jest": "30.0.0" }, "ui": { "tailwind": "4.0.0" } } ``` Reference with `catalog:`: ```json packages/app/package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} "dependencies": { "jest": "catalog:testing", "tailwind": "catalog:ui" } ``` ## Benefits of Using Catalogs * **Consistency**: Ensures all packages use the same version of critical dependencies * **Maintenance**: Update a dependency version in one place instead of across multiple package.json files * **Clarity**: Makes it obvious which dependencies are standardized across your monorepo * **Simplicity**: No need for complex version resolution strategies or external tools ## Real-World Example Here's a more comprehensive example for a React application: **Root package.json** ```json package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} { "name": "react-monorepo", "workspaces": { "packages": ["packages/*"], "catalog": { "react": "^19.0.0", "react-dom": "^19.0.0", "react-router-dom": "^6.15.0" }, "catalogs": { "build": { "webpack": "5.88.2", "babel": "7.22.10" }, "testing": { "jest": "29.6.2", "react-testing-library": "14.0.0" } } }, "devDependencies": { "typescript": "5.1.6" } } ``` ```json packages/app/package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} { "name": "app", "dependencies": { "react": "catalog:", "react-dom": "catalog:", "react-router-dom": "catalog:", "@monorepo/ui": "workspace:*", "@monorepo/utils": "workspace:*" }, "devDependencies": { "webpack": "catalog:build", "babel": "catalog:build", "jest": "catalog:testing", "react-testing-library": "catalog:testing" } } ``` ```json packages/ui/package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} { "name": "@monorepo/ui", "dependencies": { "react": "catalog:", "react-dom": "catalog:" }, "devDependencies": { "jest": "catalog:testing", "react-testing-library": "catalog:testing" } } ``` ```json packages/utils/package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} { "name": "@monorepo/utils", "dependencies": { "react": "catalog:" }, "devDependencies": { "jest": "catalog:testing" } } ``` ## Updating Versions To update versions across all packages, simply change the version in the root package.json: ```json package.json icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} "catalog": { "react": "^19.1.0", // Updated from ^19.0.0 "react-dom": "^19.1.0" // Updated from ^19.0.0 } ``` Then run `bun install` to update all packages. ## Lockfile Integration Bun's lockfile tracks catalog versions, making it easy to ensure consistent installations across different environments. The lockfile includes: * The catalog definitions from your package.json * The resolution of each cataloged dependency ```json bun.lock(excerpt) icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}} { "lockfileVersion": 1, "workspaces": { "": { "name": "react-monorepo", }, "packages/app": { "name": "app", "dependencies": { "react": "catalog:", "react-dom": "catalog:", ... }, }, ... }, "catalog": { "react": "^19.0.0", "react-dom": "^19.0.0", ... }, "catalogs": { "build": { "webpack": "5.88.2", ... }, ... }, "packages": { ... } } ``` ## Limitations and Edge Cases * Catalog references must match a dependency defined in either `catalog` or one of the named `catalogs` * Empty strings and whitespace in catalog names are ignored (treated as default catalog) * Invalid dependency versions in catalogs will fail to resolve during `bun install` * Catalogs are only available within workspaces; they cannot be used outside the monorepo Bun's catalog system provides a powerful yet simple way to maintain consistency across your monorepo without introducing additional complexity to your workflow. ## Publishing When you run `bun publish` or `bun pm pack`, Bun automatically replaces `catalog:` references in your `package.json` with the resolved version numbers. The published package includes regular semver strings and no longer depends on your catalog definitions. --- # Source: https://bun.com/docs/runtime/child-process.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Spawn > Spawn child processes with `Bun.spawn` or `Bun.spawnSync` ## Spawn a process (`Bun.spawn()`) Provide a command as an array of strings. The result of `Bun.spawn()` is a `Bun.Subprocess` object. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const proc = Bun.spawn(["bun", "--version"]); console.log(await proc.exited); // 0 ``` The second argument to `Bun.spawn` is a parameters object that can be used to configure the subprocess. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const proc = Bun.spawn(["bun", "--version"], { cwd: "./path/to/subdir", // specify a working directory env: { ...process.env, FOO: "bar" }, // specify environment variables onExit(proc, exitCode, signalCode, error) { // exit handler }, }); proc.pid; // process ID of subprocess ``` ## Input stream By default, the input stream of the subprocess is undefined; it can be configured with the `stdin` parameter. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const proc = Bun.spawn(["cat"], { stdin: await fetch("https://raw.githubusercontent.com/oven-sh/bun/main/examples/hashing.js"), }); const text = await proc.stdout.text(); console.log(text); // "const input = "hello world".repeat(400); ..." ``` | Value | Description | | ------------------------ | ------------------------------------------------ | | `null` | **Default.** Provide no input to the subprocess | | `"pipe"` | Return a `FileSink` for fast incremental writing | | `"inherit"` | Inherit the `stdin` of the parent process | | `Bun.file()` | Read from the specified file | | `TypedArray \| DataView` | Use a binary buffer as input | | `Response` | Use the response `body` as input | | `Request` | Use the request `body` as input | | `ReadableStream` | Use a readable stream as input | | `Blob` | Use a blob as input | | `number` | Read from the file with a given file descriptor | The `"pipe"` option lets incrementally write to the subprocess's input stream from the parent process. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const proc = Bun.spawn(["cat"], { stdin: "pipe", // return a FileSink for writing }); // enqueue string data proc.stdin.write("hello"); // enqueue binary data const enc = new TextEncoder(); proc.stdin.write(enc.encode(" world!")); // send buffered data proc.stdin.flush(); // close the input stream proc.stdin.end(); ``` Passing a `ReadableStream` to `stdin` lets you pipe data from a JavaScript `ReadableStream` directly to the subprocess's input: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const stream = new ReadableStream({ start(controller) { controller.enqueue("Hello from "); controller.enqueue("ReadableStream!"); controller.close(); }, }); const proc = Bun.spawn(["cat"], { stdin: stream, stdout: "pipe", }); const output = await proc.stdout.text(); console.log(output); // "Hello from ReadableStream!" ``` ## Output streams You can read results from the subprocess via the `stdout` and `stderr` properties. By default these are instances of `ReadableStream`. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const proc = Bun.spawn(["bun", "--version"]); const text = await proc.stdout.text(); console.log(text); // => "1.3.3\n" ``` Configure the output stream by passing one of the following values to `stdout/stderr`: | Value | Description | | ------------ | --------------------------------------------------------------------------------------------------- | | `"pipe"` | **Default for `stdout`.** Pipe the output to a `ReadableStream` on the returned `Subprocess` object | | `"inherit"` | **Default for `stderr`.** Inherit from the parent process | | `"ignore"` | Discard the output | | `Bun.file()` | Write to the specified file | | `number` | Write to the file with the given file descriptor | ## Exit handling Use the `onExit` callback to listen for the process exiting or being killed. ```ts index.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const proc = Bun.spawn(["bun", "--version"], { onExit(proc, exitCode, signalCode, error) { // exit handler }, }); ``` For convenience, the `exited` property is a `Promise` that resolves when the process exits. ```ts index.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const proc = Bun.spawn(["bun", "--version"]); await proc.exited; // resolves when process exit proc.killed; // boolean — was the process killed? proc.exitCode; // null | number proc.signalCode; // null | "SIGABRT" | "SIGALRM" | ... ``` To kill a process: ```ts index.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const proc = Bun.spawn(["bun", "--version"]); proc.kill(); proc.killed; // true proc.kill(15); // specify a signal code proc.kill("SIGTERM"); // specify a signal name ``` The parent `bun` process will not terminate until all child processes have exited. Use `proc.unref()` to detach the child process from the parent. ```ts index.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const proc = Bun.spawn(["bun", "--version"]); proc.unref(); ``` ## Resource usage You can get information about the process's resource usage after it has exited: ```ts index.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const proc = Bun.spawn(["bun", "--version"]); await proc.exited; const usage = proc.resourceUsage(); console.log(`Max memory used: ${usage.maxRSS} bytes`); console.log(`CPU time (user): ${usage.cpuTime.user} µs`); console.log(`CPU time (system): ${usage.cpuTime.system} µs`); ``` ## Using AbortSignal You can abort a subprocess using an `AbortSignal`: ```ts index.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const controller = new AbortController(); const { signal } = controller; const proc = Bun.spawn({ cmd: ["sleep", "100"], signal, }); // Later, to abort the process: controller.abort(); ``` ## Using timeout and killSignal You can set a timeout for a subprocess to automatically terminate after a specific duration: ```ts index.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // Kill the process after 5 seconds const proc = Bun.spawn({ cmd: ["sleep", "10"], timeout: 5000, // 5 seconds in milliseconds }); await proc.exited; // Will resolve after 5 seconds ``` By default, timed-out processes are killed with the `SIGTERM` signal. You can specify a different signal with the `killSignal` option: ```ts index.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // Kill the process with SIGKILL after 5 seconds const proc = Bun.spawn({ cmd: ["sleep", "10"], timeout: 5000, killSignal: "SIGKILL", // Can be string name or signal number }); ``` The `killSignal` option also controls which signal is sent when an AbortSignal is aborted. ## Using maxBuffer For spawnSync, you can limit the maximum number of bytes of output before the process is killed: ```ts index.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // Kill 'yes' after it emits over 100 bytes of output const result = Bun.spawnSync({ cmd: ["yes"], // or ["bun", "exec", "yes"] on Windows maxBuffer: 100, }); // process exits ``` ## Inter-process communication (IPC) Bun supports direct inter-process communication channel between two `bun` processes. To receive messages from a spawned Bun subprocess, specify an `ipc` handler. ```ts parent.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const child = Bun.spawn(["bun", "child.ts"], { ipc(message) { /** * The message received from the sub process **/ }, }); ``` The parent process can send messages to the subprocess using the `.send()` method on the returned `Subprocess` instance. A reference to the sending subprocess is also available as the second argument in the `ipc` handler. ```ts parent.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const childProc = Bun.spawn(["bun", "child.ts"], { ipc(message, childProc) { /** * The message received from the sub process **/ childProc.send("Respond to child"); }, }); childProc.send("I am your father"); // The parent can send messages to the child as well ``` Meanwhile the child process can send messages to its parent using with `process.send()` and receive messages with `process.on("message")`. This is the same API used for `child_process.fork()` in Node.js. ```ts child.ts theme={"theme":{"light":"github-light","dark":"dracula"}} process.send("Hello from child as string"); process.send({ message: "Hello from child as object" }); process.on("message", message => { // print message from parent console.log(message); }); ``` ```ts child.ts theme={"theme":{"light":"github-light","dark":"dracula"}} // send a string process.send("Hello from child as string"); // send an object process.send({ message: "Hello from child as object" }); ``` The `serialization` option controls the underlying communication format between the two processes: * `advanced`: (default) Messages are serialized using the JSC `serialize` API, which supports cloning [everything `structuredClone` supports](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm). This does not support transferring ownership of objects. * `json`: Messages are serialized using `JSON.stringify` and `JSON.parse`, which does not support as many object types as `advanced` does. To disconnect the IPC channel from the parent process, call: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} childProc.disconnect(); ``` ### IPC between Bun & Node.js To use IPC between a `bun` process and a Node.js process, set `serialization: "json"` in `Bun.spawn`. This is because Node.js and Bun use different JavaScript engines with different object serialization formats. ```js bun-node-ipc.js icon="file-code" theme={"theme":{"light":"github-light","dark":"dracula"}} if (typeof Bun !== "undefined") { const prefix = `[bun ${process.versions.bun} 🐇]`; const node = Bun.spawn({ cmd: ["node", __filename], ipc({ message }) { console.log(message); node.send({ message: `${prefix} 👋 hey node` }); node.kill(); }, stdio: ["inherit", "inherit", "inherit"], serialization: "json", }); node.send({ message: `${prefix} 👋 hey node` }); } else { const prefix = `[node ${process.version}]`; process.on("message", ({ message }) => { console.log(message); process.send({ message: `${prefix} 👋 hey bun` }); }); } ``` *** ## Terminal (PTY) support For interactive terminal applications, you can spawn a subprocess with a pseudo-terminal (PTY) attached using the `terminal` option. This makes the subprocess think it's running in a real terminal, enabling features like colored output, cursor movement, and interactive prompts. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const proc = Bun.spawn(["bash"], { terminal: { cols: 80, rows: 24, data(terminal, data) { // Called when data is received from the terminal process.stdout.write(data); }, }, }); // Write to the terminal proc.terminal.write("echo hello\n"); // Wait for the process to exit await proc.exited; // Close the terminal proc.terminal.close(); ``` When the `terminal` option is provided: * The subprocess sees `process.stdout.isTTY` as `true` * `stdin`, `stdout`, and `stderr` are all connected to the terminal * `proc.stdin`, `proc.stdout`, and `proc.stderr` return `null` — use the terminal instead * Access the terminal via `proc.terminal` ### Terminal options | Option | Description | Default | | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------ | | `cols` | Number of columns | `80` | | `rows` | Number of rows | `24` | | `name` | Terminal type for PTY configuration (set `TERM` env var separately via `env` option) | `"xterm-256color"` | | `data` | Callback when data is received `(terminal, data) => void` | — | | `exit` | Callback when PTY stream closes (EOF or error). `exitCode` is PTY lifecycle status (0=EOF, 1=error), not subprocess exit code. Use `proc.exited` for process exit. | — | | `drain` | Callback when ready for more data `(terminal) => void` | — | ### Terminal methods The `Terminal` object returned by `proc.terminal` has the following methods: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // Write data to the terminal proc.terminal.write("echo hello\n"); // Resize the terminal proc.terminal.resize(120, 40); // Set raw mode (disable line buffering and echo) proc.terminal.setRawMode(true); // Keep event loop alive while terminal is open proc.terminal.ref(); proc.terminal.unref(); // Close the terminal proc.terminal.close(); ``` ### Reusable Terminal You can create a terminal independently and reuse it across multiple subprocesses: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} await using terminal = new Bun.Terminal({ cols: 80, rows: 24, data(term, data) { process.stdout.write(data); }, }); // Spawn first process const proc1 = Bun.spawn(["echo", "first"], { terminal }); await proc1.exited; // Reuse terminal for another process const proc2 = Bun.spawn(["echo", "second"], { terminal }); await proc2.exited; // Terminal is closed automatically by `await using` ``` When passing an existing `Terminal` object: * The terminal can be reused across multiple spawns * You control when to close the terminal * The `exit` callback fires when you call `terminal.close()`, not when each subprocess exits * Use `proc.exited` to detect individual subprocess exits This is useful for running multiple commands in sequence through the same terminal session. Terminal support is only available on POSIX systems (Linux, macOS). It is not available on Windows. *** ## Blocking API (`Bun.spawnSync()`) Bun provides a synchronous equivalent of `Bun.spawn` called `Bun.spawnSync`. This is a blocking API that supports the same inputs and parameters as `Bun.spawn`. It returns a `SyncSubprocess` object, which differs from `Subprocess` in a few ways. 1. It contains a `success` property that indicates whether the process exited with a zero exit code. 2. The `stdout` and `stderr` properties are instances of `Buffer` instead of `ReadableStream`. 3. There is no `stdin` property. Use `Bun.spawn` to incrementally write to the subprocess's input stream. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} const proc = Bun.spawnSync(["echo", "hello"]); console.log(proc.stdout.toString()); // => "hello\n" ``` As a rule of thumb, the asynchronous `Bun.spawn` API is better for HTTP servers and apps, and `Bun.spawnSync` is better for building command-line tools. *** ## Benchmarks ⚡️ Under the hood, `Bun.spawn` and `Bun.spawnSync` use [`posix_spawn(3)`](https://man7.org/linux/man-pages/man3/posix_spawn.3.html). Bun's `spawnSync` spawns processes 60% faster than the Node.js `child_process` module. ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun spawn.mjs ``` ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} cpu: Apple M1 Max runtime: bun 1.x (arm64-darwin) benchmark time (avg) (min … max) p75 p99 p995 --------------------------------------------------------- ----------------------------- spawnSync echo hi 888.14 µs/iter (821.83 µs … 1.2 ms) 905.92 µs 1 ms 1.03 ms ``` ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} node spawn.node.mjs ``` ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} cpu: Apple M1 Max runtime: node v18.9.1 (arm64-darwin) benchmark time (avg) (min … max) p75 p99 p995 --------------------------------------------------------- ----------------------------- spawnSync echo hi 1.47 ms/iter (1.14 ms … 2.64 ms) 1.57 ms 2.37 ms 2.52 ms ``` *** ## Reference A reference of the Spawn API and types are shown below. The real types have complex generics to strongly type the `Subprocess` streams with the options passed to `Bun.spawn` and `Bun.spawnSync`. For full details, find these types as defined [bun.d.ts](https://github.com/oven-sh/bun/blob/main/packages/bun-types/bun.d.ts). ```ts See Typescript Definitions expandable theme={"theme":{"light":"github-light","dark":"dracula"}} interface Bun { spawn(command: string[], options?: SpawnOptions.OptionsObject): Subprocess; spawnSync(command: string[], options?: SpawnOptions.OptionsObject): SyncSubprocess; spawn(options: { cmd: string[] } & SpawnOptions.OptionsObject): Subprocess; spawnSync(options: { cmd: string[] } & SpawnOptions.OptionsObject): SyncSubprocess; } namespace SpawnOptions { interface OptionsObject { cwd?: string; env?: Record; stdio?: [Writable, Readable, Readable]; stdin?: Writable; stdout?: Readable; stderr?: Readable; onExit?( subprocess: Subprocess, exitCode: number | null, signalCode: number | null, error?: ErrorLike, ): void | Promise; ipc?(message: any, subprocess: Subprocess): void; serialization?: "json" | "advanced"; windowsHide?: boolean; windowsVerbatimArguments?: boolean; argv0?: string; signal?: AbortSignal; timeout?: number; killSignal?: string | number; maxBuffer?: number; terminal?: TerminalOptions; // PTY support (POSIX only) } type Readable = | "pipe" | "inherit" | "ignore" | null // equivalent to "ignore" | undefined // to use default | BunFile | ArrayBufferView | number; type Writable = | "pipe" | "inherit" | "ignore" | null // equivalent to "ignore" | undefined // to use default | BunFile | ArrayBufferView | number | ReadableStream | Blob | Response | Request; } interface Subprocess extends AsyncDisposable { readonly stdin: FileSink | number | undefined | null; readonly stdout: ReadableStream> | number | undefined | null; readonly stderr: ReadableStream> | number | undefined | null; readonly readable: ReadableStream> | number | undefined | null; readonly terminal: Terminal | undefined; readonly pid: number; readonly exited: Promise; readonly exitCode: number | null; readonly signalCode: NodeJS.Signals | null; readonly killed: boolean; kill(exitCode?: number | NodeJS.Signals): void; ref(): void; unref(): void; send(message: any): void; disconnect(): void; resourceUsage(): ResourceUsage | undefined; } interface SyncSubprocess { stdout: Buffer | undefined; stderr: Buffer | undefined; exitCode: number; success: boolean; resourceUsage: ResourceUsage; signalCode?: string; exitedDueToTimeout?: true; pid: number; } interface TerminalOptions { cols?: number; rows?: number; name?: string; data?: (terminal: Terminal, data: Uint8Array) => void; /** Called when PTY stream closes (EOF or error). exitCode is PTY lifecycle status (0=EOF, 1=error), not subprocess exit code. */ exit?: (terminal: Terminal, exitCode: number, signal: string | null) => void; drain?: (terminal: Terminal) => void; } interface Terminal extends AsyncDisposable { readonly stdin: number; readonly stdout: number; readonly closed: boolean; write(data: string | BufferSource): number; resize(cols: number, rows: number): void; setRawMode(enabled: boolean): void; ref(): void; unref(): void; close(): void; } interface ResourceUsage { contextSwitches: { voluntary: number; involuntary: number; }; cpuTime: { user: number; system: number; total: number; }; maxRSS: number; messages: { sent: number; received: number; }; ops: { in: number; out: number; }; shmSize: number; signalCount: number; swapCount: number; } type Signal = | "SIGABRT" | "SIGALRM" | "SIGBUS" | "SIGCHLD" | "SIGCONT" | "SIGFPE" | "SIGHUP" | "SIGILL" | "SIGINT" | "SIGIO" | "SIGIOT" | "SIGKILL" | "SIGPIPE" | "SIGPOLL" | "SIGPROF" | "SIGPWR" | "SIGQUIT" | "SIGSEGV" | "SIGSTKFLT" | "SIGSTOP" | "SIGSYS" | "SIGTERM" | "SIGTRAP" | "SIGTSTP" | "SIGTTIN" | "SIGTTOU" | "SIGUNUSED" | "SIGURG" | "SIGUSR1" | "SIGUSR2" | "SIGVTALRM" | "SIGWINCH" | "SIGXCPU" | "SIGXFSZ" | "SIGBREAK" | "SIGLOST" | "SIGINFO"; ``` --- # Source: https://bun.com/docs/guides/runtime/cicd.md # Source: https://bun.com/docs/guides/install/cicd.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Install dependencies with Bun in GitHub Actions Use the official [`setup-bun`](https://github.com/oven-sh/setup-bun) GitHub Action to install `bun` in your GitHub Actions runner. ```yaml workflow.yml icon="file-code" theme={"theme":{"light":"github-light","dark":"dracula"}} title: my-workflow jobs: my-job: title: my-job runs-on: ubuntu-latest steps: # ... - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 // [!code ++] # run any `bun` or `bunx` command - run: bun install // [!code ++] ``` *** To specify a version of Bun to install: ```yaml workflow.yml icon="file-code" theme={"theme":{"light":"github-light","dark":"dracula"}} title: my-workflow jobs: my-job: title: my-job runs-on: ubuntu-latest steps: # ... - uses: oven-sh/setup-bun@v2 with: # [!code ++] version: "latest" # or "canary" # [!code ++] ``` *** Refer to the [README.md](https://github.com/oven-sh/setup-bun) for complete documentation of the `setup-bun` GitHub Action. --- # Source: https://bun.com/docs/guides/http/cluster.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Start a cluster of HTTP servers > Run multiple HTTP servers concurrently via the "reusePort" option to share the same port across multiple processes To run multiple HTTP servers concurrently, use the `reusePort` option in `Bun.serve()` which shares the same port across multiple processes. This automatically load balances incoming requests across multiple instances of Bun. ```ts server.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} import { serve } from "bun"; const id = Math.random().toString(36).slice(2); serve({ port: process.env.PORT || 8080, development: false, // Share the same port across multiple processes // This is the important part! reusePort: true, async fetch(request) { return new Response("Hello from Bun #" + id + "!\n"); }, }); ``` *** **Linux only** — Windows and macOS ignore the `reusePort` option. This is an operating system limitation with `SO_REUSEPORT`, unfortunately. After saving the file, start your servers on the same port. Under the hood, this uses the Linux `SO_REUSEPORT` and `SO_REUSEADDR` socket options to ensure fair load balancing across multiple processes. [Learn more about `SO_REUSEPORT` and `SO_REUSEADDR`](https://lwn.net/Articles/542629/) ```ts cluster.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} import { spawn } from "bun"; const cpus = navigator.hardwareConcurrency; // Number of CPU cores const buns = new Array(cpus); for (let i = 0; i < cpus; i++) { buns[i] = spawn({ cmd: ["bun", "./server.ts"], stdout: "inherit", stderr: "inherit", stdin: "inherit", }); } function kill() { for (const bun of buns) { bun.kill(); } } process.on("SIGINT", kill); process.on("exit", kill); ``` *** Bun has also implemented the `node:cluster` module, but this is a faster, simple, and limited alternative. --- # Source: https://bun.com/docs/test/code-coverage.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Code coverage > Learn how to use Bun's built-in code coverage reporting to track test coverage and find untested areas in your codebase Bun's test runner now supports built-in code coverage reporting. This makes it easy to see how much of the codebase is covered by tests, and find areas that are not currently well-tested. ## Enabling Coverage `bun:test` supports seeing which lines of code are covered by tests. To use this feature, pass `--coverage` to the CLI. It will print out a coverage report to the console: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun test --coverage -------------|---------|---------|------------------- File | % Funcs | % Lines | Uncovered Line #s -------------|---------|---------|------------------- All files | 38.89 | 42.11 | index-0.ts | 33.33 | 36.84 | 10-15,19-24 index-1.ts | 33.33 | 36.84 | 10-15,19-24 index-10.ts | 33.33 | 36.84 | 10-15,19-24 index-2.ts | 33.33 | 36.84 | 10-15,19-24 index-3.ts | 33.33 | 36.84 | 10-15,19-24 index-4.ts | 33.33 | 36.84 | 10-15,19-24 index-5.ts | 33.33 | 36.84 | 10-15,19-24 index-6.ts | 33.33 | 36.84 | 10-15,19-24 index-7.ts | 33.33 | 36.84 | 10-15,19-24 index-8.ts | 33.33 | 36.84 | 10-15,19-24 index-9.ts | 33.33 | 36.84 | 10-15,19-24 index.ts | 100.00 | 100.00 | -------------|---------|---------|------------------- ``` ### Enable by Default To always enable coverage reporting by default, add the following line to your `bunfig.toml`: ```toml title="bunfig.toml" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # Always enable coverage coverage = true ``` By default coverage reports will include test files and exclude sourcemaps. This is usually what you want, but it can be configured otherwise in `bunfig.toml`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] coverageSkipTestFiles = true # default false ``` ## Coverage Thresholds It is possible to specify a coverage threshold in `bunfig.toml`. If your test suite does not meet or exceed this threshold, `bun test` will exit with a non-zero exit code to indicate the failure. ### Simple Threshold ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # To require 90% line-level and function-level coverage coverageThreshold = 0.9 ``` ### Detailed Thresholds ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # To set different thresholds for lines and functions coverageThreshold = { lines = 0.9, functions = 0.9, statements = 0.9 } ``` Setting any of these thresholds enables `fail_on_low_coverage`, causing the test run to fail if coverage is below the threshold. ## Coverage Reporters By default, coverage reports will be printed to the console. For persistent code coverage reports in CI environments and for other tools, you can pass a `--coverage-reporter=lcov` CLI option or `coverageReporter` option in `bunfig.toml`. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] coverageReporter = ["text", "lcov"] # default ["text"] coverageDir = "path/to/somewhere" # default "coverage" ``` ### Available Reporters | Reporter | Description | | -------- | ---------------------------------------------------- | | `text` | Prints a text summary of the coverage to the console | | `lcov` | Save coverage in lcov format | ### LCOV Coverage Reporter To generate an lcov report, you can use the lcov reporter. This will generate an `lcov.info` file in the coverage directory. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] coverageReporter = "lcov" ``` ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} # Or via CLI bun test --coverage --coverage-reporter=lcov ``` The LCOV format is widely supported by various tools and services: * **Code editors**: VS Code extensions can show coverage inline * **CI/CD services**: GitHub Actions, GitLab CI, CircleCI * **Coverage services**: Codecov, Coveralls * **IDEs**: WebStorm, IntelliJ IDEA #### Using LCOV with GitHub Actions ```yaml title=".github/workflows/test.yml" icon="file-code" theme={"theme":{"light":"github-light","dark":"dracula"}} name: Test with Coverage on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - run: bun install - run: bun test --coverage --coverage-reporter=lcov - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 with: file: ./coverage/lcov.info ``` ## Excluding Files from Coverage ### Skip Test Files By default, test files themselves are included in coverage reports. You can exclude them with: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] coverageSkipTestFiles = true # default false ``` This will exclude files matching test patterns (e.g., `*.test.ts`, `*.spec.js`) from the coverage report. ### Ignore Specific Paths and Patterns You can exclude specific files or file patterns from coverage reports using `coveragePathIgnorePatterns`: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # Single pattern coveragePathIgnorePatterns = "**/*.spec.ts" # Multiple patterns coveragePathIgnorePatterns = [ "**/*.spec.ts", "**/*.test.ts", "src/utils/**", "*.config.js" ] ``` This option accepts glob patterns and works similarly to Jest's `collectCoverageFrom` ignore patterns. Files matching any of these patterns will be excluded from coverage calculation and reporting in both text and LCOV outputs. #### Common Use Cases ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] coveragePathIgnorePatterns = [ # Exclude utility files "src/utils/**", # Exclude configuration files "*.config.js", "webpack.config.ts", "vite.config.ts", # Exclude specific test patterns "**/*.spec.ts", "**/*.e2e.ts", # Exclude build artifacts "dist/**", "build/**", # Exclude generated files "src/generated/**", "**/*.generated.ts", # Exclude vendor/third-party code "vendor/**", "third-party/**" ] ``` ## Sourcemaps Internally, Bun transpiles all files by default, so Bun automatically generates an internal source map that maps lines of your original source code onto Bun's internal representation. If for any reason you want to disable this, set `test.coverageIgnoreSourcemaps` to `true`; this will rarely be desirable outside of advanced use cases. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] coverageIgnoreSourcemaps = true # default false ``` When using this option, you probably want to stick a `// @bun` comment at the top of the source file to opt out of the transpilation process. ## Coverage Defaults By default, coverage reports: * **Exclude** `node_modules` directories * **Exclude** files loaded via non-JS/TS loaders (e.g., `.css`, `.txt`) unless a custom JS loader is specified * **Include** test files themselves (can be disabled with `coverageSkipTestFiles = true`) * Can exclude additional files with `coveragePathIgnorePatterns` ## Advanced Configuration ### Custom Coverage Directory ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] coverageDir = "coverage-reports" # default "coverage" ``` ### Multiple Reporters ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] coverageReporter = ["text", "lcov"] ``` ### Coverage with Specific Test Patterns ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} # Run coverage only on specific test files bun test --coverage src/components/*.test.ts # Run coverage with name pattern bun test --coverage --test-name-pattern="API" ``` ## CI/CD Integration ### GitHub Actions Example ```yaml title=".github/workflows/coverage.yml" icon="file-code" theme={"theme":{"light":"github-light","dark":"dracula"}} name: Coverage Report on: [push, pull_request] jobs: coverage: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Bun uses: oven-sh/setup-bun@v2 - name: Install dependencies run: bun install - name: Run tests with coverage run: bun test --coverage --coverage-reporter=lcov - name: Upload to Codecov uses: codecov/codecov-action@v3 with: file: ./coverage/lcov.info fail_ci_if_error: true ``` ### GitLab CI Example ```yaml title=".gitlab-ci.yml" theme={"theme":{"light":"github-light","dark":"dracula"}} test:coverage: stage: test script: - bun install - bun test --coverage --coverage-reporter=lcov coverage: '/Lines\s*:\s*(\d+.\d+)%/' artifacts: reports: coverage_report: coverage_format: cobertura path: coverage/lcov.info ``` ## Interpreting Coverage Reports ### Text Output Explanation ``` -------------|---------|---------|------------------- File | % Funcs | % Lines | Uncovered Line #s -------------|---------|---------|------------------- All files | 85.71 | 90.48 | src/ | 85.71 | 90.48 | utils.ts | 100.00 | 100.00 | api.ts | 75.00 | 85.71 | 15-18,25 main.ts | 80.00 | 88.89 | 42,50-52 -------------|---------|---------|------------------- ``` * **% Funcs**: Percentage of functions that were called during tests * **% Lines**: Percentage of executable lines that were run during tests * **Uncovered Line #s**: Specific line numbers that were not executed ### What to Aim For * **80%+ overall coverage**: Generally considered good * **90%+ critical paths**: Important business logic should be well-tested * **100% utility functions**: Pure functions and utilities are easy to test completely * **Lower coverage for UI components**: Often acceptable as they may require integration tests ## Best Practices ### Focus on Quality, Not Just Quantity ```ts title="test.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // Good: Test actual functionality test("calculateTax should handle different tax rates", () => { expect(calculateTax(100, 0.08)).toBe(8); expect(calculateTax(100, 0.1)).toBe(10); expect(calculateTax(0, 0.08)).toBe(0); }); // Avoid: Just hitting lines for coverage test("calculateTax exists", () => { calculateTax(100, 0.08); // No assertions! }); ``` ### Test Edge Cases ```ts title="test.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} test("user input validation", () => { // Test normal case expect(validateEmail("user@example.com")).toBe(true); // Test edge cases that improve coverage meaningfully expect(validateEmail("")).toBe(false); expect(validateEmail("invalid")).toBe(false); expect(validateEmail(null)).toBe(false); }); ``` ### Use Coverage to Find Missing Tests ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} # Run coverage to identify untested code bun test --coverage # Look at specific files that need attention bun test --coverage src/critical-module.ts ``` ### Combine with Other Quality Metrics Coverage is just one metric. Also consider: * **Code review quality** * **Integration test coverage** * **Error handling tests** * **Performance tests** * **Type safety** ## Troubleshooting ### Coverage Not Showing for Some Files If files aren't appearing in coverage reports, they might not be imported by your tests. Coverage only tracks files that are actually loaded. ```ts title="test.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // Make sure to import the modules you want to test import { myFunction } from "../src/my-module"; test("my function works", () => { expect(myFunction()).toBeDefined(); }); ``` ### False Coverage Reports If you see coverage reports that don't match your expectations: 1. Check if source maps are working correctly 2. Verify file patterns in `coveragePathIgnorePatterns` 3. Ensure test files are actually importing the code to test ### Performance Issues with Large Codebases For large projects, coverage collection can slow down tests: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # Exclude large directories you don't need coverage for coveragePathIgnorePatterns = [ "node_modules/**", "vendor/**", "generated/**" ] ``` Consider running coverage only on CI or specific branches rather than every test run during development. --- # Source: https://bun.com/docs/guides/runtime/codesign-macos-executable.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Codesign a single-file JavaScript executable on macOS > Fix the "can't be opened because it is from an unidentified developer" Gatekeeper warning when running your JavaScript executable. Compile your executable using the `--compile` flag. ```sh theme={"theme":{"light":"github-light","dark":"dracula"}} bun build --compile ./path/to/entry.ts --outfile myapp ``` *** List your available signing identities. One of these will be your signing identity that you pass to the `codesign` command. This command requires macOS. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} security find-identity -v -p codesigning ``` ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} 1. XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "Developer ID Application: Your Name (ZZZZZZZZZZ)" 1 valid identities found ``` *** Optional, but recommended: create an `entitlements.plist` file with the necessary permissions for the JavaScript engine to work correctly. ```xml entitlements.plist icon="file-code" theme={"theme":{"light":"github-light","dark":"dracula"}} com.apple.security.cs.allow-jit com.apple.security.cs.allow-unsigned-executable-memory com.apple.security.cs.disable-executable-page-protection com.apple.security.cs.allow-dyld-environment-variables com.apple.security.cs.disable-library-validation ``` *** Sign your executable using the `codesign` command and verify it works. ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} codesign --entitlements entitlements.plist -vvvv --deep --sign "XXXXXXXXXX" ./myapp --force codesign -vvv --verify ./myapp ``` *** For more information on macOS codesigning, refer to [Apple's Code Signing documentation](https://developer.apple.com/documentation/security/code_signing_services). For details about creating single-file executables with Bun, see [Standalone Executables](/bundler/executables). This guide requires Bun v1.2.4 or newer. --- # Source: https://bun.com/docs/runtime/color.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Color > Format colors as CSS, ANSI, numbers, hex strings, and more `Bun.color(input, outputFormat?)` leverages Bun's CSS parser to parse, normalize, and convert colors from user input to a variety of output formats, including: | Format | Example | | ------------ | -------------------------------- | | `"css"` | `"red"` | | `"ansi"` | `"\x1b[38;2;255;0;0m"` | | `"ansi-16"` | `"\x1b[38;5;\tm"` | | `"ansi-256"` | `"\x1b[38;5;196m"` | | `"ansi-16m"` | `"\x1b[38;2;255;0;0m"` | | `"number"` | `0x1a2b3c` | | `"rgb"` | `"rgb(255, 99, 71)"` | | `"rgba"` | `"rgba(255, 99, 71, 0.5)"` | | `"hsl"` | `"hsl(120, 50%, 50%)"` | | `"hex"` | `"#1a2b3c"` | | `"HEX"` | `"#1A2B3C"` | | `"{rgb}"` | `{ r: 255, g: 99, b: 71 }` | | `"{rgba}"` | `{ r: 255, g: 99, b: 71, a: 1 }` | | `"[rgb]"` | `[ 255, 99, 71 ]` | | `"[rgba]"` | `[ 255, 99, 71, 255]` | There are many different ways to use this API: * Validate and normalize colors to persist in a database (`number` is the most database-friendly) * Convert colors to different formats * Colorful logging beyond the 16 colors many use today (use `ansi` if you don't want to figure out what the user's terminal supports, otherwise use `ansi-16`, `ansi-256`, or `ansi-16m` for how many colors the terminal supports) * Format colors for use in CSS injected into HTML * Get the `r`, `g`, `b`, and `a` color components as JavaScript objects or numbers from a CSS color string You can think of this as an alternative to the popular npm packages [`color`](https://github.com/Qix-/color) and [`tinycolor2`](https://github.com/bgrins/TinyColor) except with full support for parsing CSS color strings and zero dependencies built directly into Bun. ### Flexible input You can pass in any of the following: * Standard CSS color names like `"red"` * Numbers like `0xff0000` * Hex strings like `"#f00"` * RGB strings like `"rgb(255, 0, 0)"` * RGBA strings like `"rgba(255, 0, 0, 1)"` * HSL strings like `"hsl(0, 100%, 50%)"` * HSLA strings like `"hsla(0, 100%, 50%, 1)"` * RGB objects like `{ r: 255, g: 0, b: 0 }` * RGBA objects like `{ r: 255, g: 0, b: 0, a: 1 }` * RGB arrays like `[255, 0, 0]` * RGBA arrays like `[255, 0, 0, 255]` * LAB strings like `"lab(50% 50% 50%)"` * ... anything else that CSS can parse as a single color value ### Format colors as CSS The `"css"` format outputs valid CSS for use in stylesheets, inline styles, CSS variables, css-in-js, etc. It returns the most compact representation of the color as a string. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Bun.color("red", "css"); // "red" Bun.color(0xff0000, "css"); // "#f000" Bun.color("#f00", "css"); // "red" Bun.color("#ff0000", "css"); // "red" Bun.color("rgb(255, 0, 0)", "css"); // "red" Bun.color("rgba(255, 0, 0, 1)", "css"); // "red" Bun.color("hsl(0, 100%, 50%)", "css"); // "red" Bun.color("hsla(0, 100%, 50%, 1)", "css"); // "red" Bun.color({ r: 255, g: 0, b: 0 }, "css"); // "red" Bun.color({ r: 255, g: 0, b: 0, a: 1 }, "css"); // "red" Bun.color([255, 0, 0], "css"); // "red" Bun.color([255, 0, 0, 255], "css"); // "red" ``` If the input is unknown or fails to parse, `Bun.color` returns `null`. ### Format colors as ANSI (for terminals) The `"ansi"` format outputs ANSI escape codes for use in terminals to make text colorful. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Bun.color("red", "ansi"); // "\u001b[38;2;255;0;0m" Bun.color(0xff0000, "ansi"); // "\u001b[38;2;255;0;0m" Bun.color("#f00", "ansi"); // "\u001b[38;2;255;0;0m" Bun.color("#ff0000", "ansi"); // "\u001b[38;2;255;0;0m" Bun.color("rgb(255, 0, 0)", "ansi"); // "\u001b[38;2;255;0;0m" Bun.color("rgba(255, 0, 0, 1)", "ansi"); // "\u001b[38;2;255;0;0m" Bun.color("hsl(0, 100%, 50%)", "ansi"); // "\u001b[38;2;255;0;0m" Bun.color("hsla(0, 100%, 50%, 1)", "ansi"); // "\u001b[38;2;255;0;0m" Bun.color({ r: 255, g: 0, b: 0 }, "ansi"); // "\u001b[38;2;255;0;0m" Bun.color({ r: 255, g: 0, b: 0, a: 1 }, "ansi"); // "\u001b[38;2;255;0;0m" Bun.color([255, 0, 0], "ansi"); // "\u001b[38;2;255;0;0m" Bun.color([255, 0, 0, 255], "ansi"); // "\u001b[38;2;255;0;0m" ``` This gets the color depth of stdout and automatically chooses one of `"ansi-16m"`, `"ansi-256"`, `"ansi-16"` based on the environment variables. If stdout doesn't support any form of ANSI color, it returns an empty string. As with the rest of Bun's color API, if the input is unknown or fails to parse, it returns `null`. #### 24-bit ANSI colors (`ansi-16m`) The `"ansi-16m"` format outputs 24-bit ANSI colors for use in terminals to make text colorful. 24-bit color means you can display 16 million colors on supported terminals, and requires a modern terminal that supports it. This converts the input color to RGBA, and then outputs that as an ANSI color. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Bun.color("red", "ansi-16m"); // "\x1b[38;2;255;0;0m" Bun.color(0xff0000, "ansi-16m"); // "\x1b[38;2;255;0;0m" Bun.color("#f00", "ansi-16m"); // "\x1b[38;2;255;0;0m" Bun.color("#ff0000", "ansi-16m"); // "\x1b[38;2;255;0;0m" ``` #### 256 ANSI colors (`ansi-256`) The `"ansi-256"` format approximates the input color to the nearest of the 256 ANSI colors supported by some terminals. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Bun.color("red", "ansi-256"); // "\u001b[38;5;196m" Bun.color(0xff0000, "ansi-256"); // "\u001b[38;5;196m" Bun.color("#f00", "ansi-256"); // "\u001b[38;5;196m" Bun.color("#ff0000", "ansi-256"); // "\u001b[38;5;196m" ``` To convert from RGBA to one of the 256 ANSI colors, we ported the algorithm that [`tmux` uses](https://github.com/tmux/tmux/blob/dae2868d1227b95fd076fb4a5efa6256c7245943/colour.c#L44-L55). #### 16 ANSI colors (`ansi-16`) The `"ansi-16"` format approximates the input color to the nearest of the 16 ANSI colors supported by most terminals. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Bun.color("red", "ansi-16"); // "\u001b[38;5;\tm" Bun.color(0xff0000, "ansi-16"); // "\u001b[38;5;\tm" Bun.color("#f00", "ansi-16"); // "\u001b[38;5;\tm" Bun.color("#ff0000", "ansi-16"); // "\u001b[38;5;\tm" ``` This works by first converting the input to a 24-bit RGB color space, then to `ansi-256`, and then we convert that to the nearest 16 ANSI color. ### Format colors as numbers The `"number"` format outputs a 24-bit number for use in databases, configuration, or any other use case where a compact representation of the color is desired. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Bun.color("red", "number"); // 16711680 Bun.color(0xff0000, "number"); // 16711680 Bun.color({ r: 255, g: 0, b: 0 }, "number"); // 16711680 Bun.color([255, 0, 0], "number"); // 16711680 Bun.color("rgb(255, 0, 0)", "number"); // 16711680 Bun.color("rgba(255, 0, 0, 1)", "number"); // 16711680 Bun.color("hsl(0, 100%, 50%)", "number"); // 16711680 Bun.color("hsla(0, 100%, 50%, 1)", "number"); // 16711680 ``` ### Get the red, green, blue, and alpha channels You can use the `"{rgba}"`, `"{rgb}"`, `"[rgba]"` and `"[rgb]"` formats to get the red, green, blue, and alpha channels as objects or arrays. #### `{rgba}` object The `"{rgba}"` format outputs an object with the red, green, blue, and alpha channels. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} type RGBAObject = { // 0 - 255 r: number; // 0 - 255 g: number; // 0 - 255 b: number; // 0 - 1 a: number; }; ``` Example: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Bun.color("hsl(0, 0%, 50%)", "{rgba}"); // { r: 128, g: 128, b: 128, a: 1 } Bun.color("red", "{rgba}"); // { r: 255, g: 0, b: 0, a: 1 } Bun.color(0xff0000, "{rgba}"); // { r: 255, g: 0, b: 0, a: 1 } Bun.color({ r: 255, g: 0, b: 0 }, "{rgba}"); // { r: 255, g: 0, b: 0, a: 1 } Bun.color([255, 0, 0], "{rgba}"); // { r: 255, g: 0, b: 0, a: 1 } ``` To behave similarly to CSS, the `a` channel is a decimal number between `0` and `1`. The `"{rgb}"` format is similar, but it doesn't include the alpha channel. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Bun.color("hsl(0, 0%, 50%)", "{rgb}"); // { r: 128, g: 128, b: 128 } Bun.color("red", "{rgb}"); // { r: 255, g: 0, b: 0 } Bun.color(0xff0000, "{rgb}"); // { r: 255, g: 0, b: 0 } Bun.color({ r: 255, g: 0, b: 0 }, "{rgb}"); // { r: 255, g: 0, b: 0 } Bun.color([255, 0, 0], "{rgb}"); // { r: 255, g: 0, b: 0 } ``` #### `[rgba]` array The `"[rgba]"` format outputs an array with the red, green, blue, and alpha channels. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} // All values are 0 - 255 type RGBAArray = [number, number, number, number]; ``` Example: ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Bun.color("hsl(0, 0%, 50%)", "[rgba]"); // [128, 128, 128, 255] Bun.color("red", "[rgba]"); // [255, 0, 0, 255] Bun.color(0xff0000, "[rgba]"); // [255, 0, 0, 255] Bun.color({ r: 255, g: 0, b: 0 }, "[rgba]"); // [255, 0, 0, 255] Bun.color([255, 0, 0], "[rgba]"); // [255, 0, 0, 255] ``` Unlike the `"{rgba}"` format, the alpha channel is an integer between `0` and `255`. This is useful for typed arrays where each channel must be the same underlying type. The `"[rgb]"` format is similar, but it doesn't include the alpha channel. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Bun.color("hsl(0, 0%, 50%)", "[rgb]"); // [128, 128, 128] Bun.color("red", "[rgb]"); // [255, 0, 0] Bun.color(0xff0000, "[rgb]"); // [255, 0, 0] Bun.color({ r: 255, g: 0, b: 0 }, "[rgb]"); // [255, 0, 0] Bun.color([255, 0, 0], "[rgb]"); // [255, 0, 0] ``` ### Format colors as hex strings The `"hex"` format outputs a lowercase hex string for use in CSS or other contexts. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Bun.color("hsl(0, 0%, 50%)", "hex"); // "#808080" Bun.color("red", "hex"); // "#ff0000" Bun.color(0xff0000, "hex"); // "#ff0000" Bun.color({ r: 255, g: 0, b: 0 }, "hex"); // "#ff0000" Bun.color([255, 0, 0], "hex"); // "#ff0000" ``` The `"HEX"` format is similar, but it outputs a hex string with uppercase letters instead of lowercase letters. ```ts theme={"theme":{"light":"github-light","dark":"dracula"}} Bun.color("hsl(0, 0%, 50%)", "HEX"); // "#808080" Bun.color("red", "HEX"); // "#FF0000" Bun.color(0xff0000, "HEX"); // "#FF0000" Bun.color({ r: 255, g: 0, b: 0 }, "HEX"); // "#FF0000" Bun.color([255, 0, 0], "HEX"); // "#FF0000" ``` ### Bundle-time client-side color formatting Like many of Bun's APIs, you can use macros to invoke `Bun.color` at bundle-time for use in client-side JavaScript builds: ```ts client-side.ts theme={"theme":{"light":"github-light","dark":"dracula"}} import { color } from "bun" with { type: "macro" }; console.log(color("#f00", "css")); ``` Then, build the client-side code: ```sh theme={"theme":{"light":"github-light","dark":"dracula"}} bun build ./client-side.ts ``` This will output the following to `client-side.js`: ```js theme={"theme":{"light":"github-light","dark":"dracula"}} // client-side.ts console.log("red"); ``` --- # Source: https://bun.com/docs/guides/websocket/compression.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Enable compression for WebSocket messages Per-message compression can be enabled with the `perMessageDeflate` parameter. When set, all messages will be compressed using the [permessage-deflate](https://tools.ietf.org/html/rfc7692) WebSocket extension. ```ts server.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} Bun.serve({ // ... websocket: { // enable compression perMessageDeflate: true, }, }); ``` *** To enable compression for individual messages, pass `true` as the second parameter to `ws.send()`. ```ts server.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} Bun.serve({ // ... websocket: { async message(ws, message) { // send a compressed message ws.send(message, true); }, }, }); ``` --- # Source: https://bun.com/docs/guides/test/concurrent-test-glob.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Selectively run tests concurrently with glob patterns > Set a glob pattern to decide which tests from which files run in parallel This guide demonstrates how to use the `concurrentTestGlob` option to selectively run tests concurrently based on file naming patterns. ## Project Structure ```sh title="Project Structure" icon="folder-tree" theme={"theme":{"light":"github-light","dark":"dracula"}} my-project/ ├── bunfig.toml ├── tests/ │ ├── unit/ │ │ ├── math.test.ts # Sequential │ │ └── utils.test.ts # Sequential │ └── integration/ │ ├── concurrent-api.test.ts # Concurrent │ └── concurrent-database.test.ts # Concurrent ``` ## Configuration Configure your `bunfig.toml` to run test files with "concurrent-" prefix concurrently: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # Run all test files with "concurrent-" prefix concurrently concurrentTestGlob = "**/concurrent-*.test.ts" ``` ## Test Files ### Unit Test (Sequential) Sequential tests are good for tests that share state or have specific ordering requirements: ```ts title="tests/unit/math.test.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} import { test, expect } from "bun:test"; // These tests run sequentially by default let sharedState = 0; test("addition", () => { sharedState = 5 + 3; expect(sharedState).toBe(8); }); test("uses previous state", () => { // This test depends on the previous test's state expect(sharedState).toBe(8); }); ``` ### Integration Test (Concurrent) Tests in files matching the glob pattern automatically run concurrently: ```ts title="tests/integration/concurrent-api.test.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} import { test, expect } from "bun:test"; // These tests automatically run concurrently due to filename matching the glob pattern. // Using test() is equivalent to test.concurrent() when the file matches concurrentTestGlob. // Each test is independent and can run in parallel. test("fetch user data", async () => { const response = await fetch("/api/user/1"); expect(response.ok).toBe(true); }); // can also use test.concurrent() for explicitly marking it as concurrent test.concurrent("fetch posts", async () => { const response = await fetch("/api/posts"); expect(response.ok).toBe(true); }); // can also use test.serial() for explicitly marking it as sequential test.serial("fetch comments", async () => { const response = await fetch("/api/comments"); expect(response.ok).toBe(true); }); ``` ## Running Tests ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} # Run all tests - concurrent-*.test.ts files will run concurrently bun test # Override: Force ALL tests to run concurrently # Note: This overrides bunfig.toml and runs all tests concurrently, regardless of glob bun test --concurrent # Run only unit tests (sequential) bun test tests/unit # Run only integration tests (concurrent due to glob pattern) bun test tests/integration ``` ## Benefits 1. **Gradual Migration**: Migrate to concurrent tests file by file by renaming them 2. **Clear Organization**: File naming convention indicates execution mode 3. **Performance**: Integration tests run faster in parallel 4. **Safety**: Unit tests remain sequential where needed 5. **Flexibility**: Easy to change execution mode by renaming files ## Migration Strategy To migrate existing tests to concurrent execution: 1. **Start with independent integration tests** - These typically don't share state 2. **Rename files to match the glob pattern**: `mv api.test.ts concurrent-api.test.ts` 3. **Verify tests still pass** - Run `bun test` to ensure no race conditions 4. **Monitor for shared state issues** - Watch for flaky tests or unexpected failures 5. **Continue migrating stable tests incrementally** - Don't rush the migration ## Tips * **Use descriptive prefixes**: `concurrent-`, `parallel-`, `async-` * **Keep related sequential tests together** in the same directory * **Document why certain tests must remain sequential** with comments * **Use `test.concurrent()` for fine-grained control** in sequential files (Note: In files matched by `concurrentTestGlob`, plain `test()` already runs concurrently) ## Multiple Patterns You can specify multiple patterns for different test categories: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] concurrentTestGlob = [ "**/integration/*.test.ts", "**/e2e/*.test.ts", "**/concurrent-*.test.ts" ] ``` This configuration will run tests concurrently if they match any of these patterns: * All tests in `integration/` directories * All tests in `e2e/` directories * All tests with `concurrent-` prefix anywhere in the project --- # Source: https://bun.com/docs/test/configuration.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Test configuration > Learn how to configure Bun test behavior using bunfig.toml and command-line options Configure `bun test` via `bunfig.toml` file and command-line options. This page documents the available configuration options for `bun test`. ## Configuration File You can configure `bun test` behavior by adding a `[test]` section to your `bunfig.toml` file: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # Options go here ``` ## Test Discovery ### root The `root` option specifies a root directory for test discovery, overriding the default behavior of scanning from the project root. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] root = "src" # Only scan for tests in the src directory ``` This is useful when you want to: * Limit test discovery to specific directories * Exclude certain parts of your project from test scanning * Organize tests in a specific subdirectory structure #### Examples ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # Only run tests in the src directory root = "src" # Run tests in a specific test directory root = "tests" # Run tests in multiple specific directories (not currently supported - use patterns instead) # root = ["src", "lib"] # This syntax is not supported ``` ### Preload Scripts Load scripts before running tests using the `preload` option: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] preload = ["./test-setup.ts", "./global-mocks.ts"] ``` This is equivalent to using `--preload` on the command line: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun test --preload ./test-setup.ts --preload ./global-mocks.ts ``` #### Common Preload Use Cases ```ts title="test-setup.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // Global test setup import { beforeAll, afterAll } from "bun:test"; beforeAll(() => { // Set up test database setupTestDatabase(); }); afterAll(() => { // Clean up cleanupTestDatabase(); }); ``` ```ts title="global-mocks.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // Global mocks import { mock } from "bun:test"; // Mock environment variables process.env.NODE_ENV = "test"; process.env.API_URL = "http://localhost:3001"; // Mock external dependencies mock.module("./external-api", () => ({ fetchData: mock(() => Promise.resolve({ data: "test" })), })); ``` ## Timeouts ### Default Timeout Set the default timeout for all tests: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] timeout = 10000 # 10 seconds (default is 5000ms) ``` This applies to all tests unless overridden by individual test timeouts: ```ts title="test.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // This test will use the default timeout from bunfig.toml test("uses default timeout", () => { // test implementation }); // This test overrides the default timeout test("custom timeout", () => { // test implementation }, 30000); // 30 seconds ``` ## Reporters ### JUnit Reporter Configure the JUnit reporter output file path directly in the config file: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test.reporter] junit = "path/to/junit.xml" # Output path for JUnit XML report ``` This complements the `--reporter=junit` and `--reporter-outfile` CLI flags: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} # Equivalent command line usage bun test --reporter=junit --reporter-outfile=./junit.xml ``` #### Multiple Reporters You can use multiple reporters simultaneously: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} # CLI approach bun test --reporter=junit --reporter-outfile=./junit.xml # Config file approach ``` ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test.reporter] junit = "./reports/junit.xml" [test] # Also enable coverage reporting coverage = true coverageReporter = ["text", "lcov"] ``` ## Memory Usage ### smol Mode Enable the `--smol` memory-saving mode specifically for the test runner: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] smol = true # Reduce memory usage during test runs ``` This is equivalent to using the `--smol` flag on the command line: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun test --smol ``` The `smol` mode reduces memory usage by: * Using less memory for the JavaScript heap * Being more aggressive about garbage collection * Reducing buffer sizes where possible This is useful for: * CI environments with limited memory * Large test suites that consume significant memory * Development environments with memory constraints ## Test execution ### concurrentTestGlob Automatically run test files matching a glob pattern with concurrent test execution enabled. This is useful for gradually migrating test suites to concurrent execution or for running specific test types concurrently. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] concurrentTestGlob = "**/concurrent-*.test.ts" # Run files matching this pattern concurrently ``` Test files matching this pattern will behave as if the `--concurrent` flag was passed, running all tests within those files concurrently. This allows you to: * Gradually migrate your test suite to concurrent execution * Run integration tests concurrently while keeping unit tests sequential * Separate fast concurrent tests from tests that require sequential execution The `--concurrent` CLI flag will override this setting when specified, forcing all tests to run concurrently regardless of the glob pattern. #### randomize Run tests in random order to identify tests with hidden dependencies: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] randomize = true ``` #### seed Specify a seed for reproducible random test order. Requires `randomize = true`: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] randomize = true seed = 2444615283 ``` #### rerunEach Re-run each test file multiple times to identify flaky tests: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] rerunEach = 3 ``` ## Coverage Options ### Basic Coverage Settings ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # Enable coverage by default coverage = true # Set coverage reporter coverageReporter = ["text", "lcov"] # Set coverage output directory coverageDir = "./coverage" ``` ### Skip Test Files from Coverage Exclude files matching test patterns (e.g., `*.test.ts`) from the coverage report: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] coverageSkipTestFiles = true # Exclude test files from coverage reports ``` ### Coverage Thresholds The coverage threshold can be specified either as a number or as an object with specific thresholds: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # Simple threshold - applies to lines, functions, and statements coverageThreshold = 0.8 # Detailed thresholds coverageThreshold = { lines = 0.9, functions = 0.8, statements = 0.85 } ``` Setting any of these enables `fail_on_low_coverage`, causing the test run to fail if coverage is below the threshold. #### Threshold Examples ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # Require 90% coverage across the board coverageThreshold = 0.9 # Different requirements for different metrics coverageThreshold = { lines = 0.85, # 85% line coverage functions = 0.90, # 90% function coverage statements = 0.80 # 80% statement coverage } ``` ### Coverage Path Ignore Patterns Exclude specific files or file patterns from coverage reports using glob patterns: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # Single pattern coveragePathIgnorePatterns = "**/*.spec.ts" # Multiple patterns coveragePathIgnorePatterns = [ "**/*.spec.ts", "**/*.test.ts", "src/utils/**", "*.config.js", "generated/**", "vendor/**" ] ``` Files matching any of these patterns will be excluded from coverage calculation and reporting. See the [coverage documentation](/test/code-coverage) for more details and examples. #### Common Ignore Patterns ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] coveragePathIgnorePatterns = [ # Test files "**/*.test.ts", "**/*.spec.ts", "**/*.e2e.ts", # Configuration files "*.config.js", "*.config.ts", "webpack.config.*", "vite.config.*", # Build output "dist/**", "build/**", ".next/**", # Generated code "generated/**", "**/*.generated.ts", # Vendor/third-party "vendor/**", "third-party/**", # Utilities that don't need testing "src/utils/constants.ts", "src/types/**" ] ``` ### Sourcemap Handling Internally, Bun transpiles every file. That means code coverage must also go through sourcemaps before they can be reported. We expose this as a flag to allow you to opt out of this behavior, but it will be confusing because during the transpilation process, Bun may move code around and change variable names. This option is mostly useful for debugging coverage issues. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] coverageIgnoreSourcemaps = true # Don't use sourcemaps for coverage analysis ``` When using this option, you probably want to stick a `// @bun` comment at the top of the source file to opt out of the transpilation process. ## Install Settings Inheritance The `bun test` command inherits relevant network and installation configuration (registry, cafile, prefer, exact, etc.) from the `[install]` section of `bunfig.toml`. This is important if tests need to interact with private registries or require specific install behaviors triggered during the test run. ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] # These settings are inherited by bun test registry = "https://npm.company.com/" exact = true prefer = "offline" [test] # Test-specific configuration coverage = true timeout = 10000 ``` ## Environment Variables Environment variables for tests should be set using `.env` files. Bun automatically loads `.env` files from your project root. For test-specific variables, create a `.env.test` file: ```ini title=".env.test" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} NODE_ENV=test DATABASE_URL=postgresql://localhost:5432/test_db LOG_LEVEL=error ``` Then load it with `--env-file`: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun test --env-file=.env.test ``` ## Complete Configuration Example Here's a comprehensive example showing all available test configuration options: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [install] # Install settings inherited by tests registry = "https://registry.npmjs.org/" exact = true [test] # Test discovery root = "src" preload = ["./test-setup.ts", "./global-mocks.ts"] # Execution settings timeout = 10000 smol = true # Coverage configuration coverage = true coverageReporter = ["text", "lcov"] coverageDir = "./coverage" coverageThreshold = { lines = 0.85, functions = 0.90, statements = 0.80 } coverageSkipTestFiles = true coveragePathIgnorePatterns = [ "**/*.spec.ts", "src/utils/**", "*.config.js", "generated/**" ] # Advanced coverage settings coverageIgnoreSourcemaps = false # Reporter configuration [test.reporter] junit = "./reports/junit.xml" ``` ## CLI Override Behavior Command-line options always override configuration file settings: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] timeout = 5000 coverage = false ``` ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} # These CLI flags override the config file bun test --timeout 10000 --coverage # timeout will be 10000ms and coverage will be enabled ``` ## Conditional Configuration You can use different configurations for different environments: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # Default test configuration coverage = false timeout = 5000 # Override for CI environment [test.ci] coverage = true coverageThreshold = 0.8 timeout = 30000 ``` Then in CI: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} # Use CI-specific settings bun test --config=ci ``` ## Validation and Troubleshooting ### Invalid Configuration Bun will warn about invalid configuration options: ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] invalidOption = true # This will generate a warning ``` ### Common Configuration Issues 1. **Path Resolution**: Relative paths in config are resolved relative to the config file location 2. **Pattern Matching**: Glob patterns use standard glob syntax 3. **Type Mismatches**: Ensure numeric values are not quoted unless they should be strings ```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # Correct timeout = 10000 # Incorrect - will be treated as string timeout = "10000" ``` ### Debugging Configuration To see what configuration is being used: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} # Show effective configuration bun test --dry-run # Verbose output to see configuration loading bun test --verbose ``` --- # Source: https://bun.com/docs/runtime/console.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Console > The console object in Bun Bun provides a browser- and Node.js-compatible [console](https://developer.mozilla.org/en-US/docs/Web/API/console) global. This page only documents Bun-native APIs. *** ## Object inspection depth Bun allows you to configure how deeply nested objects are displayed in `console.log()` output: * **CLI flag**: Use `--console-depth ` to set the depth for a single run * **Configuration**: Set `console.depth` in your `bunfig.toml` for persistent configuration * **Default**: Objects are inspected to a depth of `2` levels ```js theme={"theme":{"light":"github-light","dark":"dracula"}} const nested = { a: { b: { c: { d: "deep" } } } }; console.log(nested); // Default (depth 2): { a: { b: [Object] } } // With depth 4: { a: { b: { c: { d: 'deep' } } } } ``` The CLI flag takes precedence over the configuration file setting. *** ## Reading from stdin In Bun, the `console` object can be used as an `AsyncIterable` to sequentially read lines from `process.stdin`. ```ts adder.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} for await (const line of console) { console.log(line); } ``` This is useful for implementing interactive programs, like the following addition calculator. ```ts adder.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} console.log(`Let's add some numbers!`); console.write(`Count: 0\n> `); let count = 0; for await (const line of console) { count += Number(line); console.write(`Count: ${count}\n> `); } ``` To run the file: ```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun adder.ts Let's add some numbers! Count: 0 > 5 Count: 5 > 5 Count: 10 > 5 Count: 15 ``` --- # Source: https://bun.com/docs/guides/websocket/context.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Set per-socket contextual data on a WebSocket When building a WebSocket server, it's typically necessary to store some identifying information or context associated with each connected client. With [Bun.serve()](/runtime/http/websockets#contextual-data), this "contextual data" is set when the connection is initially upgraded by passing a `data` parameter in the `server.upgrade()` call. ```ts server.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} Bun.serve({ fetch(req, server) { const success = server.upgrade(req, { data: { socketId: Math.random(), }, }); if (success) return undefined; // handle HTTP request normally // ... }, websocket: { // TypeScript: specify the type of ws.data like this data: {} as { socketId: number }, // define websocket handlers async message(ws, message) { // the contextual data is available as the `data` property // on the WebSocket instance console.log(`Received ${message} from ${ws.data.socketId}}`); }, }, }); ``` *** It's common to read cookies/headers from the incoming request to identify the connecting client. ```ts server.ts icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} type WebSocketData = { createdAt: number; token: string; userId: string; }; Bun.serve({ async fetch(req, server) { // use a library to parse cookies const cookies = parseCookies(req.headers.get("Cookie")); const token = cookies["X-Token"]; const user = await getUserFromToken(token); const upgraded = server.upgrade(req, { data: { createdAt: Date.now(), token: cookies["X-Token"], userId: user.id, }, }); if (upgraded) return undefined; }, websocket: { // TypeScript: specify the type of ws.data like this data: {} as WebSocketData, async message(ws, message) { // save the message to a database await saveMessageToDatabase({ message: String(message), userId: ws.data.userId, }); }, }, }); ``` --- # Source: https://bun.com/docs/project/contributing.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Contributing > Contributing to Bun Configuring a development environment for Bun can take 10-30 minutes depending on your internet connection and computer speed. You will need \~10GB of free disk space for the repository and build artifacts. If you are using Windows, please refer to [this guide](/project/building-windows) ## Using Nix (Alternative) A Nix flake is provided as an alternative to manual dependency installation: ```bash theme={"theme":{"light":"github-light","dark":"dracula"}} nix develop # or explicitly use the pure shell # nix develop .#pure export CMAKE_SYSTEM_PROCESSOR=$(uname -m) bun bd ``` This provides all dependencies in an isolated, reproducible environment without requiring sudo. ## Install Dependencies (Manual) Using your system's package manager, install Bun's dependencies: ```bash macOS (Homebrew) theme={"theme":{"light":"github-light","dark":"dracula"}} brew install automake ccache cmake coreutils gnu-sed go icu4c libiconv libtool ninja pkg-config rust ruby ``` ```bash Ubuntu/Debian theme={"theme":{"light":"github-light","dark":"dracula"}} sudo apt install curl wget lsb-release software-properties-common cargo cmake git golang libtool ninja-build pkg-config rustc ruby-full xz-utils ``` ```bash Arch theme={"theme":{"light":"github-light","dark":"dracula"}} sudo pacman -S base-devel cmake git go libiconv libtool make ninja pkg-config python rust sed unzip ruby ``` ```bash Fedora theme={"theme":{"light":"github-light","dark":"dracula"}} sudo dnf install cargo clang19 llvm19 lld19 cmake git golang libtool ninja-build pkg-config rustc ruby libatomic-static libstdc++-static sed unzip which libicu-devel 'perl(Math::BigInt)' ``` ```bash openSUSE Tumbleweed theme={"theme":{"light":"github-light","dark":"dracula"}} sudo zypper install go cmake ninja automake git icu rustup && rustup toolchain install stable ``` > **Note**: The Zig compiler is automatically installed and updated by the build scripts. Manual installation is not required. Before starting, you will need to already have a release build of Bun installed, as we use our bundler to transpile and minify our code, as well as for code generation scripts. ```bash Native theme={"theme":{"light":"github-light","dark":"dracula"}} curl -fsSL https://bun.com/install | bash ``` ```bash npm theme={"theme":{"light":"github-light","dark":"dracula"}} npm install -g bun ``` ```bash Homebrew theme={"theme":{"light":"github-light","dark":"dracula"}} brew tap oven-sh/bun brew install bun ``` ### Optional: Install `ccache` ccache is used to cache compilation artifacts, significantly speeding up builds: ```bash theme={"theme":{"light":"github-light","dark":"dracula"}} # For macOS brew install ccache # For Ubuntu/Debian sudo apt install ccache # For Arch sudo pacman -S ccache # For Fedora sudo dnf install ccache # For openSUSE sudo zypper install ccache ``` Our build scripts will automatically detect and use `ccache` if available. You can check cache statistics with `ccache --show-stats`. ## Install LLVM Bun requires LLVM 19 (`clang` is part of LLVM). This version requirement is to match WebKit (precompiled), as mismatching versions will cause memory allocation failures at runtime. In most cases, you can install LLVM through your system package manager: ```bash macOS (Homebrew) theme={"theme":{"light":"github-light","dark":"dracula"}} brew install llvm@19 ``` ```bash Ubuntu/Debian theme={"theme":{"light":"github-light","dark":"dracula"}} # LLVM has an automatic installation script that is compatible with all versions of Ubuntu wget https://apt.llvm.org/llvm.sh -O - | sudo bash -s -- 19 all ``` ```bash Arch theme={"theme":{"light":"github-light","dark":"dracula"}} sudo pacman -S llvm clang lld ``` ```bash Fedora theme={"theme":{"light":"github-light","dark":"dracula"}} sudo dnf install llvm clang lld-devel ``` ```bash openSUSE Tumbleweed theme={"theme":{"light":"github-light","dark":"dracula"}} sudo zypper install clang19 lld19 llvm19 ``` If none of the above solutions apply, you will have to install it [manually](https://github.com/llvm/llvm-project/releases/tag/llvmorg-19.1.7). Make sure Clang/LLVM 19 is in your path: ```bash theme={"theme":{"light":"github-light","dark":"dracula"}} which clang-19 ``` If not, run this to manually add it: ```bash macOS (Homebrew) theme={"theme":{"light":"github-light","dark":"dracula"}} # use fish_add_path if you're using fish # use path+="$(brew --prefix llvm@19)/bin" if you are using zsh export PATH="$(brew --prefix llvm@19)/bin:$PATH" ``` ```bash Arch theme={"theme":{"light":"github-light","dark":"dracula"}} # use fish_add_path if you're using fish export PATH="$PATH:/usr/lib/llvm19/bin" ``` ⚠️ Ubuntu distributions (\<= 20.04) may require installation of the C++ standard library independently. See the [troubleshooting section](#span-file-not-found-on-ubuntu) for more information. ## Building Bun After cloning the repository, run the following command to build. This may take a while as it will clone submodules and build dependencies. ```bash theme={"theme":{"light":"github-light","dark":"dracula"}} bun run build ``` The binary will be located at `./build/debug/bun-debug`. It is recommended to add this to your `$PATH`. To verify the build worked, let's print the version number on the development build of Bun. ```bash theme={"theme":{"light":"github-light","dark":"dracula"}} build/debug/bun-debug --version x.y.z_debug ``` ## VSCode VSCode is the recommended IDE for working on Bun, as it has been configured. Once opening, you can run `Extensions: Show Recommended Extensions` to install the recommended extensions for Zig and C++. ZLS is automatically configured. If you use a different editor, make sure that you tell ZLS to use the automatically installed Zig compiler, which is located at `./vendor/zig/zig.exe`. The filename is `zig.exe` so that it works as expected on Windows, but it still works on macOS/Linux (it just has a surprising file extension). We recommend adding `./build/debug` to your `$PATH` so that you can run `bun-debug` in your terminal: ```sh theme={"theme":{"light":"github-light","dark":"dracula"}} bun-debug ``` ## Running debug builds The `bd` package.json script compiles and runs a debug build of Bun, only printing the output of the build process if it fails. ```sh theme={"theme":{"light":"github-light","dark":"dracula"}} bun bd bun bd test foo.test.ts bun bd ./foo.ts ``` Bun generally takes about 2.5 minutes to compile a debug build when there are Zig changes. If your development workflow is "change one line, save, rebuild", you will spend too much time waiting for the build to finish. Instead: * Batch up your changes * Ensure zls is running with incremental watching for LSP errors (if you use VSCode and install Zig and run `bun run build` once to download Zig, this should just work) * Prefer using the debugger ("CodeLLDB" in VSCode) to step through the code. * Use debug logs. `BUN_DEBUG_=1` will enable debug logging for the corresponding `Output.scoped(., .hidden)` logs. You can also set `BUN_DEBUG_QUIET_LOGS=1` to disable all debug logging that isn't explicitly enabled. To dump debug logs into a file, `BUN_DEBUG=.log`. Debug logs are aggressively removed in release builds. * src/js/\*\*.ts changes are pretty much instant to rebuild. C++ changes are a bit slower, but still much faster than the Zig code (Zig is one compilation unit, C++ is many). ## Code generation scripts Several code generation scripts are used during Bun's build process. These are run automatically when changes are made to certain files. In particular, these are: * `./src/codegen/generate-jssink.ts` -- Generates `build/debug/codegen/JSSink.cpp`, `build/debug/codegen/JSSink.h` which implement various classes for interfacing with `ReadableStream`. This is internally how `FileSink`, `ArrayBufferSink`, `"type": "direct"` streams and other code related to streams works. * `./src/codegen/generate-classes.ts` -- Generates `build/debug/codegen/ZigGeneratedClasses*`, which generates Zig & C++ bindings for JavaScriptCore classes implemented in Zig. In `**/*.classes.ts` files, we define the interfaces for various classes, methods, prototypes, getters/setters etc which the code generator reads to generate boilerplate code implementing the JavaScript objects in C++ and wiring them up to Zig * `./src/codegen/cppbind.ts` -- Generates automatic Zig bindings for C++ functions marked with `[[ZIG_EXPORT]]` attributes. * `./src/codegen/bundle-modules.ts` -- Bundles built-in modules like `node:fs`, `bun:ffi` into files we can include in the final binary. In development, these can be reloaded without rebuilding Zig (you still need to run `bun run build`, but it re-reads the transpiled files from disk afterwards). In release builds, these are embedded into the binary. * `./src/codegen/bundle-functions.ts` -- Bundles globally-accessible functions implemented in JavaScript/TypeScript like `ReadableStream`, `WritableStream`, and a handful more. These are used similarly to the builtin modules, but the output more closely aligns with what WebKit/Safari does for Safari's built-in functions so that we can copy-paste the implementations from WebKit as a starting point. ## Modifying ESM modules Certain modules like `node:fs`, `node:stream`, `bun:sqlite`, and `ws` are implemented in JavaScript. These live in `src/js/{node,bun,thirdparty}` files and are pre-bundled using Bun. ## Release build To compile a release build of Bun, run: ```bash theme={"theme":{"light":"github-light","dark":"dracula"}} bun run build:release ``` The binary will be located at `./build/release/bun` and `./build/release/bun-profile`. ### Download release build from pull requests To save you time spent building a release build locally, we provide a way to run release builds from pull requests. This is useful for manually testing changes in a release build before they are merged. To run a release build from a pull request, you can use the `bun-pr` npm package: ```sh theme={"theme":{"light":"github-light","dark":"dracula"}} bunx bun-pr bunx bun-pr bunx bun-pr "https://github.com/oven-sh/bun/pull/1234566" bunx bun-pr --asan # Linux x64 only ``` This will download the release build from the pull request and add it to `$PATH` as `bun-${pr-number}`. You can then run the build with `bun-${pr-number}`. ```sh theme={"theme":{"light":"github-light","dark":"dracula"}} bun-1234566 --version ``` This works by downloading the release build from the GitHub Actions artifacts on the linked pull request. You may need the `gh` CLI installed to authenticate with GitHub. ## AddressSanitizer [AddressSanitizer](https://en.wikipedia.org/wiki/AddressSanitizer) helps find memory issues, and is enabled by default in debug builds of Bun on Linux and macOS. This includes the Zig code and all dependencies. It makes the Zig code take about 2x longer to build, if that's stopping you from being productive you can disable it by setting `-Denable_asan=$,true,false>` to `-Denable_asan=false` in the `cmake/targets/BuildBun.cmake` file, but generally we recommend batching your changes up between builds. To build a release build with Address Sanitizer, run: ```bash theme={"theme":{"light":"github-light","dark":"dracula"}} bun run build:release:asan ``` In CI, we run our test suite with at least one target that is built with Address Sanitizer. ## Building WebKit locally + Debug mode of JSC WebKit is not cloned by default (to save time and disk space). To clone and build WebKit locally, run: ```bash theme={"theme":{"light":"github-light","dark":"dracula"}} # Clone WebKit into ./vendor/WebKit git clone https://github.com/oven-sh/WebKit vendor/WebKit # Check out the commit hash specified in `set(WEBKIT_VERSION )` in cmake/tools/SetupWebKit.cmake git -C vendor/WebKit checkout # Build bun with the local JSC build — this automatically configures and builds JSC bun run build:local ``` `bun run build:local` handles everything: configuring JSC, building JSC, and building Bun. On subsequent runs, JSC will incrementally rebuild if any WebKit sources changed. `ninja -Cbuild/debug-local` also works after the first build, and will build Bun+JSC. The build output goes to `./build/debug-local` (instead of `./build/debug`), so you'll need to update a couple of places: * The first line in `src/js/builtins.d.ts` * The `CompilationDatabase` line in `.clangd` config should be `CompilationDatabase: build/debug-local` * In `build.zig`, the `codegen_path` option should be `build/debug-local/codegen` (instead of `build/debug/codegen`) * In `.vscode/launch.json`, many configurations use `./build/debug/`, change them as you see fit Note that the WebKit folder, including build artifacts, is 8GB+ in size. If you are using a JSC debug build and using VScode, make sure to run the `C/C++: Select a Configuration` command to configure intellisense to find the debug headers. Note that if you make changes to our [WebKit fork](https://github.com/oven-sh/WebKit), you will also have to change `SetupWebKit.cmake` to point to the commit hash. ## Troubleshooting ### 'span' file not found on Ubuntu ⚠️ Please note that the instructions below are specific to issues occurring on Ubuntu. It is unlikely that the same issues will occur on other Linux distributions. The Clang compiler typically uses the `libstdc++` C++ standard library by default. `libstdc++` is the default C++ Standard Library implementation provided by the GNU Compiler Collection (GCC). While Clang may link against the `libc++` library, this requires explicitly providing the `-stdlib` flag when running Clang. Bun relies on C++20 features like `std::span`, which are not available in GCC versions lower than 11. GCC 10 doesn't have all of the C++20 features implemented. As a result, running `make setup` may fail with the following error: ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} fatal error: 'span' file not found #include ^~~~~~ ``` The issue may manifest when initially running `bun setup` as Clang being unable to compile a simple program: ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} The C++ compiler "/usr/bin/clang++-19" is not able to compile a simple test program. ``` To fix the error, we need to update the GCC version to 11. To do this, we'll need to check if the latest version is available in the distribution's official repositories or use a third-party repository that provides GCC 11 packages. Here are general steps: ```bash theme={"theme":{"light":"github-light","dark":"dracula"}} sudo apt update sudo apt install gcc-11 g++-11 # If the above command fails with `Unable to locate package gcc-11` we need # to add the APT repository sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test # Now run `apt install` again sudo apt install gcc-11 g++-11 ``` Now, we need to set GCC 11 as the default compiler: ```bash theme={"theme":{"light":"github-light","dark":"dracula"}} sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 100 sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-11 100 ``` ### libarchive If you see an error on macOS when compiling `libarchive`, run: ```bash theme={"theme":{"light":"github-light","dark":"dracula"}} brew install pkg-config ``` ### macOS `library not found for -lSystem` If you see this error when compiling, run: ```bash theme={"theme":{"light":"github-light","dark":"dracula"}} xcode-select --install ``` ### Cannot find `libatomic.a` Bun defaults to linking `libatomic` statically, as not all systems have it. If you are building on a distro that does not have a static libatomic available, you can run the following command to enable dynamic linking: ```bash theme={"theme":{"light":"github-light","dark":"dracula"}} bun run build -DUSE_STATIC_LIBATOMIC=OFF ``` The built version of Bun may not work on other systems if compiled this way. ## Using bun-debug * Disable logging: `BUN_DEBUG_QUIET_LOGS=1 bun-debug ...` (to disable all debug logging) * Enable logging for a specific zig scope: `BUN_DEBUG_EventLoop=1 bun-debug ...` (to allow `std.log.scoped(.EventLoop)`) * Bun transpiles every file it runs, to see the actual executed source in a debug build find it in `/tmp/bun-debug-src/...path/to/file`, for example the transpiled version of `/home/bun/index.ts` would be in `/tmp/bun-debug-src/home/bun/index.ts` --- # Source: https://bun.com/docs/runtime/http/cookies.md # Source: https://bun.com/docs/runtime/cookies.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Cookies > Use Bun's native APIs for working with HTTP cookies Bun provides native APIs for working with HTTP cookies through `Bun.Cookie` and `Bun.CookieMap`. These APIs offer fast, easy-to-use methods for parsing, generating, and manipulating cookies in HTTP requests and responses. ## CookieMap class `Bun.CookieMap` provides a Map-like interface for working with collections of cookies. It implements the `Iterable` interface, allowing you to use it with `for...of` loops and other iteration methods. ```ts title="cookies.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // Empty cookie map const cookies = new Bun.CookieMap(); // From a cookie string const cookies1 = new Bun.CookieMap("name=value; foo=bar"); // From an object const cookies2 = new Bun.CookieMap({ session: "abc123", theme: "dark", }); // From an array of name/value pairs const cookies3 = new Bun.CookieMap([ ["session", "abc123"], ["theme", "dark"], ]); ``` ### In HTTP servers In Bun's HTTP server, the `cookies` property on the request object (in `routes`) is an instance of `CookieMap`: ```ts title="server.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const server = Bun.serve({ routes: { "/": req => { // Access request cookies const cookies = req.cookies; // Get a specific cookie const sessionCookie = cookies.get("session"); if (sessionCookie != null) { console.log(sessionCookie); } // Check if a cookie exists if (cookies.has("theme")) { // ... } // Set a cookie, it will be automatically applied to the response cookies.set("visited", "true"); return new Response("Hello"); }, }, }); console.log("Server listening at: " + server.url); ``` ### Methods #### `get(name: string): string | null` Retrieves a cookie by name. Returns `null` if the cookie doesn't exist. ```ts title="get-cookie.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // Get by name const cookie = cookies.get("session"); if (cookie != null) { console.log(cookie); } ``` #### `has(name: string): boolean` Checks if a cookie with the given name exists. ```ts title="has-cookie.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // Check if cookie exists if (cookies.has("session")) { // Cookie exists } ``` #### `set(name: string, value: string): void` #### `set(options: CookieInit): void` #### `set(cookie: Cookie): void` Adds or updates a cookie in the map. Cookies default to `{ path: "/", sameSite: "lax" }`. ```ts title="set-cookie.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // Set by name and value cookies.set("session", "abc123"); // Set using options object cookies.set({ name: "theme", value: "dark", maxAge: 3600, secure: true, }); // Set using Cookie instance const cookie = new Bun.Cookie("visited", "true"); cookies.set(cookie); ``` #### `delete(name: string): void` #### `delete(options: CookieStoreDeleteOptions): void` Removes a cookie from the map. When applied to a Response, this adds a cookie with an empty string value and an expiry date in the past. A cookie will only delete successfully on the browser if the domain and path is the same as it was when the cookie was created. ```ts title="delete-cookie.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // Delete by name using default domain and path. cookies.delete("session"); // Delete with domain/path options. cookies.delete({ name: "session", domain: "example.com", path: "/admin", }); ``` #### `toJSON(): Record` Converts the cookie map to a serializable format. ```ts title="cookie-to-json.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const json = cookies.toJSON(); ``` #### `toSetCookieHeaders(): string[]` Returns an array of values for Set-Cookie headers that can be used to apply all cookie changes. When using `Bun.serve()`, you don't need to call this method explicitly. Any changes made to the `req.cookies` map are automatically applied to the response headers. This method is primarily useful when working with other HTTP server implementations. ```js title="node-server.js" icon="file-code" theme={"theme":{"light":"github-light","dark":"dracula"}} import { createServer } from "node:http"; import { CookieMap } from "bun"; const server = createServer((req, res) => { const cookieHeader = req.headers.cookie || ""; const cookies = new CookieMap(cookieHeader); cookies.set("view-count", Number(cookies.get("view-count") || "0") + 1); cookies.delete("session"); res.writeHead(200, { "Content-Type": "text/plain", "Set-Cookie": cookies.toSetCookieHeaders(), }); res.end(`Found ${cookies.size} cookies`); }); server.listen(3000, () => { console.log("Server running at http://localhost:3000/"); }); ``` ### Iteration `CookieMap` provides several methods for iteration: ```ts title="iterate-cookies.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // Iterate over [name, cookie] entries for (const [name, value] of cookies) { console.log(`${name}: ${value}`); } // Using entries() for (const [name, value] of cookies.entries()) { console.log(`${name}: ${value}`); } // Using keys() for (const name of cookies.keys()) { console.log(name); } // Using values() for (const value of cookies.values()) { console.log(value); } // Using forEach cookies.forEach((value, name) => { console.log(`${name}: ${value}`); }); ``` ### Properties #### `size: number` Returns the number of cookies in the map. ```ts title="cookie-size.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} console.log(cookies.size); // Number of cookies ``` ## Cookie class `Bun.Cookie` represents an HTTP cookie with its name, value, and attributes. ```ts title="cookie-class.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} import { Cookie } from "bun"; // Create a basic cookie const cookie = new Bun.Cookie("name", "value"); // Create a cookie with options const secureSessionCookie = new Bun.Cookie("session", "abc123", { domain: "example.com", path: "/admin", expires: new Date(Date.now() + 86400000), // 1 day httpOnly: true, secure: true, sameSite: "strict", }); // Parse from a cookie string const parsedCookie = new Bun.Cookie("name=value; Path=/; HttpOnly"); // Create from an options object const objCookie = new Bun.Cookie({ name: "theme", value: "dark", maxAge: 3600, secure: true, }); ``` ### Constructors ```ts title="constructors.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // Basic constructor with name/value new Bun.Cookie(name: string, value: string); // Constructor with name, value, and options new Bun.Cookie(name: string, value: string, options: CookieInit); // Constructor from cookie string new Bun.Cookie(cookieString: string); // Constructor from cookie object new Bun.Cookie(options: CookieInit); ``` ### Properties ```ts title="cookie-properties.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} cookie.name; // string - Cookie name cookie.value; // string - Cookie value cookie.domain; // string | null - Domain scope (null if not specified) cookie.path; // string - URL path scope (defaults to "/") cookie.expires; // number | undefined - Expiration timestamp (ms since epoch) cookie.secure; // boolean - Require HTTPS cookie.sameSite; // "strict" | "lax" | "none" - SameSite setting cookie.partitioned; // boolean - Whether the cookie is partitioned (CHIPS) cookie.maxAge; // number | undefined - Max age in seconds cookie.httpOnly; // boolean - Accessible only via HTTP (not JavaScript) ``` ### Methods #### `isExpired(): boolean` Checks if the cookie has expired. ```ts title="is-expired.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} // Expired cookie (Date in the past) const expiredCookie = new Bun.Cookie("name", "value", { expires: new Date(Date.now() - 1000), }); console.log(expiredCookie.isExpired()); // true // Valid cookie (Using maxAge instead of expires) const validCookie = new Bun.Cookie("name", "value", { maxAge: 3600, // 1 hour in seconds }); console.log(validCookie.isExpired()); // false // Session cookie (no expiration) const sessionCookie = new Bun.Cookie("name", "value"); console.log(sessionCookie.isExpired()); // false ``` #### `serialize(): string` #### `toString(): string` Returns a string representation of the cookie suitable for a `Set-Cookie` header. ```ts title="serialize-cookie.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const cookie = new Bun.Cookie("session", "abc123", { domain: "example.com", path: "/admin", expires: new Date(Date.now() + 86400000), secure: true, httpOnly: true, sameSite: "strict", }); console.log(cookie.serialize()); // => "session=abc123; Domain=example.com; Path=/admin; Expires=Sun, 19 Mar 2025 15:03:26 GMT; Secure; HttpOnly; SameSite=strict" console.log(cookie.toString()); // => "session=abc123; Domain=example.com; Path=/admin; Expires=Sun, 19 Mar 2025 15:03:26 GMT; Secure; HttpOnly; SameSite=strict" ``` #### `toJSON(): CookieInit` Converts the cookie to a plain object suitable for JSON serialization. ```ts title="cookie-json.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const cookie = new Bun.Cookie("session", "abc123", { secure: true, httpOnly: true, }); const json = cookie.toJSON(); // => { // name: "session", // value: "abc123", // path: "/", // secure: true, // httpOnly: true, // sameSite: "lax", // partitioned: false // } // Works with JSON.stringify const jsonString = JSON.stringify(cookie); ``` ### Static methods #### `Cookie.parse(cookieString: string): Cookie` Parses a cookie string into a `Cookie` instance. ```ts title="parse-cookie.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const cookie = Bun.Cookie.parse("name=value; Path=/; Secure; SameSite=Lax"); console.log(cookie.name); // "name" console.log(cookie.value); // "value" console.log(cookie.path); // "/" console.log(cookie.secure); // true console.log(cookie.sameSite); // "lax" ``` #### `Cookie.from(name: string, value: string, options?: CookieInit): Cookie` Factory method to create a cookie. ```ts title="cookie-from.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} const cookie = Bun.Cookie.from("session", "abc123", { httpOnly: true, secure: true, maxAge: 3600, }); ``` ## Types ```ts title="types.ts" icon="https://mintcdn.com/bun-1dd33a4e/Hq64iapoQXHbYMEN/icons/typescript.svg?fit=max&auto=format&n=Hq64iapoQXHbYMEN&q=85&s=c6cceedec8f82d2cc803d7c6ec82b240" theme={"theme":{"light":"github-light","dark":"dracula"}} interface CookieInit { name?: string; value?: string; domain?: string; /** Defaults to '/'. To allow the browser to set the path, use an empty string. */ path?: string; expires?: number | Date | string; secure?: boolean; /** Defaults to `lax`. */ sameSite?: CookieSameSite; httpOnly?: boolean; partitioned?: boolean; maxAge?: number; } interface CookieStoreDeleteOptions { name: string; domain?: string | null; path?: string; } interface CookieStoreGetOptions { name?: string; url?: string; } type CookieSameSite = "strict" | "lax" | "none"; class Cookie { constructor(name: string, value: string, options?: CookieInit); constructor(cookieString: string); constructor(cookieObject?: CookieInit); readonly name: string; value: string; domain?: string; path: string; expires?: Date; secure: boolean; sameSite: CookieSameSite; partitioned: boolean; maxAge?: number; httpOnly: boolean; isExpired(): boolean; serialize(): string; toString(): string; toJSON(): CookieInit; static parse(cookieString: string): Cookie; static from(name: string, value: string, options?: CookieInit): Cookie; } class CookieMap implements Iterable<[string, string]> { constructor(init?: string[][] | Record | string); get(name: string): string | null; toSetCookieHeaders(): string[]; has(name: string): boolean; set(name: string, value: string, options?: CookieInit): void; set(options: CookieInit): void; delete(name: string): void; delete(options: CookieStoreDeleteOptions): void; delete(name: string, options: Omit): void; toJSON(): Record; readonly size: number; entries(): IterableIterator<[string, string]>; keys(): IterableIterator; values(): IterableIterator; forEach(callback: (value: string, key: string, map: CookieMap) => void): void; [Symbol.iterator](): IterableIterator<[string, string]>; } ``` --- # Source: https://bun.com/docs/guides/test/coverage-threshold.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Set a code coverage threshold with the Bun test runner Bun's test runner supports built-in code coverage reporting via the `--coverage` flag. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun test --coverage ``` ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} test.test.ts: ✓ math > add [0.71ms] ✓ math > multiply [0.03ms] ✓ random [0.13ms] -------------|---------|---------|------------------- File | % Funcs | % Lines | Uncovered Line #s -------------|---------|---------|------------------- All files | 66.67 | 77.78 | math.ts | 50.00 | 66.67 | random.ts | 50.00 | 66.67 | -------------|---------|---------|------------------- 3 pass 0 fail 3 expect() calls ``` *** To set a minimum coverage threshold, add the following line to your `bunfig.toml`. This requires that 90% of your codebase is covered by tests. ```toml bunfig.toml icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # to require 90% line-level and function-level coverage coverageThreshold = 0.9 ``` *** If your test suite does not meet this threshold, `bun test` will exit with a non-zero exit code to signal a failure. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun test --coverage ``` ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} $ echo $? 1 # this is the exit code of the previous command ``` *** Different thresholds can be set for line-level and function-level coverage. ```toml bunfig.toml icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] # to set different thresholds for lines and functions coverageThreshold = { lines = 0.5, functions = 0.7 } ``` *** See [Docs > Test runner > Coverage](/test/code-coverage) for complete documentation on code coverage reporting in Bun. --- # Source: https://bun.com/docs/guides/test/coverage.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # Generate code coverage reports with the Bun test runner Bun's test runner supports built-in *code coverage reporting*. This makes it easy to see how much of the codebase is covered by tests and find areas that are not currently well-tested. *** Pass the `--coverage` flag to `bun test` to enable this feature. This will print a coverage report after the test run. The coverage report lists the source files that were executed during the test run, the percentage of functions and lines that were executed, and the line ranges that were not executed during the run. ```sh terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}} bun test --coverage ``` ```txt theme={"theme":{"light":"github-light","dark":"dracula"}} test.test.ts: ✓ math > add [0.71ms] ✓ math > multiply [0.03ms] ✓ random [0.13ms] -------------|---------|---------|------------------- File | % Funcs | % Lines | Uncovered Line #s -------------|---------|---------|------------------- All files | 66.67 | 77.78 | math.ts | 50.00 | 66.67 | random.ts | 50.00 | 66.67 | -------------|---------|---------|------------------- 3 pass 0 fail 3 expect() calls ``` *** To always enable coverage reporting by default, add the following line to your `bunfig.toml`: ```toml bunfig.toml icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}} [test] coverage = true # always enable coverage ``` *** Refer to [Docs > Test runner > Coverage](/test/code-coverage) for complete documentation on code coverage reporting in Bun. --- # Source: https://bun.com/docs/runtime/templating/create.md > ## Documentation Index > Fetch the complete documentation index at: https://bun.com/docs/llms.txt > Use this file to discover all available pages before exploring further. # bun create > Create a new Bun project from a React component, a `create-