aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/api/file-io.md12
-rw-r--r--docs/api/http.md107
-rw-r--r--docs/api/streams.md6
-rw-r--r--docs/cli/bun-install.md4
-rw-r--r--docs/cli/install.md69
-rw-r--r--docs/cli/test.md18
-rw-r--r--docs/ecosystem/stric.md16
-rw-r--r--docs/install/index.md9
-rw-r--r--docs/install/registries.md4
-rw-r--r--docs/installation.md12
-rw-r--r--docs/nav.ts18
-rw-r--r--docs/project/development.md55
-rw-r--r--docs/project/licensing.md5
-rw-r--r--docs/runtime/configuration.md3
-rw-r--r--docs/runtime/nodejs-apis.md16
-rw-r--r--docs/runtime/typescript.md11
-rw-r--r--docs/test/lifecycle.md4
-rw-r--r--docs/test/mocks.md55
-rw-r--r--docs/test/time.md106
-rw-r--r--docs/test/writing.md92
20 files changed, 537 insertions, 85 deletions
diff --git a/docs/api/file-io.md b/docs/api/file-io.md
index effc57580..be9cf0991 100644
--- a/docs/api/file-io.md
+++ b/docs/api/file-io.md
@@ -285,7 +285,13 @@ interface Bun {
write(
destination: string | number | BunFile | URL,
- input: string | Blob | ArrayBuffer | SharedArrayBuffer | TypedArray | Response,
+ input:
+ | string
+ | Blob
+ | ArrayBuffer
+ | SharedArrayBuffer
+ | TypedArray
+ | Response,
): Promise<number>;
}
@@ -301,7 +307,9 @@ interface BunFile {
}
export interface FileSink {
- write(chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer): number;
+ write(
+ chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
+ ): number;
flush(): number | Promise<number>;
end(error?: Error): number | Promise<number>;
start(options?: { highWaterMark?: number }): void;
diff --git a/docs/api/http.md b/docs/api/http.md
index aed9da27c..8520604e8 100644
--- a/docs/api/http.md
+++ b/docs/api/http.md
@@ -67,7 +67,7 @@ Bun.serve({
fetch(req) {
throw new Error("woops!");
},
- error(error: Error) {
+ error(error) {
return new Response(`<pre>${error}\n${error.stack}</pre>`, {
headers: {
"Content-Type": "text/html",
@@ -95,37 +95,37 @@ server.stop();
## TLS
-Bun supports TLS out of the box, powered by [OpenSSL](https://www.openssl.org/). Enable TLS by passing in a value for `key` and `cert`; both are required to enable TLS. If needed, supply a `passphrase` to decrypt the `keyFile`.
+Bun supports TLS out of the box, powered by [BoringSSL](https://boringssl.googlesource.com/boringssl). Enable TLS by passing in a value for `key` and `cert`; both are required to enable TLS.
-```ts
-Bun.serve({
- fetch(req) {
- return new Response("Hello!!!");
- },
-
- // can be string, BunFile, TypedArray, Buffer, or array thereof
- key: Bun.file("./key.pem"),
- cert: Bun.file("./cert.pem"),
+```ts-diff
+ Bun.serve({
+ fetch(req) {
+ return new Response("Hello!!!");
+ },
- // passphrase, only required if key is encrypted
- passphrase: "super-secret",
-});
++ tls: {
++ key: Bun.file("./key.pem"),
++ cert: Bun.file("./cert.pem"),
++ }
+ });
```
-The `key` and `cert` fields expect the _contents_ of your TLS key and certificate. This can be a string, `BunFile`, `TypedArray`, or `Buffer`.
+The `key` and `cert` fields expect the _contents_ of your TLS key and certificate, _not a path to it_. This can be a string, `BunFile`, `TypedArray`, or `Buffer`.
```ts
Bun.serve({
fetch() {},
- // BunFile
- key: Bun.file("./key.pem"),
- // Buffer
- key: fs.readFileSync("./key.pem"),
- // string
- key: fs.readFileSync("./key.pem", "utf8"),
- // array of above
- key: [Bun.file('./key1.pem'), Bun.file('./key2.pem')],
+ tls: {
+ // BunFile
+ key: Bun.file("./key.pem"),
+ // Buffer
+ key: fs.readFileSync("./key.pem"),
+ // string
+ key: fs.readFileSync("./key.pem", "utf8"),
+ // array of above
+ key: [Bun.file("./key1.pem"), Bun.file("./key2.pem")],
+ },
});
```
@@ -135,17 +135,35 @@ Bun.serve({
{% /callout %}
+If your private key is encrypted with a passphrase, provide a value for `passphrase` to decrypt it.
+
+```ts-diff
+ Bun.serve({
+ fetch(req) {
+ return new Response("Hello!!!");
+ },
+
+ tls: {
+ key: Bun.file("./key.pem"),
+ cert: Bun.file("./cert.pem"),
++ passphrase: "my-secret-passphrase",
+ }
+ });
+```
+
Optionally, you can override the trusted CA certificates by passing a value for `ca`. By default, the server will trust the list of well-known CAs curated by Mozilla. When `ca` is specified, the Mozilla list is overwritten.
-```ts
-Bun.serve({
- fetch(req) {
- return new Response("Hello!!!");
- },
- key: Bun.file("./key.pem"), // path to TLS key
- cert: Bun.file("./cert.pem"), // path to TLS cert
- ca: Bun.file("./ca.pem"), // path to root CA certificate
-});
+```ts-diff
+ Bun.serve({
+ fetch(req) {
+ return new Response("Hello!!!");
+ },
+ tls: {
+ key: Bun.file("./key.pem"), // path to TLS key
+ cert: Bun.file("./cert.pem"), // path to TLS cert
++ ca: Bun.file("./ca.pem"), // path to root CA certificate
+ }
+ });
```
To override Diffie-Helman parameters:
@@ -153,7 +171,10 @@ To override Diffie-Helman parameters:
```ts
Bun.serve({
// ...
- dhParamsFile: "./dhparams.pem", // path to Diffie Helman parameters
+ tls: {
+ // other config
+ dhParamsFile: "/path/to/dhparams.pem", // path to Diffie Helman parameters
+ },
});
```
@@ -274,11 +295,21 @@ interface Bun {
port?: number;
development?: boolean;
error?: (error: Error) => Response | Promise<Response>;
- keyFile?: string;
- certFile?: string;
- caFile?: string;
- dhParamsFile?: string;
- passphrase?: string;
+ tls?: {
+ key?:
+ | string
+ | TypedArray
+ | BunFile
+ | Array<string | TypedArray | BunFile>;
+ cert?:
+ | string
+ | TypedArray
+ | BunFile
+ | Array<string | TypedArray | BunFile>;
+ ca?: string | TypedArray | BunFile | Array<string | TypedArray | BunFile>;
+ passphrase?: string;
+ dhParamsFile?: string;
+ };
maxRequestBodySize?: number;
lowMemoryMode?: boolean;
}): Server;
diff --git a/docs/api/streams.md b/docs/api/streams.md
index 7f3e3bcb4..210090927 100644
--- a/docs/api/streams.md
+++ b/docs/api/streams.md
@@ -28,8 +28,6 @@ for await (const chunk of stream) {
}
```
-For a more complete discusson of streams in Bun, see [API > Streams](/docs/api/streams).
-
## Direct `ReadableStream`
Bun implements an optimized version of `ReadableStream` that avoid unnecessary data copying & queue management logic. With a traditional `ReadableStream`, chunks of data are _enqueued_. Each chunk is copied into a queue, where it sits until the stream is ready to send more data.
@@ -154,7 +152,9 @@ export class ArrayBufferSink {
stream?: boolean;
}): void;
- write(chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer): number;
+ write(
+ chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
+ ): number;
/**
* Flush the internal buffer
*
diff --git a/docs/cli/bun-install.md b/docs/cli/bun-install.md
index 11cf3ee81..8050070be 100644
--- a/docs/cli/bun-install.md
+++ b/docs/cli/bun-install.md
@@ -47,6 +47,9 @@ registry = "https://registry.yarnpkg.com/"
# Install for production? This is the equivalent to the "--production" CLI argument
production = false
+# Disallow changes to lockfile? This is the equivalent to the "--fozen-lockfile" CLI argument
+frozenLockfile = false
+
# Don't actually install
dryRun = true
@@ -108,6 +111,7 @@ export interface Install {
scopes: Scopes;
registry: Registry;
production: boolean;
+ frozenLockfile: boolean;
dryRun: boolean;
optional: boolean;
dev: boolean;
diff --git a/docs/cli/install.md b/docs/cli/install.md
index 695c975f9..584350a42 100644
--- a/docs/cli/install.md
+++ b/docs/cli/install.md
@@ -49,6 +49,12 @@ To install in production mode (i.e. without `devDependencies`):
$ bun install --production
```
+To install with reproducible dependencies, use `--frozen-lockfile`. If your `package.json` disagrees with `bun.lockb`, Bun will exit with an error. This is useful for production builds and CI environments.
+
+```bash
+$ bun install --frozen-lockfile
+```
+
To perform a dry run (i.e. don't actually install anything):
```bash
@@ -80,6 +86,9 @@ peer = false
# equivalent to `--production` flag
production = false
+# equivalent to `--frozen-lockfile` flag
+frozenLockfile = false
+
# equivalent to `--dry-run` flag
dryRun = false
```
@@ -115,6 +124,26 @@ To add a package as an optional dependency (`"optionalDependencies"`):
$ bun add --optional lodash
```
+To add a package and pin to the resolved version, use `--exact`. This will resolve the version of the package and add it to your `package.json` with an exact version number instead of a version range.
+
+```bash
+$ bun add react --exact
+```
+
+This will add the following to your `package.json`:
+
+```jsonc
+{
+ "dependencies": {
+ // without --exact
+ "react": "^18.2.0", // this matches >= 18.2.0 < 19.0.0
+
+ // with --exact
+ "react": "18.2.0" // this matches only 18.2.0 exactly
+ }
+}
+```
+
To install a package globally:
```bash
@@ -197,6 +226,46 @@ In addition, the `--save` flag can be used to add `cool-pkg` to the `dependencie
}
```
+## Trusted dependencies
+
+Unlike other npm clients, Bun does not execute arbitrary lifecycle scripts for installed dependencies, such as `postinstall`. These scripts represent a potential security risk, as they can execute arbitrary code on your machine.
+
+<!-- Bun maintains an allow-list of popular packages containing `postinstall` scripts that are known to be safe. To run lifecycle scripts for packages that aren't on this list, add the package to `trustedDependencies` in your package.json. -->
+
+To tell Bun to allow lifecycle scripts for a particular package, add the package to `trustedDependencies` in your package.json.
+
+<!-- ```json-diff
+ {
+ "name": "my-app",
+ "version": "1.0.0",
++ "trustedDependencies": {
++ "my-trusted-package": "*"
++ }
+ }
+``` -->
+
+```json-diff
+ {
+ "name": "my-app",
+ "version": "1.0.0",
++ "trustedDependencies": ["my-trusted-package"]
+ }
+```
+
+Bun reads this field and will run lifecycle scripts for `my-trusted-package`.
+
+<!-- If you specify a version range, Bun will only execute lifecycle scripts if the resolved package version matches the range. -->
+<!--
+```json
+{
+ "name": "my-app",
+ "version": "1.0.0",
+ "trustedDependencies": {
+ "my-trusted-package": "^1.0.0"
+ }
+}
+``` -->
+
## Git dependencies
To add a dependency from a git repository:
diff --git a/docs/cli/test.md b/docs/cli/test.md
index d19a45a12..7af8dcc20 100644
--- a/docs/cli/test.md
+++ b/docs/cli/test.md
@@ -65,6 +65,24 @@ $ bun test --preload ./setup.ts
See [Test > Lifecycle](/docs/test/lifecycle) for complete documentation.
+## Mocks
+
+Create mocks with the `mock` function. Mocks are automatically reset between tests.
+
+```
+import { test, expect, mock } from "bun:test";
+const random = mock(() => Math.random());
+
+test("random", async () => {
+ const val = random();
+ expect(val).toBeGreaterThan(0);
+ expect(random).toHaveBeenCalled();
+ expect(random).toHaveBeenCalledTimes(1);
+});
+```
+
+See [Test > Mocks](/docs/test/mocks) for complete documentation.
+
## Snapshot testing
Snapshots are supported by `bun test`. See [Test > Snapshots](/docs/test/snapshots) for complete documentation.
diff --git a/docs/ecosystem/stric.md b/docs/ecosystem/stric.md
index b6b93725c..5f2787d75 100644
--- a/docs/ecosystem/stric.md
+++ b/docs/ecosystem/stric.md
@@ -1,20 +1,20 @@
[Stric](https://github.com/bunsvr) is a minimalist, fast web framework for Bun.
```ts#index.ts
-import { App } from "@stricjs/core";
+import { Router } from '@stricjs/router';
// Export the fetch handler and serve with Bun
-export default new App()
- // Return "Hi!" on every request
- .use(() => new Response("Hi!"));
+export default new Router()
+ // Return 'Hi' on every request
+ .get('/', () => new Response('Hi'));
```
-Stric provides support for [ArrowJS](https://www.arrow-js.com), a library for building reactive interfaces in **native** JavaScript.
+Stric provides support for [ArrowJS](https://www.arrow-js.com), a library for building reactive interfaces.
{% codetabs %}
```ts#src/App.ts
-import { html } from "@stricjs/arrow/utils";
+import { html } from '@stricjs/arrow/utils';
// Code inside this function can use web APIs
export function render() {
@@ -23,10 +23,10 @@ export function render() {
};
// Set the path to handle
-export const path = "/";
+export const path = '/';
```
```ts#index.ts
-import { PageRouter } from "@stricjs/arrow";
+import { PageRouter } from '@stricjs/arrow';
// Create a page router, build and serve directly
new PageRouter().serve();
diff --git a/docs/install/index.md b/docs/install/index.md
index 48e001275..162a4abac 100644
--- a/docs/install/index.md
+++ b/docs/install/index.md
@@ -49,6 +49,12 @@ To install in production mode (i.e. without `devDependencies`):
$ bun install --production
```
+To install dependencies without allowing changes to lockfile (useful on CI):
+
+```bash
+$ bun install --frozen-lockfile
+```
+
To perform a dry run (i.e. don't actually install anything):
```bash
@@ -80,6 +86,9 @@ peer = false
# equivalent to `--production` flag
production = false
+# equivalent to `--frozen-lockfile` flag
+frozenLockfile = false
+
# equivalent to `--dry-run` flag
dryRun = false
```
diff --git a/docs/install/registries.md b/docs/install/registries.md
index e4090e3c9..86657ca26 100644
--- a/docs/install/registries.md
+++ b/docs/install/registries.md
@@ -24,3 +24,7 @@ To configure a private registry scoped to a particular organization:
# registry with token
"@myorg3" = { token = "$npm_token", url = "https://registry.myorg.com/" }
```
+
+### `.npmrc`
+
+Bun does not currently read `.npmrc` files. For private registries, migrate your registry configuration to `bunfig.toml` as documented above.
diff --git a/docs/installation.md b/docs/installation.md
index 06ca2b34d..9fce0b511 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -3,17 +3,17 @@ Bun ships as a single executable that can be installed a few different ways.
{% callout %}
**Windows users** — Bun does not currently provide a native Windows build. We're working on this; progress can be tracked at [this issue](https://github.com/oven-sh/bun/issues/43). In the meantime, use one of the installation methods below for Windows Subsystem for Linux.
-**Linux users** — Kernel version 5.6 or higher is strongly recommended, but the minimum is 5.1.
+**Linux users** — The `unzip` package is required to install Bun. Kernel version 5.6 or higher is strongly recommended, but the minimum is 5.1.
{% /callout %}
{% codetabs %}
-```bash#Native
-$ curl -fsSL https://bun.sh/install | bash # for macOS, Linux, and WSL
+```bash#NPM
+$ npm install -g bun # the last `npm` command you'll ever need
```
-```bash#npm
-$ npm install -g bun # the last `npm` command you'll ever need
+```bash#Native
+$ curl -fsSL https://bun.sh/install | bash # for macOS, Linux, and WSL
```
```bash#Homebrew
@@ -26,7 +26,7 @@ $ docker pull oven/bun
$ docker run --rm --init --ulimit memlock=-1:-1 oven/bun
```
-```bash#proto
+```bash#Proto
$ proto install bun
```
diff --git a/docs/nav.ts b/docs/nav.ts
index 12333e6da..5b35036d3 100644
--- a/docs/nav.ts
+++ b/docs/nav.ts
@@ -135,13 +135,13 @@ export default {
description:
"Install all dependencies with `bun install`, or manage dependencies with `bun add` and `bun remove`.",
}),
- page("install/workspaces", "Workspaces", {
- description: "Bun's package manager supports workspaces and mono-repo development workflows.",
- }),
page("install/cache", "Global cache", {
description:
"Bun's package manager installs all packages into a shared global cache to avoid redundant re-downloads.",
}),
+ page("install/workspaces", "Workspaces", {
+ description: "Bun's package manager supports workspaces and mono-repo development workflows.",
+ }),
page("install/lockfile", "Lockfile", {
description:
"Bun's binary lockfile `bun.lockb` tracks your resolved dependency ytrr, making future installs fast and repeatable.",
@@ -180,6 +180,9 @@ export default {
page("cli/test", "`bun test`", {
description: "Bun's test runner uses Jest-compatible syntax but runs 100x faster.",
}),
+ page("test/hot", "Watch mode", {
+ description: "Reload your tests automatically on change.",
+ }),
page("test/writing", "Writing tests", {
description:
"Write your tests using Jest-like expect matchers, plus setup/teardown hooks, snapshot testing, and more",
@@ -187,15 +190,18 @@ export default {
page("test/lifecycle", "Lifecycle hooks", {
description: "Add lifecycle hooks to your tests that run before/after each test or test run",
}),
+ page("test/mocks", "Mocks", {
+ description: "Mocks functions and track method calls",
+ }),
page("test/snapshots", "Snapshots", {
description: "Add lifecycle hooks to your tests that run before/after each test or test run",
}),
+ page("test/time", "Dates and times", {
+ description: "Control the date & time in your tests for more reliable and deterministic tests",
+ }),
page("test/dom", "DOM testing", {
description: "Write headless tests for UI and React/Vue/Svelte/Lit components with happy-dom",
}),
- page("test/hot", "Watch mode", {
- description: "Reload your tests automatically on change.",
- }),
divider("Package runner"),
page("cli/bunx", "`bunx`", {
diff --git a/docs/project/development.md b/docs/project/development.md
index 92a414c5f..93327824f 100644
--- a/docs/project/development.md
+++ b/docs/project/development.md
@@ -41,9 +41,7 @@ $ brew install llvm@15
```
```bash#Ubuntu/Debian
-# On Ubuntu 22.04 and newer, LLVM 15 is available in the default repositories
-$ sudo apt install llvm-15 lld-15 clang-15
-# On older versions,
+$ # 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 -- 15 all
```
@@ -85,7 +83,7 @@ $ brew install automake ccache cmake coreutils esbuild gnu-sed go libiconv libto
```
```bash#Ubuntu/Debian
-$ sudo apt install cargo ccache cmake esbuild git golang libtool ninja-build pkg-config rustc
+$ sudo apt install cargo ccache cmake git golang libtool ninja-build pkg-config rustc esbuild
```
```bash#Arch
@@ -94,7 +92,19 @@ $ pacman -S base-devel ccache cmake esbuild git go libiconv libtool make ninja p
{% /codetabs %}
-In addition to this, you will need either `bun` or `npm` installed to install the package.json dependencies.
+{% details summary="Ubuntu — Unable to locate package esbuild" %}
+
+The `apt install esbuild` command may fail with an `Unable to locate package` error if you are using a Ubuntu mirror that does not contain an exact copy of the original Ubuntu server. Note that the same error may occur if you are not using any mirror but have the Ubuntu Universe enabled in the `sources.list`. In this case, you can install esbuild manually:
+
+```bash
+$ curl -fsSL https://esbuild.github.io/dl/latest | sh
+$ chmod +x ./esbuild
+$ sudo mv ./esbuild /usr/local/bin
+```
+
+{% /details %}
+
+In addition to this, you will need an npm package manager (`bun`, `npm`, etc) to install the `package.json` dependencies.
## Install Zig
@@ -102,12 +112,12 @@ Zig can be installed either with our npm package [`@oven/zig`](https://www.npmjs
```bash
$ bun install -g @oven/zig
-$ zigup 0.11.0-dev.2777+b95cdf0ae
+$ zigup 0.11.0-dev.3737+9eb008717
```
## Building
-After cloning the repository, prepare bun to be built:
+After cloning the repository, run the following command. The runs
```bash
$ make setup
@@ -217,6 +227,37 @@ You'll need a very recent version of Valgrind due to DWARF 5 debug symbols. You
$ valgrind --fair-sched=try --track-origins=yes bun-debug <args>
```
+## Updating `WebKit`
+
+The Bun team will occasionally bump the version of WebKit used in Bun. When this happens, you may see something like this with you run `git status`.
+
+```bash
+$ git status
+On branch my-branch
+Changes not staged for commit:
+ (use "git add <file>..." to update what will be committed)
+ (use "git restore <file>..." to discard changes in working directory)
+ modified: src/bun.js/WebKit (new commits)
+```
+
+For performance reasons, `bun submodule update` does not automatically update the WebKit submodule. To update, run the following commands from the root of the Bun repo:
+
+```bash
+$ bun install
+$ make bindings
+```
+
+<!-- Check the [Bun repo](https://github.com/oven-sh/bun/tree/main/src/bun.js) to get the hash of the commit of WebKit is currently being used.
+
+{% image width="270" src="https://github.com/oven-sh/bun/assets/3084745/51730b73-89ef-4358-9a41-9563a60a54be" /%} -->
+
+<!--
+```bash
+$ cd src/bun.js/WebKit
+$ git fetch
+$ git checkout <hash>
+``` -->
+
## Troubleshooting
### libarchive
diff --git a/docs/project/licensing.md b/docs/project/licensing.md
index ea49acb1d..ac7fef774 100644
--- a/docs/project/licensing.md
+++ b/docs/project/licensing.md
@@ -85,6 +85,11 @@ Bun statically links these libraries:
---
+- [`libbase64`](https://github.com/aklomp/base64/blob/master/LICENSE)
+- BSD 2-Clause
+
+---
+
- A fork of [`uWebsockets`](https://github.com/jarred-sumner/uwebsockets)
- Apache 2.0 licensed
diff --git a/docs/runtime/configuration.md b/docs/runtime/configuration.md
index e1572c990..2ae81713a 100644
--- a/docs/runtime/configuration.md
+++ b/docs/runtime/configuration.md
@@ -129,6 +129,9 @@ peer = false
# equivalent to `--production` flag
production = false
+# equivalent to `--frozen-lockfile` flag
+frozenLockfile = false
+
# equivalent to `--dry-run` flag
dryRun = false
```
diff --git a/docs/runtime/nodejs-apis.md b/docs/runtime/nodejs-apis.md
index ac42559a0..3dfe76b97 100644
--- a/docs/runtime/nodejs-apis.md
+++ b/docs/runtime/nodejs-apis.md
@@ -1,6 +1,6 @@
Bun aims for complete Node.js API compatibility. Most `npm` packages intended for `Node.js` environments will work with Bun out of the box; the best way to know for certain is to try it.
-This page is updated regularly to reflect compatibility status of the latest version of Bun.
+This page is updated regularly to reflect compatibility status of the latest version of Bun. If you run into any bugs with a particular package, please [open an issue](https://bun.sh/issues). Opening issues for compatibility bugs helps us prioritize what to work on next.
## Built-in modules
@@ -51,7 +51,7 @@ This page is updated regularly to reflect compatibility status of the latest ver
- {% anchor id="node_crypto" %} [`node:crypto`](https://nodejs.org/api/crypto.html) {% /anchor %}
- 🟡
-- Missing `crypto.Certificate` `crypto.ECDH` `crypto.KeyObject` `crypto.X509Certificate` `crypto.checkPrime{Sync}` `crypto.createPrivateKey` `crypto.createPublicKey` `crypto.createSecretKey` `crypto.diffieHellman` `crypto.generateKey{Sync}` `crypto.generateKeyPair{Sync}` `crypto.generatePrime{Sync}` `crypto.getCipherInfo` `crypto.getCurves` `crypto.{get|set}Fips` `crypto.hkdf` `crypto.hkdfSync` `crypto.randomInt` `crypto.secureHeapUsed` `crypto.setEngine` `crypto.sign` `crypto.verify`
+- Missing `crypto.Certificate` `crypto.ECDH` `crypto.KeyObject` `crypto.X509Certificate` `crypto.checkPrime{Sync}` `crypto.createPrivateKey` `crypto.createPublicKey` `crypto.createSecretKey` `crypto.diffieHellman` `crypto.generateKey{Sync}` `crypto.generateKeyPair{Sync}` `crypto.generatePrime{Sync}` `crypto.getCipherInfo` `crypto.{get|set}Fips` `crypto.hkdf` `crypto.hkdfSync` `crypto.secureHeapUsed` `crypto.setEngine` `crypto.sign` `crypto.verify`
---
@@ -87,7 +87,7 @@ This page is updated regularly to reflect compatibility status of the latest ver
- {% anchor id="node_fs" %} [`node:fs`](https://nodejs.org/api/fs.html) {% /anchor %}
- 🟡
-- Missing `fs.fdatasync{Sync}` `fs.opendir{Sync}` `fs.readv{Sync}` `fs.{watch|watchFile|unwatchFile}` `fs.writev{Sync}`.
+- Missing `fs.fdatasync{Sync}` `fs.opendir{Sync}` `fs.{watchFile|unwatchFile}` `fs.{cp|cpSync}`.
---
@@ -123,7 +123,7 @@ This page is updated regularly to reflect compatibility status of the latest ver
- {% anchor id="node_net" %} [`node:net`](https://nodejs.org/api/net.html) {% /anchor %}
- 🟡
-- Missing `net.createServer` `net.{get|set}DefaultAutoSelectFamily` `net.SocketAddress` `net.BlockList`.
+- Missing `net.{get|set}DefaultAutoSelectFamily` `net.SocketAddress` `net.BlockList`.
---
@@ -201,7 +201,7 @@ This page is updated regularly to reflect compatibility status of the latest ver
- {% anchor id="node_tls" %} [`node:tls`](https://nodejs.org/api/tls.html) {% /anchor %}
- 🟡
-- Missing `tls.Server` `tls.createServer` `tls.createSecurePair` `tls.checkServerIdentity` `tls.rootCertificates`
+- Missing `tls.createSecurePair` `tls.checkServerIdentity` `tls.rootCertificates`
---
@@ -219,13 +219,13 @@ This page is updated regularly to reflect compatibility status of the latest ver
- {% anchor id="node_url" %} [`node:url`](https://nodejs.org/api/url.html) {% /anchor %}
- 🟡
-- Missing `url.domainTo{ASCII|Unicode}` `url.urlToHttpOptions`. Recommended to use `URL` and `URLSearchParams` globals instead.
+- Missing `url.domainTo{ASCII|Unicode}`. Recommended to use `URL` and `URLSearchParams` globals instead.
---
- {% anchor id="node_util" %} [`node:util`](https://nodejs.org/api/util.html) {% /anchor %}
- 🟡
-- Missing `util.MIMEParams` `util.MIMEType` `util.formatWithOptions()` `util.getSystemErrorMap()` `util.getSystemErrorName()` `util.parseArgs()` `util.stripVTControlCharacters()` `util.toUSVString()` `util.transferableAbortController()` `util.transferableAbortSignal()`.
+- Missing `util.MIMEParams` `util.MIMEType` `util.formatWithOptions()` `util.getSystemErrorMap()` `util.getSystemErrorName()` `util.parseArgs()` `util.stripVTControlCharacters()` `util.transferableAbortController()` `util.transferableAbortSignal()`.
---
@@ -558,7 +558,7 @@ The table below lists all globals implemented by Node.js and Bun's current compa
- {% anchor id="node_require" %} [`require()`](https://nodejs.org/api/globals.html#require) {% /anchor %}
- 🟢
-- Fully implemented.
+- Fully implemented, as well as [`require.main`](https://nodejs.org/api/modules.html#requiremain), [`require.cache`](https://nodejs.org/api/modules.html#requirecache), and [`require.resolve`](https://nodejs.org/api/modules.html#requireresolverequest-options)
---
diff --git a/docs/runtime/typescript.md b/docs/runtime/typescript.md
index d466bb016..b79b1ec6d 100644
--- a/docs/runtime/typescript.md
+++ b/docs/runtime/typescript.md
@@ -93,6 +93,17 @@ These are the recommended `compilerOptions` for a Bun project.
}
```
+### Add DOM types
+
+Settings `"types": ["bun-types"]` means TypeScript will ignore other global type definitions, including `lib: ["dom"]`. To add DOM types into your project, add the following [triple-slash directives](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html) at the top of any TypeScript file in your project.
+
+```ts
+/// <reference lib="dom" />
+/// <reference lib="dom.iterable" />
+```
+
+The same applies to other global type definition _libs_ like `webworker`.
+
## Path mapping
When resolving modules, Bun's runtime respects path mappings defined in [`compilerOptions.paths`](https://www.typescriptlang.org/tsconfig#paths) in your `tsconfig.json`. No other runtime does this.
diff --git a/docs/test/lifecycle.md b/docs/test/lifecycle.md
index ccb7ce85d..fd804c9bb 100644
--- a/docs/test/lifecycle.md
+++ b/docs/test/lifecycle.md
@@ -10,7 +10,7 @@ The test runner supports the following lifecycle hooks. This is useful for loadi
Perform per-test setup and teardown logic with `beforeEach` and `afterEach`.
```ts
-import { expect, test } from "bun:test";
+import { beforeEach, afterEach } from "bun:test";
beforeEach(() => {
console.log("running test.");
@@ -70,7 +70,7 @@ afterAll(() => {
Then use `--preload` to run the setup script before any test files.
```ts
-bun test --preload ./setup.ts
+$ bun test --preload ./setup.ts
```
To avoid typing `--preload` every time you run tests, it can be added to your `bunfig.toml`:
diff --git a/docs/test/mocks.md b/docs/test/mocks.md
new file mode 100644
index 000000000..31b5dab41
--- /dev/null
+++ b/docs/test/mocks.md
@@ -0,0 +1,55 @@
+Create mocks with the `mock` function.
+
+```ts
+import { test, expect, mock } from "bun:test";
+const random = mock(() => Math.random());
+
+test("random", async () => {
+ const val = random();
+ expect(val).toBeGreaterThan(0);
+ expect(random).toHaveBeenCalled();
+ expect(random).toHaveBeenCalledTimes(1);
+});
+```
+
+The result of `mock()` is a new function that's been decorated with some additional properties.
+
+```ts
+import { mock } from "bun:test";
+const random = mock((multiplier: number) => multiplier * Math.random());
+
+random(2);
+random(10);
+
+random.mock.calls;
+// [[ 2 ], [ 10 ]]
+
+random.mock.results;
+// [
+// { type: "return", value: 0.6533907460954099 },
+// { type: "return", value: 0.6452713933037312 }
+// ]
+```
+
+## `.spyOn()`
+
+It's possible to track calls to a function without replacing it with a mock. Use `spyOn()` to create a spy; these spies can be passed to `.toHaveBeenCalled()` and `.toHaveBeenCalledTimes()`.
+
+```ts
+import { test, expect, spyOn } from "bun:test";
+
+const ringo = {
+ name: "Ringo",
+ sayHi() {
+ console.log(`Hello I'm ${this.name}`);
+ },
+};
+
+const spy = spyOn(ringo, "sayHi");
+
+test("spyon", () => {
+ expect(spy).toHaveBeenCalledTimes(0);
+ ringo.sayHi();
+ expect(spy).toHaveBeenCalledTimes(1);
+});
+```
diff --git a/docs/test/time.md b/docs/test/time.md
new file mode 100644
index 000000000..4a0f98407
--- /dev/null
+++ b/docs/test/time.md
@@ -0,0 +1,106 @@
+`bun:test` lets you change what time it is in your tests. This was introduced in Bun v0.6.13.
+
+This works with any of the following:
+
+- `Date.now`
+- `new Date()`
+- `new Intl.DateTimeFormat().format()`
+
+Timers are not impacted yet, but may be in a future release of Bun.
+
+## `setSystemTime`
+
+To change the system time, use `setSystemTime`:
+
+```ts
+import { setSystemTime, beforeAll, test, expect } from "bun:test";
+
+beforeAll(() => {
+ setSystemTime(new Date("2020-01-01T00:00:00.000Z"));
+});
+
+test("it is 2020", () => {
+ expect(new Date().getFullYear()).toBe(2020);
+});
+```
+
+To support existing tests that use Jest's `useFakeTimers` and `useRealTimers`, you can use `useFakeTimers` and `useRealTimers`:
+
+```ts
+test("just like in jest", () => {
+ jest.useFakeTimers();
+ jest.setSystemTime(new Date("2020-01-01T00:00:00.000Z"));
+ expect(new Date().getFullYear()).toBe(2020);
+ jest.useRealTimers();
+ expect(new Date().getFullYear()).toBeGreaterThan(2020);
+});
+
+test("unlike in jest", () => {
+ const OriginalDate = Date;
+ jest.useFakeTimers();
+ if (typeof Bun === "undefined") {
+ // In Jest, the Date constructor changes
+ // That can cause all sorts of bugs because suddenly Date !== Date before the test.
+ expect(Date).not.toBe(OriginalDate);
+ expect(Date.now).not.toBe(OriginalDate.now);
+ } else {
+ // In bun:test, Date constructor does not change when you useFakeTimers
+ expect(Date).toBe(OriginalDate);
+ expect(Date.now).toBe(OriginalDate.now);
+ }
+});
+```
+
+{% callout %}
+**Timers** — Note that we have not implemented builtin support for mocking timers yet, but this is on the roadmap.
+{% /callout %}
+
+### Reset the system time
+
+To reset the system time, pass no arguments to `setSystemTime`:
+
+```ts
+import { setSystemTime, beforeAll } from "bun:test";
+
+test("it was 2020, for a moment.", () => {
+ // Set it to something!
+ setSystemTime(new Date("2020-01-01T00:00:00.000Z"));
+ expect(new Date().getFullYear()).toBe(2020);
+
+ // reset it!
+ setSystemTime();
+
+ expect(new Date().getFullYear()).toBeGreaterThan(2020);
+});
+```
+
+## Set the time zone
+
+To change the time zone, either pass the `$TZ` environment variable to `bun test`.
+
+```sh
+TZ=America/Los_Angeles bun test
+```
+
+Or set `process.env.TZ` at runtime:
+
+```ts
+import { test, expect } from "bun:test";
+
+test("Welcome to California!", () => {
+ process.env.TZ = "America/Los_Angeles";
+ expect(new Date().getTimezoneOffset()).toBe(420);
+ expect(new Intl.DateTimeFormat().resolvedOptions().timeZone).toBe(
+ "America/Los_Angeles",
+ );
+});
+
+test("Welcome to New York!", () => {
+ // Unlike in Jest, you can set the timezone multiple times at runtime and it will work.
+ process.env.TZ = "America/New_York";
+ expect(new Date().getTimezoneOffset()).toBe(240);
+ expect(new Intl.DateTimeFormat().resolvedOptions().timeZone).toBe(
+ "America/New_York",
+ );
+});
+```
diff --git a/docs/test/writing.md b/docs/test/writing.md
index 391ee91c2..6a29bf81f 100644
--- a/docs/test/writing.md
+++ b/docs/test/writing.md
@@ -63,6 +63,21 @@ test("2 * 2", done => {
});
```
+## Timeouts
+
+Optionally specify a per-test timeout in milliseconds by passing a number as the third argument to `test`.
+
+```ts
+import { test } from "bun:test";
+
+test.skip("wat", async () => {
+ const data = await slowOperation();
+ expect(data).toBe(42);
+}, 500); // test must run in <500ms
+```
+
+## `test.skip`
+
Skip individual tests with `test.skip`. These tests will not be run.
```ts
@@ -74,6 +89,8 @@ test.skip("wat", () => {
});
```
+## `test.todo`
+
Mark a test as a todo with `test.todo`. These tests _will_ be run, and the test runner will expect them to fail. If they pass, you will be prompted to mark it as a regular test.
```ts
@@ -84,6 +101,71 @@ test.todo("fix this", () => {
});
```
+To exlusively run tests marked as _todo_, use `bun test --todo`.
+
+```sh
+$ bun test --todo
+```
+
+## `test.only`
+
+To run a particular test or suite of tests use `test.only()` or `describe.only()`. Once declared, running `bun test --skip` will only execute tests/suites that have been marked with `.only()`.
+
+```ts
+import { test, describe } from "bun:test";
+
+test("test #1", () => {
+ // does not run
+});
+
+test.only("test #2", () => {
+ // runs
+});
+
+describe.only("only", () => {
+ test("test #3", () => {
+ // runs
+ });
+});
+```
+
+The following command will only execute tests #2 and #3.
+
+```sh
+$ bun test --only
+```
+
+## `test.if`
+
+To run a test conditionally, use `test.if()`. The test will run if the condition is truthy. This is particularly useful for tests that should only run on specific architectures or operating systems.
+
+```ts
+test.if(Math.random() > 0.5)("runs half the time", () => {
+ // ...
+});
+```
+
+```ts
+test.if(Math.random() > 0.5)("runs half the time", () => {
+ // ...
+});
+
+const macOS = process.arch === "darwin";
+test.if(macOS)("runs on macOS", () => {
+ // runs if macOS
+});
+```
+
+To instead skip a test based on some condition, use `test.skipIf()` or `describe.skipIf()`.
+
+```ts
+const macOS = process.arch === "darwin";
+
+test.skipIf(macOS)("runs on non-macOS", () => {
+ // runs if *not* macOS
+});
+```
+
## Matchers
Bun implements the following matchers. Full Jest compatibility is on the roadmap; track progress [here](https://github.com/oven-sh/bun/issues/1825).
@@ -217,13 +299,13 @@ Bun implements the following matchers. Full Jest compatibility is on the roadmap
---
-- 🔴
-- [`.resolves()`](https://jestjs.io/docs/expect#resolves)
+- 🟢
+- [`.resolves()`](https://jestjs.io/docs/expect#resolves) (since Bun v0.6.12+)
---
-- 🔴
-- [`.rejects()`](https://jestjs.io/docs/expect#rejects)
+- 🟢
+- [`.rejects()`](https://jestjs.io/docs/expect#rejects) (since Bun v0.6.12+)
---
@@ -277,7 +359,7 @@ Bun implements the following matchers. Full Jest compatibility is on the roadmap
---
-- 🔴
+- 🟢
- [`.toBeCloseTo()`](https://jestjs.io/docs/expect#tobeclosetonumber-numdigits)
---