Various docs updates (#3437)

* Various docs updates

* Add mocks page

* Fix make

* WebKit instructions

* Update instructions

* Updates

* Update nodejs compat table

* Document trusted deps

* Tweak trustedDependencies docs

* Document --exact

* Update test docs

* Tweaks

* Boring

* Remove redundant j

* Undo makefile changes

* Undo makefile changes

* Update page title

* Regen

* Undo changes
This commit is contained in:
Colin McDonnell
2023-07-06 13:02:29 -07:00
committed by GitHub
parent 95ddfcc437
commit 109ebc14fd
13 changed files with 355 additions and 53 deletions

View File

@@ -67,7 +67,7 @@ Bun.serve({
fetch(req) {
throw new Error("woops!");
},
error(error: Error) {
error(error) {
return new Response(`<pre>${error}\n${error.stack}</pre>`, {
headers: {
"Content-Type": "text/html",
@@ -95,37 +95,37 @@ server.stop();
## TLS
Bun supports TLS out of the box, powered by [OpenSSL](https://www.openssl.org/). Enable TLS by passing in a value for `key` and `cert`; both are required to enable TLS. If needed, supply a `passphrase` to decrypt the `keyFile`.
Bun supports TLS out of the box, powered by [BoringSSL](https://boringssl.googlesource.com/boringssl). Enable TLS by passing in a value for `key` and `cert`; both are required to enable TLS.
```ts
Bun.serve({
fetch(req) {
return new Response("Hello!!!");
},
```ts-diff
Bun.serve({
fetch(req) {
return new Response("Hello!!!");
},
// can be string, BunFile, TypedArray, Buffer, or array thereof
key: Bun.file("./key.pem"),
cert: Bun.file("./cert.pem"),
// passphrase, only required if key is encrypted
passphrase: "super-secret",
});
+ tls: {
+ key: Bun.file("./key.pem"),
+ cert: Bun.file("./cert.pem"),
+ }
});
```
The `key` and `cert` fields expect the _contents_ of your TLS key and certificate. This can be a string, `BunFile`, `TypedArray`, or `Buffer`.
The `key` and `cert` fields expect the _contents_ of your TLS key and certificate, _not a path to it_. This can be a string, `BunFile`, `TypedArray`, or `Buffer`.
```ts
Bun.serve({
fetch() {},
// BunFile
key: Bun.file("./key.pem"),
// Buffer
key: fs.readFileSync("./key.pem"),
// string
key: fs.readFileSync("./key.pem", "utf8"),
// array of above
key: [Bun.file('./key1.pem'), Bun.file('./key2.pem')],
tls: {
// BunFile
key: Bun.file("./key.pem"),
// Buffer
key: fs.readFileSync("./key.pem"),
// string
key: fs.readFileSync("./key.pem", "utf8"),
// array of above
key: [Bun.file("./key1.pem"), Bun.file("./key2.pem")],
},
});
```
@@ -135,17 +135,35 @@ Bun.serve({
{% /callout %}
If your private key is encrypted with a passphrase, provide a value for `passphrase` to decrypt it.
```ts-diff
Bun.serve({
fetch(req) {
return new Response("Hello!!!");
},
tls: {
key: Bun.file("./key.pem"),
cert: Bun.file("./cert.pem"),
+ passphrase: "my-secret-passphrase",
}
});
```
Optionally, you can override the trusted CA certificates by passing a value for `ca`. By default, the server will trust the list of well-known CAs curated by Mozilla. When `ca` is specified, the Mozilla list is overwritten.
```ts
Bun.serve({
fetch(req) {
return new Response("Hello!!!");
},
key: Bun.file("./key.pem"), // path to TLS key
cert: Bun.file("./cert.pem"), // path to TLS cert
ca: Bun.file("./ca.pem"), // path to root CA certificate
});
```ts-diff
Bun.serve({
fetch(req) {
return new Response("Hello!!!");
},
tls: {
key: Bun.file("./key.pem"), // path to TLS key
cert: Bun.file("./cert.pem"), // path to TLS cert
+ ca: Bun.file("./ca.pem"), // path to root CA certificate
}
});
```
To override Diffie-Helman parameters:
@@ -153,7 +171,10 @@ To override Diffie-Helman parameters:
```ts
Bun.serve({
// ...
dhParamsFile: "./dhparams.pem", // path to Diffie Helman parameters
tls: {
// other config
dhParamsFile: "/path/to/dhparams.pem", // path to Diffie Helman parameters
},
});
```
@@ -274,11 +295,21 @@ interface Bun {
port?: number;
development?: boolean;
error?: (error: Error) => Response | Promise<Response>;
keyFile?: string;
certFile?: string;
caFile?: string;
dhParamsFile?: string;
passphrase?: string;
tls?: {
key?:
| string
| TypedArray
| BunFile
| Array<string | TypedArray | BunFile>;
cert?:
| string
| TypedArray
| BunFile
| Array<string | TypedArray | BunFile>;
ca?: string | TypedArray | BunFile | Array<string | TypedArray | BunFile>;
passphrase?: string;
dhParamsFile?: string;
};
maxRequestBodySize?: number;
lowMemoryMode?: boolean;
}): Server;

View File

@@ -28,8 +28,6 @@ for await (const chunk of stream) {
}
```
For a more complete discusson of streams in Bun, see [API > Streams](/docs/api/streams).
## Direct `ReadableStream`
Bun implements an optimized version of `ReadableStream` that avoid unnecessary data copying & queue management logic. With a traditional `ReadableStream`, chunks of data are _enqueued_. Each chunk is copied into a queue, where it sits until the stream is ready to send more data.
@@ -154,7 +152,9 @@ export class ArrayBufferSink {
stream?: boolean;
}): void;
write(chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer): number;
write(
chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
): number;
/**
* Flush the internal buffer
*

View File

@@ -49,7 +49,7 @@ To install in production mode (i.e. without `devDependencies`):
$ bun install --production
```
To install dependencies without allowing changes to lockfile (useful on CI):
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
@@ -124,6 +124,26 @@ To add a package as an optional dependency (`"optionalDependencies"`):
$ bun add --optional lodash
```
To add a package and pin to the resolved version, use `--exact`. This will resolve the version of the package and add it to your `package.json` with an exact version number instead of a version range.
```bash
$ bun add react --exact
```
This will add the following to your `package.json`:
```jsonc
{
"dependencies": {
// without --exact
"react": "^18.2.0", // this matches >= 18.2.0 < 19.0.0
// with --exact
"react": "18.2.0" // this matches only 18.2.0 exactly
}
}
```
To install a package globally:
```bash
@@ -206,6 +226,36 @@ In addition, the `--save` flag can be used to add `cool-pkg` to the `dependencie
}
```
## Trusted dependencies
Unlike other npm clients, Bun does not execute arbitrary lifecycle scripts for installed dependencies, such as `postinstall`. These scripts represent a potential security risk, as they can execute arbitrary code on your machine.
<!-- Bun maintains an allow-list of popular packages containing `postinstall` scripts that are known to be safe. To run lifecycle scripts for packages that aren't on this list, add the package to `trustedDependencies` in your package.json. -->
To tell Bun to allow lifecycle scripts for a particular package, add the package to `trustedDependencies` in your package.json.
```json-diff
{
"name": "my-app",
"version": "1.0.0",
+ "trustedDependencies": {
+ "my-trusted-package": "*"
+ }
}
```
Bun reads this field and will run lifecycle scripts for `my-trusted-package`. If you specify a version range, Bun will only execute lifecycle scripts if the resolved package version matches the range.
```json
{
"name": "my-app",
"version": "1.0.0",
"trustedDependencies": {
"my-trusted-package": "^1.0.0"
}
}
```
## Git dependencies
To add a dependency from a git repository:

View File

@@ -65,6 +65,24 @@ $ bun test --preload ./setup.ts
See [Test > Lifecycle](/docs/test/lifecycle) for complete documentation.
## Mocks
Create mocks with the `mock` function. Mocks are automatically reset between tests.
```
import { test, expect, mock } from "bun:test";
const random = mock(() => Math.random());
test("random", async () => {
const val = random();
expect(val).toBeGreaterThan(0);
expect(random).toHaveBeenCalled();
expect(random).toHaveBeenCalledTimes(1);
});
```
See [Test > Mocks](/docs/test/mocks) for complete documentation.
## Snapshot testing
Snapshots are supported by `bun test`. See [Test > Snapshots](/docs/test/snapshots) for complete documentation.

View File

@@ -135,13 +135,13 @@ export default {
description:
"Install all dependencies with `bun install`, or manage dependencies with `bun add` and `bun remove`.",
}),
page("install/workspaces", "Workspaces", {
description: "Bun's package manager supports workspaces and mono-repo development workflows.",
}),
page("install/cache", "Global cache", {
description:
"Bun's package manager installs all packages into a shared global cache to avoid redundant re-downloads.",
}),
page("install/workspaces", "Workspaces", {
description: "Bun's package manager supports workspaces and mono-repo development workflows.",
}),
page("install/lockfile", "Lockfile", {
description:
"Bun's binary lockfile `bun.lockb` tracks your resolved dependency ytrr, making future installs fast and repeatable.",
@@ -190,10 +190,13 @@ export default {
page("test/lifecycle", "Lifecycle hooks", {
description: "Add lifecycle hooks to your tests that run before/after each test or test run",
}),
page("test/mocks", "Mocks", {
description: "Mocks functions and track method calls",
}),
page("test/snapshots", "Snapshots", {
description: "Add lifecycle hooks to your tests that run before/after each test or test run",
}),
page("test/time", "Time", {
page("test/time", "Dates and times", {
description: "Control the date & time in your tests for more reliable and deterministic tests",
}),
page("test/dom", "DOM testing", {

View File

@@ -217,6 +217,37 @@ You'll need a very recent version of Valgrind due to DWARF 5 debug symbols. You
$ valgrind --fair-sched=try --track-origins=yes bun-debug <args>
```
## Updating `WebKit`
The Bun team will occasionally bump the version of WebKit used in Bun. When this happens, you may see something like this with you run `git status`.
```bash
$ git status
On branch my-branch
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: src/bun.js/WebKit (new commits)
```
For performance reasons, `bun submodule update` does not automatically update the WebKit submodule. To update, run the following commands from the root of the Bun repo:
```bash
$ bun install
$ make bindings
```
<!-- Check the [Bun repo](https://github.com/oven-sh/bun/tree/main/src/bun.js) to get the hash of the commit of WebKit is currently being used.
{% image width="270" src="https://github.com/oven-sh/bun/assets/3084745/51730b73-89ef-4358-9a41-9563a60a54be" /%} -->
<!--
```bash
$ cd src/bun.js/WebKit
$ git fetch
$ git checkout <hash>
``` -->
## Troubleshooting
### libarchive

View File

@@ -51,7 +51,7 @@ This page is updated regularly to reflect compatibility status of the latest ver
- {% anchor id="node_crypto" %} [`node:crypto`](https://nodejs.org/api/crypto.html) {% /anchor %}
- 🟡
- Missing `crypto.Certificate` `crypto.ECDH` `crypto.KeyObject` `crypto.X509Certificate` `crypto.checkPrime{Sync}` `crypto.createPrivateKey` `crypto.createPublicKey` `crypto.createSecretKey` `crypto.diffieHellman` `crypto.generateKey{Sync}` `crypto.generateKeyPair{Sync}` `crypto.generatePrime{Sync}` `crypto.getCipherInfo` `crypto.getCurves` `crypto.{get|set}Fips` `crypto.hkdf` `crypto.hkdfSync` `crypto.randomInt` `crypto.secureHeapUsed` `crypto.setEngine` `crypto.sign` `crypto.verify`
- Missing `crypto.Certificate` `crypto.ECDH` `crypto.KeyObject` `crypto.X509Certificate` `crypto.checkPrime{Sync}` `crypto.createPrivateKey` `crypto.createPublicKey` `crypto.createSecretKey` `crypto.diffieHellman` `crypto.generateKey{Sync}` `crypto.generateKeyPair{Sync}` `crypto.generatePrime{Sync}` `crypto.getCipherInfo` `crypto.getCurves` `crypto.{get|set}Fips` `crypto.hkdf` `crypto.hkdfSync` `crypto.secureHeapUsed` `crypto.setEngine` `crypto.sign` `crypto.verify`
---
@@ -87,7 +87,7 @@ This page is updated regularly to reflect compatibility status of the latest ver
- {% anchor id="node_fs" %} [`node:fs`](https://nodejs.org/api/fs.html) {% /anchor %}
- 🟡
- Missing `fs.fdatasync{Sync}` `fs.opendir{Sync}` `fs.readv{Sync}` `fs.{watch|watchFile|unwatchFile}` `fs.writev{Sync}`.
- Missing `fs.fdatasync{Sync}` `fs.opendir{Sync}` `fs.{watchFile|unwatchFile}` `fs.{cp|cpSync}`.
---
@@ -558,7 +558,7 @@ The table below lists all globals implemented by Node.js and Bun's current compa
- {% anchor id="node_require" %} [`require()`](https://nodejs.org/api/globals.html#require) {% /anchor %}
- 🟢
- Fully implemented.
- Fully implemented, as well as [`require.main`](https://nodejs.org/api/modules.html#requiremain), [`require.cache`](https://nodejs.org/api/modules.html#requirecache), and [`require.resolve`](https://nodejs.org/api/modules.html#requireresolverequest-options)
---

View File

@@ -93,6 +93,17 @@ These are the recommended `compilerOptions` for a Bun project.
}
```
### Add DOM types
Settings `"types": ["bun-types"]` means TypeScript will ignore other global type definitions, including `lib: ["dom"]`. To add DOM types into your project, add the following [triple-slash directives](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html) at the top of any TypeScript file in your project.
```ts
/// <reference lib="dom" />
/// <reference lib="dom.iterable" />
```
The same applies to other global type definition _libs_ like `webworker`.
## Path mapping
When resolving modules, Bun's runtime respects path mappings defined in [`compilerOptions.paths`](https://www.typescriptlang.org/tsconfig#paths) in your `tsconfig.json`. No other runtime does this.

View File

@@ -70,7 +70,7 @@ afterAll(() => {
Then use `--preload` to run the setup script before any test files.
```ts
bun test --preload ./setup.ts
$ bun test --preload ./setup.ts
```
To avoid typing `--preload` every time you run tests, it can be added to your `bunfig.toml`:

55
docs/test/mocks.md Normal file
View File

@@ -0,0 +1,55 @@
Create mocks with the `mock` function.
```ts
import { test, expect, mock } from "bun:test";
const random = mock(() => Math.random());
test("random", async () => {
const val = random();
expect(val).toBeGreaterThan(0);
expect(random).toHaveBeenCalled();
expect(random).toHaveBeenCalledTimes(1);
});
```
The result of `mock()` is a new function that's been decorated with some additional properties.
```ts
import { mock } from "bun:test";
const random = mock((multiplier: number) => multiplier * Math.random());
random(2);
random(10);
random.mock.calls;
// [[ 2 ], [ 10 ]]
random.mock.results;
// [
// { type: "return", value: 0.6533907460954099 },
// { type: "return", value: 0.6452713933037312 }
// ]
```
## `.spyOn()`
It's possible to track calls to a function without replacing it with a mock. Use `spyOn()` to create a spy; these spies can be passed to `.toHaveBeenCalled()` and `.toHaveBeenCalledTimes()`.
```ts
import { test, expect, spyOn } from "bun:test";
const ringo = {
name: "Ringo",
sayHi() {
console.log(`Hello I'm ${this.name}`);
},
};
const spy = spyOn(ringo, "sayHi");
test("spyon", () => {
expect(spy).toHaveBeenCalledTimes(0);
ringo.sayHi();
expect(spy).toHaveBeenCalledTimes(1);
});
```

View File

@@ -51,7 +51,9 @@ test("unlike in jest", () => {
});
```
Note that we have not implemented builtin support for mocking timers yet, but this is on the roadmap.
{% callout %}
**Timers** — Note that we have not implemented builtin support for mocking timers yet, but this is on the roadmap.
{% /callout %}
### Reset the system time
@@ -74,7 +76,13 @@ test("it was 2020, for a moment.", () => {
## Set the time zone
To change the time zone, either pass the `$TZ` environment variable to `bun test`, or set `process.env.TZ` at runtime:
To change the time zone, either pass the `$TZ` environment variable to `bun test`.
```sh
TZ=America/Los_Angeles bun test
```
Or set `process.env.TZ` at runtime:
```ts
import { test, expect } from "bun:test";
@@ -88,7 +96,7 @@ test("Welcome to California!", () => {
});
test("Welcome to New York!", () => {
// Unlike in jest, you can set the timezone multiple times at runtime and it will work.
// Unlike in Jest, you can set the timezone multiple times at runtime and it will work.
process.env.TZ = "America/New_York";
expect(new Date().getTimezoneOffset()).toBe(240);
expect(new Intl.DateTimeFormat().resolvedOptions().timeZone).toBe(

View File

@@ -63,6 +63,21 @@ test("2 * 2", done => {
});
```
## Timeouts
Optionally specify a per-test timeout in milliseconds by passing a number as the third argument to `test`.
```ts
import { test } from "bun:test";
test.skip("wat", async () => {
const data = await slowOperation();
expect(data).toBe(42);
}, 500); // test must run in <500ms
```
## `test.skip`
Skip individual tests with `test.skip`. These tests will not be run.
```ts
@@ -74,6 +89,8 @@ test.skip("wat", () => {
});
```
## `test.todo`
Mark a test as a todo with `test.todo`. These tests _will_ be run, and the test runner will expect them to fail. If they pass, you will be prompted to mark it as a regular test.
```ts
@@ -84,6 +101,71 @@ test.todo("fix this", () => {
});
```
To exlusively run tests marked as _todo_, use `bun test --todo`.
```sh
$ bun test --todo
```
## `test.only`
To run a particular test or suite of tests use `test.only()` or `describe.only()`. Once declared, running `bun test --skip` will only execute tests/suites that have been marked with `.only()`.
```ts
import { test, describe } from "bun:test";
test("test #1", () => {
// does not run
});
test.only("test #2", () => {
// runs
});
describe.only("only", () => {
test("test #3", () => {
// runs
});
});
```
The following command will only execute tests #2 and #3.
```sh
$ bun test --only
```
## `test.if`
To run a test conditionally, use `test.if()`. The test will run if the condition is truthy. This is particularly useful for tests that should only run on specific architectures or operating systems.
```ts
test.if(Math.random() > 0.5)("runs half the time", () => {
// ...
});
```
```ts
test.if(Math.random() > 0.5)("runs half the time", () => {
// ...
});
const macOS = process.arch === "darwin";
test.if(macOS)("runs on macOS", () => {
// runs if macOS
});
```
To instead skip a test based on some condition, use `test.skipIf()` or `describe.skipIf()`.
```ts
const macOS = process.arch === "darwin";
test.skipIf(macOS)("runs on non-macOS", () => {
// runs if *not* macOS
});
```
## Matchers
Bun implements the following matchers. Full Jest compatibility is on the roadmap; track progress [here](https://github.com/oven-sh/bun/issues/1825).