aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/api/binary-data.md10
-rw-r--r--docs/api/file-io.md2
-rw-r--r--docs/api/file-system-router.md1
-rw-r--r--docs/api/http.md6
-rw-r--r--docs/api/import-meta.md2
-rw-r--r--docs/api/spawn.md54
-rw-r--r--docs/api/sqlite.md14
-rw-r--r--docs/api/transpiler.md2
-rw-r--r--docs/api/utils.md4
-rw-r--r--docs/api/websockets.md17
-rw-r--r--docs/api/workers.md21
-rw-r--r--docs/bundler/index.md20
-rw-r--r--docs/bundler/intro.md2
-rw-r--r--docs/bundler/loaders.md2
-rw-r--r--docs/bundler/macros.md2
-rw-r--r--docs/bundler/vs-esbuild.md6
-rw-r--r--docs/cli/add.md155
-rw-r--r--docs/cli/bun-create.md (renamed from docs/templates.md)36
-rw-r--r--docs/cli/bun-install.md13
-rw-r--r--docs/cli/bundler.md2
-rw-r--r--docs/cli/create.md256
-rw-r--r--docs/cli/init.md (renamed from docs/cli/bun-init.md)28
-rw-r--r--docs/cli/install.md273
-rw-r--r--docs/cli/link.md46
-rw-r--r--docs/cli/pm.md (renamed from docs/install/utilities.md)0
-rw-r--r--docs/cli/remove.md5
-rw-r--r--docs/cli/run.md69
-rw-r--r--docs/cli/test.md41
-rw-r--r--docs/cli/update.md7
-rw-r--r--docs/dev/css.md2
-rw-r--r--docs/dev/frameworks.md151
-rw-r--r--docs/dev/nextjs.md33
-rw-r--r--docs/guides/binary/blob-to-stream.md2
-rw-r--r--docs/guides/binary/blob-to-string.md2
-rw-r--r--docs/guides/ecosystem/astro.md18
-rw-r--r--docs/guides/ecosystem/discordjs.md2
-rw-r--r--docs/guides/ecosystem/docker.md140
-rw-r--r--docs/guides/ecosystem/elysia.md2
-rw-r--r--docs/guides/ecosystem/hono.md2
-rw-r--r--docs/guides/ecosystem/nextjs.md17
-rw-r--r--docs/guides/ecosystem/nuxt.md2
-rw-r--r--docs/guides/ecosystem/pm2.md54
-rw-r--r--docs/guides/ecosystem/prisma.md47
-rw-r--r--docs/guides/ecosystem/qwik.md107
-rw-r--r--docs/guides/ecosystem/react.md47
-rw-r--r--docs/guides/ecosystem/remix.md24
-rw-r--r--docs/guides/ecosystem/solidstart.md2
-rw-r--r--docs/guides/ecosystem/sveltekit.md4
-rw-r--r--docs/guides/ecosystem/systemd.md113
-rw-r--r--docs/guides/ecosystem/vite.md5
-rw-r--r--docs/guides/http/file-uploads.md2
-rw-r--r--docs/guides/install/azure-artifacts.md73
-rw-r--r--docs/guides/install/custom-registry.md2
-rw-r--r--docs/guides/install/jfrog-artifactory.md28
-rw-r--r--docs/guides/install/registry-scope.md8
-rw-r--r--docs/guides/install/trusted.md50
-rw-r--r--docs/guides/install/workspaces.md8
-rw-r--r--docs/guides/process/ipc.md66
-rw-r--r--docs/guides/read-file/exists.md2
-rw-r--r--docs/guides/read-file/stream.md2
-rw-r--r--docs/guides/runtime/read-env.md2
-rw-r--r--docs/guides/runtime/set-env.md2
-rw-r--r--docs/guides/runtime/tsconfig-paths.md4
-rw-r--r--docs/guides/runtime/typescript.md69
-rw-r--r--docs/guides/runtime/vscode-debugger.md6
-rw-r--r--docs/guides/test/happy-dom.md2
-rw-r--r--docs/guides/test/migrate-from-jest.md112
-rw-r--r--docs/guides/test/mock-functions.md2
-rw-r--r--docs/guides/test/spy-on.md2
-rw-r--r--docs/guides/util/entrypoint.md4
-rw-r--r--docs/guides/websocket/context.md2
-rw-r--r--docs/guides/websocket/simple.md2
-rw-r--r--docs/index.md9
-rw-r--r--docs/install/index.md4
-rw-r--r--docs/install/lifecycle.md44
-rw-r--r--docs/install/lockfile.md30
-rw-r--r--docs/install/overrides.md73
-rw-r--r--docs/install/workspaces.md51
-rw-r--r--docs/installation.md134
-rw-r--r--docs/nav.ts51
-rw-r--r--docs/project/contributing.md (renamed from docs/project/development.md)100
-rw-r--r--docs/quickstart.md18
-rw-r--r--docs/runtime/bunfig.md429
-rw-r--r--docs/runtime/configuration.md210
-rw-r--r--docs/runtime/env.md147
-rw-r--r--docs/runtime/hot.md21
-rw-r--r--docs/runtime/jsx.md4
-rw-r--r--docs/runtime/modules.md189
-rw-r--r--docs/runtime/nodejs-apis.md725
-rw-r--r--docs/runtime/plugins.md104
-rw-r--r--docs/runtime/typescript.md109
-rw-r--r--docs/test/lifecycle.md8
-rw-r--r--docs/test/mocks.md40
-rw-r--r--docs/test/writing.md106
-rw-r--r--docs/typescript.md73
95 files changed, 2916 insertions, 2085 deletions
diff --git a/docs/api/binary-data.md b/docs/api/binary-data.md
index a75d08309..91b314b98 100644
--- a/docs/api/binary-data.md
+++ b/docs/api/binary-data.md
@@ -26,10 +26,10 @@ Below is a quick "cheat sheet" that doubles as a table of contents. Click an ite
---
-<!-- - [`File`](#file)
-- _Browser only_. A subclass of `Blob` that represents a file. Has a `name` and `lastModified` timestamp. There is experimental support in Node.js v20; Bun does not support `File` yet; most of its functionality is provided by `BunFile`.
+- [`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)`.
@@ -412,7 +412,7 @@ For complete documentation, refer to the [Node.js documentation](https://nodejs.
`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 recieve instances of `Blob` from an external source (like an `<input type="file">` element in the browser) or library. That said, it is possible to create a `Blob` from one or more string or binary "blob parts".
+It isn't common to directly create `Blob` instances. More often, you'll receive instances of `Blob` from an external source (like an `<input type="file">` 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
const blob = new Blob(["<html>Hello</html>"], {
@@ -507,7 +507,7 @@ for await (const chunk of stream) {
}
```
-For a more complete discusson of streams in Bun, see [API > Streams](/docs/api/streams).
+For a more complete discussion of streams in Bun, see [API > Streams](/docs/api/streams).
## Conversion
diff --git a/docs/api/file-io.md b/docs/api/file-io.md
index e6902cc6a..f37473c33 100644
--- a/docs/api/file-io.md
+++ b/docs/api/file-io.md
@@ -2,7 +2,7 @@
<!-- **Note** — The `Bun.file` and `Bun.write` APIs documented on this page are heavily optimized and represent the recommended way to perform file-system tasks using Bun. Existing Node.js projects may use Bun's [nearly complete](/docs/runtime/nodejs-apis#node-fs) implementation of the [`node:fs`](https://nodejs.org/api/fs.html) module. -->
-**Note** — The `Bun.file` and `Bun.write` APIs documented on this page are heavily optimized and represent the recommended way to perform file-system tasks using Bun. For operations that are not yet available with `Bun.file`, such as `mkdir`, you can use Bun's [nearly complete](/docs/runtime/nodejs-apis#node-fs) implementation of the [`node:fs`](https://nodejs.org/api/fs.html) module.
+**Note** — The `Bun.file` and `Bun.write` APIs documented on this page are heavily optimized and represent the recommended way to perform file-system tasks using Bun. For operations that are not yet available with `Bun.file`, such as `mkdir` or `readdir`, you can use Bun's [nearly complete](/docs/runtime/nodejs-apis#node-fs) implementation of the [`node:fs`](https://nodejs.org/api/fs.html) module.
{% /callout %}
diff --git a/docs/api/file-system-router.md b/docs/api/file-system-router.md
index 964652401..8e1fbe0fc 100644
--- a/docs/api/file-system-router.md
+++ b/docs/api/file-system-router.md
@@ -93,6 +93,7 @@ interface Bun {
style: "nextjs";
origin?: string;
assetPrefix?: string;
+ fileExtensions?: string[];
});
reload(): void;
diff --git a/docs/api/http.md b/docs/api/http.md
index 629570335..3f476feb2 100644
--- a/docs/api/http.md
+++ b/docs/api/http.md
@@ -71,7 +71,7 @@ In development mode, Bun will surface errors in-browser with a built-in error pa
{% image src="/images/exception_page.png" caption="Bun's built-in 500 page" /%}
-To handle server-side errors, implement an `error` handler. This function should return a `Response` to served to the client when an error occurs. This response will supercede Bun's default error page in `development` mode.
+To handle server-side errors, implement an `error` handler. This function should return a `Response` to serve to the client when an error occurs. This response will supersede Bun's default error page in `development` mode.
```ts
Bun.serve({
@@ -212,9 +212,7 @@ $ bun --hot server.ts
To stream a file, return a `Response` object with a `BunFile` object as the body.
```ts
-import { serve, file } from "bun";
-
-serve({
+Bun.serve({
fetch(req) {
return new Response(Bun.file("./hello.txt"));
},
diff --git a/docs/api/import-meta.md b/docs/api/import-meta.md
index 3c22308ce..37f35884d 100644
--- a/docs/api/import-meta.md
+++ b/docs/api/import-meta.md
@@ -39,7 +39,7 @@ import.meta.resolveSync("zod")
---
- `import.meta.resolve{Sync}`
-- Resolve a module specifier (e.g. `"zod"` or `"./file.tsx`) to an absolute path. While file would be imported if the specifier were imported from this file?
+- Resolve a module specifier (e.g. `"zod"` or `"./file.tsx"`) to an absolute path. While file would be imported if the specifier were imported from this file?
```ts
import.meta.resolveSync("zod");
diff --git a/docs/api/spawn.md b/docs/api/spawn.md
index a85f9d08c..644f8cee3 100644
--- a/docs/api/spawn.md
+++ b/docs/api/spawn.md
@@ -183,6 +183,60 @@ const proc = Bun.spawn(["echo", "hello"]);
proc.unref();
```
+## 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.
+{%callout%}
+**Note** — This API is only compatible with other `bun` processes. Use `process.execPath` to get a path to the currently running `bun` executable.
+{%/callout%}
+
+```ts#parent.ts
+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
+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
+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);
+});
+```
+
+All messages are serialized using the JSC `serialize` API, which allows for the same set of [transferrable types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Transferable_objects) supported by `postMessage` and `structuredClone`, including strings, typed arrays, streams, and objects.
+
+```ts#child.ts
+// send a string
+process.send("Hello from child as string");
+
+// send an object
+process.send({ message: "Hello from child as object" });
+```
+
## 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.
diff --git a/docs/api/sqlite.md b/docs/api/sqlite.md
index e04b8ded7..3749fb8b4 100644
--- a/docs/api/sqlite.md
+++ b/docs/api/sqlite.md
@@ -99,6 +99,20 @@ const query = db.prepare("SELECT * FROM foo WHERE bar = ?");
{% /callout %}
+## WAL mode
+
+SQLite supports [write-ahead log mode](https://www.sqlite.org/wal.html) (WAL) which dramatically improves performance, especially in situations with many concurrent writes. It's broadly recommended to enable WAL mode for most typical applications.
+
+To enable WAL mode, run this pragma query at the beginning of your application:
+
+```ts
+db.exec("PRAGMA journal_mode = WAL;");
+```
+
+{% details summary="What is WAL mode" %}
+In WAL mode, writes to the database are written directly to a separate file called the "WAL file" (write-ahead log). This file will be later integrated into the main database file. Think of it as a buffer for pending writes. Refer to the [SQLite docs](https://www.sqlite.org/wal.html) for a more detailed overview.
+{% /details %}
+
## Statements
A `Statement` is a _prepared query_, which means it's been parsed and compiled into an efficient binary form. It can be executed multiple times in a performant way.
diff --git a/docs/api/transpiler.md b/docs/api/transpiler.md
index 6d81a1ef9..ede4ee7cc 100644
--- a/docs/api/transpiler.md
+++ b/docs/api/transpiler.md
@@ -76,7 +76,7 @@ await transpiler.transform("<div>hi!</div>", "tsx");
```
{% details summary="Nitty gritty" %}
-The `.tranform()` method runs the transpiler in Bun's worker threadpool, so if you run it 100 times, it will run it across `Math.floor($cpu_count * 0.8)` threads, without blocking the main JavaScript thread.
+The `.transform()` method runs the transpiler in Bun's worker threadpool, so if you run it 100 times, it will run it across `Math.floor($cpu_count * 0.8)` threads, without blocking the main JavaScript thread.
If your code uses a macro, it will potentially spawn a new copy of Bun's JavaScript runtime environment in that new thread.
{% /details %}
diff --git a/docs/api/utils.md b/docs/api/utils.md
index de2dc6994..9889d6aa0 100644
--- a/docs/api/utils.md
+++ b/docs/api/utils.md
@@ -183,7 +183,7 @@ const currentFile = import.meta.url;
Bun.openInEditor(currentFile);
```
-You can override this via the `debug.editor` setting in your [`bunfig.toml`](/docs/runtime/configuration)
+You can override this via the `debug.editor` setting in your [`bunfig.toml`](/docs/runtime/bunfig)
```toml-diff#bunfig.toml
+ [debug]
@@ -204,7 +204,7 @@ Bun.ArrayBufferSink;
## `Bun.deepEquals()`
-Nestedly checks if two objects are equivalent. This is used internally by `expect().toEqual()` in `bun:test`.
+Recursively checks if two objects are equivalent. This is used internally by `expect().toEqual()` in `bun:test`.
```ts
const foo = { a: 1, b: 2, c: { d: 3 } };
diff --git a/docs/api/websockets.md b/docs/api/websockets.md
index e704419bb..4e55b8761 100644
--- a/docs/api/websockets.md
+++ b/docs/api/websockets.md
@@ -87,7 +87,7 @@ ws.send(new Uint8Array([1, 2, 3])); // TypedArray | DataView
### Headers
-Once the upgrade succeeds, Bun will send a `101 Switching Protocols` response per the [spec](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism). Additional `headers` can be attched to this `Response` in the call to `server.upgrade()`.
+Once the upgrade succeeds, Bun will send a `101 Switching Protocols` response per the [spec](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism). Additional `headers` can be attached to this `Response` in the call to `server.upgrade()`.
```ts
Bun.serve({
@@ -161,7 +161,7 @@ socket.addEventListener("message", event => {
### Pub/Sub
-Bun's `ServerWebSocket` implementation implements a native publish-subscribe API for topic-based broadcasting. Individual sockets can `.subscribe()` to a topic (specified with a string identifier) and `.publish()` messages to all other subscribers to that topic. This topic-based broadcast API is similar to [MQTT](https://en.wikipedia.org/wiki/MQTT) and [Redis Pub/Sub](https://redis.io/topics/pubsub).
+Bun's `ServerWebSocket` implementation implements a native publish-subscribe API for topic-based broadcasting. Individual sockets can `.subscribe()` to a topic (specified with a string identifier) and `.publish()` messages to all other subscribers to that topic (excluding itself). This topic-based broadcast API is similar to [MQTT](https://en.wikipedia.org/wiki/MQTT) and [Redis Pub/Sub](https://redis.io/topics/pubsub).
```ts
const server = Bun.serve<{ username: string }>({
@@ -200,7 +200,18 @@ const server = Bun.serve<{ username: string }>({
console.log(`Listening on ${server.hostname}:${server.port}`);
```
-Calling `.publish(data)` will send the message to all subscribers of a topic _except_ the socket that called `.publish()`.
+Calling `.publish(data)` will send the message to all subscribers of a topic _except_ the socket that called `.publish()`. To send a message to all subscribers of a topic, use the `.publish()` method on the `Server` instance.
+
+```ts
+const server = Bun.serve({
+ websocket: {
+ // ...
+ },
+});
+
+// listen for some external event
+server.publish("the-group-chat", "Hello world");
+```
### Compression
diff --git a/docs/api/workers.md b/docs/api/workers.md
index 417b77148..2b8c4fe13 100644
--- a/docs/api/workers.md
+++ b/docs/api/workers.md
@@ -10,7 +10,7 @@ Bun implements a minimal version of the [Web Workers API](https://developer.mozi
Like in browsers, [`Worker`](https://developer.mozilla.org/en-US/docs/Web/API/Worker) is a global. Use it to create a new worker thread.
-From the main thread:
+### From the main thread
```js#Main_thread
const workerURL = new URL("worker.ts", import.meta.url).href;
@@ -22,16 +22,25 @@ worker.onmessage = event => {
};
```
-Worker thread:
+### Worker thread
```ts#worker.ts_(Worker_thread)
+// prevents TS errors
+declare var self: Worker;
+
self.onmessage = (event: MessageEvent) => {
console.log(event.data);
postMessage("world");
};
```
-You can use `import`/`export` syntax in your worker code. Unlike in browsers, there's no need to specify `{type: "module"}` to use ES Modules.
+To prevent TypeScript errors when using `self`, add this line to the top of your worker file.
+
+```ts
+declare var self: Worker;
+```
+
+You can use `import` and `export` syntax in your worker code. Unlike in browsers, there's no need to specify `{type: "module"}` to use ES Modules.
To simplify error handling, the initial script to load is resolved at the time `new Worker(url)` is called.
@@ -123,14 +132,14 @@ By default, an active `Worker` will keep the main (spawning) process alive, so a
### `worker.unref()`
-To stop a running worker from keeping the process alive, call `worker.unref()`. This decouples the lifetime of the worker to the lifetime of the main process, and is equivlent to what Node.js' `worker_threads` does.
+To stop a running worker from keeping the process alive, call `worker.unref()`. This decouples the lifetime of the worker to the lifetime of the main process, and is equivalent to what Node.js' `worker_threads` does.
```ts
const worker = new Worker(new URL("worker.ts", import.meta.url).href);
worker.unref();
```
-Note: `worker.unref()` is not available in browers.
+Note: `worker.unref()` is not available in browsers.
### `worker.ref()`
@@ -151,7 +160,7 @@ const worker = new Worker(new URL("worker.ts", import.meta.url).href, {
});
```
-Note: `worker.ref()` is not available in browers.
+Note: `worker.ref()` is not available in browsers.
## Memory usage with `smol`
diff --git a/docs/bundler/index.md b/docs/bundler/index.md
index 585a6ac52..3069654b2 100644
--- a/docs/bundler/index.md
+++ b/docs/bundler/index.md
@@ -29,6 +29,10 @@ The bundler is a key piece of infrastructure in the JavaScript ecosystem. As a b
Let's jump into the bundler API.
+{% callout %}
+Note that the Bun bundler is not intended to replace `tsc` for typechecking or generating type declarations.
+{% /callout %}
+
## Basic example
Let's build our first bundle. You have the following two files, which implement a simple client-side rendered React app.
@@ -132,6 +136,14 @@ Visit `http://localhost:5000` to see your bundled app in action.
{% /details %}
+## Watch mode
+
+Like the runtime and test runner, the bundler supports watch mode natively.
+
+```sh
+$ bun build ./index.tsx --outdir ./out --watch
+```
+
## Content types
Like the Bun runtime, the bundler supports an array of file types out of the box. The following table breaks down the bundler's set of standard "loaders". Refer to [Bundler > File types](/docs/runtime/loaders) for full documentation.
@@ -316,7 +328,7 @@ Depending on the target, Bun will apply different module resolution rules and op
All bundles generated with `target: "bun"` are marked with a special `// @bun` pragma, which indicates to the Bun runtime that there's no need to re-transpile the file before execution.
- If any entrypoints contains a Bun shebang (`#!/usr/bin/env bun`) the bundler will default to `target: "bun"` instead of `"browser`.
+ If any entrypoints contains a Bun shebang (`#!/usr/bin/env bun`) the bundler will default to `target: "bun"` instead of `"browser"`.
---
@@ -1084,7 +1096,7 @@ interface BuildArtifact extends Blob {
The `outputs` array contains all the files that were generated by the build. Each artifact implements the `Blob` interface.
```ts
-const build = Bun.build({
+const build = await Bun.build({
/* */
});
@@ -1128,7 +1140,7 @@ Each artifact also contains the following properties:
Similar to `BunFile`, `BuildArtifact` objects can be passed directly into `new Response()`.
```ts
-const build = Bun.build({
+const build = await Bun.build({
/* */
});
@@ -1144,7 +1156,7 @@ The Bun runtime implements special pretty-printing of `BuildArtifact` object to
```ts#Build_script
// build.ts
-const build = Bun.build({/* */});
+const build = await Bun.build({/* */});
const artifact = build.outputs[0];
console.log(artifact);
diff --git a/docs/bundler/intro.md b/docs/bundler/intro.md
index 5056c26a9..8927053d5 100644
--- a/docs/bundler/intro.md
+++ b/docs/bundler/intro.md
@@ -40,7 +40,7 @@ When a user visits this website, the files are loaded in the following order:
This approach works, it requires three round-trip HTTP requests before the browser is ready to render the page. On slow internet connections, this may add up to a non-trivial delay.
-This example is extremely simplistic. A modern app may be loading dozens of modules from `node_modules`, each consisting of hundrends of files. Loading each of these files with a separate HTTP request becomes untenable very quickly. While most of these requests will be running in parallel, the number of round-trip requests can still be very high; plus, there are limits on how many simultaneous requests a browser can make.
+This example is extremely simplistic. A modern app may be loading dozens of modules from `node_modules`, each consisting of hundred of files. Loading each of these files with a separate HTTP request becomes untenable very quickly. While most of these requests will be running in parallel, the number of round-trip requests can still be very high; plus, there are limits on how many simultaneous requests a browser can make.
{% callout %}
Some recent advances like modulepreload and HTTP/3 are intended to solve some of these problems, but at the moment bundling is still the most performant approach.
diff --git a/docs/bundler/loaders.md b/docs/bundler/loaders.md
index c15ce926f..d013913d6 100644
--- a/docs/bundler/loaders.md
+++ b/docs/bundler/loaders.md
@@ -16,7 +16,7 @@ Parses the code and applies a set of default transforms, like dead-code eliminat
**JavaScript + JSX.**. Default for `.js` and `.jsx`.
-Same as the `js` loader, but JSX syntax is supported. By default, JSX is downconverted to plain JavaScript; the details of how this is done depends on the `jsx*` compiler options in your `tsconfig.json`. Refer to the TypeScript documentation [on JSX](https://www.typescriptlang.org/docs/handbook/jsx.html) for more information.
+Same as the `js` loader, but JSX syntax is supported. By default, JSX is down-converted to plain JavaScript; the details of how this is done depends on the `jsx*` compiler options in your `tsconfig.json`. Refer to the TypeScript documentation [on JSX](https://www.typescriptlang.org/docs/handbook/jsx.html) for more information.
### `ts`
diff --git a/docs/bundler/macros.md b/docs/bundler/macros.md
index ecba16c0d..c0dcff319 100644
--- a/docs/bundler/macros.md
+++ b/docs/bundler/macros.md
@@ -129,7 +129,7 @@ if (returnFalse()) {
}
```
-## Serializablility
+## Serializability
Bun's transpiler needs to be able to serialize the result of the macro so it can be inlined into the AST. All JSON-compatible data structures are supported:
diff --git a/docs/bundler/vs-esbuild.md b/docs/bundler/vs-esbuild.md
index 0d145721a..67bed3dc3 100644
--- a/docs/bundler/vs-esbuild.md
+++ b/docs/bundler/vs-esbuild.md
@@ -125,13 +125,13 @@ In Bun's CLI, simple boolean flags like `--minify` do not accept an argument. Ot
- `--target`
- n/a
-- No supported. Bun's bundler performs no syntactic downleveling at this time.
+- No supported. Bun's bundler performs no syntactic down-leveling at this time.
---
- `--watch`
-- n/a
-- Not applicable
+- `--watch`
+- No differences
---
diff --git a/docs/cli/add.md b/docs/cli/add.md
new file mode 100644
index 000000000..4b555d5a6
--- /dev/null
+++ b/docs/cli/add.md
@@ -0,0 +1,155 @@
+To add a particular package:
+
+```bash
+$ bun add preact
+```
+
+To specify a version, version range, or tag:
+
+```bash
+$ bun add zod@3.20.0
+$ bun add zod@^3.0.0
+$ bun add zod@latest
+```
+
+## `--dev`
+
+{% callout %}
+**Alias** — `--development`, `-d`, `-D`
+{% /callout %}
+
+To add a package as a dev dependency (`"devDependencies"`):
+
+```bash
+$ bun add --dev @types/react
+$ bun add -d @types/react
+```
+
+## `--optional`
+
+To add a package as an optional dependency (`"optionalDependencies"`):
+
+```bash
+$ bun add --optional lodash
+```
+
+## `--exact`
+
+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
+$ bun add react -E
+```
+
+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 view a complete list of options for this command:
+
+```bash
+$ bun add --help
+```
+
+## `--global`
+
+{% callout %}
+**Note** — This would not modify package.json of your current project folder.
+**Alias** - `bun add --global`, `bun add -g`, `bun install --global` and `bun install -g`
+{% /callout %}
+
+To install a package globally, use the `-g`/`--global` flag. This will not modify the `package.json` of your current project. Typically this is used for installing command-line tools.
+
+```bash
+$ bun add --global cowsay # or `bun add -g cowsay`
+$ cowsay "Bun!"
+ ______
+< Bun! >
+ ------
+ \ ^__^
+ \ (oo)\_______
+ (__)\ )\/\
+ ||----w |
+ || ||
+```
+
+{% details summary="Configuring global installation behavior" %}
+
+```toml
+[install]
+# where `bun add --global` installs packages
+globalDir = "~/.bun/install/global"
+
+# where globally-installed package bins are linked
+globalBinDir = "~/.bun/bin"
+```
+
+{% /details %}
+
+## 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.
+
+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"]
+ }
+```
+
+Bun reads this field and will run lifecycle scripts for `my-trusted-package`.
+
+<!-- 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. -->
+
+## Git dependencies
+
+To add a dependency from a git repository:
+
+```bash
+$ bun add git@github.com:moment/moment.git
+```
+
+Bun supports a variety of protocols, including [`github`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#github-urls), [`git`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#git-urls-as-dependencies), `git+ssh`, `git+https`, and many more.
+
+```json
+{
+ "dependencies": {
+ "dayjs": "git+https://github.com/iamkun/dayjs.git",
+ "lodash": "git+ssh://github.com/lodash/lodash.git#4.17.21",
+ "moment": "git@github.com:moment/moment.git",
+ "zod": "github:colinhacks/zod"
+ }
+}
+```
+
+## Tarball dependencies
+
+A package name can correspond to a publicly hosted `.tgz` file. During installation, Bun will download and install the package from the specified tarball URL, rather than from the package registry.
+
+```sh
+$ bun add zod@https://registry.npmjs.org/zod/-/zod-3.21.4.tgz
+```
+
+This will add the following line to your `package.json`:
+
+```json#package.json
+{
+ "dependencies": {
+ "zod": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz"
+ }
+}
+```
diff --git a/docs/templates.md b/docs/cli/bun-create.md
index c80caa153..c5cc602b6 100644
--- a/docs/templates.md
+++ b/docs/cli/bun-create.md
@@ -1,42 +1,18 @@
-## `bun init`
-
-Scaffold an empty project with the interactive `bun init` command.
-
-```bash
-$ bun init
-bun init helps you get started with a minimal project and tries to
-guess sensible defaults. Press ^C anytime to quit.
-
-package name (quickstart):
-entry point (index.ts):
-
-Done! A package.json file was saved in the current directory.
- + index.ts
- + .gitignore
- + tsconfig.json (for editor auto-complete)
- + README.md
-
-To get started, run:
- bun run index.ts
-```
-
-Press `enter` to accept the default answer for each prompt, or pass the `-y` flag to auto-accept the defaults.
-
-## `bun create`
-
{% callout %}
**Note** — You don’t need `bun create` to use Bun. You don’t need any configuration at all. This command exists to make getting started a bit quicker and easier.
{% /callout %}
Template a new Bun project with `bun create`. This is a flexible command that can be used to create a new project with a `create-<template>` npm package, a GitHub repo, or a local template.
-### From `npm`
+If you're looking to create a brand new empty project, use [`bun init`](/docs/cli/init).
+
+## From `npm`
```sh
$ bun create <template> [<destination>]
```
-Assuming you don't have a [local template](#local-templates) with the same name, this command will download and execute the `create-<template>` package from npm. The following two commands will behave identically:
+Assuming you don't have a [local template](#from-a-local-template) with the same name, this command will download and execute the `create-<template>` package from npm. The following two commands will behave identically:
```sh
$ bun create remix
@@ -45,7 +21,7 @@ $ bunx create-remix
Refer to the documentation of the associated `create-<template>` package for complete documentation and usage instructions.
-### From GitHub
+## From GitHub
This will download the contents of the GitHub repo to disk.
@@ -115,7 +91,7 @@ $ bun create https://github.com/ahfarmer/calculator ./myapp
Bun installs the files as they currently exist current default branch (usually `main` or `master`). Unlike `git clone` it doesn't download the commit history or configure a remote. -->
-### From a local template
+## From a local template
{% callout %}
**⚠️ Warning** — Unlike remote templates, running `bun create` with a local template will delete the entire destination folder if it already exists! Be careful.
diff --git a/docs/cli/bun-install.md b/docs/cli/bun-install.md
index 8050070be..0cbc21e1d 100644
--- a/docs/cli/bun-install.md
+++ b/docs/cli/bun-install.md
@@ -21,7 +21,7 @@ Configuring with `bunfig.toml` is optional. Bun tries to be zero configuration i
# Scope name The value can be a URL string or an object
"@mybigcompany" = { token = "123456", url = "https://registry.mybigcompany.com" }
-# URL is optional and fallsback to the default registry
+# URL is optional and falls back to the default registry
# The "@" in the scope is optional
mybigcompany2 = { token = "123456" }
@@ -47,7 +47,7 @@ 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
+# Disallow changes to lockfile? This is the equivalent to the "--frozen-lockfile" CLI argument
frozenLockfile = false
# Don't actually install
@@ -89,12 +89,6 @@ disableManifest = false
# Note: it does not load the lockfile, it just converts bun.lockb into a yarn.lock
print = "yarn"
-# Path to read bun.lockb from
-path = "bun.lockb"
-
-# Path to save bun.lockb to
-savePath = "bun.lockb"
-
# Save the lockfile to disk
save = true
@@ -142,8 +136,6 @@ export interface Cache {
export interface Lockfile {
print?: "yarn";
- path: string;
- savePath: string;
save: boolean;
}
```
@@ -156,7 +148,6 @@ Environment variables have a higher priority than `bunfig.toml`.
| -------------------------------- | ------------------------------------------------------------- |
| BUN_CONFIG_REGISTRY | Set an npm registry (default: <https://registry.npmjs.org>) |
| BUN_CONFIG_TOKEN | Set an auth token (currently does nothing) |
-| BUN_CONFIG_LOCKFILE_SAVE_PATH | File path to save the lockfile to (default: bun.lockb) |
| BUN_CONFIG_YARN_LOCKFILE | Save a Yarn v1-style yarn.lock |
| BUN_CONFIG_LINK_NATIVE_BINS | Point `bin` in package.json to a platform-specific dependency |
| BUN_CONFIG_SKIP_SAVE_LOCKFILE | Don’t save a lockfile |
diff --git a/docs/cli/bundler.md b/docs/cli/bundler.md
index 6900e9292..1b4c419c1 100644
--- a/docs/cli/bundler.md
+++ b/docs/cli/bundler.md
@@ -1,6 +1,6 @@
Bundling is currently an important mechanism for building complex web apps.
-Modern apps typically consist of a large number of files and package dependencies. Despite the fact that modern browsers support [ES Module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) imports, it's still too slow to fetch each file via inidividual HTTP requests. _Bundling_ is the process of concatenating several source files into a single large file that can be loaded in a single request.
+Modern apps typically consist of a large number of files and package dependencies. Despite the fact that modern browsers support [ES Module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) imports, it's still too slow to fetch each file via individual HTTP requests. _Bundling_ is the process of concatenating several source files into a single large file that can be loaded in a single request.
{% callout %}
**On bundling** — Despite recent advances like [`modulepreload`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel/modulepreload) and [HTTP/3](https://en.wikipedia.org/wiki/HTTP/3), bundling is still the most performant approach.
diff --git a/docs/cli/create.md b/docs/cli/create.md
deleted file mode 100644
index d59912f2b..000000000
--- a/docs/cli/create.md
+++ /dev/null
@@ -1,256 +0,0 @@
-## `bun init`
-
-Scaffold an empty project with `bun init`. It's an interactive tool.
-
-```bash
-$ bun init
-bun init helps you get started with a minimal project and tries to
-guess sensible defaults. Press ^C anytime to quit.
-
-package name (quickstart):
-entry point (index.ts):
-
-Done! A package.json file was saved in the current directory.
- + index.ts
- + .gitignore
- + tsconfig.json (for editor auto-complete)
- + README.md
-
-To get started, run:
- bun run index.ts
-```
-
-Press `enter` to accept the default answer for each prompt, or pass the `-y` flag to auto-accept the defaults.
-
-## `bun create`
-
-Template a new Bun project with `bun create`.
-
-```bash
-$ bun create <template> <destination>
-```
-
-{% callout %}
-**Note** — You don’t need `bun create` to use Bun. You don’t need any configuration at all. This command exists to make getting started a bit quicker and easier.
-{% /callout %}
-
-A template can take a number of forms:
-
-```bash
-$ bun create <template> # an official template (remote)
-$ bun create <username>/<repo> # a GitHub repo (remote)
-$ bun create <local-template> # a custom template (local)
-```
-
-Running `bun create` performs the following steps:
-
-- Download the template (remote templates only)
-- Copy all template files into the destination folder. By default Bun will _not overwrite_ any existing files. Use the `--force` flag to overwrite existing files.
-- Install dependencies with `bun install`.
-- Initialize a fresh Git repo. Opt out with the `--no-git` flag.
-- Run the template's configured `start` script, if defined.
-
-<!-- ## Official templates
-
-The following official templates are available.
-
-```bash
-bun create next ./myapp
-bun create react ./myapp
-bun create svelte-kit ./myapp
-bun create elysia ./myapp
-bun create hono ./myapp
-bun create kingworld ./myapp
-```
-
-Each of these corresponds to a directory in the [bun-community/create-templates](https://github.com/bun-community/create-templates) repo. If you think a major framework is missing, please open a PR there. This list will change over time as additional examples are added. To see an up-to-date list, run `bun create` with no arguments.
-
-```bash
-$ bun create
-Welcome to bun! Create a new project by pasting any of the following:
- <list of templates>
-```
-
-{% callout %}
-⚡️ **Speed** — At the time of writing, `bun create react app` runs ~11x faster on a M1 Macbook Pro than `yarn create react-app app`.
-{% /callout %} -->
-
-## GitHub repos
-
-A template of the form `<username>/<repo>` will be downloaded from GitHub.
-
-```bash
-$ bun create ahfarmer/calculator ./myapp
-```
-
-Complete GitHub URLs will also work:
-
-```bash
-$ bun create github.com/ahfarmer/calculator ./myapp
-$ bun create https://github.com/ahfarmer/calculator ./myapp
-```
-
-Bun installs the files as they currently exist current default branch (usually `main`). Unlike `git clone` it doesn't download the commit history or configure a remote.
-
-## Local templates
-
-{% callout %}
-**⚠️ Warning** — Unlike remote templates, running `bun create` with a local template will delete the entire destination folder if it already exists! Be careful.
-{% /callout %}
-Bun's templater can be extended to support custom templates defined on your local file system. These templates should live in one of the following directories:
-
-- `$HOME/.bun-create/<name>`: global templates
-- `<project root>/.bun-create/<name>`: project-specific templates
-
-{% callout %}
-**Note** — You can customize the global template path by setting the `BUN_CREATE_DIR` environment variable.
-{% /callout %}
-
-To create a local template, navigate to `$HOME/.bun-create` and create a new directory with the desired name of your template.
-
-```bash
-$ cd $HOME/.bun-create
-$ mkdir foo
-$ cd foo
-```
-
-Then, create a `package.json` file in that directory with the following contents:
-
-```json
-{
- "name": "foo"
-}
-```
-
-You can run `bun create foo` elsewhere on your file system to verify that Bun is correctly finding your local template.
-
-{% table %}
-
----
-
-- `postinstall`
-- runs after installing dependencies
-
----
-
-- `preinstall`
-- runs before installing dependencies
-
-<!-- ---
-
-- `start`
-- a command to auto-start the application -->
-
-{% /table %}
-
-Each of these can correspond to a string or array of strings. An array of commands will be executed in order. Here is an example:
-
-```json
-{
- "name": "@bun-examples/simplereact",
- "version": "0.0.1",
- "main": "index.js",
- "dependencies": {
- "react": "^17.0.2",
- "react-dom": "^17.0.2"
- },
- "bun-create": {
- "preinstall": "echo 'Installing...'", // a single command
- "postinstall": ["echo 'Done!'"], // an array of commands
- "start": "bun run echo 'Hello world!'"
- }
-}
-```
-
-When cloning a template, `bun create` will automatically remove the `"bun-create"` section from `package.json` before writing it to the destination folder.
-
-## Reference
-
-### CLI flags
-
-{% table %}
-
-- Flag
-- Description
-
----
-
-- `--force`
-- Overwrite existing files
-
----
-
-- `--no-install`
-- Skip installing `node_modules` & tasks
-
----
-
-- `--no-git`
-- Don’t initialize a git repository
-
----
-
-- `--open`
-- Start & open in-browser after finish
-
-{% /table %}
-
-### Environment variables
-
-{% table %}
-
-- Name
-- Description
-
----
-
-- `GITHUB_API_DOMAIN`
-- If you’re using a GitHub enterprise or a proxy, you can customize the GitHub domain Bun pings for downloads
-
----
-
-- `GITHUB_API_TOKEN`
-- This lets `bun create` work with private repositories or if you get rate-limited
-
-{% /table %}
-
-{% details summary="How `bun create` works" %}
-
-When you run `bun create ${template} ${destination}`, here’s what happens:
-
-IF remote template
-
-1. GET `registry.npmjs.org/@bun-examples/${template}/latest` and parse it
-2. GET `registry.npmjs.org/@bun-examples/${template}/-/${template}-${latestVersion}.tgz`
-3. Decompress & extract `${template}-${latestVersion}.tgz` into `${destination}`
-
- - If there are files that would overwrite, warn and exit unless `--force` is passed
-
-IF GitHub repo
-
-1. Download the tarball from GitHub’s API
-2. Decompress & extract into `${destination}`
-
- - If there are files that would overwrite, warn and exit unless `--force` is passed
-
-ELSE IF local template
-
-1. Open local template folder
-2. Delete destination directory recursively
-3. Copy files recursively using the fastest system calls available (on macOS `fcopyfile` and Linux, `copy_file_range`). Do not copy or traverse into `node_modules` folder if exists (this alone makes it faster than `cp`)
-
-4. Parse the `package.json` (again!), update `name` to be `${basename(destination)}`, remove the `bun-create` section from the `package.json` and save the updated `package.json` to disk.
- - IF Next.js is detected, add `bun-framework-next` to the list of dependencies
- - IF Create React App is detected, add the entry point in /src/index.{js,jsx,ts,tsx} to `public/index.html`
- - IF Relay is detected, add `bun-macro-relay` so that Relay works
-5. Auto-detect the npm client, preferring `pnpm`, `yarn` (v1), and lastly `npm`
-6. Run any tasks defined in `"bun-create": { "preinstall" }` with the npm client
-7. Run `${npmClient} install` unless `--no-install` is passed OR no dependencies are in package.json
-8. Run any tasks defined in `"bun-create": { "preinstall" }` with the npm client
-9. Run `git init; git add -A .; git commit -am "Initial Commit";`
-
- - Rename `gitignore` to `.gitignore`. NPM automatically removes `.gitignore` files from appearing in packages.
- - If there are dependencies, this runs in a separate thread concurrently while node_modules are being installed
- - Using libgit2 if available was tested and performed 3x slower in microbenchmarks
-
-{% /details %}
diff --git a/docs/cli/bun-init.md b/docs/cli/init.md
index bc51614e3..f17c8e1b7 100644
--- a/docs/cli/bun-init.md
+++ b/docs/cli/init.md
@@ -1,3 +1,27 @@
+Scaffold an empty Bun project with the interactive `bun init` command.
+
+```bash
+$ bun init
+bun init helps you get started with a minimal project and tries to
+guess sensible defaults. Press ^C anytime to quit.
+
+package name (quickstart):
+entry point (index.ts):
+
+Done! A package.json file was saved in the current directory.
+ + index.ts
+ + .gitignore
+ + tsconfig.json (for editor auto-complete)
+ + README.md
+
+To get started, run:
+ bun run index.ts
+```
+
+Press `enter` to accept the default answer for each prompt, or pass the `-y` flag to auto-accept the defaults.
+
+{% details summary="How `bun init` works" %}
+
`bun init` is a quick way to start a blank project with Bun. It guesses with sane defaults and is non-destructive when run multiple times.
![Demo](https://user-images.githubusercontent.com/709451/183006613-271960a3-ff22-4f7c-83f5-5e18f684c836.gif)
@@ -13,6 +37,4 @@ If you pass `-y` or `--yes`, it will assume you want to continue without asking
At the end, it runs `bun install` to install `bun-types`.
-#### How is `bun init` different than `bun create`?
-
-`bun init` is for blank projects. `bun create` applies templates.
+{% /details %}
diff --git a/docs/cli/install.md b/docs/cli/install.md
index a608a8950..573a6f106 100644
--- a/docs/cli/install.md
+++ b/docs/cli/install.md
@@ -23,43 +23,19 @@ sudo apt install --install-recommends linux-generic-hwe-20.04
{% /details %}
-## Manage dependencies
-
-### `bun install`
-
To install all dependencies of a project:
```bash
$ bun install
```
-On Linux, `bun install` tends to install packages 20-100x faster than `npm install`. On macOS, it's more like 4-80x.
-
-![package install benchmark](https://user-images.githubusercontent.com/709451/147004342-571b6123-17a9-49a2-8bfd-dcfc5204047e.png)
-
Running `bun install` will:
- **Install** all `dependencies`, `devDependencies`, and `optionalDependencies`. Bun does not install `peerDependencies` by default.
- **Run** your project's `{pre|post}install` and `{pre|post}prepare` scripts at the appropriate time. For security reasons Bun _does not execute_ lifecycle scripts of installed dependencies.
- **Write** a `bun.lockb` lockfile to the project root.
-To install in production mode (i.e. without `devDependencies`):
-
-```bash
-$ 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
-$ bun install --dry-run
-```
+## Logging
To modify logging verbosity:
@@ -68,86 +44,59 @@ $ bun install --verbose # debug logging
$ bun install --silent # no logging
```
-{% details summary="Configuring behavior" %}
-The default behavior of `bun install` can be configured in `bun.toml`:
-
-```toml
-[install]
-
-# whether to install optionalDependencies
-optional = true
-
-# whether to install devDependencies
-dev = true
-
-# whether to install peerDependencies
-peer = false
-
-# equivalent to `--production` flag
-production = false
-
-# equivalent to `--frozen-lockfile` flag
-frozenLockfile = false
-
-# equivalent to `--dry-run` flag
-dryRun = false
-```
-
-{% /details %}
-
-### `bun add`
-
-To add a particular package:
-
-```bash
-$ bun add preact
-```
-
-To specify a version, version range, or tag:
+## Lifecycle scripts
-```bash
-$ bun add zod@3.20.0
-$ bun add zod@^3.0.0
-$ bun add zod@latest
-```
+Unlike other npm clients, Bun does not execute arbitrary lifecycle scripts like `postinstall` for installed dependencies. Executing arbitrary scripts represents a potential security risk.
-To add a package as a dev dependency (`"devDependencies"`):
+To tell Bun to allow lifecycle scripts for a particular package, add the package to `trustedDependencies` in your package.json.
-```bash
-$ bun add --dev @types/react
-$ bun add -d @types/react
+```json-diff
+ {
+ "name": "my-app",
+ "version": "1.0.0",
++ "trustedDependencies": ["my-trusted-package"]
+ }
```
-To add a package as an optional dependency (`"optionalDependencies"`):
+Then re-install the package. Bun will read this field and run lifecycle scripts for `my-trusted-package`.
-```bash
-$ bun add --optional lodash
-```
+## Workspaces
-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.
+Bun supports `"workspaces"` in package.json. For complete documentation refer to [Package manager > Workspaces](/docs/install/workspaces).
-```bash
-$ bun add react --exact
+```json#package.json
+{
+ "name": "my-app",
+ "version": "1.0.0",
+ "workspaces": ["packages/*"],
+ "dependencies": {
+ "preact": "^10.5.13"
+ }
+}
```
-This will add the following to your `package.json`:
+## Overrides and resolutions
-```jsonc
-{
- "dependencies": {
- // without --exact
- "react": "^18.2.0", // this matches >= 18.2.0 < 19.0.0
+Bun supports npm's `"overrides"` and Yarn's `"resolutions"` in `package.json`. These are mechanisms for specifying a version range for _metadependencies_—the dependencies of your dependencies. Refer to [Package manager > Overrides and resolutions](/docs/install/overrides) for complete documentation.
- // with --exact
- "react": "18.2.0" // this matches only 18.2.0 exactly
+```json-diff#package.json
+ {
+ "name": "my-app",
+ "dependencies": {
+ "foo": "^2.0.0"
+ },
++ "overrides": {
++ "bar": "~4.4.0"
++ }
}
-}
```
-To install a package globally:
+## Global packages
+
+To install a package globally, use the `-g`/`--global` flag. Typically this is used for installing command-line tools.
```bash
-$ bun add --global cowsay # or `bun add -g cowsay`
+$ bun install --global cowsay # or `bun install -g cowsay`
$ cowsay "Bun!"
______
< Bun! >
@@ -159,149 +108,75 @@ $ cowsay "Bun!"
|| ||
```
-{% details summary="Configuring global installation behavior" %}
-
-```toml
-[install]
-# where `bun install --global` installs packages
-globalDir = "~/.bun/install/global"
-
-# where globally-installed package bins are linked
-globalBinDir = "~/.bun/bin"
-```
+## Production mode
-{% /details %}
-To view a complete list of options for a given command:
+To install in production mode (i.e. without `devDependencies` or `optionalDependencies`):
```bash
-$ bun add --help
+$ bun install --production
```
-### `bun remove`
-
-To remove a dependency:
+For reproducible installs, use `--frozen-lockfile`. This will install the exact versions of each package specified in the lockfile. If your `package.json` disagrees with `bun.lockb`, Bun will exit with an error. The lockfile will not be updated.
```bash
-$ bun remove preact
+$ bun install --frozen-lockfile
```
-## Local packages (`bun link`)
-
-Use `bun link` in a local directory to register the current package as a "linkable" package.
-
-```bash
-$ cd /path/to/cool-pkg
-$ cat package.json
-{
- "name": "cool-pkg",
- "version": "1.0.0"
-}
-$ bun link
-bun link v1.x (7416672e)
-Success! Registered "cool-pkg"
-
-To use cool-pkg in a project, run:
- bun link cool-pkg
+For more information on Bun's binary lockfile `bun.lockb`, refer to [Package manager > Lockfile](/docs/install/lockfile).
-Or add it in dependencies in your package.json file:
- "cool-pkg": "link:cool-pkg"
-```
+## Dry run
-This package can now be "linked" into other projects using `bun link cool-pkg`. This will create a symlink in the `node_modules` directory of the target project, pointing to the local directory.
+To perform a dry run (i.e. don't actually install anything):
```bash
-$ cd /path/to/my-app
-$ bun link cool-pkg
-```
-
-In addition, the `--save` flag can be used to add `cool-pkg` to the `dependencies` field of your app's package.json with a special version specifier that tells Bun to load from the registered local directory instead of installing from `npm`:
-
-```json-diff
- {
- "name": "my-app",
- "version": "1.0.0",
- "dependencies": {
-+ "cool-pkg": "link:cool-pkg"
- }
- }
-```
-
-## 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 install --dry-run
```
-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
+## Non-npm dependencies
-To add a dependency from a git repository:
+Bun supports installing dependencies from Git, GitHub, and local or remotely-hosted tarballs. For complete documentation refer to [Package manager > Git, GitHub, and tarball dependencies](/docs/cli/add).
-```bash
-$ bun install git@github.com:moment/moment.git
-```
-
-Bun supports a variety of protocols, including [`github`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#github-urls), [`git`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#git-urls-as-dependencies), `git+ssh`, `git+https`, and many more.
-
-```json
+```json#package.json
{
"dependencies": {
"dayjs": "git+https://github.com/iamkun/dayjs.git",
"lodash": "git+ssh://github.com/lodash/lodash.git#4.17.21",
"moment": "git@github.com:moment/moment.git",
- "zod": "github:colinhacks/zod"
+ "zod": "github:colinhacks/zod",
+ "react": "https://registry.npmjs.org/react/-/react-18.2.0.tgz"
}
}
```
-## Tarball dependencies
+## Configuration
-A package name can correspond to a publically hosted `.tgz` file. During `bun install`, Bun will download and install the package from the specified tarball URL, rather than from the package registry.
+The default behavior of `bun install` can be configured in `bunfig.toml`. The default values are shown below.
-```json#package.json
-{
- "dependencies": {
- "zod": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz"
- }
-}
+```toml
+[install]
+
+# whether to install optionalDependencies
+optional = true
+
+# whether to install devDependencies
+dev = true
+
+# whether to install peerDependencies
+peer = false
+
+# equivalent to `--production` flag
+production = false
+
+# equivalent to `--frozen-lockfile` flag
+frozenLockfile = false
+
+# equivalent to `--dry-run` flag
+dryRun = false
```
## CI/CD
-Looking to speed up your CI? Use the official `oven-sh/setup-bun` action to install `bun` in a GitHub Actions pipeline.
+Looking to speed up your CI? Use the official [`oven-sh/setup-bun`](https://github.com/oven-sh/setup-bun) action to install `bun` in a GitHub Actions pipeline.
```yaml#.github/workflows/release.yml
name: bun-types
diff --git a/docs/cli/link.md b/docs/cli/link.md
new file mode 100644
index 000000000..9adc73765
--- /dev/null
+++ b/docs/cli/link.md
@@ -0,0 +1,46 @@
+Use `bun link` in a local directory to register the current package as a "linkable" package.
+
+```bash
+$ cd /path/to/cool-pkg
+$ cat package.json
+{
+ "name": "cool-pkg",
+ "version": "1.0.0"
+}
+$ bun link
+bun link v1.x (7416672e)
+Success! Registered "cool-pkg"
+
+To use cool-pkg in a project, run:
+ bun link cool-pkg
+
+Or add it in dependencies in your package.json file:
+ "cool-pkg": "link:cool-pkg"
+```
+
+This package can now be "linked" into other projects using `bun link cool-pkg`. This will create a symlink in the `node_modules` directory of the target project, pointing to the local directory.
+
+```bash
+$ cd /path/to/my-app
+$ bun link cool-pkg
+```
+
+In addition, the `--save` flag can be used to add `cool-pkg` to the `dependencies` field of your app's package.json with a special version specifier that tells Bun to load from the registered local directory instead of installing from `npm`:
+
+```json-diff
+ {
+ "name": "my-app",
+ "version": "1.0.0",
+ "dependencies": {
++ "cool-pkg": "link:cool-pkg"
+ }
+ }
+```
+
+To _unregister_ a local package, navigate to the package's root directory and run `bun unlink`.
+
+```bash
+$ cd /path/to/cool-pkg
+$ bun unlink
+bun unlink v1.x (7416672e)
+```
diff --git a/docs/install/utilities.md b/docs/cli/pm.md
index 689f177d8..689f177d8 100644
--- a/docs/install/utilities.md
+++ b/docs/cli/pm.md
diff --git a/docs/cli/remove.md b/docs/cli/remove.md
new file mode 100644
index 000000000..8054711d3
--- /dev/null
+++ b/docs/cli/remove.md
@@ -0,0 +1,5 @@
+To remove a dependency:
+
+```bash
+$ bun remove ts-node
+```
diff --git a/docs/cli/run.md b/docs/cli/run.md
index 65c4842cc..c710e4f73 100644
--- a/docs/cli/run.md
+++ b/docs/cli/run.md
@@ -1,5 +1,28 @@
The `bun` CLI can be used to execute JavaScript/TypeScript files, `package.json` scripts, and [executable packages](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#bin).
+## Performance
+
+Bun is designed to start fast and run fast.
+
+Under the hood Bun uses the [JavaScriptCore engine](https://developer.apple.com/documentation/javascriptcore), which is developed by Apple for Safari. In most cases, the startup and running performance is faster than V8, the engine used by Node.js and Chromium-based browsers. Its transpiler and runtime are written in Zig, a modern, high-performance language. On Linux, this translates into startup times [4x faster](https://twitter.com/jarredsumner/status/1499225725492076544) than Node.js.
+
+{% table %}
+
+---
+
+- `bun hello.js`
+- `5.2ms`
+
+---
+
+- `node hello.js`
+- `25.1ms`
+
+{% /table %}
+{% caption content="Running a simple Hello World script on Linux" /%}
+
+<!-- {% image src="/images/bun-run-speed.jpeg" caption="Bun vs Node.js vs Deno running Hello World" /%} -->
+
<!-- ## Speed -->
<!--
@@ -26,10 +49,11 @@ $ bun run index.ts
$ bun run index.tsx
```
-The "naked" `bun` command is equivalent to `bun run`.
+Alternatively, you can omit the `run` keyword and use the "naked" command; it behaves identically.
```bash
$ bun index.tsx
+$ bun index.js
```
### `--watch`
@@ -40,6 +64,17 @@ To run a file in watch mode, use the `--watch` flag.
$ bun --watch run index.tsx
```
+{% callout %}
+**Note** — When using `bun run`, put Bun flags like `--watch` immediately after `bun`.
+
+```bash
+$ bun --watch run dev # ✔️ do this
+$ bun run dev --watch # ❌ don't do this
+```
+
+Flags that occur at the end of the command will be ignored and passed through to the `"dev"` script itself.
+{% /callout %}
+
### `--smol`
In memory-constrained environments, use the `--smol` flag to reduce memory usage at a cost to performance.
@@ -54,6 +89,10 @@ $ bun --smol run index.tsx
Compare to `npm run <script>` or `yarn <script>`
{% /note %}
+```sh
+$ bun [bun flags] run <script> [script flags]
+```
+
Your `package.json` can define a number of named `"scripts"` that correspond to shell commands.
```jsonc
@@ -66,10 +105,10 @@ Your `package.json` can define a number of named `"scripts"` that correspond to
}
```
-Use `bun <script>` to execute these scripts.
+Use `bun run <script>` to execute these scripts.
```bash
-$ bun clean
+$ bun run clean
$ rm -rf dist && echo 'Done.'
Cleaning...
Done.
@@ -104,22 +143,18 @@ quickstart scripts:
Bun respects lifecycle hooks. For instance, `bun run clean` will execute `preclean` and `postclean`, if defined. If the `pre<script>` fails, Bun will not execute the script itself.
-## Environment variables
+### `--bun`
-Bun automatically loads environment variables from `.env` files before running a file, script, or executable. The following files are checked, in order:
+It's common for `package.json` scripts to reference locally-installed CLIs like `vite` or `next`. These CLIs are often JavaScript files marked with a [shebang](<https://en.wikipedia.org/wiki/Shebang_(Unix)>) to indicate that they should be executed with `node`.
-1. `.env.local` (first)
-2. `NODE_ENV` === `"production"` ? `.env.production` : `.env.development`
-3. `.env`
+```js
+#!/usr/bin/env node
-To debug environment variables, run `bun run env` to view a list of resolved environment variables.
-
-## Performance
-
-Bun is designed to start fast and run fast.
-
-Under the hood Bun uses the [JavaScriptCore engine](https://developer.apple.com/documentation/javascriptcore), which is developed by Apple for Safari. In most cases, the startup and running performance is faster than V8, the engine used by Node.js and Chromium-based browsers. Its transpiler and runtime are written in Zig, a modern, high-performance language. On Linux, this translates into startup times [4x faster](https://twitter.com/jarredsumner/status/1499225725492076544) than Node.js.
+// do stuff
+```
-{% image src="/images/bun-run-speed.jpeg" caption="Bun vs Node.js vs Deno running Hello World" /%}
+By default, Bun respects this shebang and executes the script with `node`. However, you can override this behavior with the `--bun` flag. For Node.js-based CLIs, this will run the CLI with Bun instead of Node.js.
-<!-- If no `node_modules` directory is found in the working directory or above, Bun will abandon Node.js-style module resolution in favor of the `Bun module resolution algorithm`. Under Bun-style module resolution, all packages are _auto-installed_ on the fly into a [global module cache](/docs/install/cache). For full details on this algorithm, refer to [Runtime > Modules](/docs/runtime/modules). -->
+```bash
+$ bun run --bun vite
+```
diff --git a/docs/cli/test.md b/docs/cli/test.md
index dfe78c45b..d505cd6a8 100644
--- a/docs/cli/test.md
+++ b/docs/cli/test.md
@@ -1,4 +1,4 @@
-Bun ships with a fast built-in test runner. Tests are executed with the Bun runtime, and support the following features.
+Bun ships with a fast, built-in, Jest-compatible test runner. Tests are executed with the Bun runtime, and support the following features.
- TypeScript and JSX
- Lifecycle hooks
@@ -7,6 +7,10 @@ Bun ships with a fast built-in test runner. Tests are executed with the Bun runt
- Watch mode with `--watch`
- Script pre-loading with `--preload`
+{% callout %}
+Bun aims for compatibility with Jest, but not everything is implemented. To track compatibility, see [this tracking issue](https://github.com/oven-sh/bun/issues/1825).
+{% /callout %}
+
## Run tests
```bash
@@ -103,7 +107,11 @@ See [Test > Lifecycle](/docs/test/lifecycle) for complete documentation.
## Mocks
-Create mocks with the `mock` function. Mocks are automatically reset between tests.
+{% callout %}
+Module mocking (`jest.mock()`) is not yet supported. Track support for it [here](https://github.com/oven-sh/bun/issues/5394).
+{% /callout %}
+
+Create mock functions with the `mock` function. Mocks are automatically reset between tests.
```ts
import { test, expect, mock } from "bun:test";
@@ -117,11 +125,38 @@ test("random", async () => {
});
```
+Alternatively, you can use `jest.fn()`, it behaves identically.
+
+```ts-diff
+- import { test, expect, mock } from "bun:test";
++ import { test, expect, jest } from "bun:test";
+
+- const random = mock(() => Math.random());
++ const random = jest.fn(() => Math.random());
+```
+
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.
+Snapshots are supported by `bun test`.
+
+```ts
+// example usage of toMatchSnapshot
+import { test, expect } from "bun:test";
+
+test("snapshot", async () => {
+ expect({ a: 1 }).toMatchSnapshot();
+});
+```
+
+To update snapshots, use the `--update-snapshots` flag.
+
+```sh
+$ bun test --update-snapshots
+```
+
+See [Test > Snapshots](/docs/test/snapshots) for complete documentation.
## UI & DOM testing
diff --git a/docs/cli/update.md b/docs/cli/update.md
new file mode 100644
index 000000000..dfda37f01
--- /dev/null
+++ b/docs/cli/update.md
@@ -0,0 +1,7 @@
+To update all dependencies to the latest version _that's compatible with the version range specified in your `package.json`_:
+
+```sh
+$ bun update
+```
+
+This will not edit your `package.json`. There's currently no command to force-update all dependencies to the latest version regardless version ranges.
diff --git a/docs/dev/css.md b/docs/dev/css.md
index a74f5d1ea..53ebc6c06 100644
--- a/docs/dev/css.md
+++ b/docs/dev/css.md
@@ -49,7 +49,7 @@ This is useful for preventing flash of unstyled content.
## With `bun bun`
-Bun bundles `.css` files imported via `@import` into a single file. It doesn’t autoprefix or minify CSS today. Multiple `.css` files imported in one JavaScript file will _not_ be bundled into one file. You’ll have to import those from a `.css` file.
+Bun bundles `.css` files imported via `@import` into a single file. It doesn’t auto-prefix or minify CSS today. Multiple `.css` files imported in one JavaScript file will _not_ be bundled into one file. You’ll have to import those from a `.css` file.
This input:
diff --git a/docs/dev/frameworks.md b/docs/dev/frameworks.md
deleted file mode 100644
index 9af7fc45b..000000000
--- a/docs/dev/frameworks.md
+++ /dev/null
@@ -1,151 +0,0 @@
-{% callout %}
-**Warning** — This will soon have breaking changes. It was designed when Bun was mostly a dev server and not a JavaScript runtime.
-{% /callout %}
-
-Frameworks preconfigure Bun to enable developers to use Bun with their existing tooling.
-
-Frameworks are configured via the `framework` object in the `package.json` of the framework (not in the application’s `package.json`):
-
-Here is an example:
-
-```json
-{
- "name": "bun-framework-next",
- "version": "0.0.0-18",
- "description": "",
- "framework": {
- "displayName": "Next.js",
- "static": "public",
- "assetPrefix": "_next/",
- "router": {
- "dir": ["pages", "src/pages"],
- "extensions": [".js", ".ts", ".tsx", ".jsx"]
- },
- "css": "onimportcss",
- "development": {
- "client": "client.development.tsx",
- "fallback": "fallback.development.tsx",
- "server": "server.development.tsx",
- "css": "onimportcss",
- "define": {
- "client": {
- ".env": "NEXT_PUBLIC_",
- "defaults": {
- "process.env.__NEXT_TRAILING_SLASH": "false",
- "process.env.NODE_ENV": "\"development\"",
- "process.env.__NEXT_ROUTER_BASEPATH": "''",
- "process.env.__NEXT_SCROLL_RESTORATION": "false",
- "process.env.__NEXT_I18N_SUPPORT": "false",
- "process.env.__NEXT_HAS_REWRITES": "false",
- "process.env.__NEXT_ANALYTICS_ID": "null",
- "process.env.__NEXT_OPTIMIZE_CSS": "false",
- "process.env.__NEXT_CROSS_ORIGIN": "''",
- "process.env.__NEXT_STRICT_MODE": "false",
- "process.env.__NEXT_IMAGE_OPTS": "null"
- }
- },
- "server": {
- ".env": "NEXT_",
- "defaults": {
- "process.env.__NEXT_TRAILING_SLASH": "false",
- "process.env.__NEXT_OPTIMIZE_FONTS": "false",
- "process.env.NODE_ENV": "\"development\"",
- "process.env.__NEXT_OPTIMIZE_IMAGES": "false",
- "process.env.__NEXT_OPTIMIZE_CSS": "false",
- "process.env.__NEXT_ROUTER_BASEPATH": "''",
- "process.env.__NEXT_SCROLL_RESTORATION": "false",
- "process.env.__NEXT_I18N_SUPPORT": "false",
- "process.env.__NEXT_HAS_REWRITES": "false",
- "process.env.__NEXT_ANALYTICS_ID": "null",
- "process.env.__NEXT_CROSS_ORIGIN": "''",
- "process.env.__NEXT_STRICT_MODE": "false",
- "process.env.__NEXT_IMAGE_OPTS": "null",
- "global": "globalThis",
- "window": "undefined"
- }
- }
- }
- }
- }
-}
-```
-
-Here are type definitions:
-
-```ts
-type Framework = Environment & {
- // This changes what’s printed in the console on load
- displayName?: string;
-
- // This allows a prefix to be added (and ignored) to requests.
- // Useful for integrating an existing framework that expects internal routes to have a prefix
- // e.g. "_next"
- assetPrefix?: string;
-
- development?: Environment;
- production?: Environment;
-
- // The directory used for serving unmodified assets like fonts and images
- // Defaults to "public" if exists, else "static", else disabled.
- static?: string;
-
- // "onimportcss" disables the automatic "onimportcss" feature
- // If the framework does routing, you may want to handle CSS manually
- // "facade" removes CSS imports from JavaScript files,
- // and replaces an imported object with a proxy that mimics CSS module support without doing any class renaming.
- css?: "onimportcss" | "facade";
-
- // Bun's filesystem router
- router?: Router;
-};
-
-type Define = {
- // By passing ".env", Bun will automatically load .env.local, .env.development, and .env if exists in the project root
- // (in addition to the processes’ environment variables)
- // When "*", all environment variables will be automatically injected into the JavaScript loader
- // When a string like "NEXT_PUBLIC_", only environment variables starting with that prefix will be injected
-
- ".env": string | "*";
-
- // These environment variables will be injected into the JavaScript loader
- // These are the equivalent of Webpack’s resolve.alias and esbuild’s --define.
- // Values are parsed as JSON, so they must be valid JSON. The only exception is '' is a valid string, to simplify writing stringified JSON in JSON.
- // If not set, `process.env.NODE_ENV` will be transformed into "development".
- "defaults": Record<string, string>;
-};
-
-type Environment = {
- // This is a wrapper for the client-side entry point for a route.
- // This allows frameworks to run initialization code on pages.
- client: string;
- // This is a wrapper for the server-side entry point for a route.
- // This allows frameworks to run initialization code on pages.
- server: string;
- // This runs when "server" code fails to load due to an exception.
- fallback: string;
-
- // This is how environment variables and .env is configured.
- define?: Define;
-};
-
-// Bun's filesystem router
-// Currently, Bun supports pages by either an absolute match or a parameter match.
-// pages/index.tsx will be executed on navigation to "/" and "/index"
-// pages/posts/[id].tsx will be executed on navigation to "/posts/123"
-// Routes & parameters are automatically passed to `fallback` and `server`.
-type Router = {
- // This determines the folder to look for pages
- dir: string[];
-
- // These are the allowed file extensions for pages.
- extensions?: string[];
-};
-```
-
-To use a framework, you pass `bun bun --use package-name`.
-
-Your framework’s `package.json` `name` should start with `bun-framework-`. This is so that people can type something like `bun bun --use next` and it will check `bun-framework-next` first. This is similar to how Babel plugins tend to start with `babel-plugin-`.
-
-For developing frameworks, you can also do `bun bun --use ./relative-path-to-framework`.
-
-If you’re interested in adding a framework integration, please reach out. There’s a lot here, and it’s not entirely documented yet.
diff --git a/docs/dev/nextjs.md b/docs/dev/nextjs.md
deleted file mode 100644
index 92849c989..000000000
--- a/docs/dev/nextjs.md
+++ /dev/null
@@ -1,33 +0,0 @@
-To create a new Next.js app with bun:
-
-```bash
-$ bun create next ./app
-$ cd app
-$ bun dev # start dev server
-```
-
-To use an existing Next.js app with bun:
-
-```bash
-$ bun add bun-framework-next
-$ echo "framework = 'next'" > bunfig.toml
-$ bun bun # bundle dependencies
-$ bun dev # start dev server
-```
-
-Many of Next.js’ features are supported, but not all.
-
-Here’s what doesn’t work yet:
-
-- `getStaticPaths`
-- same-origin `fetch` inside of `getStaticProps` or `getServerSideProps`
-- locales, zones, `assetPrefix` (workaround: change `--origin \"http://localhost:3000/assetPrefixInhere\"`)
-- `next/image` is polyfilled to a regular `<img src>` tag.
-- `proxy` and anything else in `next.config.js`
-- API routes, middleware (middleware is easier to support, though! Similar SSR API)
-- styled-jsx (technically not Next.js, but often used with it)
-- React Server Components
-
-When using Next.js, Bun automatically reads configuration from `.env.local`, `.env.development` and `.env` (in that order). `process.env.NEXT_PUBLIC_` and `process.env.NEXT_` automatically are replaced via `--define`.
-
-Currently, any time you import new dependencies from `node_modules`, you will need to re-run `bun bun --use next`. This will eventually be automatic.
diff --git a/docs/guides/binary/blob-to-stream.md b/docs/guides/binary/blob-to-stream.md
index 37a916ab3..ff2b3fbe0 100644
--- a/docs/guides/binary/blob-to-stream.md
+++ b/docs/guides/binary/blob-to-stream.md
@@ -2,7 +2,7 @@
name: 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, inluding `.stream()`. This returns `Promise<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<ReadableStream>`.
```ts
const blob = new Blob(["hello world"]);
diff --git a/docs/guides/binary/blob-to-string.md b/docs/guides/binary/blob-to-string.md
index 05692c32e..0b334af66 100644
--- a/docs/guides/binary/blob-to-string.md
+++ b/docs/guides/binary/blob-to-string.md
@@ -2,7 +2,7 @@
name: 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, inluding `.text()`.
+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
const blob = new Blob(["hello world"]);
diff --git a/docs/guides/ecosystem/astro.md b/docs/guides/ecosystem/astro.md
index 6a8a9fa5f..04be12012 100644
--- a/docs/guides/ecosystem/astro.md
+++ b/docs/guides/ecosystem/astro.md
@@ -2,15 +2,15 @@
name: Build an app with Astro and Bun
---
-Initialize a fresh Astro app with `bunx create-astro`. The `create-astro` package detects when you are using `bunx` and will automatically install dependencies using `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
-$ bunx create-astro
+$ bun create astro
╭─────╮ Houston:
│ ◠ ◡ ◠ We're glad to have you on board.
╰─────╯
- astro v2.10.5 Launch sequence initiated.
+ astro v3.1.4 Launch sequence initiated.
dir Where should we create your new project?
./fumbling-field
@@ -55,21 +55,17 @@ By default, Bun will run the dev server with Node.js. To use the Bun runtime ins
```sh
$ bunx --bun astro dev
- 🚀 astro v2.10.5 started in 200ms
+ 🚀 astro v3.1.4 started in 200ms
- ┃ Local http://localhost:3000/
+ ┃ Local http://localhost:4321/
┃ Network use --host to expose
-
-01:48:34 PM [content] Watching src/content/ for changes
-01:48:34 PM [content] Types generated
-01:48:34 PM [astro] update /.astro/types.d.ts
```
---
-Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. Astro will hot-reload your app as you edit your source files.
+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.
-{% image src="https://github.com/vitejs/vite/assets/3084745/bb1d5063-32f4-4598-b33e-50b44a1c4e8a" caption="An Astro starter app running on Bun" %}
+{% image src="https://i.imgur.com/Dswiu6w.png" caption="An Astro v3 starter app running on Bun" %}
---
diff --git a/docs/guides/ecosystem/discordjs.md b/docs/guides/ecosystem/discordjs.md
index 0a70f6f05..ec12a247d 100644
--- a/docs/guides/ecosystem/discordjs.md
+++ b/docs/guides/ecosystem/discordjs.md
@@ -74,4 +74,4 @@ Ready! Logged in as my-bot#1234
---
-You're up and running with a bare-bones Discord.js bot! This is a basic guide to setting up your bot with Bun; we recommend the [official Discord docs](https://discordjs.guide/) for complete information on the `discord.js` API.
+You're up and running with a bare-bones Discord.js bot! This is a basic guide to setting up your bot with Bun; we recommend the [official discord.js docs](https://discordjs.guide/) for complete information on the `discord.js` API.
diff --git a/docs/guides/ecosystem/docker.md b/docs/guides/ecosystem/docker.md
new file mode 100644
index 000000000..26a1eaccd
--- /dev/null
+++ b/docs/guides/ecosystem/docker.md
@@ -0,0 +1,140 @@
+---
+name: Containerize a Bun application with Docker
+---
+
+{% callout %}
+This guide assumes you already have [Docker Desktop](https://www.docker.com/products/docker-desktop/) installed.
+{% /callout %}
+
+[Docker](https://www.docker.com) is a platform for packaging and running an application as a lightweight, portable _container_ that encapsulates all the necessary dependencies.
+
+---
+
+To _containerize_ our application, we define a `Dockerfile`. This file contains a list of instructions to initialize the container, copy our local project files into it, install dependencies, and starts the application.
+
+```docker#Dockerfile
+# use the official Bun image
+# see all versions at https://hub.docker.com/r/oven/bun/tags
+FROM oven/bun:1 as base
+WORKDIR /usr/src/app
+
+# install dependencies into temp directory
+# this will cache them and speed up future builds
+FROM base AS install
+RUN mkdir -p /temp/dev
+COPY package.json bun.lockb /temp/dev/
+RUN cd /temp/dev && bun install --frozen-lockfile
+
+# install with --production (exclude devDependencies)
+RUN mkdir -p /temp/prod
+COPY package.json bun.lockb /temp/prod/
+RUN cd /temp/prod && bun install --frozen-lockfile --production
+
+# copy node_modules from temp directory
+# then copy all (non-ignored) project files into the image
+FROM install AS prerelease
+COPY --from=install /temp/dev/node_modules node_modules
+COPY . .
+
+# [optional] tests & build
+ENV NODE_ENV=production
+RUN bun test
+RUN bun run build
+
+# copy production dependencies and source code into final image
+FROM base AS release
+COPY --from=install /temp/prod/node_modules node_modules
+COPY --from=prerelease /usr/src/app/index.ts .
+COPY --from=prerelease /usr/src/app/package.json .
+
+# run the app
+USER bun
+EXPOSE 3000/tcp
+ENTRYPOINT [ "bun", "run", "index.ts" ]
+```
+
+---
+
+Now that you have your docker image, let's look at `.dockerignore` which has the same syntax as `.gitignore`, here you need to specify the files/directories that must not go in any stage of the docker build. An example for a ignore file is
+
+```txt#.dockerignore
+node_modules
+Dockerfile*
+docker-compose*
+.dockerignore
+.git
+.gitignore
+README.md
+LICENSE
+.vscode
+Makefile
+helm-charts
+.env
+.editorconfig
+.idea
+coverage*
+```
+
+---
+
+We'll now use `docker build` to convert this `Dockerfile` into a _Docker image_, is a self-contained template containing all the dependencies and configuration required to run the application.
+
+The `-t` flag lets us specify a name for the image, and `--pull` tells Docker to automatically download the latest version of the base image (`oven/bun`). The initial build will take longer, as Docker will download all the base images and dependencies.
+
+```bash
+$ docker build --pull -t bun-hello-world .
+[+] Building 0.9s (21/21) FINISHED
+ => [internal] load build definition from Dockerfile 0.0s
+ => => transferring dockerfile: 37B 0.0s
+ => [internal] load .dockerignore 0.0s
+ => => transferring context: 35B 0.0s
+ => [internal] load metadata for docker.io/oven/bun:1 0.8s
+ => [auth] oven/bun:pull token for registry-1.docker.io 0.0s
+ => [base 1/2] FROM docker.io/oven/bun:1@sha256:373265748d3cd3624cb3f3ee6004f45b1fc3edbd07a622aeeec17566d2756997 0.0s
+ => [internal] load build context 0.0s
+ => => transferring context: 155B 0.0s
+ # ...lots of commands...
+ => exporting to image 0.0s
+ => => exporting layers 0.0s
+ => => writing image sha256:360663f7fdcd6f11e8e94761d5592e2e4dfc8d167f034f15cd5a863d5dc093c4 0.0s
+ => => naming to docker.io/library/bun-hello-world 0.0s
+```
+
+---
+
+We've built a new _Docker image_. Now let's use that image to spin up an actual, running _container_.
+
+We'll use `docker run` to start a new container using the `bun-hello-world` image. It will be run in _detached_ mode (`-d`) and we'll map the container's port 3000 to our local machine's port 3000 (`-p 3000:3000`).
+
+The `run` command prints a string representing the _container ID_.
+
+```sh
+$ docker run -d -p 3000:3000 bun-hello-world
+7f03e212a15ede8644379bce11a13589f563d3909a9640446c5bbefce993678d
+```
+
+---
+
+The container is now running in the background. Visit [localhost:3000](http://localhost:3000). You should see a `Hello, World!` message.
+
+---
+
+To stop the container, we'll use `docker stop <container-id>`.
+
+```sh
+$ docker stop 7f03e212a15ede8644379bce11a13589f563d3909a9640446c5bbefce993678d
+```
+
+---
+
+If you can't find the container ID, you can use `docker ps` to list all running containers.
+
+```sh
+$ docker ps
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+7f03e212a15e bun-hello-world "bun run index.ts" 2 minutes ago Up 2 minutes 0.0.0.0:3000->3000/tcp flamboyant_cerf
+```
+
+---
+
+That's it! Refer to the [Docker documentation](https://docs.docker.com/) for more advanced usage.
diff --git a/docs/guides/ecosystem/elysia.md b/docs/guides/ecosystem/elysia.md
index ae1a8e37b..019686a63 100644
--- a/docs/guides/ecosystem/elysia.md
+++ b/docs/guides/ecosystem/elysia.md
@@ -21,7 +21,7 @@ const app = new Elysia()
.get('/', () => 'Hello Elysia')
.listen(8080)
-console.log(`🦊 Elysia is running at on port ${app.server.port}...`)
+console.log(`🦊 Elysia is running at on port ${app.server?.port}...`)
```
---
diff --git a/docs/guides/ecosystem/hono.md b/docs/guides/ecosystem/hono.md
index 6d928a655..df662973d 100644
--- a/docs/guides/ecosystem/hono.md
+++ b/docs/guides/ecosystem/hono.md
@@ -18,7 +18,7 @@ export default app;
Use `create-hono` to get started with one of Hono's project templates. Select `bun` when prompted for a template.
```bash
-$ bunx create-hono myapp
+$ bun create hono myapp
✔ Which template do you want to use? › bun
cloned honojs/starter#main to /path/to/myapp
✔ Copied project files
diff --git a/docs/guides/ecosystem/nextjs.md b/docs/guides/ecosystem/nextjs.md
index a455eb23e..d8bf337c2 100644
--- a/docs/guides/ecosystem/nextjs.md
+++ b/docs/guides/ecosystem/nextjs.md
@@ -3,7 +3,7 @@ name: Build an app with Next.js and Bun
---
{% callout %}
-Next.js currently relies on Node.js APIs that Bun does not yet implement. The guide below uses Bun to initialize a project and install dependencies, but it uses Node.js to run the dev server.
+The Next.js [App Router](https://nextjs.org/docs/app) currently relies on Node.js APIs that Bun does not yet implement. The guide below uses Bun to initialize a project and install dependencies, but it uses Node.js to run the dev server.
{% /callout %}
---
@@ -11,7 +11,7 @@ Next.js currently relies on Node.js APIs that Bun does not yet implement. The gu
Initialize a Next.js app with `create-next-app`. This automatically installs dependencies using `npm`.
```sh
-$ bunx create-next-app
+$ bun create next-app
✔ What is your project named? … my-app
✔ Would you like to use TypeScript with this project? … No / Yes
✔ Would you like to use ESLint with this project? … No / Yes
@@ -23,7 +23,16 @@ Creating a new Next.js app in /path/to/my-app.
---
-To start the dev server, run `bun run dev` from the project root.
+To start the dev server with Bun, run `bun --bun run dev` from the project root.
+
+```sh
+$ cd my-app
+$ bun --bun run dev
+```
+
+---
+
+To run the dev server with Node.js instead, omit `--bun`.
```sh
$ cd my-app
@@ -32,4 +41,4 @@ $ bun run dev
---
-Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. Any changes you make to `pages/index.tsx` will be hot-reloaded in the browser.
+Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. Any changes you make to `(pages/app)/index.tsx` will be hot-reloaded in the browser.
diff --git a/docs/guides/ecosystem/nuxt.md b/docs/guides/ecosystem/nuxt.md
index c86029dc2..ca42c765b 100644
--- a/docs/guides/ecosystem/nuxt.md
+++ b/docs/guides/ecosystem/nuxt.md
@@ -22,7 +22,7 @@ bun install v1.x (16b4bf34)
---
-To start the dev server, run `bun run dev` from the project root. This will execute the `nuxt dev` command (as defined in the `"dev"` script in `package.json`).
+To start the dev server, run `bun --bun run dev` from the project root. This will execute the `nuxt dev` command (as defined in the `"dev"` script in `package.json`).
{% callout %}
The `nuxt` CLI uses Node.js by default; passing the `--bun` flag forces the dev server to use the Bun runtime instead.
diff --git a/docs/guides/ecosystem/pm2.md b/docs/guides/ecosystem/pm2.md
new file mode 100644
index 000000000..c775c8ca3
--- /dev/null
+++ b/docs/guides/ecosystem/pm2.md
@@ -0,0 +1,54 @@
+---
+name: Run Bun as a daemon with PM2
+---
+
+[PM2](https://pm2.keymetrics.io/) is a popular process manager that manages and runs your applications as daemons (background processes).
+
+It offers features like process monitoring, automatic restarts, and easy scaling. Using a process manager is common when deploying a Bun application on a cloud-hosted virtual private server (VPS), as it:
+
+- Keeps your Node.js application running continuously.
+- Ensure high availability and reliability of your application.
+- Monitor and manage multiple processes with ease.
+- Simplify the deployment process.
+
+---
+
+You can use PM2 with Bun in two ways: as a CLI option or in a configuration file.
+
+### With `--interpreter`
+
+---
+
+To start your application with PM2 and Bun as the interpreter, open your terminal and run the following command:
+
+```bash
+pm2 start --interpreter ~/.bun/bin/bun index.ts
+```
+
+---
+
+### With a configuration file
+
+---
+
+Alternatively, you can create a PM2 configuration file. Create a file named `pm2.config.js` in your project directory and add the following content.
+
+```javascript
+module.exports = {
+ name: "app", // Name of your application
+ script: "index.ts", // Entry point of your application
+ interpreter: "~/.bun/bin/bun", // Path to the Bun interpreter
+};
+```
+
+---
+
+After saving the file, you can start your application with PM2
+
+```bash
+pm2 start pm2.config.js
+```
+
+---
+
+That’s it! Your JavaScript/TypeScript web server is now running as a daemon with PM2 using Bun as the interpreter.
diff --git a/docs/guides/ecosystem/prisma.md b/docs/guides/ecosystem/prisma.md
index e697e2133..af83a47e4 100644
--- a/docs/guides/ecosystem/prisma.md
+++ b/docs/guides/ecosystem/prisma.md
@@ -2,20 +2,26 @@
name: Get started using Prisma
---
+{% callout %}
+**Note** — At the moment Prisma needs Node.js to be installed to run certain generation code. Make sure Node.js is installed in the environment where you're running `bunx prisma` commands.
+{% /callout %}
+
+---
+
Prisma works out of the box with Bun. First, create a directory and initialize it with `bun init`.
```bash
-mkdir prisma-app
-cd prisma-app
-bun init
+$ mkdir prisma-app
+$ cd prisma-app
+$ bun init
```
---
-Then add Prisma as a dependency.
+Then install the Prisma CLI (`prisma`) and Prisma Client (`@prisma/client`) as dependencies.
```bash
-bun add prisma
+$ bun add prisma @prisma/client
```
---
@@ -23,7 +29,7 @@ bun add prisma
We'll use the Prisma CLI with `bunx` to initialize our schema and migration directory. For simplicity we'll be using an in-memory SQLite database.
```bash
-bunx prisma init --datasource-provider sqlite
+$ bunx prisma init --datasource-provider sqlite
```
---
@@ -54,14 +60,37 @@ Then generate and run initial migration.
This will generate a `.sql` migration file in `prisma/migrations`, create a new SQLite instance, and execute the migration against the new instance.
```bash
-bunx prisma migrate dev --name init
+$ bunx prisma migrate dev --name init
+Environment variables loaded from .env
+Prisma schema loaded from prisma/schema.prisma
+Datasource "db": SQLite database "dev.db" at "file:./dev.db"
+
+SQLite database dev.db created at file:./dev.db
+
+Applying migration `20230928182242_init`
+
+The following migration(s) have been created and applied from new schema changes:
+
+migrations/
+ └─ 20230928182242_init/
+ └─ migration.sql
+
+Your database is now in sync with your schema.
+
+✔ Generated Prisma Client (v5.3.1) to ./node_modules/@prisma/client in 41ms
```
---
-Prisma automatically generates our _Prisma client_ whenever we execute a new migration. The client provides a fully typed API for reading and writing from our database.
+As indicated in the output, Prisma re-generates our _Prisma client_ whenever we execute a new migration. The client provides a fully typed API for reading and writing from our database. You can manually re-generate the client with the Prisma CLI.
+
+```sh
+$ bunx prisma generate
+```
+
+---
-It can be imported from `@prisma/client`.
+We can import the generated client from `@prisma/client`.
```ts#src/index.ts
import {PrismaClient} from "@prisma/client";
diff --git a/docs/guides/ecosystem/qwik.md b/docs/guides/ecosystem/qwik.md
new file mode 100644
index 000000000..45d3f9c1a
--- /dev/null
+++ b/docs/guides/ecosystem/qwik.md
@@ -0,0 +1,107 @@
+---
+name: Build an app with Qwik and Bun
+---
+
+Initialize a new Qwik app with `bunx create-qwik`.
+
+The `create-qwik` package detects when you are using `bunx` and will automatically install dependencies using `bun`.
+
+```sh
+$ bun create qwik
+
+ ............
+ .::: :--------:.
+ .:::: .:-------:.
+ .:::::. .:-------.
+ ::::::. .:------.
+ ::::::. :-----:
+ ::::::. .:-----.
+ :::::::. .-----.
+ ::::::::.. ---:.
+ .:::::::::. :-:.
+ ..::::::::::::
+ ...::::
+
+
+┌ Let's create a Qwik App ✨ (v1.2.10)
+│
+◇ Where would you like to create your new project? (Use '.' or './' for current directory)
+│ ./my-app
+│
+● Creating new project in /path/to/my-app ... 🐇
+│
+◇ Select a starter
+│ Basic App
+│
+◇ Would you like to install bun dependencies?
+│ Yes
+│
+◇ Initialize a new git repository?
+│ No
+│
+◇ Finishing the install. Wanna hear a joke?
+│ Yes
+│
+○ ────────────────────────────────────────────────────────╮
+│ │
+│ How do you know if there’s an elephant under your bed? │
+│ Your head hits the ceiling! │
+│ │
+├──────────────────────────────────────────────────────────╯
+│
+◇ App Created 🐰
+│
+◇ Installed bun dependencies 📋
+│
+○ Result ─────────────────────────────────────────────╮
+│ │
+│ Success! Project created in my-app directory │
+│ │
+│ Integrations? Add Netlify, Cloudflare, Tailwind... │
+│ bun qwik add │
+│ │
+│ Relevant docs: │
+│ https://qwik.builder.io/docs/getting-started/ │
+│ │
+│ Questions? Start the conversation at: │
+│ https://qwik.builder.io/chat │
+│ https://twitter.com/QwikDev │
+│ │
+│ Presentations, Podcasts and Videos: │
+│ https://qwik.builder.io/media/ │
+│ │
+│ Next steps: │
+│ cd my-app │
+│ bun start │
+│ │
+│ │
+├──────────────────────────────────────────────────────╯
+│
+└ Happy coding! 🎉
+
+```
+
+---
+
+Run `bun run dev` to start the development server.
+
+```sh
+$ bun run dev
+ $ vite--mode ssr
+
+ VITE v4.4.7 ready in 1190 ms
+
+ ➜ Local: http://localhost:5173/
+ ➜ Network: use --host to expose
+ ➜ press h to show help
+```
+
+---
+
+Open [http://localhost:5173](http://localhost:5173) with your browser to see the result. Qwik will hot-reload your app as you edit your source files.
+
+{% image src="https://github.com/oven-sh/bun/assets/3084745/ec35f2f7-03dd-4c90-851e-fb4ad150bb28" alt="Qwik screenshot" /%}
+
+---
+
+Refer to the [Qwik docs](https://qwik.builder.io/docs/getting-started/) for complete documentation.
diff --git a/docs/guides/ecosystem/react.md b/docs/guides/ecosystem/react.md
index b712e210e..f3c16c153 100644
--- a/docs/guides/ecosystem/react.md
+++ b/docs/guides/ecosystem/react.md
@@ -2,29 +2,48 @@
name: Use React and JSX
---
-React just works with Bun. Bun supports `.jsx` and `.tsx` files out of the box. Bun's internal transpiler converts JSX syntax into vanilla JavaScript before execution.
-
-```tsx#react.tsx
-function Component(props: {message: string}) {
- return (
- <body>
- <h1 style={{color: 'red'}}>{props.message}</h1>
- </body>
- );
-}
-
-console.log(<Component message="Hello world!" />);
+React just works with Bun. Bun supports `.jsx` and `.tsx` files out of the box.
+
+Remember that JSX is just a special syntax for including HTML-like syntax in JavaScript files. It's commonReact uses JSX syntax, as do other React alternatives like [Preact](https://preactjs.com/) and [Solid](https://www.solidjs.com/). Bun's internal transpiler converts JSX syntax into vanilla JavaScript before execution.
+
+---
+
+Bun _assumes_ you're using React (unless you [configure it otherwise](/docs/runtime/bunfig#jsx)) so a line like this:
+
+```
+const element = <h1>Hello, world!</h1>;
```
---
-Bun implements special logging for JSX to make debugging easier.
+is internally converted into something like this:
+
+```ts
+// jsxDEV
+import { jsx } from "react/jsx-dev-runtime";
+
+const element = jsx("h1", { children: "Hello, world!" });
+```
+
+---
+
+This code requires `react` to run, so make sure you you've installed React.
```bash
-$ bun run react.tsx
+$ bun install react
+```
+
+---
+
+Bun implements special logging for JSX components to make debugging easier.
+
+```bash
+$ bun run log-my-component.tsx
<Component message="Hello world!" />
```
---
+As far as "official support" for React goes, that's it. React is a library like any other, and Bun can run that library. Bun is not a framework, so you should use a framework like [Vite](https://vitejs.dev/) to build an app with server-side rendering and hot reloading in the browser.
+
Refer to [Runtime > JSX](/docs/runtime/jsx) for complete documentation on configuring JSX.
diff --git a/docs/guides/ecosystem/remix.md b/docs/guides/ecosystem/remix.md
index ee6185294..5adf648ec 100644
--- a/docs/guides/ecosystem/remix.md
+++ b/docs/guides/ecosystem/remix.md
@@ -3,7 +3,7 @@ name: Build an app with Remix and Bun
---
{% callout %}
-Remix currently relies on Node.js APIs that Bun does not yet implement. The guide below uses Bun to initialize a project and install dependencies, but it uses Node.js to run the dev server.
+Currently the Remix development server (`remix dev`) relies on Node.js APIs that Bun does not yet implement. The guide below uses Bun to initialize a project and install dependencies, but it uses Node.js to run the dev server.
{% /callout %}
---
@@ -11,14 +11,14 @@ Remix currently relies on Node.js APIs that Bun does not yet implement. The guid
Initialize a Remix app with `create-remix`.
```sh
-$ bunx create-remix
+$ bun create remix
remix v1.19.3 💿 Let's build a better website...
dir Where should we create your new project?
./my-app
- ◼ Using basic template See https://remix.run/docs/pages/templates for more
+ ◼ Using basic template See https://remix.run/docs/en/main/guides/templates#templates for more
✔ Template copied
git Initialize a new git repository?
@@ -58,3 +58,21 @@ $ bun run dev
Open [http://localhost:3000](http://localhost:3000) to see the app. Any changes you make to `app/routes/_index.tsx` will be hot-reloaded in the browser.
{% image src="https://github.com/oven-sh/bun/assets/3084745/c26f1059-a5d4-4c0b-9a88-d9902472fd77" caption="Remix app running on localhost" /%}
+
+---
+
+To build and start your app, run `bun run build` then `bun run start` from the project root.
+
+```sh
+$ bun run build
+ $ remix build
+ info building... (NODE_ENV=production)
+ info built (158ms)
+$ bun start
+ $ remix-serve ./build/index.js
+ [remix-serve] http://localhost:3000 (http://192.168.86.237:3000)
+```
+
+---
+
+Read the [Remix docs](https://remix.run/) for more information on how to build apps with Remix.
diff --git a/docs/guides/ecosystem/solidstart.md b/docs/guides/ecosystem/solidstart.md
index ca2ef471e..fb8d54d91 100644
--- a/docs/guides/ecosystem/solidstart.md
+++ b/docs/guides/ecosystem/solidstart.md
@@ -11,7 +11,7 @@ SolidStart currently relies on Node.js APIs that Bun does not yet implement. The
Initialize a SolidStart app with `create-solid`.
```sh
-$ bunx create-solid my-app
+$ bun create solid my-app
create-solid version 0.2.31
Welcome to the SolidStart setup wizard!
diff --git a/docs/guides/ecosystem/sveltekit.md b/docs/guides/ecosystem/sveltekit.md
index 172b77299..6386673bc 100644
--- a/docs/guides/ecosystem/sveltekit.md
+++ b/docs/guides/ecosystem/sveltekit.md
@@ -2,10 +2,10 @@
name: Build an app with SvelteKit and Bun
---
-Use `bunx` to scaffold your app with the `create-svelte` CLI. Answer the prompts to select a template and set up your development environment.
+Use `bun create` to scaffold your app with the `svelte` package. Answer the prompts to select a template and set up your development environment.
```sh
-$ bunx create-svelte my-app
+$ bun create svelte@latest my-app
┌ Welcome to SvelteKit!
◇ Which Svelte app template?
diff --git a/docs/guides/ecosystem/systemd.md b/docs/guides/ecosystem/systemd.md
new file mode 100644
index 000000000..c22fc9ae2
--- /dev/null
+++ b/docs/guides/ecosystem/systemd.md
@@ -0,0 +1,113 @@
+---
+name: Run Bun as a daemon with systemd
+---
+
+[systemd](https://systemd.io) is an init system and service manager for Linux operating systems that manages the startup and control of system processes and services.
+
+<!-- systemd provides aggressive parallelization capabilities, uses socket and D-Bus activation for starting services, offers on-demand starting of daemons, keeps track of processes using Linux control groups, maintains mount and auto mount points, and implements an elaborate transactional dependency-based service control logic. systemd supports SysV and LSB init scripts and works as a replacement for sysvinit. -->
+
+<!-- Other parts include a logging daemon, utilities to control basic system configuration like the hostname, date, locale, maintain a list of logged-in users and running containers and virtual machines, system accounts, runtime directories and settings, and daemons to manage simple network configuration, network time synchronization, log forwarding, and name resolution. -->
+
+---
+
+To run a Bun application as a daemon using **systemd** you'll need to create a _service file_ in `/lib/systemd/system/`.
+
+```sh
+$ cd /lib/systemd/system
+$ touch my-app.service
+```
+
+---
+
+Here is a typical service file that runs an application on system start. You can use this as a template for your own service. Replace `YOUR_USER` with the name of the user you want to run the application as. To run as `root`, replace `YOUR_USER` with `root`, though this is generally not recommended for security reasons.
+
+Refer to the [systemd documentation](https://www.freedesktop.org/software/systemd/man/systemd.service.html) for more information on each setting.
+
+```ini#my-app.service
+[Unit]
+# describe the app
+Description=My App
+# start the app after the network is available
+After=network.target
+
+[Service]
+# usually you'll use 'simple'
+# one of https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type=
+Type=simple
+# which user to use when starting the app
+User=YOUR_USER
+# path to your application's root directory
+WorkingDirectory=/home/YOUR_USER/path/to/my-app
+# the command to start the app
+# requires absolute paths
+ExecStart=/home/YOUR_USER/.bun/bin/bun run index.ts
+# restart policy
+# one of {no|on-success|on-failure|on-abnormal|on-watchdog|on-abort|always}
+Restart=always
+
+[Install]
+# start the app automatically
+WantedBy=multi-user.target
+```
+
+---
+
+If your application starts a webserver, note that non-`root` users are not able to listen on ports 80 or 443 by default. To permanently allow Bun to listen on these ports when executed by a non-`root` user, use the following command. This step isn't necessary when running as `root`.
+
+```bash
+$ sudo setcap CAP_NET_BIND_SERVICE=+eip ~/.bun/bin/bun
+```
+
+---
+
+With the service file configured, you can now _enable_ the service. Once enabled, it will start automatically on reboot. This requires `sudo` permissions.
+
+```bash
+$ sudo systemctl enable my-app
+```
+
+---
+
+To start the service without rebooting, you can manually _start_ it.
+
+```bash
+$ sudo systemctl start my-app
+```
+
+---
+
+Check the status of your application with `systemctl status`. If you've started your app successfully, you should see something like this:
+
+```bash
+$ sudo systemctl status my-app
+● my-app.service - My App
+ Loaded: loaded (/lib/systemd/system/my-app.service; enabled; preset: enabled)
+ Active: active (running) since Thu 2023-10-12 11:34:08 UTC; 1h 8min ago
+ Main PID: 309641 (bun)
+ Tasks: 3 (limit: 503)
+ Memory: 40.9M
+ CPU: 1.093s
+ CGroup: /system.slice/my-app.service
+ └─309641 /home/YOUR_USER/.bun/bin/bun run /home/YOUR_USER/application/index.ts
+```
+
+---
+
+To update the service, edit the contents of the service file, then reload the daemon.
+
+```bash
+$ sudo systemctl daemon-reload
+```
+
+---
+
+For a complete guide on the service unit configuration, you can check [this page](https://www.freedesktop.org/software/systemd/man/systemd.service.html). Or refer to this cheatsheet of common commands:
+
+```bash
+$ sudo systemctl daemon-reload # tell systemd that some files got changed
+$ sudo systemctl enable my-app # enable the app (to allow auto-start)
+$ sudo systemctl disable my-app # disable the app (turns off auto-start)
+$ sudo systemctl start my-app # start the app if is stopped
+$ sudo systemctl stop my-app # stop the app
+$ sudo systemctl restart my-app # restart the app
+```
diff --git a/docs/guides/ecosystem/vite.md b/docs/guides/ecosystem/vite.md
index 3cad145f9..cf77e7249 100644
--- a/docs/guides/ecosystem/vite.md
+++ b/docs/guides/ecosystem/vite.md
@@ -11,7 +11,7 @@ While Vite currently works with Bun, it has not been heavily optimized, nor has
Vite works out of the box with Bun. Get started with one of Vite's templates.
```bash
-$ bunx create-vite my-app
+$ bun create vite my-app
✔ Select a framework: › React
✔ Select a variant: › TypeScript + SWC
Scaffolding project in /path/to/my-app...
@@ -30,8 +30,7 @@ bun install
Start the development server with the `vite` CLI using `bunx`.
-The `--bun` flag tells Bun to run Vite's CLI using `bun` instead of `node`; by default Bun respects Vite's `#!/usr/bin/env node` [shebang line](<https://en.wikipedia.org/wiki/Shebang_(Unix)>). After Bun 1.0 this flag will no longer be necessary.
-
+The `--bun` flag tells Bun to run Vite's CLI using `bun` instead of `node`; by default Bun respects Vite's `#!/usr/bin/env node` [shebang line](<https://en.wikipedia.org/wiki/Shebang_(Unix)>).
```bash
bunx --bun vite
```
diff --git a/docs/guides/http/file-uploads.md b/docs/guides/http/file-uploads.md
index 7cc0e742a..ce23b5d0c 100644
--- a/docs/guides/http/file-uploads.md
+++ b/docs/guides/http/file-uploads.md
@@ -59,7 +59,7 @@ Listening on http://localhost:4000
Our form will send a `POST` request to the `/action` endpoint with the form data. Let's handle that request in our server.
-First we use the [`.formData()`](https://developer.mozilla.org/en-US/docs/Web/API/Request/formData) method on the incoming `Request` to asynchonously parse its contents to a `FormData` instance. Then we can use the [`.get()`](https://developer.mozilla.org/en-US/docs/Web/API/FormData/get) method to extract the value of the `name` and `profilePicture` fields. Here `name` corresponds to a `string` and `profilePicture` is a `Blob`.
+First we use the [`.formData()`](https://developer.mozilla.org/en-US/docs/Web/API/Request/formData) method on the incoming `Request` to asynchronously parse its contents to a `FormData` instance. Then we can use the [`.get()`](https://developer.mozilla.org/en-US/docs/Web/API/FormData/get) method to extract the value of the `name` and `profilePicture` fields. Here `name` corresponds to a `string` and `profilePicture` is a `Blob`.
Finally, we write the `Blob` to disk using [`Bun.write()`](/docs/api/file-io#writing-files-bun-write).
diff --git a/docs/guides/install/azure-artifacts.md b/docs/guides/install/azure-artifacts.md
new file mode 100644
index 000000000..659e75fd6
--- /dev/null
+++ b/docs/guides/install/azure-artifacts.md
@@ -0,0 +1,73 @@
+---
+name: Using bun install with an Azure Artifacts npm registry
+---
+
+{% callout %}
+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.
+{% /callout %}
+
+[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
+[install.registry]
+url = "https://pkgs.dev.azure.com/my-azure-artifacts-user/_packaging/my-azure-artifacts-user/npm/registry"
+username = "my-azure-artifacts-user"
+# Bun v1.0.3+ supports using an environment variable here
+password = "$NPM_PASSWORD"
+```
+
+---
+
+Then assign your Azure Personal Access Token to the the `NPM_PASSWORD` environment variable. Bun [automatically reads](/docs/runtime/env) `.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.
+
+```txt#.env
+NPM_PASSWORD=<paste token here>
+```
+
+---
+
+### 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 `<USERNAME>` and `<PASSWORD>` with the apprropriate values.
+
+```bash#shell
+NPM_CONFIG_REGISTRY=https://pkgs.dev.azure.com/my-azure-artifacts-user/_packaging/my-azure-artifacts-user/npm/registry/:username=<USERNAME>:_password=<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.
+
+{% callout %}
+**Tip** — If it ends with `==`, it probably is base64 encoded.
+{% /callout %}
+
+---
+
+To decode a base64-encoded password, open your browser console and run:
+
+```js
+atob("<base64-encoded password>");
+```
+
+---
+
+Alternatively, use the `base64` command line tool, but doing so means it may be saved in your terminal history which is not recommended:
+
+```bash
+echo "base64-encoded-password" | base64 --decode
+```
diff --git a/docs/guides/install/custom-registry.md b/docs/guides/install/custom-registry.md
index 64b3cf76b..12bb3b77f 100644
--- a/docs/guides/install/custom-registry.md
+++ b/docs/guides/install/custom-registry.md
@@ -18,7 +18,7 @@ registry = "https://username:password@registry.npmjs.org"
---
-Your `bunfig.toml` can reference environment variables. Bun automatically loads environment variables from `.env.local`, `.env.[NODE_ENV]`, and `.env`. See [Docs > Environment variables](/docs/cli/run#environment-variables) for more information.
+Your `bunfig.toml` can reference environment variables. Bun automatically loads environment variables from `.env.local`, `.env.[NODE_ENV]`, and `.env`. See [Docs > Environment variables](/docs/runtime/env) for more information.
```toml#bunfig.toml
[install]
diff --git a/docs/guides/install/jfrog-artifactory.md b/docs/guides/install/jfrog-artifactory.md
new file mode 100644
index 000000000..e4872982b
--- /dev/null
+++ b/docs/guides/install/jfrog-artifactory.md
@@ -0,0 +1,28 @@
+---
+name: Using bun install with Artifactory
+---
+
+[JFrog Artifactory](https://jfrog.com/artifactory/) is a package management system for npm, Docker, Maven, NuGet, Ruby, Helm, and more. It allows you to host your own private npm registry, npm packages, and other types of packages as well.
+
+To use it with `bun install`, add a `bunfig.toml` file to your project with the following contents:
+
+---
+
+### Configure with bunfig.toml
+
+Make sure to replace `MY_SUBDOMAIN` with your JFrog Artifactory subdomain, such as `jarred1234` and MY_TOKEN with your JFrog Artifactory token.
+
+```toml#bunfig.toml
+[install.registry]
+url = "https://MY_SUBDOMAIN.jfrog.io/artifactory/api/npm/npm/_auth=MY_TOKEN"
+# Bun v1.0.3+ supports using an environment variable here
+# url = "$NPM_CONFIG_REGISTRY"
+```
+
+---
+
+### Configure with `$NPM_CONFIG_REGISTRY`
+
+Like with npm, you can use the `NPM_CONFIG_REGISTRY` environment variable to configure JFrog Artifactory with bun install.
+
+---
diff --git a/docs/guides/install/registry-scope.md b/docs/guides/install/registry-scope.md
index 48f7dee79..aade23116 100644
--- a/docs/guides/install/registry-scope.md
+++ b/docs/guides/install/registry-scope.md
@@ -11,7 +11,11 @@ Bun does not read `.npmrc` files; instead private registries are configured via
# as an object with username/password
# you can reference environment variables
-"@myorg2" = { username = "myusername", password = "$npm_pass", url = "https://registry.myorg.com/" }
+"@myorg2" = {
+ username = "myusername",
+ password = "$npm_pass",
+ url = "https://registry.myorg.com/"
+}
# as an object with token
"@myorg3" = { token = "$npm_token", url = "https://registry.myorg.com/" }
@@ -20,7 +24,7 @@ Bun does not read `.npmrc` files; instead private registries are configured via
---
-Your `bunfig.toml` can reference environment variables. Bun automatically loads environment variables from `.env.local`, `.env.[NODE_ENV]`, and `.env`. See [Docs > Environment variables](/docs/cli/run#environment-variables) for more information.
+Your `bunfig.toml` can reference environment variables. Bun automatically loads environment variables from `.env.local`, `.env.[NODE_ENV]`, and `.env`. See [Docs > Environment variables](/docs/runtime/env) for more information.
```toml#bunfig.toml
[install.scopes]
diff --git a/docs/guides/install/trusted.md b/docs/guides/install/trusted.md
new file mode 100644
index 000000000..0c1ac6362
--- /dev/null
+++ b/docs/guides/install/trusted.md
@@ -0,0 +1,50 @@
+---
+name: Add a trusted dependency
+---
+
+Unlike other npm clients, Bun does not execute arbitrary lifecycle scripts for installed dependencies, such as `postinstall` and `node-gyp` builds. These scripts represent a potential security risk, as they can execute arbitrary code on your machine.
+
+{% callout %}
+Soon, Bun will include a built-in allow-list that automatically allows lifecycle scripts to be run by popular packages that are known to be safe. This is still under development.
+{% /callout %}
+
+---
+
+If you are seeing one of the following errors, you are probably trying to use a package that uses `postinstall` to work properly:
+
+- `error: could not determine executable to run for package`
+- `InvalidExe`
+
+---
+
+To tell Bun to allow lifecycle scripts for a particular package, add the package to `trustedDependencies` in your package.json.
+
+Note that this only allows lifecycle scripts for the specific package listed in `trustedDependencies`, _not_ the dependencies of that dependency!
+
+<!-- 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. -->
+
+```json-diff
+ {
+ "name": "my-app",
+ "version": "1.0.0",
++ "trustedDependencies": ["my-trusted-package"]
+ }
+```
+
+---
+
+Once this is added, run a fresh install. Bun will re-install your dependencies and properly install
+
+```sh
+$ rm -rf node_modules
+$ rm bun.lockb
+$ bun install
+```
+
+---
+
+Note that this only allows lifecycle scripts for the specific package listed in `trustedDependencies`, _not_ the dependencies of that dependency!
+
+---
+
+See [Docs > Package manager > Trusted dependencies](/docs/install/lifecycle) for complete documentation of trusted dependencies.
diff --git a/docs/guides/install/workspaces.md b/docs/guides/install/workspaces.md
index f87c1e337..b271a33b0 100644
--- a/docs/guides/install/workspaces.md
+++ b/docs/guides/install/workspaces.md
@@ -4,6 +4,8 @@ name: Configuring a monorepo using workspaces
Bun's package manager supports npm `"workspaces"`. This allows you to split a codebase into multiple distinct "packages" that live in the same repository, can depend on each other, and (when possible) share a `node_modules` directory.
+Clone [this sample project](https://github.com/colinhacks/bun-workspaces) to experiment with workspaces.
+
---
The root `package.json` should not contain any `"dependencies"`, `"devDependencies"`, etc. Each individual package should be self-contained and declare its own dependencies. Similarly, it's conventional to declare `"private": true` to avoid accidentally publishing the root package to `npm`.
@@ -35,13 +37,13 @@ It's common to place all packages in a `packages` directory. The `"workspaces"`
---
-To add one workspace as a dependency of another, modify its `package.json`. Here we're adding `stuff-a` as a dependency of `stuff-b`.
+To add dependencies between workspaces, use the `"workspace:*"` syntax. Here we're adding `stuff-a` as a dependency of `stuff-b`.
-```json#packages/stuff-b/package.json
+```json-diff#packages/stuff-b/package.json
{
"name": "stuff-b",
"dependencies": {
-+ "stuff-a": "*"
++ "stuff-a": "workspace:*"
}
}
```
diff --git a/docs/guides/process/ipc.md b/docs/guides/process/ipc.md
new file mode 100644
index 000000000..af029a524
--- /dev/null
+++ b/docs/guides/process/ipc.md
@@ -0,0 +1,66 @@
+---
+name: Spawn a child process and communicate using IPC
+---
+
+Use [`Bun.spawn()`](/docs/api/spawn) to spawn a child process. When spawning a second `bun` process, you can open a direct inter-process communication (IPC) channel between the two processes.
+
+{%callout%}
+**Note** — This API is only compatible with other `bun` processes. Use `process.execPath` to get a path to the currently running `bun` executable.
+{%/callout%}
+
+```ts#parent.ts
+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
+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
+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);
+});
+```
+
+---
+
+All messages are serialized using the JSC `serialize` API, which allows for the same set of [transferrable types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Transferable_objects) supported by `postMessage` and `structuredClone`, including strings, typed arrays, streams, and objects.
+
+```ts#child.ts
+// send a string
+process.send("Hello from child as string");
+
+// send an object
+process.send({ message: "Hello from child as object" });
+```
+
+---
+
+See [Docs > API > Child processes](/docs/api/spawn) for complete documentation.
diff --git a/docs/guides/read-file/exists.md b/docs/guides/read-file/exists.md
index fd6cbbf9a..0359f5728 100644
--- a/docs/guides/read-file/exists.md
+++ b/docs/guides/read-file/exists.md
@@ -8,7 +8,7 @@ The `Bun.file()` function accepts a path and returns a `BunFile` instance. Use t
const path = "/path/to/package.json";
const file = Bun.file(path);
-file.exists(); // boolean;
+await file.exists(); // boolean;
```
---
diff --git a/docs/guides/read-file/stream.md b/docs/guides/read-file/stream.md
index ac4bd9e2f..bc54af2ce 100644
--- a/docs/guides/read-file/stream.md
+++ b/docs/guides/read-file/stream.md
@@ -8,7 +8,7 @@ The `Bun.file()` function accepts a path and returns a `BunFile` instance. The `
const path = "/path/to/package.json";
const file = Bun.file(path);
-const stream = await file.stream();
+const stream = file.stream();
```
---
diff --git a/docs/guides/runtime/read-env.md b/docs/guides/runtime/read-env.md
index 512f731dd..7295a6726 100644
--- a/docs/guides/runtime/read-env.md
+++ b/docs/guides/runtime/read-env.md
@@ -29,4 +29,4 @@ FOOBAR=aaaaaa
---
-See [Docs > Runtime > Environment variables](/docs/cli/run#environment-variables) for more information on using environment variables with Bun.
+See [Docs > Runtime > Environment variables](/docs/runtime/env) for more information on using environment variables with Bun.
diff --git a/docs/guides/runtime/set-env.md b/docs/guides/runtime/set-env.md
index 97cac3488..684da940a 100644
--- a/docs/guides/runtime/set-env.md
+++ b/docs/guides/runtime/set-env.md
@@ -34,4 +34,4 @@ $ FOO=helloworld bun run dev
---
-See [Docs > Runtime > Environment variables](/docs/cli/run#environment-variables) for more information on using environment variables with Bun.
+See [Docs > Runtime > Environment variables](/docs/runtime/env) for more information on using environment variables with Bun.
diff --git a/docs/guides/runtime/tsconfig-paths.md b/docs/guides/runtime/tsconfig-paths.md
index 5c3f591f5..176051d5a 100644
--- a/docs/guides/runtime/tsconfig-paths.md
+++ b/docs/guides/runtime/tsconfig-paths.md
@@ -8,8 +8,8 @@ Bun reads the `paths` field in your `tsconfig.json` to re-write import paths. Th
{
"compilerOptions": {
"paths": {
- "my-custom-name": "zod",
- "@components/*": "./src/components/*"
+ "my-custom-name": ["zod"],
+ "@components/*": ["./src/components/*"]
}
}
}
diff --git a/docs/guides/runtime/typescript.md b/docs/guides/runtime/typescript.md
new file mode 100644
index 000000000..f6afe02c1
--- /dev/null
+++ b/docs/guides/runtime/typescript.md
@@ -0,0 +1,69 @@
+---
+name: Install TypeScript declarations for Bun
+---
+
+To install TypeScript definitions for Bun's built-in APIs in your project, install `bun-types`.
+
+```sh
+$ bun add -d bun-types # dev dependency
+```
+
+---
+
+Then include `"bun-types"` in the `compilerOptions.types` in your `tsconfig.json`:
+
+```json-diff
+ {
+ "compilerOptions": {
++ "types": ["bun-types"]
+ }
+ }
+```
+
+---
+
+Unfortunately, setting a value for `"types"` means that TypeScript will ignore other global type definitions, including `lib: ["dom"]`. If you need 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" />
+```
+
+---
+
+Below is the full set of recommended `compilerOptions` for a Bun project. With this `tsconfig.json`, you can use top-level await, extensioned or extensionless imports, and JSX.
+
+```jsonc
+{
+ "compilerOptions": {
+ // add Bun type definitions
+ "types": ["bun-types"],
+
+ // enable latest features
+ "lib": ["esnext"],
+ "module": "esnext",
+ "target": "esnext",
+
+ // if TS 5.x+
+ "moduleResolution": "bundler",
+ "noEmit": true,
+ "allowImportingTsExtensions": true,
+ "moduleDetection": "force",
+ // if TS 4.x or earlier
+ // "moduleResolution": "nodenext",
+
+ "jsx": "react-jsx", // support JSX
+ "allowJs": true, // allow importing `.js` from `.ts`
+ "esModuleInterop": true, // allow default imports for CommonJS modules
+
+ // best practices
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "skipLibCheck": true
+ }
+}
+```
+
+---
+
+Refer to [Ecosystem > TypeScript](/docs/runtime/typescript) for a complete guide to TypeScript support in Bun.
diff --git a/docs/guides/runtime/vscode-debugger.md b/docs/guides/runtime/vscode-debugger.md
index 616524c17..fdfdb2f2e 100644
--- a/docs/guides/runtime/vscode-debugger.md
+++ b/docs/guides/runtime/vscode-debugger.md
@@ -2,6 +2,12 @@
name: Debugging Bun with the VS Code extension
---
+{% note %}
+
+VSCode extension support is currently buggy. We recommend the [Web Debugger](https://bun.sh/guides/runtime/web-debugger) for now.
+
+{% /note %}
+
Bun speaks the [WebKit Inspector Protocol](https://github.com/oven-sh/bun/blob/main/packages/bun-vscode/types/jsc.d.ts) so you can debug your code with an interactive debugger.
---
diff --git a/docs/guides/test/happy-dom.md b/docs/guides/test/happy-dom.md
index 9c6728f88..072790929 100644
--- a/docs/guides/test/happy-dom.md
+++ b/docs/guides/test/happy-dom.md
@@ -49,7 +49,7 @@ test("set button text", () => {
---
-With Happy DOM propertly configured, this test runs as expected.
+With Happy DOM properly configured, this test runs as expected.
```sh
$ bun test
diff --git a/docs/guides/test/migrate-from-jest.md b/docs/guides/test/migrate-from-jest.md
new file mode 100644
index 000000000..4adbddc34
--- /dev/null
+++ b/docs/guides/test/migrate-from-jest.md
@@ -0,0 +1,112 @@
+---
+name: Migrate from Jest to Bun's test runner
+---
+
+In many cases, Bun's test runner can run Jest test suites with no code changes. Just run `bun test` instead of `npx jest`, `yarn test`, etc.
+
+```sh-diff
+- $ npx jest
+- $ yarn test
++ $ bun test
+```
+
+---
+
+There's often no need for code changes.
+
+- Bun internally re-writes imports from `@jest/globals` to use the `bun:test` equivalents.
+- If you're relying on Jest to inject `test`, `expect`, etc. as globals, Bun does that too.
+
+But if you'd rather switch to the `bun:test` imports, you can do that too.
+
+```ts-diff
+- import {test, expect} from "@jest/globals";
++ import {test, expect} from "bun:test";
+```
+
+---
+
+Bun implements the vast majority of Jest's matchers, but compatibility isn't 100% yet. Refer to the full compatibility table at [Docs > Test runner > Writing tests](/docs/test/writing#matchers).
+
+Some notable missing features:
+
+- `expect.extend()`
+- `expect().toMatchInlineSnapshot()`
+- `expect().toHaveBeenCalledWith()`
+- `expect().toHaveReturned()`
+
+---
+
+If you're using `testEnvironment: "jsdom"` to run your tests in a browser-like environment, you should follow the [DOM testing with Bun and happy-dom](/guides/test/happy-dom) guide to inject browser APIs into the global scope. This guide relies on [`happy-dom`](https://github.com/capricorn86/happy-dom), which is a leaner and faster alternative to [`jsdom`](https://github.com/jsdom/jsdom).
+
+At the moment jsdom does not work in Bun due to its internal use of V8 APIs. Track support for it [here](https://github.com/oven-sh/bun/issues/3554).
+
+```toml#bunfig.toml
+[test]
+preload = ["./happy-dom.ts"]
+```
+
+---
+
+Replace `bail` in your Jest config with the `--bail` CLI flag.
+
+<!-- ```ts-diff
+- import type {Config} from 'jest';
+-
+- const config: Config = {
+- bail: 3
+- };
+``` -->
+
+```sh-diff
+$ bun test --bail 3
+```
+
+---
+
+Replace `collectCoverage` with the `--coverage` CLI flag.
+
+<!-- ```ts-diff
+- import type {Config} from 'jest';
+-
+- const config: Config = {
+- collectCoverageFrom: [
+- '**/*.{js,jsx}',
+- '!**/node_modules/**',
+- '!**/vendor/**',
+- ],
+- };
+``` -->
+
+```sh
+$ bun test --coverage
+```
+
+---
+
+Replace `testTimeout` with the `--test-timeout` CLI flag.
+
+```sh
+$ bun test --timeout 10000
+```
+
+---
+
+Many other flags become irrelevant or obsolete when using `bun test`.
+
+- `transform` — Buns supports TypeScript & JSX. Other file types can be configured with [Plugins](/docs/runtime/plugins).
+- `extensionsToTreatAsEsm`
+- `haste` — Bun uses it's own internal source maps
+- `watchman`, `watchPlugins`, `watchPathIgnorePatterns` — use `--watch` to run tests in watch mode
+- `verbose` — set `logLevel: "debug"` in [`bunfig.toml`](/docs/runtime/bunfig#loglevel)
+
+---
+
+Settings that aren't mentioned here are not supported or have no equivalent. Please [file a feature request](https://github.com/oven-sh/bun) if something important is missing.
+
+---
+
+See also:
+
+- [Mark a test as a todo](/guides/test/todo-tests)
+- [Docs > Test runner > Writing tests](/docs/test/writing)
diff --git a/docs/guides/test/mock-functions.md b/docs/guides/test/mock-functions.md
index c7e8af411..fbcf03e86 100644
--- a/docs/guides/test/mock-functions.md
+++ b/docs/guides/test/mock-functions.md
@@ -47,7 +47,7 @@ random.mock.results;
These extra properties make it possible to write `expect` assertions about usage of the mock function, including how many times it was called, the arguments, and the return values.
```ts
-import { test, mock } from "bun:test";
+import { test, expect, mock } from "bun:test";
const random = mock((multiplier: number) => multiplier * Math.random());
diff --git a/docs/guides/test/spy-on.md b/docs/guides/test/spy-on.md
index 003c05d96..4d4902f9d 100644
--- a/docs/guides/test/spy-on.md
+++ b/docs/guides/test/spy-on.md
@@ -36,7 +36,7 @@ Once the spy is created, it can be used to write `expect` assertions relating to
+ test("turtles", ()=>{
+ expect(spy).toHaveBeenCalledTimes(0);
+ leo.sayHi("pizza");
-+ expect(spy).toHaveBeenCalledTimes(0);
++ expect(spy).toHaveBeenCalledTimes(1);
+ expect(spy.mock.calls).toEqual([[ "pizza" ]]);
+ })
```
diff --git a/docs/guides/util/entrypoint.md b/docs/guides/util/entrypoint.md
index e53d4c9a1..63d71b630 100644
--- a/docs/guides/util/entrypoint.md
+++ b/docs/guides/util/entrypoint.md
@@ -5,9 +5,9 @@ name: Check if the current file is the entrypoint
Bun provides a handful of module-specific utilities on the [`import.meta`](/docs/api/import-meta) object. Use `import.meta.main` to check if the current file is the entrypoint of the current process.
```ts#index.ts
-if(import.meta.main){
+if (import.meta.main) {
// this file is directly executed with `bun run`
-}else{
+} else {
// this file is being imported by another file
}
```
diff --git a/docs/guides/websocket/context.md b/docs/guides/websocket/context.md
index 9e387d685..8658c5d4b 100644
--- a/docs/guides/websocket/context.md
+++ b/docs/guides/websocket/context.md
@@ -47,7 +47,7 @@ Bun.serve<WebSocketData>({
// use a library to parse cookies
const cookies = parseCookies(req.headers.get("Cookie"));
const token = cookies["X-Token"];
- const user = await getUserFromToken(ws.data.authToken);
+ const user = await getUserFromToken(token);
const upgraded = server.upgrade(req, {
data: {
diff --git a/docs/guides/websocket/simple.md b/docs/guides/websocket/simple.md
index 5aabf2fdf..e1d95ce36 100644
--- a/docs/guides/websocket/simple.md
+++ b/docs/guides/websocket/simple.md
@@ -29,5 +29,5 @@ const server = Bun.serve<{ authToken: string }>({
},
});
-console.log(`Listening on localhost:\${server.port}`);
+console.log(`Listening on ${server.hostname}:${server.port}`);
```
diff --git a/docs/index.md b/docs/index.md
index 0cc294150..3fbb7576d 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -26,7 +26,7 @@ Get started with one of the quick links below, or read on to learn more about Bu
{% arrowbutton href="/docs/installation" text="Install Bun" /%}
{% arrowbutton href="/docs/quickstart" text="Do the quickstart" /%}
{% arrowbutton href="/docs/cli/install" text="Install a package" /%}
-{% arrowbutton href="/docs/templates" text="Use a project template" /%}
+{% arrowbutton href="/docs/cli/bun-create" text="Use a project template" /%}
{% arrowbutton href="/docs/bundler" text="Bundle code for production" /%}
{% arrowbutton href="/docs/api/http" text="Build an HTTP server" /%}
{% arrowbutton href="/docs/api/websockets" text="Build a Websocket server" /%}
@@ -37,11 +37,14 @@ Get started with one of the quick links below, or read on to learn more about Bu
## What is a runtime?
-JavaScript (or, more formally, ECMAScript) is just a _specification_ for a programming language. Anyone can write a JavaScript _engine_ that ingests a valid JavaScript program and executes it. The two most popular engines in use today are V8 (developed by Google) and JavaScriptCore (developed by Apple). Both are open source.
+JavaScript (or, more formally, ECMAScript) is just a _specification_ for a programming language. Anyone can write a JavaScript _engine_ that ingests a valid JavaScript program and executes it. The two most popular engines in use today are V8 (developed by Google)
+and JavaScriptCore (developed by Apple). Both are open source.
+
+But most JavaScript programs don't run in a vacuum. They need a way to access the outside world to perform useful tasks. This is where _runtimes_ come in. They implement additional APIs that are then made available to the JavaScript programs they execute.
### Browsers
-But most JavaScript programs don't run in a vacuum. They need a way to access the outside world to perform useful tasks. This is where _runtimes_ come in. They implement additional APIs that are then made available to the JavaScript programs they execute. Notably, browsers ship with JavaScript runtimes that implement a set of Web-specific APIs that are exposed via the global `window` object. Any JavaScript code executed by the browser can use these APIs to implement interactive or dynamic behavior in the context of the current webpage.
+Notably, browsers ship with JavaScript runtimes that implement a set of Web-specific APIs that are exposed via the global `window` object. Any JavaScript code executed by the browser can use these APIs to implement interactive or dynamic behavior in the context of the current webpage.
<!-- JavaScript runtime that exposes JavaScript engines are designed to run "vanilla" JavaScript programs, but it's often JavaScript _runtimes_ use an engine internally to execute the code and implement additional APIs that are then made available to executed programs.
JavaScript was [initially designed](https://en.wikipedia.org/wiki/JavaScript) as a language to run in web browsers to implement interactivity and dynamic behavior in web pages. Browsers are the first JavaScript runtimes. JavaScript programs that are executed in browsers have access to a set of Web-specific global APIs on the `window` object. -->
diff --git a/docs/install/index.md b/docs/install/index.md
index 540ade9f0..11e0d4fd4 100644
--- a/docs/install/index.md
+++ b/docs/install/index.md
@@ -69,7 +69,7 @@ $ bun install --silent # no logging
```
{% details summary="Configuring behavior" %}
-The default behavior of `bun install` can be configured in `bun.toml`:
+The default behavior of `bun install` can be configured in `bunfig.toml`:
```toml
[install]
@@ -188,7 +188,7 @@ Bun supports a variety of protocols, including [`github`](https://docs.npmjs.com
## Tarball dependencies
-A package name can correspond to a publically hosted `.tgz` file. During `bun install`, Bun will download and install the package from the specified tarball URL, rather than from the package registry.
+A package name can correspond to a publicly hosted `.tgz` file. During `bun install`, Bun will download and install the package from the specified tarball URL, rather than from the package registry.
```json#package.json
{
diff --git a/docs/install/lifecycle.md b/docs/install/lifecycle.md
new file mode 100644
index 000000000..035ead24d
--- /dev/null
+++ b/docs/install/lifecycle.md
@@ -0,0 +1,44 @@
+Packages on `npm` can define _lifecycle scripts_ in their `package.json`. Some of the most common are below, but there are [many others](https://docs.npmjs.com/cli/v10/using-npm/scripts).
+
+- `preinstall`: Runs before the package is installed
+- `postinstall`: Runs after the package is installed
+- `preuninstall`: Runs before the package is uninstalled
+- `prepublishOnly`: Runs before the package is published
+
+These scripts are arbitrary shell commands that the package manager is expected to read and execute at the appropriate time. But executing arbitrary scripts represents a potential security risk, so—unlike other `npm` clients—Bun does not execute arbitrary lifecycle scripts by default.
+
+## `postinstall`
+
+The `postinstall` script is particularly important. It's widely used to build or install platform-specific binaries for packages that are implemented as [native Node.js add-ons](https://nodejs.org/api/addons.html). For example, `node-sass` is a popular package that uses `postinstall` to build a native binary for Sass.
+
+```json
+{
+ "name": "my-app",
+ "version": "1.0.0",
+ "dependencies": {
+ "node-sass": "^6.0.1"
+ }
+}
+```
+
+## `trustedDependencies`
+
+Instead of executing arbitrary scripts, Bun uses a "default-secure" approach. You can add certain packages to an allow list, and Bun will execute lifecycle scripts for those packages. To tell Bun to allow lifecycle scripts for a particular package, add the package name to `trustedDependencies` array in your `package.json`.
+
+```json-diff
+ {
+ "name": "my-app",
+ "version": "1.0.0",
++ "trustedDependencies": ["node-sass"]
+ }
+```
+
+Once added to `trustedDependencies`, install/re-install the package. Bun will read this field and run lifecycle scripts for `my-trusted-package`.
+
+## `--ignore-scripts`
+
+To disable lifecycle scripts for all packages, use the `--no-scripts` flag.
+
+```bash
+$ bun install --no-scripts
+```
diff --git a/docs/install/lockfile.md b/docs/install/lockfile.md
index 599403913..f8e3001ca 100644
--- a/docs/install/lockfile.md
+++ b/docs/install/lockfile.md
@@ -10,30 +10,24 @@ Run `bun install -y` to generate a Yarn-compatible `yarn.lock` (v1) that can be
#### How do I `git diff` Bun's lockfile?
-To add to the global gitattributes file:
-
-- First try `$XDG_CONFIG_HOME/git/attributes`
-- If `$XDG_CONFIG_HOME` is not set, try `~/.config/git/attributes`
-
-For example, on macOS, add the following to `~/.config/git/attributes`:
+Add the following to your local or global `.gitattributes` file:
```
-*.lockb diff=lockb
+*.lockb binary diff=lockb
```
-Then add the following to `~/.gitconfig`:
+Then add the following to you local git config with:
-```
-[diff "lockb"]
- textconv = bun
- binary = true
+```sh
+$ git config diff.lockb.textconv bun
+$ git config diff.lockb.binary true
```
-To only add to the local gitattributes file:
+Or to your global git config (system-wide) with the `--global` option:
```sh
-$ git config diff.lockb.textconv bun
-$ git config diff.lockb.binary true
+$ git config --global diff.lockb.textconv bun
+$ git config --global diff.lockb.binary true
```
**Why this works:**
@@ -85,12 +79,6 @@ print = "yarn"
```toml
[install.lockfile]
-# path to read bun.lockb from
-path = "bun.lockb"
-
-# path to save bun.lockb to
-savePath = "bun.lockb"
-
# whether to save the lockfile to disk
save = true
diff --git a/docs/install/overrides.md b/docs/install/overrides.md
new file mode 100644
index 000000000..f226c35bd
--- /dev/null
+++ b/docs/install/overrides.md
@@ -0,0 +1,73 @@
+Bun supports npm's `"overrides"` and Yarn's `"resolutions"` in `package.json`. These are mechanisms for specifying a version range for _metadependencies_—the dependencies of your dependencies. Refer to [Package manager > Overrides and resolutions](/docs/install/overrides) for complete documentation.
+
+```json-diff#package.json
+ {
+ "name": "my-app",
+ "dependencies": {
+ "foo": "^2.0.0"
+ },
++ "overrides": {
++ "bar": "~4.4.0"
++ }
+ }
+```
+
+By default, Bun will install the latest version of all dependencies and metadependencies, according to the ranges specified in each package's `package.json`. Let's say you have a project with one dependency, `foo`, which in turn has a dependency on `bar`. This means `bar` is a _metadependency_ of our project.
+
+```json#package.json
+{
+ "name": "my-app",
+ "dependencies": {
+ "foo": "^2.0.0"
+ }
+}
+```
+
+When you run `bun install`, Bun will install the latest versions of each package.
+
+```
+# tree layout of node_modules
+node_modules
+├── foo@1.2.3
+└── bar@4.5.6
+```
+
+But what if a security vulnerability was introduced in `bar@4.5.6`? We may want a way to pin `bar` to an older version that doesn't have the vulerability. This is where `"overrides"`/`"resolutions"` come in.
+
+## `"overrides"`
+
+Add `bar` to the `"overrides"` field in `package.json`. Bun will defer to the specified version range when determining which version of `bar` to install, whether it's a dependency or a metadependency.
+
+{% callout %}
+**Note** — Bun currently only supports top-level `"overrides"`. [Nested overrides](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#overrides) are not supported.
+{% /callout %}
+
+```json-diff#package.json
+ {
+ "name": "my-app",
+ "dependencies": {
+ "foo": "^2.0.0"
+ },
++ "overrides": {
++ "bar": "~4.4.0"
++ }
+ }
+```
+
+## `"resolutions"`
+
+The syntax is similar for `"resolutions"`, which is Yarn's alternative to `"overrides"`. Bun supports this feature to make migration from Yarn easier.
+
+As with `"overrides"`, _nested resolutions_ are not currently supported.
+
+```json-diff#package.json
+ {
+ "name": "my-app",
+ "dependencies": {
+ "foo": "^2.0.0"
+ },
++ "resolutions": {
++ "bar": "~4.4.0"
++ }
+ }
+```
diff --git a/docs/install/workspaces.md b/docs/install/workspaces.md
index f2a45048a..079ef7dd4 100644
--- a/docs/install/workspaces.md
+++ b/docs/install/workspaces.md
@@ -1,12 +1,39 @@
Bun supports [`workspaces`](https://docs.npmjs.com/cli/v9/using-npm/workspaces?v=true#description) in `package.json`. Workspaces make it easy to develop complex software as a _monorepo_ consisting of several independent packages.
-To try it, specify a list of sub-packages in the `workspaces` field of your `package.json`; it's conventional to place these sub-packages in a directory called `packages`.
+It's common for a monorepo to have the following structure:
+
+```
+tree
+<root>
+├── README.md
+├── bun.lockb
+├── package.json
+├── tsconfig.json
+└── packages
+    ├── pkg-a
+    │   ├── index.ts
+    │   ├── package.json
+    │   └── tsconfig.json
+    ├── pkg-b
+    │   ├── index.ts
+    │   ├── package.json
+    │   └── tsconfig.json
+    └── pkg-c
+    ├── index.ts
+    ├── package.json
+    └── tsconfig.json
+```
+
+In the root `package.json`, the `"workspaces"` key is used to indicate which subdirectories should be considered packages/workspaces within the monorepo. It conventional to place all the workspace in a directory called `packages`.
```json
{
"name": "my-project",
"version": "1.0.0",
- "workspaces": ["packages/*"]
+ "workspaces": ["packages/*"],
+ "devDependencies": {
+ "example-package-in-monorepo": "workspace:*"
+ }
}
```
@@ -14,9 +41,25 @@ To try it, specify a list of sub-packages in the `workspaces` field of your `pac
**Glob support** — Bun supports simple `<directory>/*` globs in `"workspaces"`. Full glob syntax (e.g. `**` and `?`) is not yet supported.
{% /callout %}
-This has a couple major benefits.
+Each workspace has it's own `package.json` When referencing other packages in the monorepo, use `"workspace:*"` as the version field in your `package.json`.
+
+```json
+{
+ "name": "pkg-a",
+ "version": "1.0.0",
+ "dependencies": {
+ "pkg-b": "workspace:*"
+ }
+}
+```
+
+{% callout %}
+**Version support** — Bun supports simple `workspace:*` versions in `"dependencies"`. Full version syntax (e.g. `workspace:^*`) is not yet supported.
+{% /callout %}
+
+Workspaces have a couple major benefits.
-- **Code can be split into logical parts.** If one package relies on another, you can simply add it as a dependency with `bun add`. If package `b` depends on `a`, `bun install` will symlink your local `packages/a` directory into the `node_modules` folder of `b`, instead of trying to download it from the npm registry.
+- **Code can be split into logical parts.** If one package relies on another, you can simply add it as a dependency in `package.json`. If package `b` depends on `a`, `bun install` will install your local `packages/a` directory into `node_modules` instead of downloading it from the npm registry.
- **Dependencies can be de-duplicated.** If `a` and `b` share a common dependency, it will be _hoisted_ to the root `node_modules` directory. This reduces redundant disk usage and minimizes "dependency hell" issues associated with having multiple versions of a package installed simultaneously.
{% callout %}
diff --git a/docs/installation.md b/docs/installation.md
index ad6e31c8f..6aa51737a 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -1,15 +1,20 @@
Bun ships as a single executable that can be installed a few different ways.
-## macOS and Linux
+## Installing
+
+### macOS and Linux
{% callout %}
-**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.
+**Linux users** — The `unzip` package is required to install Bun. Use `sudo apt install unzip` to install `unzip` package.
+Kernel version 5.6 or higher is strongly recommended, but the minimum is 5.1. Use `uname -r` to check Kernel version.
{% /callout %}
{% codetabs %}
```bash#macOS/Linux_(curl)
$ curl -fsSL https://bun.sh/install | bash # for macOS, Linux, and WSL
+# to install a specific version
+$ curl -fsSL https://bun.sh/install | bash -s "bun-v1.0.0"
```
```bash#NPM
@@ -32,7 +37,7 @@ $ proto install bun
{% /codetabs %}
-## Windows
+### Windows
Bun provides a _limited, experimental_ native build for Windows. At the moment, only the Bun runtime is supported.
@@ -46,6 +51,77 @@ The test runner, package manager, and bundler are still under development. The f
- `bun link/unlink`
- `bun build`
+## Docker
+
+Bun provides a [Docker image](https://hub.docker.com/r/oven/bun/tags) that supports both Linux x64 and arm64.
+
+```bash
+$ docker pull oven/bun
+$ docker run --rm --init --ulimit memlock=-1:-1 oven/bun
+```
+
+There are also image variants for different operating systems.
+
+```bash
+$ docker pull oven/bun:debian
+$ docker pull oven/bun:slim
+$ docker pull oven/bun:alpine
+$ docker pull oven/bun:distroless
+```
+
+## Checking installation
+
+To check that Bun was installed successfully, open a new terminal window and run `bun --version`.
+
+```sh
+$ bun --version
+1.x.y
+```
+
+To see the precise commit of [oven-sh/bun](https://github.com/oven-sh/bun) that you're using, run `bun --revision`.
+
+```sh
+$ bun --revision
+1.x.y+b7982ac1318937560f38e0f8eb18f45eaa43480f
+```
+
+If you've installed Bun but are seeing a `command not found` error, you may have to manually add the installation directory (`~/.bun/bin`) to your `PATH`.
+
+{% details summary="How to add to your `PATH`" %}
+First, determine what shell you're using:
+
+```sh
+$ echo $SHELL
+/bin/zsh # or /bin/bash or /bin/fish
+```
+
+Then add these lines below to bottom of your shell's configuration file.
+
+{% codetabs %}
+
+```bash#~/.zshrc
+# add to ~/.zshrc
+export BUN_INSTALL="$HOME/.bun"
+export PATH="$BUN_INSTALL/bin:$PATH"
+```
+
+```bash#~/.bashrc
+# add to ~/.bashrc
+export BUN_INSTALL="$HOME/.bun"
+export PATH="$BUN_INSTALL/bin:$PATH"
+```
+
+```sh#~/.config/fish/config.fish
+# add to ~/.config/fish/config.fish
+export BUN_INSTALL="$HOME/.bun"
+export PATH="$BUN_INSTALL/bin:$PATH"
+```
+
+{% /codetabs %}
+Save the file. You'll need to open a new shell/terminal window for the changes to take effect.
+
+{% /details %}
+
## Upgrading
Once installed, the binary can upgrade itself.
@@ -68,6 +144,10 @@ $ bun upgrade --canary
[View canary build](https://github.com/oven-sh/bun/releases/tag/canary)
+{% callout %}
+**Note** — To switch back to a stable release from canary, run `bun upgrade` again with no flags.
+{% /callout %}
+
<!--
## Native
@@ -113,29 +193,9 @@ $ docker run --rm --init --ulimit memlock=-1:-1 oven/bun:edge
this is some output
``` -->
-## TypeScript
+<!-- ## Completions
-To install TypeScript definitions for Bun's built-in APIs in your project, install `bun-types`.
-
-```sh
-$ bun add -d bun-types # dev dependency
-```
-
-Then include `"bun-types"` in the `compilerOptions.types` in your `tsconfig.json`:
-
-```json-diff
- {
- "compilerOptions": {
-+ "types": ["bun-types"]
- }
- }
-```
-
-Refer to [Ecosystem > TypeScript](/docs/runtime/typescript) for a complete guide to TypeScript support in Bun.
-
-## Completions
-
-Shell auto-completion should be configured automatically when Bun is installed.
+Shell auto-completion should be configured automatically when Bun is installed!
If not, run the following command. It uses `$SHELL` to determine which shell you're using and writes a completion file to the appropriate place on disk. It's automatically re-run on every `bun upgrade`.
@@ -148,4 +208,28 @@ To write the completions to a custom location:
```bash
$ bun completions > path-to-file # write to file
$ bun completions /path/to/directory # write into directory
+``` -->
+
+## Uninstall
+
+If you need to remove Bun from your system, use the following commands.
+
+{% codetabs %}
+
+```bash#macOS/Linux_(curl)
+$ rm -rf ~/.bun # for macOS, Linux, and WSL
+```
+
+```bash#NPM
+$ npm uninstall -g bun
```
+
+```bash#Homebrew
+$ brew uninstall bun
+```
+
+```bash#Proto
+$ proto uninstall bun
+```
+
+{% /codetabs %}
diff --git a/docs/nav.ts b/docs/nav.ts
index 633177ade..edd50089e 100644
--- a/docs/nav.ts
+++ b/docs/nav.ts
@@ -35,12 +35,16 @@ export default {
page("quickstart", "Quickstart", {
description: "Get started with Bun by building and running a simple HTTP server in 6 lines of TypeScript.",
}),
- page("templates", "Templates", {
- description: "Hit the ground running with one of Bun's official templates, or download a template from GitHub.",
+ page("typescript", "TypeScript", {
+ description: "Install and configure type declarations for Bun's APIs",
}),
- page("guides", "Guides", {
- description: "A set of walkthrough guides and code snippets for performing common tasks with Bun",
- href: "/guides",
+
+ divider("Templating"),
+ page("cli/init", "`bun init`", {
+ description: "Scaffold an empty Bun project.",
+ }),
+ page("cli/bun-create", "`bun create`", {
+ description: "Scaffold a new Bun project from an official template or GitHub repo.",
}),
// page("typescript", "TypeScript"),
@@ -78,7 +82,6 @@ export default {
// page("bundev", "Dev server"),
// page("benchmarks", "Benchmarks"),
- // divider("Runtime"),
divider("Runtime"),
page("cli/run", "`bun run`", {
description: "Use `bun run` to execute JavaScript/TypeScript files and package.json scripts.",
@@ -101,6 +104,9 @@ export default {
// page("runtime/apis", "APIs", {
// description: `Bun is a new JavaScript runtime designed to be a faster, leaner, more modern replacement for Node.js.`,
// }),
+ page("runtime/env", "Environment variables", {
+ description: `How to read and set environment variables, plus how to use them to configure Bun`,
+ }),
page("runtime/bun-apis", "Bun APIs", {
description: `Bun provides a set of highly optimized native APIs for performing common tasks.`,
}),
@@ -129,7 +135,7 @@ export default {
page("runtime/autoimport", "Auto-install", {
description: `Never use node_modules again. Bun can optionally auto-install your dependencies on the fly.`,
}),
- page("runtime/configuration", "Configuration", {
+ page("runtime/bunfig", "bunfig.toml", {
description: `Bun's runtime is configurable with environment variables and the bunfig.toml config file.`,
}),
page("runtime/debugger", "Debugger", {
@@ -146,6 +152,21 @@ export default {
description:
"Install all dependencies with `bun install`, or manage dependencies with `bun add` and `bun remove`.",
}),
+ page("cli/add", "`bun add`", {
+ description: "Add dependencies to your project.",
+ }),
+ page("cli/remove", "`bun remove`", {
+ description: "Remove dependencies from your project.",
+ }),
+ page("cli/update", "`bun update`", {
+ description: "Update your project's dependencies.",
+ }),
+ page("cli/link", "`bun link`", {
+ description: "Install local packages as dependencies in your project.",
+ }),
+ page("cli/pm", "`bun pm`", {
+ description: "Utilities relating to package management with Bun.",
+ }),
page("install/cache", "Global cache", {
description:
"Bun's package manager installs all packages into a shared global cache to avoid redundant re-downloads.",
@@ -153,20 +174,26 @@ export default {
page("install/workspaces", "Workspaces", {
description: "Bun's package manager supports workspaces and mono-repo development workflows.",
}),
+ page("install/lifecycle", "Lifecycle scripts", {
+ description: "How Bun handles package lifecycle scripts with trustedDependencies",
+ }),
page("install/lockfile", "Lockfile", {
description:
- "Bun's binary lockfile `bun.lockb` tracks your resolved dependency ytrr, making future installs fast and repeatable.",
+ "Bun's binary lockfile `bun.lockb` tracks your resolved dependency tree, making future installs fast and repeatable.",
}),
page("install/registries", "Scopes and registries", {
description: "How to configure private scopes and custom package registries.",
}),
- page("install/utilities", "Utilities", {
- description: "Use `bun pm` to introspect your global module cache or project dependency tree.",
+ page("install/overrides", "Overrides and resolutions", {
+ description: "Specify version ranges for nested dependencies",
}),
+ // page("install/utilities", "Utilities", {
+ // description: "Use `bun pm` to introspect your global module cache or project dependency tree.",
+ // }),
divider("Bundler"),
page("bundler", "`Bun.build`", {
- description: "Bundle code for comsumption in the browser with Bun's native bundler.",
+ description: "Bundle code for consumption in the browser with Bun's native bundler.",
}),
// page("bundler/intro", "How bundlers work", {
// description: "A visual introduction to bundling",
@@ -328,7 +355,7 @@ export default {
page("project/benchmarking", "Benchmarking", {
description: `Bun is designed for performance. Learn how to benchmark Bun yourself.`,
}),
- page("project/development", "Development", {
+ page("project/contributing", "Contributing", {
description: "Learn how to contribute to Bun and get your local development environment up and running.",
}),
page("project/licensing", "License", {
diff --git a/docs/project/development.md b/docs/project/contributing.md
index c5345772c..9d0bee9f5 100644
--- a/docs/project/development.md
+++ b/docs/project/contributing.md
@@ -32,31 +32,37 @@ $ proto install bun
## Install LLVM
-Bun requires LLVM 15 and Clang 15 (`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:
+Bun requires LLVM 16 and Clang 16 (`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:
{% codetabs %}
```bash#macOS (Homebrew)
-$ brew install llvm@15
+$ brew install llvm@16
```
```bash#Ubuntu/Debian
$ # 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
+$ wget https://apt.llvm.org/llvm.sh -O - | sudo bash -s -- 16 all
```
```bash#Arch
$ sudo pacman -S llvm clang lld
```
+```bash#Fedora
+$ sudo dnf install 'dnf-command(copr)'
+$ sudo dnf copr enable -y @fedora-llvm-team/llvm-snapshots
+$ sudo dnf install llvm clang lld
+```
+
{% /codetabs %}
-If none of the above solutions apply, you will have to install it [manually](https://github.com/llvm/llvm-project/releases/tag/llvmorg-15.0.7).
+If none of the above solutions apply, you will have to install it [manually](https://github.com/llvm/llvm-project/releases/tag/llvmorg-16.0.6).
-Make sure LLVM 15 is in your path:
+Make sure LLVM 16 is in your path:
```bash
-$ which clang-15
+$ which clang-16
```
If not, run this to manually link it:
@@ -65,9 +71,17 @@ If not, run this to manually link it:
```bash#macOS (Homebrew)
# use fish_add_path if you're using fish
-$ export PATH="$PATH:$(brew --prefix llvm@15)/bin"
-$ export LDFLAGS="$LDFLAGS -L$(brew --prefix llvm@15)/lib"
-$ export CPPFLAGS="$CPPFLAGS -I$(brew --prefix llvm@15)/include"
+$ export PATH="$PATH:$(brew --prefix llvm@16)/bin"
+$ export LDFLAGS="$LDFLAGS -L$(brew --prefix llvm@16)/lib"
+$ export CPPFLAGS="$CPPFLAGS -I$(brew --prefix llvm@16)/include"
+```
+
+```bash#Arch
+
+$ export PATH="$PATH:/usr/lib/llvm16/bin"
+$ export LDFLAGS="$LDFLAGS -L/usr/lib/llvm16/lib"
+$ export CPPFLAGS="$CPPFLAGS -I/usr/lib/llvm16/include"
+
```
{% /codetabs %}
@@ -87,7 +101,11 @@ $ sudo apt install cargo ccache cmake git golang libtool ninja-build pkg-config
```
```bash#Arch
-$ pacman -S base-devel ccache cmake esbuild git go libiconv libtool make ninja pkg-config python rust sed unzip
+$ sudo pacman -S base-devel ccache cmake esbuild git go libiconv libtool make ninja pkg-config python rust sed unzip
+```
+
+```bash#Fedora
+$ sudo dnf install cargo ccache cmake git golang libtool ninja-build pkg-config rustc golang-github-evanw-esbuild libatomic-static libstdc++-static sed unzip
```
{% /codetabs %}
@@ -112,11 +130,11 @@ Zig can be installed either with our npm package [`@oven/zig`](https://www.npmjs
```bash
$ bun install -g @oven/zig
-$ zigup 0.12.0-dev.163+6780a6bbf
+$ zigup 0.12.0-dev.888+130227491
```
{% callout %}
-We last updated Zig on **July 18th, 2023**
+We last updated Zig on **October 12th, 2023**
{% /callout %}
## First Build
@@ -276,26 +294,6 @@ The above will probably also need Zig and/or C++ code rebuilt.
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.
-### ZLS
-
-ZLS is the language server for Zig. The latest binary that the extension auto-updates may not function with the version of Zig that Bun uses. It may be more reliable to build ZLS from source:
-
-```bash
-$ git clone https://github.com/zigtools/zls
-$ cd zls
-$ git checkout f91ff831f4959efcb7e648dba4f0132c296d26c0
-$ zig build
-```
-
-Then add absolute paths to Zig and ZLS in your vscode config:
-
-```json
-{
- "zig.zigPath": "/path/to/zig/install/zig",
- "zig.zls.path": "/path/to/zls/zig-out/bin/zls"
-}
-```
-
## JavaScript builtins
When you change anything in `src/js/builtins/*` or switch branches, run this:
@@ -387,34 +385,32 @@ $ 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, `make submodule` does not automatically update the WebKit submodule. To update, run the following commands from the root of the Bun repo:
+The Bun team will occasionally bump the version of WebKit used in Bun. When this happens, you may see errors in `src/bun.js/bindings` during builds. When you see this, install the latest version of `bun-webkit` and re-compile.
```bash
$ bun install
$ make cpp
```
-<!-- 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.
+## Building WebKit locally + Debug mode of JSC
-{% image width="270" src="https://github.com/oven-sh/bun/assets/3084745/51730b73-89ef-4358-9a41-9563a60a54be" /%} -->
+WebKit is not cloned by default (to save time and disk space). To clone and build WebKit locally, run:
-<!--
```bash
-$ cd src/bun.js/WebKit
-$ git fetch
-$ git checkout <hash>
-``` -->
+# once you run this, `make submodule` can be used to automatically
+# update WebKit and the other submodules
+$ git submodule update --init --depth 1 --checkout src/bun.js/WebKit
+# to make a jsc release build
+$ make jsc
+# JSC debug build does not work perfectly with Bun yet, this is actively being
+# worked on and will eventually become the default.
+$ make jsc-build-linux-compile-debug cpp
+$ make jsc-build-mac-compile-debug cpp
+```
+
+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.
## Troubleshooting
@@ -475,7 +471,7 @@ If you see an error about `cmakeconfig.h` not being found, this is because the p
$ bun install
```
-Check to see the command installed webkit, and you can manully look for `node_modules/bun-webkit-{platform}-{arch}`:
+Check to see the command installed webkit, and you can manually look for `node_modules/bun-webkit-{platform}-{arch}`:
```bash
# this should reveal two directories. if not, something went wrong
diff --git a/docs/quickstart.md b/docs/quickstart.md
index ea36a961f..ae7fc6087 100644
--- a/docs/quickstart.md
+++ b/docs/quickstart.md
@@ -42,6 +42,22 @@ const server = Bun.serve({
console.log(`Listening on http://localhost:${server.port} ...`);
```
+If you're using TypeScript, you may see a type error on the `Bun` global. To fix this, install `bun-types`.
+
+```sh
+$ bun add -d bun-types
+```
+
+Then add the following line to your `compilerOptions` in `tsconfig.json`.
+
+```json-diff#tsconfig.json
+{
+ "compilerOptions": {
++ "types": ["bun-types"]
+ }
+}
+```
+
Run the file from your shell.
```bash
@@ -74,7 +90,7 @@ Then run it with `bun run start`.
```bash
$ bun run start
$ bun run index.ts
- Listening on http://localhost:4000...
+ Listening on http://localhost:3000 ...
```
{% callout %}
diff --git a/docs/runtime/bunfig.md b/docs/runtime/bunfig.md
new file mode 100644
index 000000000..6950d8233
--- /dev/null
+++ b/docs/runtime/bunfig.md
@@ -0,0 +1,429 @@
+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
+# 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
+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
+# 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
+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
+[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. If
+
+```toml
+[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 permit to enable/disable the analytics records. Bun records bundle timings (so we can answer with data, "is Bun getting faster?") and feature usage (e.g., "are people actually using macros?"). The request body size is about 60 bytes, so it's not a lot of data. By default the telemetry is enabled. Equivalent of `DO_NOT_TRACK` env variable.
+
+```toml
+telemetry = false
+```
+
+## Test runner
+
+The test runner is configured under the `[test]` section of your bunfig.toml.
+
+```toml
+[test]
+# configuration goes here
+```
+
+### `test.root`
+
+The root directory to run tests from. Default `.`.
+
+```toml
+[test]
+root = "./__tests__"
+```
+
+### `test.preload`
+
+Same as the top-level `preload` field, but only applies to `bun test`.
+
+```toml
+[test]
+preload = ["./setup.ts"]
+```
+
+### `test.smol`
+
+Same as the top-level `smol` field, but only applies to `bun test`.
+
+```toml
+[test]
+smol = true
+```
+
+### `test.coverage`
+
+Enables coverage reporting. Default `false`. Use `--coverage` to override.
+
+```toml
+[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
+[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
+[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
+[test]
+coverageSkipTestFiles = false
+```
+
+## 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
+[install]
+# configuration here
+```
+
+### `install.optional`
+
+Whether to install optional dependencies. Default `true`.
+
+```toml
+[install]
+optional = true
+```
+
+### `install.dev`
+
+Whether to install development dependencies. Default `true`.
+
+```toml
+[install]
+dev = true
+```
+
+### `install.peer`
+
+Whether to install peer dependencies. Default `true`.
+
+```toml
+[install]
+peer = false
+```
+
+### `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
+[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
+[install]
+exact = false
+```
+
+<!--
+### `install.prefer`
+
+Whether the package manager should prefer offline or online dependency resolution. Default `"online"`.
+
+```toml
+[install]
+prefer = "online"
+```
+
+Valid values are:
+
+{% table %}
+
+---
+
+- `"online"`
+- Prefer online resolution. This is the default. If a package is not found in the local cache, it will be downloaded from the registry.
+
+---
+
+- `"offline"`
+- Prefer offline resolution. When possible, packages will be installed from the global cache. This minimizes the fraction of the time Bun will check for newer versions from the registry. If a package is not found in the global cache, it will be downloaded from the registry.
+
+{% /table %} -->
+
+### `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
+[install]
+auto = "auto"
+```
+
+Valid values are:
+
+{% table %}
+
+- 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, the auto-install any packages that aren't found. You can enable this from the CLI with `bun -i`.
+
+{% /table %}
+
+### `install.frozenLockfile`
+
+When true, `bun install` will not update `bun.lockb`. Default `false`. If `package.json` and the existing `bun.lockb` are not in agreement, this will error.
+
+```toml
+[install]
+frozenLockfile = false
+```
+
+### `install.dryRun`
+
+Whether to install optional dependencies. Default `false`. When true, it's equivalent to setting `--dry-run` on all `bun install` commands.
+
+```toml
+[install]
+dryRun = false
+```
+
+### `install.globalDir`
+
+To configure the directory where Bun puts globally installed packages.
+
+```toml
+[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.
+
+```toml
+# 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
+[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.scopes`
+
+To configure a registry for a particular scope (e.g. `@myorg/<package>`) use `install.scopes`. You can reference environment variables with `$variable` notation.
+
+```toml
+[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.cache`
+
+To configure the cache behavior:
+
+```toml
+[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
+[install.lockfile]
+save = true
+```
+
+Whether to generate a non-Bun lockfile alongside `bun.lockb`. (A `bun.lockb` will always be created.) Currently `"yarn"` is the only supported value.
+
+```toml
+[install.lockfile]
+print = "yarn"
+```
+
+<!-- ## Debugging -->
+
+<!--
+```toml
+[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"
+``` -->
diff --git a/docs/runtime/configuration.md b/docs/runtime/configuration.md
deleted file mode 100644
index 96385b87d..000000000
--- a/docs/runtime/configuration.md
+++ /dev/null
@@ -1,210 +0,0 @@
-There are two primary mechanisms for configuring the behavior of Bun.
-
-- environment variables
-- `bunfig.toml`: Bun's configuration file
-
-Configuring with `bunfig.toml` is optional. Bun aims to be zero-configuration out of the box, but is also highly configurable for advanced use cases. Your `bunfig.toml` should live in your project root alongside `package.json`.
-
-You can also create a global configuration file at 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 overridding global. CLI flags will override `bunfig` setting where applicable.
-
-## Runtime
-
-```toml
-# scripts to run before `bun run`ning a file or script
-# useful for registering plugins
-preload = ["./preload.ts"]
-
-# equivalent to corresponding tsconfig compilerOptions
-jsx = "react"
-jsxFactory = "h"
-jsxFragment = "Fragment"
-jsxImportSource = "react"
-
-# Reduce memory usage at the cost of performance
-smol = true
-
-# Set Bun's log level
-logLevel = "debug" # "debug", "warn", "error"
-
-[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]
-# When loading a .bagel file, run the JS parser
-".bagel" = "js"
-```
-
-## Test runner
-
-```toml
-[test]
-# Scripts to run before all test files
-preload = ["./setup.ts"]
-
-# Reduce memory usage at the cost of performance
-smol = true
-```
-
-## Package manager
-
-Package management is a complex issue; to support a range of use cases, the behavior of `bun install` can be configured in [`bunfig.toml`](/docs/runtime/configuration).
-
-### Default flags
-
-The following settings modify the core behavior of Bun's package management commands. **The default values are shown below.**
-
-```toml
-[install]
-
-# whether to install optionalDependencies
-optional = true
-
-# whether to install devDependencies
-dev = true
-
-# whether to install peerDependencies
-peer = false
-
-# equivalent to `--production` flag
-production = false
-
-# equivalent to `--frozen-lockfile` flag
-frozenLockfile = false
-
-# equivalent to `--dry-run` flag
-dryRun = false
-```
-
-### Private scopes and registries
-
-The default registry is `https://registry.npmjs.org/`. This can be globally configured in `bunfig.toml`:
-
-```toml
-[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"
-```
-
-To configure scoped registries:
-
-```toml
-[install.scopes]
-# registry as string
-myorg1 = "https://username:password@registry.myorg.com/"
-
-# registry with username/password
-# you can reference environment variables
-myorg12 = { username = "myusername", password = "$NPM_PASS", url = "https://registry.myorg.com/" }
-
-# registry with token
-myorg3 = { token = "$npm_token", url = "https://registry.myorg.com/" }
-```
-
-### Cache
-
-To configure caching behavior:
-
-```toml
-[install]
-# where `bun install --global` installs packages
-globalDir = "~/.bun/install/global"
-
-# where globally-installed package bins are linked
-globalBinDir = "~/.bun/bin"
-
-[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
-```
-
-### Lockfile
-
-To configure lockfile behavior:
-
-```toml
-[install.lockfile]
-
-# path to read bun.lockb from
-path = "bun.lockb"
-
-# path to save bun.lockb to
-savePath = "bun.lockb"
-
-# whether to save the lockfile to disk
-save = true
-
-# whether to save a non-Bun lockfile alongside bun.lockb
-# only "yarn" is supported
-print = "yarn"
-```
-
-### Debugging
-
-```toml
-[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"
-```
-
-## Environment variables
-
-These environment variables are checked by Bun to detect functionality and toggle features.
-
-{% table %}
-
-- Name
-- Description
-
----
-
-- `TMPDIR`
-- Bun occasionally requires a directory to store intermediate assets during bundling or other operations. If unset, defaults to the platform-specific temporary directory: `/tmp` on Linux, `/private/tmp` on macOS.
-
----
-
-- `NO_COLOR`
-- If `NO_COLOR=1`, then ANSI color output is [disabled](https://no-color.org/).
-
----
-
-- `FORCE_COLOR`
-- If `FORCE_COLOR=1`, then ANSI color output is force enabled, even if `NO_COLOR` is set.
-
----
-
-- `DO_NOT_TRACK`
-- If `DO_NOT_TRACK=1`, then analytics are [disabled](https://do-not-track.dev/). Bun records bundle timings (so we can answer with data, "is Bun getting faster?") and feature usage (e.g., "are people actually using macros?"). The request body size is about 60 bytes, so it's not a lot of data.
-
-{% /table %}
diff --git a/docs/runtime/env.md b/docs/runtime/env.md
new file mode 100644
index 000000000..e38eabffd
--- /dev/null
+++ b/docs/runtime/env.md
@@ -0,0 +1,147 @@
+Bun reads your `.env` files automatically and provides idiomatic ways to read and write your environment variables programmatically. Plus, some aspects of Bun's runtime behavior can be configured with Bun-specific environment variables.
+
+## Setting environment variables
+
+Bun reads the following files automatically (listed in order of increasing precedence).
+
+- `.env`
+- `.env.production`, `.env.development`, `.env.test` (depending on value of `NODE_ENV`)
+- `.env.local`
+
+```txt#.env
+FOO=hello
+BAR=world
+```
+
+Variables can also be set via the command line.
+
+```sh
+$ FOO=helloworld bun run dev
+```
+
+Or programmatically by assigning a property to `process.env`.
+
+```ts
+process.env.FOO = "hello";
+```
+
+### Quotation marks
+
+Bun supports double quotes, single quotes, and
+
+### Expansion
+
+Environment variables are automatically _expanded_. This means you can reference previously-defined variables in your environment variables.
+
+```txt#.env
+FOO=world
+BAR=hello$FOO
+```
+
+```ts
+process.env.BAR; // => "helloworld"
+```
+
+This is useful for constructing connection strings or other compound values.
+
+```txt#.env
+DB_USER=postgres
+DB_PASSWORD=secret
+DB_HOST=localhost
+DB_PORT=5432
+DB_URL=postgres://$DB_USER:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_NAME
+```
+
+This can be disabled by escaping the `$` with a backslash.
+
+```txt#.env
+FOO=world
+BAR=hello\$FOO
+```
+
+```ts
+process.env.BAR; // => "hello$FOO"
+```
+
+### `dotenv`
+
+Generally speaking, you won't need `dotenv` or `dotenv-expand` anymore, because Bun reads `.env` files automatically.
+
+## Reading environment variables
+
+The current environment variables can be accessed via `process.env`.
+
+```ts
+process.env.API_TOKEN; // => "secret"
+```
+
+Bun also exposes these variables via `Bun.env`, which is a simple alias of `process.env`.
+
+```ts
+Bun.env.API_TOKEN; // => "secret"
+```
+
+To print all currently-set environment variables to the command line, run `bun run env`. This is useful for debugging.
+
+```sh
+$ bun run env
+BAZ=stuff
+FOOBAR=aaaaaa
+<lots more lines>
+```
+
+## TypeScript
+
+In TypeScript, all properties of `process.env` are typed as `string | undefined`.
+
+```ts
+Bun.env.whatever;
+// string | undefined
+```
+
+To get autocompletion and tell TypeScript to treat a variable as a non-optional string, we'll use [interface merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces).
+
+```ts
+declare module "bun" {
+ interface Env {
+ AWESOME: string;
+ }
+}
+```
+
+Add this line to any file in your project. It will globally add the `AWESOME` property to `process.env` and `Bun.env`.
+
+```ts
+process.env.AWESOME; // => string
+```
+
+## Configuring Bun
+
+These environment variables are read by Bun and configure aspects of its behavior.
+
+{% table %}
+
+- Name
+- Description
+
+---
+
+- `TMPDIR`
+- Bun occasionally requires a directory to store intermediate assets during bundling or other operations. If unset, defaults to the platform-specific temporary directory: `/tmp` on Linux, `/private/tmp` on macOS.
+
+---
+
+- `NO_COLOR`
+- If `NO_COLOR=1`, then ANSI color output is [disabled](https://no-color.org/).
+
+---
+
+- `FORCE_COLOR`
+- If `FORCE_COLOR=1`, then ANSI color output is force enabled, even if `NO_COLOR` is set.
+
+---
+
+- `DO_NOT_TRACK`
+- If `DO_NOT_TRACK=1`, then analytics are [disabled](https://do-not-track.dev/). Bun records bundle timings (so we can answer with data, "is Bun getting faster?") and feature usage (e.g., "are people actually using macros?"). The request body size is about 60 bytes, so it's not a lot of data. Equivalent of `telemetry=false` in bunfig.
+
+{% /table %}
diff --git a/docs/runtime/hot.md b/docs/runtime/hot.md
index 07f3f0f66..c54868689 100644
--- a/docs/runtime/hot.md
+++ b/docs/runtime/hot.md
@@ -1,6 +1,6 @@
Bun supports two kinds of automatic reloading via CLI flags:
-- `--watch` mode, which hard restarts Bun's process when imported files change/
+- `--watch` mode, which hard restarts Bun's process when imported files change.
- `--hot` mode, which soft reloads the code (without restarting the process) when imported files change.
## `--watch` mode
@@ -52,6 +52,7 @@ serve({
{% /codetabs %}
+In this example, Bun is
![bun watch gif](https://user-images.githubusercontent.com/709451/228439002-7b9fad11-0db2-4e48-b82d-2b88c8625625.gif)
Running `bun test` in watch mode and `save-on-keypress` enabled:
@@ -64,7 +65,9 @@ $ bun --watch test
## `--hot` mode
-Use `bun --hot` to enable hot reloading when executing code with Bun.
+Use `bun --hot` to enable hot reloading when executing code with Bun. This is distinct from `--watch` mode in that Bun does not hard-restart the entire process. Instead, it detects code changes and updates its internal module cache with the new code.
+
+**Note** — This is not the same as hot reloading in the browser! Many frameworks provide a "hot reloading" experience, where you can edit & save your frontend code (say, a React component) and see the changes reflected in the browser without refreshing the page. Bun's `--hot` is the server-side equivalent of this experience. To get hot reloading in the browser, use a framework like [Vite](https://vitejs.dev).
```bash
$ bun --hot server.ts
@@ -99,15 +102,13 @@ Traditional file watchers like `nodemon` restart the entire process, so HTTP ser
### HTTP servers
-Bun provides the following simplified API for implementing HTTP servers. Refer to [API > HTTP](/docs/api/http) for full details.
+This makes it possible, for instance, to update your HTTP request handler without shutting down the server itself. When you save the file, your HTTP server will be reloaded with the updated code without the process being restarted. This results in seriously fast refresh speeds.
```ts#server.ts
-import {serve} from "bun";
-
globalThis.count ??= 0;
globalThis.count++;
-serve({
+Bun.serve({
fetch(req: Request) {
return new Response(`Reloaded ${globalThis.count} times`);
},
@@ -115,18 +116,16 @@ serve({
});
```
-The file above is simply exporting an object with a `fetch` handler defined. When this file is executed, Bun interprets this as an HTTP server and passes the exported object into `Bun.serve`.
-
-When you save the file, your HTTP server be reloaded with the updated code without the process being restarted. This results in seriously fast refresh speeds.
+<!-- The file above is simply exporting an object with a `fetch` handler defined. When this file is executed, Bun interprets this as an HTTP server and passes the exported object into `Bun.serve`. -->
-{% image src="https://user-images.githubusercontent.com/709451/195477632-5fd8a73e-014d-4589-9ba2-e075ad9eb040.gif" alt="Bun vs Nodemon refresh speeds" caption="Bun on the left, Nodemon on the right." /%}
+<!-- {% image src="https://user-images.githubusercontent.com/709451/195477632-5fd8a73e-014d-4589-9ba2-e075ad9eb040.gif" alt="Bun vs Nodemon refresh speeds" caption="Bun on the left, Nodemon on the right." /%} -->
{% callout %}
**Note** — In a future version of Bun, support for Vite's `import.meta.hot` is planned to enable better lifecycle management for hot reloading and to align with the ecosystem.
{% /callout %}
-{% details summary="Implementation `details`" %}
+{% details summary="Implementation details" %}
On hot reload, Bun:
diff --git a/docs/runtime/jsx.md b/docs/runtime/jsx.md
index ab9a14a8d..31a61652b 100644
--- a/docs/runtime/jsx.md
+++ b/docs/runtime/jsx.md
@@ -14,7 +14,7 @@ console.log(<Component message="Hello world!" />);
## Configuration
-Bun reads your `tsconfig.json` or `jsconfig.json` configuration files to determines how to perform the JSX transform internally. To avoid using either of these, the following options can also be defined in [`bunfig.toml`](/docs/runtime/configuration).
+Bun reads your `tsconfig.json` or `jsconfig.json` configuration files to determines how to perform the JSX transform internally. To avoid using either of these, the following options can also be defined in [`bunfig.toml`](/docs/runtime/bunfig).
The following compiler options are respected.
@@ -175,7 +175,7 @@ The function name used to represent [JSX fragments](https://react.dev/reference/
// output
import { myjsx, MyFragment } from "react";
- createElement("Box", { width: 5 }, "Hello");
+ myjsx(MyFragment, null, "Hello");
```
{% /table %}
diff --git a/docs/runtime/modules.md b/docs/runtime/modules.md
index 380903c6f..486ddea5f 100644
--- a/docs/runtime/modules.md
+++ b/docs/runtime/modules.md
@@ -24,24 +24,29 @@ export function hello() {
{% /codetabs %}
-When we run `index.ts`, it prints "Hello world".
+When we run `index.ts`, it prints "Hello world!".
```bash
$ bun index.ts
Hello world!
```
-In this case, we are importing from `./hello`, a relative path with no extension. To resolve this import, Bun will check for the following files in order:
+In this case, we are importing from `./hello`, a relative path with no extension. **Extensioned imports are optional but supported.** To resolve this import, Bun will check for the following files in order:
-- `./hello.ts`
- `./hello.tsx`
-- `./hello.js`
+- `./hello.jsx`
+- `./hello.ts`
- `./hello.mjs`
+- `./hello.js`
- `./hello.cjs`
+- `./hello.json`
+- `./hello/index.tsx`
+- `./hello/index.jsx`
- `./hello/index.ts`
+- `./hello/index.mjs`
- `./hello/index.js`
+- `./hello/index.cjs`
- `./hello/index.json`
-- `./hello/index.mjs`
Import paths are case-insensitive, meaning these are all valid imports:
@@ -58,7 +63,7 @@ import { hello } from "./hello";
import { hello } from "./hello.ts"; // this works
```
-There is one exception: if you import `from "*.js{x}"`, Bun will additionally check for a matching `*.ts{x}` file, to be compatible with TypeScript's [ES module support](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html#new-file-extensions).
+If you import `from "*.js{x}"`, Bun will additionally check for a matching `*.ts{x}` file, to be compatible with TypeScript's [ES module support](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html#new-file-extensions).
```ts#index.ts
import { hello } from "./hello";
@@ -88,7 +93,86 @@ exports.hello = hello;
That said, using CommonJS is discouraged in new projects.
-## Resolution
+## Module systems
+
+Bun has native support for CommonJS and ES modules. ES Modules are the recommended module format for new projects, but CommonJS modules are still widely used in the Node.js ecosystem.
+
+In Bun's JavaScript runtime, `require` can be used by both ES Modules and CommonJS modules. If the target module is an ES Module, `require` returns the module namespace object (equivalent to `import * as`). If the target module is a CommonJS module, `require` returns the `module.exports` object (as in Node.js).
+
+| Module Type | `require()` | `import * as` |
+| ----------- | ---------------- | ----------------------------------------------------------------------- |
+| ES Module | Module Namespace | Module Namespace |
+| CommonJS | module.exports | `default` is `module.exports`, keys of module.exports are named exports |
+
+### Using `require()`
+
+You can `require()` any file or package, even `.ts` or `.mjs` files.
+
+```ts
+const { foo } = require("./foo"); // extensions are optional
+const { bar } = require("./bar.mjs");
+const { baz } = require("./baz.tsx");
+```
+
+{% details summary="What is a CommonJS module?" %}
+
+In 2016, ECMAScript added support for [ES Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules). ES Modules are the standard for JavaScript modules. However, millions of npm packages still use CommonJS modules.
+
+CommonJS modules are modules that use `module.exports` to export values. Typically, `require` is used to import CommonJS modules.
+
+```ts
+// my-commonjs.cjs
+const stuff = require("./stuff");
+module.exports = { stuff };
+```
+
+The biggest difference between CommonJS and ES Modules is that CommonJS modules are synchronous, while ES Modules are asynchronous. There are other differences too.
+
+- ES Modules support top-level `await` and CommonJS modules don't.
+- ES Modules are always in [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode), while CommonJS modules are not.
+- Browsers do not have native support for CommonJS modules, but they do have native support for ES Modules via `<script type="module">`.
+- CommonJS modules are not statically analyzable, while ES Modules only allow static imports and exports.
+
+**CommonJS Modules:** These are a type of module system used in JavaScript. One key feature of CommonJS modules is that they load and execute synchronously. This means that when you import a CommonJS module, the code in that module runs immediately, and your program waits for it to finish before moving on to the next task. It's similar to reading a book from start to finish without skipping pages.
+
+**ES Modules (ESM):** These are another type of module system introduced in JavaScript. They have a slightly different behavior compared to CommonJS. In ESM, static imports (imports made using `import` statements) are synchronous, just like CommonJS. This means that when you import an ESM using a regular `import` statement, the code in that module runs immediately, and your program proceeds in a step-by-step manner. Think of it like reading a book page by page.
+
+**Dynamic imports:** Now, here comes the part that might be confusing. ES Modules also support importing modules on the fly via the `import()` function. This is called a "dynamic import" and it's asynchronous, so it doesn't block the main program execution. Instead, it fetches and loads the module in the background while your program continues to run. Once the module is ready, you can use it. This is like getting additional information from a book while you're still reading it, without having to pause your reading.
+
+**In summary:**
+
+- CommonJS modules and static ES Modules (`import` statements) work in a similar synchronous way, like reading a book from start to finish.
+- ES Modules also offer the option to import modules asynchronously using the `import()` function. This is like looking up additional information in the middle of reading the book without stopping.
+
+{% /details %}
+
+### Using `import`
+
+You can `import` any file or package, even `.cjs` files.
+
+```ts
+import { foo } from "./foo"; // extensions are optional
+import bar from "./bar.ts";
+import { stuff } from "./my-commonjs.cjs";
+```
+
+### Using `import` and `require()` together
+
+In Bun, you can use `import` or `require` in the same file—they both work, all the time.
+
+```ts
+import { stuff } from "./my-commonjs.cjs";
+import Stuff from "./my-commonjs.cjs";
+const myStuff = require("./my-commonjs.cjs");
+```
+
+### Top level await
+
+The only exception to this rule is top-level await. You can't `require()` a file that uses top-level await, since the `require()` function is inherently synchronous.
+
+Fortunately, very few libraries use top-level await, so this is rarely a problem. But if you're using top-level await in your application code, make sure that file isn't being `require()` from elsewhere in your application. Instead, you should use `import` or [dynamic `import()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import).
+
+## Importing packages
Bun implements the Node.js module resolution algorithm, so you can import packages from `node_modules` with a bare specifier.
@@ -107,8 +191,8 @@ Once it finds the `foo` package, Bun reads the `package.json` to determine how t
"bun": "./index.js",
"worker": "./index.js",
"node": "./index.js",
- "require": "./index.js", # if importer is CommonJS
- "import": "./index.mjs", # if importer is ES module
+ "require": "./index.js", // if importer is CommonJS
+ "import": "./index.mjs", // if importer is ES module
"default": "./index.js",
}
}
@@ -116,18 +200,38 @@ Once it finds the `foo` package, Bun reads the `package.json` to determine how t
Whichever one of these conditions occurs _first_ in the `package.json` is used to determine the package's entrypoint.
-Bun respects subpath [`"exports"`](https://nodejs.org/api/packages.html#subpath-exports) and [`"imports"`](https://nodejs.org/api/packages.html#imports). Specifying any subpath in the `"exports"` map will prevent other subpaths from being importable.
+Bun respects subpath [`"exports"`](https://nodejs.org/api/packages.html#subpath-exports) and [`"imports"`](https://nodejs.org/api/packages.html#imports).
```jsonc#package.json
{
"name": "foo",
"exports": {
- ".": "./index.js",
- "./package.json": "./package.json" // subpath
+ ".": "./index.js"
}
}
```
+Subpath imports and conditional imports work in conjunction with each other.
+
+```json
+{
+ "name": "foo",
+ "exports": {
+ ".": {
+ "import": "./index.mjs",
+ "require": "./index.js"
+ }
+ }
+}
+```
+
+As in Node.js, Specifying any subpath in the `"exports"` map will prevent other subpaths from being importable; you can only import files that are explicitly exported. Given the `package.json` above:
+
+```ts
+import stuff from "foo"; // this works
+import stuff from "foo/index.mjs"; // this doesn't
+```
+
{% callout %}
**Shipping TypeScript** — Note that Bun supports the special `"bun"` export condition. If your library is written in TypeScript, you can publish your (un-transpiled!) TypeScript files to `npm` directly. If you specify your package's `*.ts` entrypoint in the `"bun"` condition, Bun will directly import and execute your TypeScript source files.
{% /callout %}
@@ -159,67 +263,6 @@ In the spirit of treating TypeScript as a first-class citizen, the Bun runtime w
If you aren't a TypeScript user, you can create a [`jsconfig.json`](https://code.visualstudio.com/docs/languages/jsconfig) in your project root to achieve the same behavior.
-## CommonJS
-
-Bun has native support for CommonJS modules. ES Modules are the recommended module format, but CommonJS modules are still widely used in the Node.js ecosystem. Bun supports both module formats.
-
-In Bun's JavaScript runtime, `require` can be used by both ES Modules and CommonJS modules. If the target module is an ES Module, `require` returns the module namespace object (equivalent to `import * as`). If the target module is a CommonJS module, `require` returns the `module.exports` object (as in Node.js).
-
-| Module Type | `require()` | `import * as` |
-| ----------- | ---------------- | ----------------------------------------------------------------------- |
-| ES Module | Module Namespace | Module Namespace |
-| CommonJS | module.exports | `default` is `module.exports`, keys of module.exports are named exports |
-
-### What is a CommonJS module?
-
-In 2016, ECMAScript added support for [ES Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules). ES Modules are the standard for JavaScript modules. However, millions of npm packages still use CommonJS modules.
-
-CommonJS modules are modules that use `module.exports` to export values. Typically, `require` is used to import CommonJS modules.
-
-```ts
-// my-commonjs.cjs
-const stuff = require("./stuff");
-module.exports = { stuff };
-```
-
-The biggest difference between CommonJS and ES Modules is that CommonJS modules are synchronous, while ES Modules are asynchronous. There are other differences too, like ES Modules support top-level `await` and CommonJS modules don't. ES Modules are always in [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode), while CommonJS modules are not. Browsers do not have native support for CommonJS modules, but they do have native support for ES Modules (`<script type="module">`). CommonJS modules are not statically analyzable, while ES Modules only allow static imports and exports.
-
-### Importing CommonJS from ESM
-
-You can `import` or `require` CommonJS modules from ESM modules.
-
-```ts
-import { stuff } from "./my-commonjs.cjs";
-import Stuff from "./my-commonjs.cjs";
-const myStuff = require("./my-commonjs.cjs");
-```
-
-### Importing ESM from CommonJS
-
-```ts
-// this works in Bun but not Node.js
-const { stuff } = require("./my-esm.mjs");
-```
-
-### Importing CommonJS from CommonJS
-
-```ts
-const { stuff } = require("./my-commonjs.cjs");
-```
-
-#### Top-level await
-
-If you are using top-level await, you must use `import()` to import ESM modules from CommonJS modules.
-
-```ts
-import("./my-esm.js").then(({ stuff }) => {
- // ...
-});
-
-// this will throw an error if "my-esm.js" uses top-level await
-const { stuff } = require("./my-esm.js");
-```
-
{% details summary="Low-level details of CommonJS interop in Bun" %}
Bun's JavaScript runtime has native support for CommonJS. When Bun's JavaScript transpiler detects usages of `module.exports`, it treats the file as CommonJS. The module loader will then wrap the transpiled module in a function shaped like this:
diff --git a/docs/runtime/nodejs-apis.md b/docs/runtime/nodejs-apis.md
index 72504e664..4b58343e0 100644
--- a/docs/runtime/nodejs-apis.md
+++ b/docs/runtime/nodejs-apis.md
@@ -1,16 +1,16 @@
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. 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.
+This page is updated regularly to reflect compatibility status of the latest version of Bun. The information below reflects Bun's compatibility with _Node.js v20_. 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
### [`node:assert`](https://nodejs.org/api/assert.html)
-🟢 Fully implemented.
+🟡 Missing `doesNotMatch`
### [`node:async_hooks`](https://nodejs.org/api/async_hooks.html)
-🟡 Only `AsyncLocalStorage`, and `AsyncResource` are implemented.
+🟡 Only `AsyncLocalStorage`, and `AsyncResource` are implemented. `AsyncResource` is missing `bind`.
### [`node:buffer`](https://nodejs.org/api/buffer.html)
@@ -18,7 +18,7 @@ This page is updated regularly to reflect compatibility status of the latest ver
### [`node:child_process`](https://nodejs.org/api/child_process.html)
-🟡 Missing `Stream` stdio, `proc.gid`, `proc.uid`. IPC has partial support and only current only works with other `bun` processes.
+🟡 Missing `Stream` stdio, `proc.gid` `proc.uid`. IPC has partial support and only current only works with other `bun` processes.
### [`node:cluster`](https://nodejs.org/api/cluster.html)
@@ -26,11 +26,13 @@ This page is updated regularly to reflect compatibility status of the latest ver
### [`node:console`](https://nodejs.org/api/console.html)
-🟡 Missing `Console` constructor.
+🟢 Fully implemented.
### [`node:crypto`](https://nodejs.org/api/crypto.html)
-🟡 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`. Some methods are not optimized yet.
+🟡 Missing `Certificate` `ECDH` `X509Certificate` `checkPrime` `checkPrimeSync` `diffieHellman` `generatePrime` `generatePrimeSync` `getCipherInfo` `getFips` `hkdf` `hkdfSync` `secureHeapUsed` `setEngine` `setFips`
+
+Some methods are not optimized yet.
### [`node:dgram`](https://nodejs.org/api/dgram.html)
@@ -42,19 +44,19 @@ This page is updated regularly to reflect compatibility status of the latest ver
### [`node:dns`](https://nodejs.org/api/dns.html)
-🟢 Fully implemented.
+🟡 Missing `cancel` `setServers` `getDefaultResultOrder`
### [`node:domain`](https://nodejs.org/api/domain.html)
-🟢 Fully implemented.
+🟡 Missing `Domain` `active`
### [`node:events`](https://nodejs.org/api/events.html)
-🟡 Missing `on`
+🟡 Missing `on` `addAbortListener` `getMaxListeners`
### [`node:fs`](https://nodejs.org/api/fs.html)
-🟡 Missing `fs.fdatasync{Sync}` `fs.opendir{Sync}`. `fs.promises.open` incorrectly returns a file descriptor instead of a `FileHandle`.
+🟡 Missing `Dir` `fdatasync` `fdatasyncSync` `openAsBlob` `opendir` `opendirSync` `statfs` `statfsSync`. `fs.promises.open` incorrectly returns a file descriptor instead of a `FileHandle`.
### [`node:http`](https://nodejs.org/api/http.html)
@@ -74,11 +76,11 @@ This page is updated regularly to reflect compatibility status of the latest ver
### [`node:module`](https://nodejs.org/api/module.html)
-🟢 Fully implemented.
+🟢 Missing `runMain` `syncBuiltinESMExports`, `Module#load()`. Attempts to override or patch the module cache will fail.
### [`node:net`](https://nodejs.org/api/net.html)
-🟡 Missing `net.{get|set}DefaultAutoSelectFamily` `net.SocketAddress` `net.BlockList`.
+🟡 Missing `BlockList` `SocketAddress` `Stream` `getDefaultAutoSelectFamily` `getDefaultAutoSelectFamilyAttemptTimeout` `setDefaultAutoSelectFamily` `setDefaultAutoSelectFamilyAttemptTimeout` `Server#ref()` `Server#unref()` `Socket#ref()` `Socket#unref()`.
### [`node:os`](https://nodejs.org/api/os.html)
@@ -90,11 +92,11 @@ This page is updated regularly to reflect compatibility status of the latest ver
### [`node:perf_hooks`](https://nodejs.org/api/perf_hooks.html)
-🟡 Only `perf_hooks.performance.now()` and `perf_hooks.performance.timeOrigin` are implemented. Recommended to use `performance` global instead of `perf_hooks.performance`.
+🟡 Only `perf_hooks.performance.now()` and `perf_hooks.performance.timeOrigin` are implemented. Missing `Performance` `PerformanceMark` `PerformanceMeasure` `PerformanceObserverEntryList` `PerformanceResourceTiming` `createHistogram` `monitorEventLoopDelay`. It's recommended to use `performance` global instead of `perf_hooks.performance`.
### [`node:process`](https://nodejs.org/api/process.html)
-🟡 See `Globals > process`.
+🟡 See [`process`](#process) Global.
### [`node:punycode`](https://nodejs.org/api/punycode.html)
@@ -114,7 +116,7 @@ This page is updated regularly to reflect compatibility status of the latest ver
### [`node:stream`](https://nodejs.org/api/stream.html)
-🟢 Fully implemented.
+🟡 Missing `getDefaultHighWaterMark` `setDefaultHighWaterMark`
### [`node:string_decoder`](https://nodejs.org/api/string_decoder.html)
@@ -122,7 +124,7 @@ This page is updated regularly to reflect compatibility status of the latest ver
### [`node:sys`](https://nodejs.org/api/util.html)
-🟡 See `node:util`.
+🟡 See [`node:util`](#node-util).
### [`node:timers`](https://nodejs.org/api/timers.html)
@@ -130,7 +132,7 @@ This page is updated regularly to reflect compatibility status of the latest ver
### [`node:tls`](https://nodejs.org/api/tls.html)
-🟡 Missing `tls.createSecurePair`
+🟡 Missing `tls.createSecurePair`.
### [`node:trace_events`](https://nodejs.org/api/tracing.html)
@@ -142,11 +144,11 @@ This page is updated regularly to reflect compatibility status of the latest ver
### [`node:url`](https://nodejs.org/api/url.html)
-🟡 Missing `url.domainTo{ASCII|Unicode}`. Recommended to use `URL` and `URLSearchParams` globals instead.
+🟡 Missing `domainToASCII` `domainToUnicode`. It's recommended to use `URL` and `URLSearchParams` globals instead.
### [`node:util`](https://nodejs.org/api/util.html)
-🟡 Missing `util.MIMEParams` `util.MIMEType` `util.getSystemErrorMap()` `util.getSystemErrorName()` `util.parseArgs()` `util.stripVTControlCharacters()` `util.transferableAbortController()` `util.transferableAbortSignal()`.
+🟡 Missing `MIMEParams` `MIMEType` `aborted` `debug` `getSystemErrorMap` `getSystemErrorName` `parseArgs` `transferableAbortController` `transferableAbortSignal` `stripVTControlCharacters`
### [`node:v8`](https://nodejs.org/api/v8.html)
@@ -154,7 +156,7 @@ This page is updated regularly to reflect compatibility status of the latest ver
### [`node:vm`](https://nodejs.org/api/vm.html)
-🟡 Core functionality works, but VM modules are not implemented. `ShadowRealm` can be used.
+🟡 Core functionality works, but VM modules are not implemented. Missing `createScript`. `ShadowRealm` can be used.
### [`node:wasi`](https://nodejs.org/api/wasi.html)
@@ -162,266 +164,11 @@ This page is updated regularly to reflect compatibility status of the latest ver
### [`node:worker_threads`](https://nodejs.org/api/worker_threads.html)
-🟡 `Worker` doesn't support the following options: `eval`, `argv`, `execArgv`, `stdin`, `stdout`, `stderr`, `trackedUnmanagedFds`, `resourceLimits`. Missing `markAsUntransferable`, `moveMessagePortToContext`, `getHeapSnapshot`.
+🟡 `Worker` doesn't support the following options: `eval` `argv` `execArgv` `stdin` `stdout` `stderr` `trackedUnmanagedFds` `resourceLimits`. Missing `markAsUntransferable` `moveMessagePortToContext` `getHeapSnapshot`.
### [`node:zlib`](https://nodejs.org/api/zlib.html)
-🟡 Missing `zlib.brotli*`. Has not been optimized.
-
-<!-- {% block className="ScrollFrame" %}
-{% table %}
-
-- Module
-- Status
-- Notes
-
----
-
-- {% anchor id="node_assert" %} [`node:assert`](https://nodejs.org/api/assert.html) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_async_hooks" %} [`node:async_hooks`](https://nodejs.org/api/async_hooks.html) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_buffer" %} [`node:buffer`](https://nodejs.org/api/buffer.html) {% /anchor %}
-- 🟢
-
----
-
-- {% anchor id="node_child_process" %} [`node:child_process`](https://nodejs.org/api/child_process.html) {% /anchor %}
-- 🟡
-- Missing IPC, `Stream` stdio, `proc.gid`, `proc.uid`, advanced serialization.
-
----
-
-- {% anchor id="node_cluster" %} [`node:cluster`](https://nodejs.org/api/cluster.html) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_console" %} [`node:console`](https://nodejs.org/api/console.html) {% /anchor %}
-- 🟢
-- Recommended to use `console` global instead
-
----
-
-- {% 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.{get|set}Fips` `crypto.hkdf` `crypto.hkdfSync` `crypto.secureHeapUsed` `crypto.setEngine` `crypto.sign` `crypto.verify`. Some methods are not optimized yet.
-
----
-
-- {% anchor id="node_dgram" %} [`node:dgram`](https://nodejs.org/api/dgram.html) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_diagnostics_channel" %} [`node:diagnostics_channel`](https://nodejs.org/api/diagnostics_channel.html) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_dns" %} [`node:dns`](https://nodejs.org/api/dns.html) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_domain" %} [`node:domain`](https://nodejs.org/api/domain.html) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_events" %} [`node:events`](https://nodejs.org/api/events.html) {% /anchor %}
-- 🟡
-- Missing `EventEmitterAsyncResource` `events.on`.
-
----
-
-- {% anchor id="node_fs" %} [`node:fs`](https://nodejs.org/api/fs.html) {% /anchor %}
-- 🟡
-- Missing `fs.fdatasync{Sync}` `fs.opendir{Sync}`. `fs.promises.open` incorrectly returns a file descriptor instead of a `FileHandle`.
-
----
-
-- {% anchor id="node_http" %} [`node:http`](https://nodejs.org/api/http.html) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_http2" %} [`node:http2`](https://nodejs.org/api/http2.html) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_https" %} [`node:https`](https://nodejs.org/api/https.html) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_inspector" %} [`node:inspector`](https://nodejs.org/api/inspector.html) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_module" %} [`node:module`](https://nodejs.org/api/module.html) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_net" %} [`node:net`](https://nodejs.org/api/net.html) {% /anchor %}
-- 🟡
-- Missing `net.{get|set}DefaultAutoSelectFamily` `net.SocketAddress` `net.BlockList`.
-
----
-
-- {% anchor id="node_os" %} [`node:os`](https://nodejs.org/api/os.html) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_path" %} [`node:path`](https://nodejs.org/api/path.html) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_perf_hooks" %} [`node:perf_hooks`](https://nodejs.org/api/perf_hooks.html) {% /anchor %}
-- 🟡
-- Only `perf_hooks.performance.now()` and `perf_hooks.performance.timeOrigin` are implemented. Recommended to use `performance` global instead of `perf_hooks.performance`.
-
----
-
-- {% anchor id="node_process" %} [`node:process`](https://nodejs.org/api/process.html) {% /anchor %}
-- 🟡
-- See `Globals > process`.
-
----
-
-- {% anchor id="node_punycode" %} [`node:punycode`](https://nodejs.org/api/punycode.html) {% /anchor %}
-- 🟢
-- Fully implemented. _Deprecated by Node.js._
-
----
-
-- {% anchor id="node_querystring" %} [`node:querystring`](https://nodejs.org/api/querystring.html) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_readline" %} [`node:readline`](https://nodejs.org/api/readline.html) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_repl" %} [`node:repl`](https://nodejs.org/api/repl.html) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_stream" %} [`node:stream`](https://nodejs.org/api/stream.html) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_string_decoder" %} [`node:string_decoder`](https://nodejs.org/api/string_decoder.html) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_sys" %} [`node:sys`](https://nodejs.org/api/util.html) {% /anchor %}
-- 🟡
-- See `node:util`.
-
----
-
-- {% anchor id="node_timers" %} [`node:timers`](https://nodejs.org/api/timers.html) {% /anchor %}
-- 🟢
-- Recommended to use global `setTimeout`, et. al. instead.
-
----
-
-- {% anchor id="node_tls" %} [`node:tls`](https://nodejs.org/api/tls.html) {% /anchor %}
-- 🟡
-- Missing `tls.createSecurePair`
-
----
-
-- {% anchor id="node_trace_events" %} [`node:trace_events`](https://nodejs.org/api/tracing.html) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_tty" %} [`node:tty`](https://nodejs.org/api/tty.html) {% /anchor %}
-- 🟡
-- Missing `tty.ReadStream` and `tty.WriteStream`.
-
----
-
-- {% anchor id="node_url" %} [`node:url`](https://nodejs.org/api/url.html) {% /anchor %}
-- 🟡
-- 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.transferableAbortController()` `util.transferableAbortSignal()`.
-
----
-
-- {% anchor id="node_v8" %} [`node:v8`](https://nodejs.org/api/v8.html) {% /anchor %}
-- 🔴
-- `serialize` and `deserialize` use JavaScriptCore's wire format instead of V8's. Otherwise, not implemented. For profiling, use [`bun:jsc`](/docs/project/benchmarking#bunjsc) instead.
-
----
-
-- {% anchor id="node_vm" %} [`node:vm`](https://nodejs.org/api/vm.html) {% /anchor %}
-- 🟡
-- Core functionality works, but VM modules are not implemented. `ShadowRealm` can be used.
-
----
-
-- {% anchor id="node_wasi" %} [`node:wasi`](https://nodejs.org/api/wasi.html) {% /anchor %}
-- 🟡
-- Partially implemented.
-
----
-
-- {% anchor id="node_worker_threads" %} [`node:worker_threads`](https://nodejs.org/api/worker_threads.html) {% /anchor %}
-- 🔴
-- Not implemented, but coming soon.
-
----
-
-- {% anchor id="node_zlib" %} [`node:zlib`](https://nodejs.org/api/zlib.html) {% /anchor %}
-- 🟡
-- Missing `zlib.brotli*`
-
-{% /table %}
-{% /block %} -->
+🟡 Missing `BrotliCompress` `BrotliDecompress` `brotliCompressSync` `brotliDecompress` `brotliDecompressSync` `createBrotliCompress` `createBrotliDecompress`. Unoptimized.
## Globals
@@ -485,7 +232,7 @@ The table below lists all globals implemented by Node.js and Bun's current compa
### [`console`](https://developer.mozilla.org/en-US/docs/Web/API/console)
-🟡 Missing `Console` constructor.
+🟢 Fully implemented.
### [`CountQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/CountQueuingStrategy)
@@ -589,7 +336,7 @@ The table below lists all globals implemented by Node.js and Bun's current compa
### [`process`](https://nodejs.org/api/process.html)
-🟡 Missing `process.allowedNodeEnvironmentFlags` `process.channel` `process.constrainedMemory()` `process.getActiveResourcesInfo/setActiveResourcesInfo()` `process.setuid/setgid/setegid/seteuid/setgroups()` `process.hasUncaughtExceptionCaptureCallback` `process.initGroups()` `process.report` `process.resourceUsage()`.
+🟡 Missing `domain` `hasUncaughtExceptionCaptureCallback` `initgroups` `report` `resourceUsage` `setUncaughtExceptionCaptureCallback` `setegid` `seteuid` `setgid` `setgroups` `setuid` `allowedNodeEnvironmentFlags` `getActiveResourcesInfo` `setActiveResourcesInfo` `moduleLoadList` `setSourceMapsEnabled` `channel`. `process.binding` is partially implemented.
### [`queueMicrotask()`](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask)
@@ -621,7 +368,7 @@ The table below lists all globals implemented by Node.js and Bun's current compa
### [`require()`](https://nodejs.org/api/globals.html#require)
-🟢 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)
+🟢 Fully implemented, including [`require.main`](https://nodejs.org/api/modules.html#requiremain), [`require.cache`](https://nodejs.org/api/modules.html#requirecache), [`require.resolve`](https://nodejs.org/api/modules.html#requireresolverequest-options)
### [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
@@ -702,421 +449,3 @@ The table below lists all globals implemented by Node.js and Bun's current compa
### [`WritableStreamDefaultWriter`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultWriter)
🟢 Fully implemented.
-
-<!-- {% table %}
-
----
-
-- {% anchor id="node_abortcontroller" %} [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_abortsignal" %} [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_blob" %} [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_buffer" %} [`Buffer`](https://nodejs.org/api/buffer.html#class-buffer) {% /anchor %}
-- 🟡
-- Incomplete implementation of `base64` and `base64url` encodings.
-
----
-
-- {% anchor id="node_bytelengthqueuingstrategy" %} [`ByteLengthQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/ByteLengthQueuingStrategy) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_dirname" %} [`__dirname`](https://nodejs.org/api/globals.html#__dirname) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_filename" %} [`__filename`](https://nodejs.org/api/globals.html#__filename) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_atob" %} [`atob()`](https://developer.mozilla.org/en-US/docs/Web/API/atob) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_broadcastchannel" %} [`BroadcastChannel`](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_btoa" %} [`btoa()`](https://developer.mozilla.org/en-US/docs/Web/API/btoa) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_clearimmediate" %} [`clearImmediate()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearImmediate) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_clearinterval" %} [`clearInterval()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearInterval) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_cleartimeout" %} [`clearTimeout()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearTimeout) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_compressionstream" %} [`CompressionStream`](https://developer.mozilla.org/en-US/docs/Web/API/CompressionStream) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_console" %} [`console`](https://developer.mozilla.org/en-US/docs/Web/API/console) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_countqueuingstrategy" %} [`CountQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/CountQueuingStrategy) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_crypto" %} [`Crypto`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_crypto" %} [`SubtleCrypto (crypto)`](https://developer.mozilla.org/en-US/docs/Web/API/crypto) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_cryptokey" %} [`CryptoKey`](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_customevent" %} [`CustomEvent`](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_decompressionstream" %} [`DecompressionStream`](https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_event" %} [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_eventtarget" %} [`EventTarget`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_exports" %} [`exports`](https://nodejs.org/api/globals.html#exports) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_fetch" %} [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/fetch) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_formdata" %} [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_global" %} [`global`](https://nodejs.org/api/globals.html#global) {% /anchor %}
-- 🟢
-- Implemented. This is an object containing all objects in the global namespace. It's rarely referenced directly, as its contents are available without an additional prefix, e.g. `__dirname` instead of `global.__dirname`.
-
----
-
-- {% anchor id="node_globalthis" %} [`globalThis`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis) {% /anchor %}
-- 🟢
-- Aliases to `global`.
-
----
-
-- {% anchor id="node_headers" %} [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_messagechannel" %} [`MessageChannel`](https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_messageevent" %} [`MessageEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_messageport" %} [`MessagePort`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_module" %} [`module`](https://nodejs.org/api/globals.html#module) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_performanceentry" %} [`PerformanceEntry`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_performancemark" %} [`PerformanceMark`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceMark) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_performancemeasure" %} [`PerformanceMeasure`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceMeasure) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_performanceobserver" %} [`PerformanceObserver`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_performanceobserverentrylist" %} [`PerformanceObserverEntryList`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserverEntryList) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_performanceresourcetiming" %} [`PerformanceResourceTiming`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_performance" %} [`performance`](https://developer.mozilla.org/en-US/docs/Web/API/performance) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_process" %} [`process`](https://nodejs.org/api/process.html) {% /anchor %}
-- 🟡
-- Missing `process.allowedNodeEnvironmentFlags` `process.channel()` `process.connected` `process.constrainedMemory()` `process.disconnect()` `process.getActiveResourcesInfo/setActiveResourcesInfo()` `process.setuid/setgid/setegid/seteuid/setgroups()` `process.hasUncaughtExceptionCaptureCallback` `process.initGroups()` `process.report` `process.resourceUsage()` `process.send()`.
-
----
-
-- {% anchor id="node_queuemicrotask" %} [`queueMicrotask()`](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_readablebytestreamcontroller" %} [`ReadableByteStreamController`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableByteStreamController) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_readablestream" %} [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_readablestreambyobreader" %} [`ReadableStreamBYOBReader`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamBYOBReader) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_readablestreambyobrequest" %} [`ReadableStreamBYOBRequest`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamBYOBRequest) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_readablestreamdefaultcontroller" %} [`ReadableStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultController) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_readablestreamdefaultreader" %} [`ReadableStreamDefaultReader`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultReader) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_require" %} [`require()`](https://nodejs.org/api/globals.html#require) {% /anchor %}
-- 🟢
-- 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)
-
----
-
-- {% anchor id="node_response" %} [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_request" %} [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_setimmediate" %} [`setImmediate()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_setinterval" %} [`setInterval()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/setInterval) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_settimeout" %} [`setTimeout()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_structuredclone" %} [`structuredClone()`](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_subtlecrypto" %} [`SubtleCrypto`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_domexception" %} [`DOMException`](https://developer.mozilla.org/en-US/docs/Web/API/DOMException) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_textdecoder" %} [`TextDecoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_textdecoderstream" %} [`TextDecoderStream`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoderStream) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_textencoder" %} [`TextEncoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_textencoderstream" %} [`TextEncoderStream`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoderStream) {% /anchor %}
-- 🔴
-- Not implemented.
-
----
-
-- {% anchor id="node_transformstream" %} [`TransformStream`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_transformstreamdefaultcontroller" %} [`TransformStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStreamDefaultController) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_url" %} [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_urlsearchparams" %} [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_webassembly" %} [`WebAssembly`](https://nodejs.org/api/globals.html#webassembly) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_writablestream" %} [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_writablestreamdefaultcontroller" %} [`WritableStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultController) {% /anchor %}
-- 🟢
-- Fully implemented.
-
----
-
-- {% anchor id="node_writablestreamdefaultwriter" %} [`WritableStreamDefaultWriter`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultWriter) {% /anchor %}
-- 🟢
-- Fully implemented.
-
-{% /table %} -->
diff --git a/docs/runtime/plugins.md b/docs/runtime/plugins.md
index 0286c7887..f2e0d7c77 100644
--- a/docs/runtime/plugins.md
+++ b/docs/runtime/plugins.md
@@ -17,7 +17,7 @@ const myPlugin: BunPlugin = {
};
```
-Plugins have to be registered before any other code runs! To achieve this, use the `preload` option in your [`bunfig.toml`](/docs/runtime/configuration). Bun automatically loads the files/modules specified in `preload` before running a file.
+Plugins have to be registered before any other code runs! To achieve this, use the `preload` option in your [`bunfig.toml`](/docs/runtime/bunfig). Bun automatically loads the files/modules specified in `preload` before running a file.
```toml
preload = ["./myPlugin.ts"]
@@ -45,7 +45,7 @@ plugin(
);
```
-Bun's plugin API is based on [esbuild](https://esbuild.github.io/plugins). Only [a subset](/docs/bundler/vs-esbuild#plugin-api) of the esbuild API is implemented, but some esbuild plugins "just work" in Bun, like the official [MDX loader](https://mdxjs.com/packages/esbuild/):
+Bun's plugin API is loosely based on [esbuild](https://esbuild.github.io/plugins). Only [a subset](/docs/bundler/vs-esbuild#plugin-api) of the esbuild API is implemented, but some esbuild plugins "just work" in Bun, like the official [MDX loader](https://mdxjs.com/packages/esbuild/):
```jsx
import { plugin } from "bun";
@@ -84,15 +84,20 @@ plugin({
});
```
-With this plugin, data can be directly imported from `.yaml` files.
+Register this file in `preload`:
+
+```toml#bunfig.toml
+preload = ["./yamlPlugin.ts"]
+```
+
+Once the plugin is registered, `.yaml` and `.yml` files can be directly imported.
{% codetabs %}
```ts#index.ts
-import "./yamlPlugin.ts"
-import {name, releaseYear} from "./data.yml"
+import data from "./data.yml"
-console.log(name, releaseYear);
+console.log(data);
```
```yaml#data.yml
@@ -127,7 +132,7 @@ In this case we're using `"object"`—a built-in loader (intended for use by plu
---
- `ts`
-- `.ts` `.mts` `cts`
+- `.ts` `.mts` `.cts`
- Transform TypeScript then transpile
---
@@ -212,6 +217,91 @@ import MySvelteComponent from "./component.svelte";
console.log(mySvelteComponent.render());
```
+## Virtual Modules
+
+{% note %}
+
+This feature is currently only available at runtime with `Bun.plugin` and not yet supported in the bundler, but you can mimick the behavior using `onResolve` and `onLoad`.
+
+{% /note %}
+
+To create virtual modules at runtime, use `builder.module(specifier, callback)` in the `setup` function of a `Bun.plugin`.
+
+For example:
+
+```js
+import { plugin } from "bun";
+
+plugin({
+ name: "my-virtual-module",
+
+ setup(build) {
+ build.module(
+ // The specifier, which can be any string
+ "my-transpiled-virtual-module",
+ // The callback to run when the module is imported or required for the first time
+ () => {
+ return {
+ contents: "console.log('hello world!')",
+ loader: "js",
+ };
+ },
+ );
+
+ build.module("my-object-virtual-module", () => {
+ return {
+ exports: {
+ foo: "bar",
+ },
+ loader: "object",
+ };
+ });
+ },
+});
+
+// Sometime later
+// All of these work
+import "my-transpiled-virtual-module";
+require("my-transpiled-virtual-module");
+await import("my-transpiled-virtual-module");
+require.resolve("my-transpiled-virtual-module");
+
+import { foo } from "my-object-virtual-module";
+const object = require("my-object-virtual-module");
+await import("my-object-virtual-module");
+require.resolve("my-object-virtual-module");
+```
+
+### Overriding existing modules
+
+You can also override existing modules with `build.module`.
+
+```js
+import { plugin } from "bun";
+build.module("my-object-virtual-module", () => {
+ return {
+ exports: {
+ foo: "bar",
+ },
+ loader: "object",
+ };
+});
+
+require("my-object-virtual-module"); // { foo: "bar" }
+await import("my-object-virtual-module"); // { foo: "bar" }
+
+build.module("my-object-virtual-module", () => {
+ return {
+ exports: {
+ baz: "quix",
+ },
+ loader: "object",
+ };
+});
+require("my-object-virtual-module"); // { baz: "quix" }
+await import("my-object-virtual-module"); // { baz: "quix" }
+```
+
## Reading the config
Plugins can read and write to the [build config](/docs/bundler#api) with `build.config`.
diff --git a/docs/runtime/typescript.md b/docs/runtime/typescript.md
index eade2f13b..e7c59fb1a 100644
--- a/docs/runtime/typescript.md
+++ b/docs/runtime/typescript.md
@@ -1,119 +1,35 @@
Bun treats TypeScript as a first-class citizen.
-## Running `.ts` files
-
-Bun can directly execute `.ts` and `.tsx` files just like vanilla JavaScript, with no extra configuration. If you import a `.ts` or `.tsx` file (or an `npm` module that exports these files), Bun internally transpiles it into JavaScript then executes the file.
-
-**Note** — Similar to other build tools, Bun does not typecheck the files. Use [`tsc`](https://www.typescriptlang.org/docs/handbook/compiler-options.html) (the official TypeScript CLI) if you're looking to catch static type errors.
-
{% callout %}
-**Is transpiling still necessary?** — Because Bun can directly execute TypeScript, you may not need to transpile your TypeScript to run in production. Bun internally transpiles every file it executes (both `.js` and `.ts`), so the additional overhead of directly executing your `.ts/.tsx` source files is negligible.
-
-That said, if you are using Bun as a development tool but still targeting Node.js or browsers in production, you'll still need to transpile.
+**Note** — To add type declarations for Bun APIs like the `Bun` global, follow the instructions at [Intro > TypeScript](/docs/typescript). This page describes how the Bun runtime runs TypeScript code.
{% /callout %}
-## Configuring `tsconfig.json`
-
-Bun supports a number of features that TypeScript doesn't support by default, such as extensioned imports, top-level await, and `exports` conditions. It also implements global APIs like the `Bun`. To enable these features, your `tsconfig.json` must be configured properly.
-
-{% callout %}
-If you initialized your project with `bun init`, everything is already configured properly.
-{% /callout %}
-
-To get started, install the `bun-types` package.
-
-```sh
-$ bun add -d bun-types # dev dependency
-```
-
-If you're using a canary build of Bun, use the `canary` tag. The canary package is updated on every commit to the `main` branch.
+## Running `.ts` files
-```sh
-$ bun add -d bun-types@canary
-```
+Bun can directly execute `.ts` and `.tsx` files just like vanilla JavaScript, with no extra configuration. If you import a `.ts` or `.tsx` file (or an `npm` module that exports these files), Bun internally transpiles it into JavaScript then executes the file.
-<!-- ### Quick setup
+**Note** — Similar to other build tools, Bun does not typecheck the files. Use [`tsc`](https://www.typescriptlang.org/docs/handbook/compiler-options.html) (the official TypeScript CLI) if you're looking to catch static type errors.
{% callout %}
-**Note** — This approach requires TypeScript 5.0 or later!
-
-{% /callout %}
-
-Add the following to your `tsconfig.json`.
+**Is transpiling still necessary?** — Because Bun can directly execute TypeScript, you may not need to transpile your TypeScript to run in production. Bun internally transpiles every file it executes (both `.js` and `.ts`), so the additional overhead of directly executing your `.ts/.tsx` source files is negligible.
-```json-diff
- {
-+ "extends": ["bun-types"]
- // other options...
- }
-```
+That said, if you are using Bun as a development tool but still targeting Node.js or browsers in production, you'll still need to transpile.
-{% callout %}
-**Note** — The `"extends"` field in your `tsconfig.json` can accept an array of values. If you're already using `"extends"`, just add `"bun-types"` to the array.
{% /callout %}
-That's it! You should be able to use Bun's full feature set without seeing any TypeScript compiler errors.
-
-### Manual setup -->
-
-### Recommended `compilerOptions`
-
-These are the recommended `compilerOptions` for a Bun project.
-
-```jsonc
-{
- "compilerOptions": {
- // add Bun type definitions
- "types": ["bun-types"],
-
- // enable latest features
- "lib": ["esnext"],
- "module": "esnext",
- "target": "esnext",
-
- // if TS 5.x+
- "moduleResolution": "bundler",
- "noEmit": true,
- "allowImportingTsExtensions": true,
- "moduleDetection": "force",
- // if TS 4.x or earlier
- "moduleResolution": "nodenext",
-
- "jsx": "react-jsx", // support JSX
- "allowJs": true, // allow importing `.js` from `.ts`
- "esModuleInterop": true, // allow default imports for CommonJS modules
-
- // best practices
- "strict": true,
- "forceConsistentCasingInFileNames": true,
- "skipLibCheck": true
- }
-}
-```
-
-### 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.
-Given the following `tsconfig.json`...
+Consider the following `tsconfig.json`.
```json
{
"compilerOptions": {
+ "baseUrl": "./src",
"paths": {
"data": ["./data.ts"]
}
@@ -121,7 +37,14 @@ Given the following `tsconfig.json`...
}
```
-...the import from `"data"` will work as expected.
+Bun will use `baseUrl` to resolve module paths.
+
+```ts
+// resolves to ./src/components/Button.tsx
+import { Button } from "components/Button.tsx";
+```
+
+Bun will also correctly resolve imports from `"data"`.
{% codetabs %}
diff --git a/docs/test/lifecycle.md b/docs/test/lifecycle.md
index fd804c9bb..3fa69b1e3 100644
--- a/docs/test/lifecycle.md
+++ b/docs/test/lifecycle.md
@@ -44,11 +44,11 @@ To scope the hooks to a test file:
```ts
import { describe, beforeAll } from "bun:test";
-describe("test group", () => {
- beforeAll(() => {
- // setup
- });
+beforeAll(() => {
+ // setup
+});
+describe("test group", () => {
// tests...
});
```
diff --git a/docs/test/mocks.md b/docs/test/mocks.md
index 31b5dab41..645e2a394 100644
--- a/docs/test/mocks.md
+++ b/docs/test/mocks.md
@@ -12,6 +12,23 @@ test("random", async () => {
});
```
+{% callout %}
+Alternatively, you can use the `jest.fn()` function, as in Jest. It behaves identically.
+
+```ts
+import { test, expect, jest } from "bun:test";
+const random = jest.fn(() => Math.random());
+
+test("random", async () => {
+ const val = random();
+ expect(val).toBeGreaterThan(0);
+ expect(random).toHaveBeenCalled();
+ expect(random).toHaveBeenCalledTimes(1);
+});
+```
+
+{% /callout %}
+
The result of `mock()` is a new function that's been decorated with some additional properties.
```ts
@@ -31,6 +48,29 @@ random.mock.results;
// ]
```
+The following properties and methods are implemented on mock functions.
+
+- [x] [mockFn.getMockName()](https://jestjs.io/docs/mock-function-api#mockfngetmockname)
+- [x] [mockFn.mock.calls](https://jestjs.io/docs/mock-function-api#mockfnmockcalls)
+- [x] [mockFn.mock.results](https://jestjs.io/docs/mock-function-api#mockfnmockresults)
+- [x] [mockFn.mock.instances](https://jestjs.io/docs/mock-function-api#mockfnmockinstances)
+- [x] [mockFn.mock.contexts](https://jestjs.io/docs/mock-function-api#mockfnmockcontexts)
+- [x] [mockFn.mock.lastCall](https://jestjs.io/docs/mock-function-api#mockfnmocklastcall)
+- [x] [mockFn.mockClear()](https://jestjs.io/docs/mock-function-api#mockfnmockclear)
+- [x] [mockFn.mockReset()](https://jestjs.io/docs/mock-function-api#mockfnmockreset)
+- [x] [mockFn.mockRestore()](https://jestjs.io/docs/mock-function-api#mockfnmockrestore)
+- [x] [mockFn.mockImplementation(fn)](https://jestjs.io/docs/mock-function-api#mockfnmockimplementationfn)
+- [x] [mockFn.mockImplementationOnce(fn)](https://jestjs.io/docs/mock-function-api#mockfnmockimplementationoncefn)
+- [x] [mockFn.mockName(name)](https://jestjs.io/docs/mock-function-api#mockfnmocknamename)
+- [x] [mockFn.mockReturnThis()](https://jestjs.io/docs/mock-function-api#mockfnmockreturnthis)
+- [x] [mockFn.mockReturnValue(value)](https://jestjs.io/docs/mock-function-api#mockfnmockreturnvaluevalue)
+- [x] [mockFn.mockReturnValueOnce(value)](https://jestjs.io/docs/mock-function-api#mockfnmockreturnvalueoncevalue)
+- [x] [mockFn.mockResolvedValue(value)](https://jestjs.io/docs/mock-function-api#mockfnmockresolvedvaluevalue)
+- [x] [mockFn.mockResolvedValueOnce(value)](https://jestjs.io/docs/mock-function-api#mockfnmockresolvedvalueoncevalue)
+- [x] [mockFn.mockRejectedValue(value)](https://jestjs.io/docs/mock-function-api#mockfnmockrejectedvaluevalue)
+- [x] [mockFn.mockRejectedValueOnce(value)](https://jestjs.io/docs/mock-function-api#mockfnmockrejectedvalueoncevalue)
+- [x] [mockFn.withImplementation(fn, callback)](https://jestjs.io/docs/mock-function-api#mockfnwithimplementationfn-callback)
+
## `.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()`.
diff --git a/docs/test/writing.md b/docs/test/writing.md
index ef26a802a..b8b0118f7 100644
--- a/docs/test/writing.md
+++ b/docs/test/writing.md
@@ -143,12 +143,6 @@ To run a test conditionally, use `test.if()`. The test will run if the condition
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", () => {
@@ -174,252 +168,252 @@ Bun implements the following matchers. Full Jest compatibility is on the roadmap
---
-- 🟢
+- ✅
- [`.not`](https://jestjs.io/docs/expect#not)
---
-- 🟢
+- ✅
- [`.toBe()`](https://jestjs.io/docs/expect#tobevalue)
---
-- 🟢
+- ✅
- [`.toEqual()`](https://jestjs.io/docs/expect#toequalvalue)
---
-- 🟢
+- ✅
- [`.toBeNull()`](https://jestjs.io/docs/expect#tobenull)
---
-- 🟢
+- ✅
- [`.toBeUndefined()`](https://jestjs.io/docs/expect#tobeundefined)
---
-- 🟢
+- ✅
- [`.toBeNaN()`](https://jestjs.io/docs/expect#tobenan)
---
-- 🟢
+- ✅
- [`.toBeDefined()`](https://jestjs.io/docs/expect#tobedefined)
---
-- 🟢
+- ✅
- [`.toBeFalsy()`](https://jestjs.io/docs/expect#tobefalsy)
---
-- 🟢
+- ✅
- [`.toBeTruthy()`](https://jestjs.io/docs/expect#tobetruthy)
---
-- 🟢
+- ✅
- [`.toContain()`](https://jestjs.io/docs/expect#tocontainitem)
---
-- 🟢
+- ✅
- [`.toStrictEqual()`](https://jestjs.io/docs/expect#tostrictequalvalue)
---
-- 🟢
+- ✅
- [`.toThrow()`](https://jestjs.io/docs/expect#tothrowerror)
---
-- 🟢
+- ✅
- [`.toHaveLength()`](https://jestjs.io/docs/expect#tohavelengthnumber)
---
-- 🟢
+- ✅
- [`.toHaveProperty()`](https://jestjs.io/docs/expect#tohavepropertykeypath-value)
---
-- 🔴
+- ❌
- [`.extend`](https://jestjs.io/docs/expect#expectextendmatchers)
---
-- 🟢
+- ✅
- [`.anything()`](https://jestjs.io/docs/expect#expectanything)
---
-- 🟢
+- ✅
- [`.any()`](https://jestjs.io/docs/expect#expectanyconstructor)
---
-- 🔴
+- ❌
- [`.arrayContaining()`](https://jestjs.io/docs/expect#expectarraycontainingarray)
---
-- 🔴
+- ❌
- [`.assertions()`](https://jestjs.io/docs/expect#expectassertionsnumber)
---
-- 🔴
+- ❌
- [`.closeTo()`](https://jestjs.io/docs/expect#expectclosetonumber-numdigits)
---
-- 🔴
+- ❌
- [`.hasAssertions()`](https://jestjs.io/docs/expect#expecthasassertions)
---
-- 🔴
+- ❌
- [`.objectContaining()`](https://jestjs.io/docs/expect#expectobjectcontainingobject)
---
-- 🟢
+- ✅
- [`.stringContaining()`](https://jestjs.io/docs/expect#expectstringcontainingstring)
---
-- 🟢
+- ✅
- [`.stringMatching()`](https://jestjs.io/docs/expect#expectstringmatchingstring--regexp)
---
-- 🔴
+- ❌
- [`.addSnapshotSerializer()`](https://jestjs.io/docs/expect#expectaddsnapshotserializerserializer)
---
-- 🟢
+- ✅
- [`.resolves()`](https://jestjs.io/docs/expect#resolves)
---
-- 🟢
+- ✅
- [`.rejects()`](https://jestjs.io/docs/expect#rejects)
---
-- 🟢
+- ✅
- [`.toHaveBeenCalled()`](https://jestjs.io/docs/expect#tohavebeencalled)
---
-- 🟢
+- ✅
- [`.toHaveBeenCalledTimes()`](https://jestjs.io/docs/expect#tohavebeencalledtimesnumber)
---
-- 🔴
+- ❌
- [`.toHaveBeenCalledWith()`](https://jestjs.io/docs/expect#tohavebeencalledwitharg1-arg2-)
---
-- 🔴
+- ❌
- [`.toHaveBeenLastCalledWith()`](https://jestjs.io/docs/expect#tohavebeenlastcalledwitharg1-arg2-)
---
-- 🔴
+- ❌
- [`.toHaveBeenNthCalledWith()`](https://jestjs.io/docs/expect#tohavebeennthcalledwithnthcall-arg1-arg2-)
---
-- 🔴
+- ❌
- [`.toHaveReturned()`](https://jestjs.io/docs/expect#tohavereturned)
---
-- 🔴
+- ❌
- [`.toHaveReturnedTimes()`](https://jestjs.io/docs/expect#tohavereturnedtimesnumber)
---
-- 🔴
+- ❌
- [`.toHaveReturnedWith()`](https://jestjs.io/docs/expect#tohavereturnedwithvalue)
---
-- 🔴
+- ❌
- [`.toHaveLastReturnedWith()`](https://jestjs.io/docs/expect#tohavelastreturnedwithvalue)
---
-- 🔴
+- ❌
- [`.toHaveNthReturnedWith()`](https://jestjs.io/docs/expect#tohaventhreturnedwithnthcall-value)
---
-- 🟢
+- ✅
- [`.toBeCloseTo()`](https://jestjs.io/docs/expect#tobeclosetonumber-numdigits)
---
-- 🟢
+- ✅
- [`.toBeGreaterThan()`](https://jestjs.io/docs/expect#tobegreaterthannumber--bigint)
---
-- 🟢
+- ✅
- [`.toBeGreaterThanOrEqual()`](https://jestjs.io/docs/expect#tobegreaterthanorequalnumber--bigint)
---
-- 🟢
+- ✅
- [`.toBeLessThan()`](https://jestjs.io/docs/expect#tobelessthannumber--bigint)
---
-- 🟢
+- ✅
- [`.toBeLessThanOrEqual()`](https://jestjs.io/docs/expect#tobelessthanorequalnumber--bigint)
---
-- 🟢
+- ✅
- [`.toBeInstanceOf()`](https://jestjs.io/docs/expect#tobeinstanceofclass)
---
-- 🔴
+- ❌
- [`.toContainEqual()`](https://jestjs.io/docs/expect#tocontainequalitem)
---
-- 🟢
+- ✅
- [`.toMatch()`](https://jestjs.io/docs/expect#tomatchregexp--string)
---
-- 🟢
+- ✅
- [`.toMatchObject()`](https://jestjs.io/docs/expect#tomatchobjectobject)
---
-- 🟢
+- ✅
- [`.toMatchSnapshot()`](https://jestjs.io/docs/expect#tomatchsnapshotpropertymatchers-hint)
---
-- 🔴
+- ❌
- [`.toMatchInlineSnapshot()`](https://jestjs.io/docs/expect#tomatchinlinesnapshotpropertymatchers-inlinesnapshot)
---
-- 🔴
+- ❌
- [`.toThrowErrorMatchingSnapshot()`](https://jestjs.io/docs/expect#tothrowerrormatchingsnapshothint)
---
-- 🔴
+- ❌
- [`.toThrowErrorMatchingInlineSnapshot()`](https://jestjs.io/docs/expect#tothrowerrormatchinginlinesnapshotinlinesnapshot)
{% /table %}
diff --git a/docs/typescript.md b/docs/typescript.md
new file mode 100644
index 000000000..ca1b5cefd
--- /dev/null
+++ b/docs/typescript.md
@@ -0,0 +1,73 @@
+To install the TypeScript definitions for Bun's built-in APIs, install `bun-types`.
+
+```sh
+$ bun add -d bun-types # dev dependency
+```
+
+Then include `"bun-types"` in the `compilerOptions.types` in your `tsconfig.json`:
+
+```json-diff
+ {
+ "compilerOptions": {
++ "types": ["bun-types"]
+ }
+ }
+```
+
+At this point, you should be able to reference the `Bun` global in your TypeScript files without seeing errors in your editor.
+
+```ts
+console.log(Bun.version);
+```
+
+## Suggested `compilerOptions`
+
+Bun supports things like top-level await, JSX, and extensioned `.ts` imports, which TypeScript doesn't allow by default. Below is a set of recommended `compilerOptions` for a Bun project, so you can use these features without seeing compiler warnings from TypeScript.
+
+```jsonc
+{
+ "compilerOptions": {
+ // add Bun type definitions
+ "types": ["bun-types"],
+
+ // enable latest features
+ "lib": ["ESNext"],
+ "module": "esnext",
+ "target": "esnext",
+
+ // if TS 5.x+
+ "moduleResolution": "bundler",
+ "noEmit": true,
+ "allowImportingTsExtensions": true,
+ "moduleDetection": "force",
+ // if TS 4.x or earlier
+ // "moduleResolution": "nodenext",
+
+ "jsx": "react-jsx", // support JSX
+ "allowJs": true, // allow importing `.js` from `.ts`
+
+ // best practices
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "skipLibCheck": true,
+ "composite": true,
+ "downlevelIteration": true,
+ "allowSyntheticDefaultImports": true
+ }
+}
+```
+
+If you run `bun init` in a new directory, this `tsconfig.json` will be generated for you.
+
+```sh
+$ bun init
+```
+
+## DOM types
+
+Unfortunately, setting a value for `"types"` means that TypeScript will ignore other global type definitions, including `lib: ["dom"]`. If you need 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" />
+```