mirror of
https://github.com/oven-sh/bun
synced 2026-02-03 15:38:46 +00:00
Compare commits
5 Commits
dylan/pyth
...
claude/upd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ad975cd90 | ||
|
|
b295cdee6b | ||
|
|
7c1f1120b7 | ||
|
|
87e0af636f | ||
|
|
38117fb07d |
@@ -28,6 +28,49 @@ for await (const chunk of stream) {
|
||||
}
|
||||
```
|
||||
|
||||
### Convenience methods
|
||||
|
||||
Bun extends `ReadableStream` with convenience methods for consuming the entire stream as different data types. These methods allow you to consume streams directly without wrapping them in a `Response`:
|
||||
|
||||
```ts
|
||||
const stream = new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue("hello ");
|
||||
controller.enqueue("world");
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
|
||||
// Consume as text
|
||||
const text = await stream.text();
|
||||
console.log(text); // => "hello world"
|
||||
|
||||
// Consume as JSON
|
||||
const jsonStream = new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue('{"message": "hello"}');
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
const data = await jsonStream.json();
|
||||
console.log(data); // => { message: "hello" }
|
||||
|
||||
// Consume as bytes
|
||||
const bytes = await stream.bytes();
|
||||
console.log(bytes); // => Uint8Array
|
||||
|
||||
// Consume as blob
|
||||
const blob = await stream.blob();
|
||||
console.log(blob); // => Blob
|
||||
```
|
||||
|
||||
These methods are particularly useful when working with streams from `fetch()` or other APIs:
|
||||
|
||||
```ts
|
||||
const response = await fetch("https://api.example.com/data.json");
|
||||
const data = await response.body.json(); // Direct JSON parsing from stream
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -831,6 +831,37 @@ npm/strip-ansi 212,992 chars long-ansi 1.36 ms/iter 1.38 ms
|
||||
|
||||
```
|
||||
|
||||
## `Math.sumPrecise`
|
||||
|
||||
`Math.sumPrecise(values: number[]): number`
|
||||
|
||||
Calculates the sum of an array of numbers with high precision using the Kahan summation algorithm. This is a TC39 Stage 3 proposal that provides more accurate summation by compensating for floating-point rounding errors.
|
||||
|
||||
```ts
|
||||
// Standard addition can accumulate rounding errors
|
||||
const numbers = [0.1, 0.2, 0.3];
|
||||
const standardSum = numbers.reduce((a, b) => a + b, 0);
|
||||
console.log(standardSum); // => 0.6000000000000001
|
||||
|
||||
// Math.sumPrecise provides more accurate results
|
||||
const preciseSum = Math.sumPrecise(numbers);
|
||||
console.log(preciseSum); // => 0.6
|
||||
```
|
||||
|
||||
This is particularly useful for financial calculations, scientific computing, or any scenario where precision in floating-point arithmetic is critical:
|
||||
|
||||
```ts
|
||||
// Financial calculation example
|
||||
const transactions = [199.99, -50.0, 25.5, -10.25, 5.76];
|
||||
const balance = Math.sumPrecise(transactions);
|
||||
console.log(balance); // => 171.00
|
||||
|
||||
// Large array of small numbers
|
||||
const smallNumbers = Array(1000).fill(0.1);
|
||||
const preciseTotal = Math.sumPrecise(smallNumbers);
|
||||
console.log(preciseTotal); // => 100 (exact)
|
||||
```
|
||||
|
||||
## `estimateShallowMemoryUsageOf` in `bun:jsc`
|
||||
|
||||
The `estimateShallowMemoryUsageOf` function returns a best-effort estimate of the memory usage of an object in bytes, excluding the memory usage of properties or other objects it references. For accurate per-object memory usage, use `Bun.generateHeapSnapshot`.
|
||||
|
||||
@@ -309,6 +309,27 @@ socket.addEventListener("close", event => {});
|
||||
socket.addEventListener("error", event => {});
|
||||
```
|
||||
|
||||
### Client compression
|
||||
|
||||
Bun's WebSocket client supports `permessage-deflate` compression extension for efficient message transmission. Compression is automatically negotiated with the server during the handshake:
|
||||
|
||||
```ts
|
||||
const socket = new WebSocket("ws://localhost:3000");
|
||||
|
||||
// Compression is automatically enabled if the server supports it
|
||||
// No additional configuration needed
|
||||
```
|
||||
|
||||
When connecting to servers that support compression, messages will be automatically compressed and decompressed transparently. This can significantly reduce bandwidth usage, especially for text-heavy applications like chat systems or real-time data feeds.
|
||||
|
||||
The client will automatically negotiate the best compression parameters with the server, including:
|
||||
|
||||
- Window size optimization
|
||||
- Context takeover settings
|
||||
- Compression threshold handling
|
||||
|
||||
For servers built with `Bun.serve`, ensure `perMessageDeflate: true` is set in the server configuration to enable compression support.
|
||||
|
||||
## Reference
|
||||
|
||||
```ts
|
||||
|
||||
@@ -184,72 +184,6 @@ New in Bun v1.2.17
|
||||
|
||||
{% /note %}
|
||||
|
||||
Bun's `--compile` flag can create standalone executables that contain both server and client code, making it ideal for full-stack applications. When you import an HTML file in your server code, Bun automatically bundles all frontend assets (JavaScript, CSS, etc.) and embeds them into the executable. When Bun sees the HTML import on the server, it kicks off a frontend build process to bundle JavaScript, CSS, and other assets.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```ts#server.ts
|
||||
import { serve } from "bun";
|
||||
import index from "./index.html";
|
||||
|
||||
const server = serve({
|
||||
routes: {
|
||||
"/": index,
|
||||
"/api/hello": { GET: () => Response.json({ message: "Hello from API" }) },
|
||||
},
|
||||
});
|
||||
|
||||
console.log(`Server running at http://localhost:${server.port}`);
|
||||
```
|
||||
|
||||
```html#index.html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>My App</title>
|
||||
<link rel="stylesheet" href="./styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World</h1>
|
||||
<script src="./app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
```js#app.js
|
||||
console.log("Hello from the client!");
|
||||
```
|
||||
|
||||
```css#styles.css
|
||||
body {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
To build this into a single executable:
|
||||
|
||||
```sh
|
||||
bun build --compile ./server.ts --outfile myapp
|
||||
```
|
||||
|
||||
This creates a self-contained binary that includes:
|
||||
|
||||
- Your server code
|
||||
- The Bun runtime
|
||||
- All frontend assets (HTML, CSS, JavaScript)
|
||||
- Any npm packages used by your server
|
||||
|
||||
The result is a single file that can be deployed anywhere without needing Node.js, Bun, or any dependencies installed. Just run:
|
||||
|
||||
```sh
|
||||
./myapp
|
||||
```
|
||||
|
||||
Bun automatically handles serving the frontend assets with proper MIME types and cache headers. The HTML import is replaced with a manifest object that `Bun.serve` uses to efficiently serve pre-bundled assets.
|
||||
|
||||
For more details on building full-stack applications with Bun, see the [full-stack guide](/docs/bundler/fullstack).
|
||||
|
||||
## Worker
|
||||
|
||||
@@ -410,12 +344,12 @@ To trim down the size of the executable a little, pass `--minify` to `bun build
|
||||
|
||||
## Using Bun.build() API
|
||||
|
||||
You can also generate standalone executables using the `Bun.build()` JavaScript API. This is useful when you need programmatic control over the build process.
|
||||
You can also generate standalone executables using the `Bun.build()` JavaScript API. This is useful when you need programmatic control over the build process, CI/CD pipelines, or complex build configurations.
|
||||
|
||||
### Basic usage
|
||||
|
||||
```js
|
||||
await Bun.build({
|
||||
const result = await Bun.build({
|
||||
entrypoints: ["./app.ts"],
|
||||
outdir: "./dist",
|
||||
compile: {
|
||||
@@ -423,50 +357,139 @@ await Bun.build({
|
||||
outfile: "myapp.exe",
|
||||
},
|
||||
});
|
||||
|
||||
console.log(`Built executable: ${result.outputs[0].path}`);
|
||||
```
|
||||
|
||||
### Windows metadata with Bun.build()
|
||||
### Cross-platform compilation
|
||||
|
||||
When targeting Windows, you can specify metadata through the `windows` object:
|
||||
Build for multiple platforms programmatically with enhanced target support:
|
||||
|
||||
```js
|
||||
await Bun.build({
|
||||
entrypoints: ["./app.ts"],
|
||||
outdir: "./dist",
|
||||
compile: {
|
||||
target: "bun-windows-x64",
|
||||
outfile: "myapp.exe",
|
||||
// Enhanced cross-platform build configuration
|
||||
const platforms = [
|
||||
{
|
||||
target: "bun-windows-x64-modern",
|
||||
outfile: "app-windows-x64.exe",
|
||||
windows: {
|
||||
title: "My Application",
|
||||
publisher: "My Company Inc",
|
||||
version: "1.2.3.4",
|
||||
description: "A powerful application built with Bun",
|
||||
copyright: "© 2024 My Company Inc",
|
||||
hideConsole: false, // Set to true for GUI applications
|
||||
icon: "./icon.ico", // Path to icon file
|
||||
version: "1.0.0.0",
|
||||
icon: "./assets/icon.ico",
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Cross-compilation with Bun.build()
|
||||
|
||||
You can cross-compile for different platforms:
|
||||
|
||||
```js
|
||||
// Build for multiple platforms
|
||||
const platforms = [
|
||||
{ target: "bun-windows-x64", outfile: "app-windows.exe" },
|
||||
{ target: "bun-linux-x64", outfile: "app-linux" },
|
||||
{ target: "bun-darwin-arm64", outfile: "app-macos" },
|
||||
{
|
||||
target: "bun-linux-x64-baseline",
|
||||
outfile: "app-linux-x64",
|
||||
},
|
||||
{
|
||||
target: "bun-darwin-arm64",
|
||||
outfile: "app-macos-arm64",
|
||||
},
|
||||
{
|
||||
target: "bun-linux-arm64-musl",
|
||||
outfile: "app-linux-arm64-alpine",
|
||||
},
|
||||
];
|
||||
|
||||
for (const platform of platforms) {
|
||||
await Bun.build({
|
||||
entrypoints: ["./app.ts"],
|
||||
console.log(`Building for ${platform.target}...`);
|
||||
|
||||
const result = await Bun.build({
|
||||
entrypoints: ["./src/app.ts"],
|
||||
outdir: "./dist",
|
||||
minify: true,
|
||||
sourcemap: "external",
|
||||
compile: platform,
|
||||
});
|
||||
|
||||
if (result.success) {
|
||||
console.log(`✅ Built: ${result.outputs[0].path}`);
|
||||
} else {
|
||||
console.error(`❌ Failed to build for ${platform.target}`);
|
||||
for (const log of result.logs) {
|
||||
console.error(log.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Windows executable configuration
|
||||
|
||||
When targeting Windows, you can configure executable metadata (Windows only):
|
||||
|
||||
```js
|
||||
await Bun.build({
|
||||
entrypoints: ["./src/main.ts"],
|
||||
compile: {
|
||||
target: "bun-windows-x64",
|
||||
outfile: "MyApplication.exe",
|
||||
windows: {
|
||||
hideConsole: false, // Set to true for GUI apps without console
|
||||
icon: "./assets/app-icon.ico",
|
||||
title: "My Application",
|
||||
publisher: "ACME Corporation",
|
||||
version: "1.0.0.0",
|
||||
description: "My application description",
|
||||
copyright: "© 2024 ACME Corporation"
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
### Build with embedded assets
|
||||
|
||||
Combine executable compilation with asset embedding for fully self-contained applications:
|
||||
|
||||
```js
|
||||
await Bun.build({
|
||||
entrypoints: [
|
||||
"./src/server.ts", // Main server code
|
||||
"./static/**/*", // All static assets
|
||||
"./config.json", // Configuration files
|
||||
],
|
||||
outdir: "./dist",
|
||||
compile: {
|
||||
target: "bun-linux-x64",
|
||||
outfile: "server",
|
||||
},
|
||||
minify: true,
|
||||
sourcemap: "linked",
|
||||
naming: {
|
||||
asset: "[name]-[hash].[ext]", // Content-based asset hashing
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
This creates a single executable that includes your server code, all static assets, and configuration files - perfect for containerized deployments or edge computing scenarios.
|
||||
|
||||
### Integration with CI/CD
|
||||
|
||||
Example GitHub Actions workflow for cross-platform builds:
|
||||
|
||||
```js
|
||||
// build-script.js
|
||||
const targets = ["bun-windows-x64", "bun-linux-x64", "bun-darwin-arm64"];
|
||||
|
||||
for (const target of targets) {
|
||||
const [os, arch] = target.split("-").slice(1);
|
||||
const ext = os === "windows" ? ".exe" : "";
|
||||
|
||||
await Bun.build({
|
||||
entrypoints: ["./src/cli.ts"],
|
||||
outdir: "./dist",
|
||||
compile: {
|
||||
target,
|
||||
outfile: `myapp-${os}-${arch}${ext}`,
|
||||
},
|
||||
minify: true,
|
||||
define: {
|
||||
"process.env.BUILD_TIME": JSON.stringify(new Date().toISOString()),
|
||||
"process.env.VERSION": JSON.stringify(
|
||||
process.env.GITHUB_REF_NAME || "dev",
|
||||
),
|
||||
},
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -338,6 +338,25 @@ All paths are resolved relative to your HTML file, making it easy to organize yo
|
||||
|
||||
If you want to submit a PR, most of the [code is here](https://github.com/oven-sh/bun/blob/main/src/js/internal/html.ts). You could even copy paste that file into your project and use it as a starting point.
|
||||
|
||||
|
||||
### Full-stack bundling
|
||||
|
||||
You can bundle both your server and client code in a single build command:
|
||||
|
||||
```ts
|
||||
await Bun.build({
|
||||
entrypoints: [
|
||||
"./server.ts", // Server code with HTML imports
|
||||
"./src/app.tsx", // Client-side React app
|
||||
],
|
||||
outdir: "./dist",
|
||||
target: "bun",
|
||||
splitting: true, // Share common dependencies
|
||||
});
|
||||
```
|
||||
|
||||
This pattern is ideal for server-side rendering, static site generation, or any scenario where you want to co-locate your frontend assets with your backend logic.
|
||||
|
||||
## How this works
|
||||
|
||||
This is a small wrapper around Bun's support for HTML imports in JavaScript.
|
||||
|
||||
@@ -240,6 +240,29 @@ $ node --preserve-symlinks ./my-file.js # https://nodejs.org/api/cli.html#--pres
|
||||
|
||||
Bun's runtime does not currently expose an equivalent of `--preserve-symlinks`, though the code for it does exist.
|
||||
|
||||
## Isolated linker
|
||||
|
||||
Use the `--linker=isolated` flag to create isolated installs similar to pnpm's approach. This creates a node_modules layout where each package gets its own isolated directory, preventing dependency conflicts.
|
||||
|
||||
```bash
|
||||
$ bun install --linker=isolated
|
||||
```
|
||||
|
||||
With isolated linker:
|
||||
|
||||
- Each package is installed in its own isolated directory
|
||||
- Dependencies are linked only where explicitly declared
|
||||
- Prevents phantom dependencies (accessing undeclared dependencies)
|
||||
- Creates a more predictable dependency resolution
|
||||
- Similar to pnpm's node_modules structure
|
||||
|
||||
This is particularly useful for:
|
||||
|
||||
- Large monorepos with complex dependency trees
|
||||
- Projects that need strict dependency isolation
|
||||
- Preventing dependency version conflicts
|
||||
- Ensuring reproducible builds across environments
|
||||
|
||||
## npm registry metadata
|
||||
|
||||
bun uses a binary format for caching NPM registry responses. This loads much faster than JSON and tends to be smaller on disk.
|
||||
|
||||
@@ -251,9 +251,11 @@ Supports `patch`, `minor`, `major`, `premajor`, `preminor`, `prepatch`, `prerele
|
||||
|
||||
## pkg
|
||||
|
||||
Manage `package.json` data with get, set, delete, and fix operations.
|
||||
Manage `package.json` data with get, set, delete, and fix operations. These commands provide programmatic access to your `package.json` file for automation and scripting.
|
||||
|
||||
All commands support dot and bracket notation:
|
||||
### Supported Notation
|
||||
|
||||
All commands support dot and bracket notation for accessing nested properties:
|
||||
|
||||
```bash
|
||||
scripts.build # dot notation
|
||||
@@ -262,24 +264,75 @@ workspaces.0 # dot with numeric index
|
||||
scripts[test:watch] # bracket for special chars
|
||||
```
|
||||
|
||||
Examples:
|
||||
### get
|
||||
|
||||
Retrieve property values from `package.json`:
|
||||
|
||||
```bash
|
||||
# set
|
||||
$ bun pm pkg get name # single property
|
||||
$ bun pm pkg get name version # multiple properties
|
||||
$ bun pm pkg get # entire package.json
|
||||
$ bun pm pkg get scripts.build # nested property
|
||||
# Single property
|
||||
$ bun pm pkg get name
|
||||
my-package
|
||||
|
||||
# set
|
||||
$ bun pm pkg set name="my-package" # simple property
|
||||
$ bun pm pkg set scripts.test="jest" version=2.0.0 # multiple properties
|
||||
$ bun pm pkg set {"private":"true"} --json # JSON values with --json flag
|
||||
# Multiple properties
|
||||
$ bun pm pkg get name version
|
||||
my-package 1.0.0
|
||||
|
||||
# delete
|
||||
$ bun pm pkg delete description # single property
|
||||
$ bun pm pkg delete scripts.test contributors[0] # multiple/nested
|
||||
# Entire package.json
|
||||
$ bun pm pkg get
|
||||
|
||||
# fix
|
||||
$ bun pm pkg fix # auto-fix common issues
|
||||
# Nested property
|
||||
$ bun pm pkg get scripts.build
|
||||
webpack --mode=production
|
||||
```
|
||||
|
||||
### set
|
||||
|
||||
Update property values in `package.json`:
|
||||
|
||||
```bash
|
||||
# Simple property
|
||||
$ bun pm pkg set name="my-new-package"
|
||||
|
||||
# Multiple properties
|
||||
$ bun pm pkg set scripts.test="jest" version=2.0.0
|
||||
|
||||
# JSON values with --json flag
|
||||
$ bun pm pkg set {"private":"true","type":"module"} --json
|
||||
|
||||
# Nested properties
|
||||
$ bun pm pkg set scripts.build="vite build" scripts.dev="vite"
|
||||
|
||||
# Arrays
|
||||
$ bun pm pkg set keywords[0]="javascript" keywords[1]="bun"
|
||||
```
|
||||
|
||||
### delete
|
||||
|
||||
Remove properties from `package.json`:
|
||||
|
||||
```bash
|
||||
# Single property
|
||||
$ bun pm pkg delete description
|
||||
|
||||
# Multiple properties
|
||||
$ bun pm pkg delete scripts.test contributors[0]
|
||||
|
||||
# Nested properties
|
||||
$ bun pm pkg delete devDependencies.eslint
|
||||
```
|
||||
|
||||
### fix
|
||||
|
||||
Automatically fix common issues in `package.json`:
|
||||
|
||||
```bash
|
||||
$ bun pm pkg fix
|
||||
```
|
||||
|
||||
This command will:
|
||||
|
||||
- Fix incorrect property types
|
||||
- Sort dependencies alphabetically
|
||||
- Remove duplicate entries
|
||||
- Validate required fields
|
||||
- Fix common formatting issues
|
||||
|
||||
@@ -49,9 +49,9 @@ Limit the dependency tree depth:
|
||||
```bash
|
||||
$ bun why express --depth 2
|
||||
express@4.18.2
|
||||
└─ express-pollyfill@1.20.1 (requires ^4.18.2)
|
||||
└─ body-parser@1.20.1 (requires ^1.20.1)
|
||||
└─ accepts@1.3.8 (requires ^1.3.8)
|
||||
└─ my-app@1.0.0 (requires ^4.18.2)
|
||||
└─ body-parser@1.20.2 (requires ^1.20.1)
|
||||
└─ accepts@1.3.8 (requires ^1.3.5)
|
||||
└─ (deeper dependencies hidden)
|
||||
```
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ To update all dependencies to the latest versions (including breaking changes):
|
||||
bun update --latest
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
### `--json`
|
||||
|
||||
Use the `--json` flag to print the raw JSON response from the registry instead of the formatted report:
|
||||
@@ -32,6 +34,47 @@ Use the `--json` flag to print the raw JSON response from the registry instead o
|
||||
$ bun audit --json
|
||||
```
|
||||
|
||||
### Exit code
|
||||
### `--audit-level`
|
||||
|
||||
Set the minimum severity level for reporting vulnerabilities. Vulnerabilities below this level will be ignored:
|
||||
|
||||
```bash
|
||||
# Only report high and critical vulnerabilities
|
||||
$ bun audit --audit-level high
|
||||
|
||||
# Report moderate and above (default)
|
||||
$ bun audit --audit-level moderate
|
||||
|
||||
# Report all vulnerabilities including low severity
|
||||
$ bun audit --audit-level low
|
||||
```
|
||||
|
||||
Available levels: `low`, `moderate`, `high`, `critical`
|
||||
|
||||
### `--prod`
|
||||
|
||||
Only audit production dependencies, excluding devDependencies:
|
||||
|
||||
```bash
|
||||
$ bun audit --prod
|
||||
```
|
||||
|
||||
This is useful for checking only the dependencies that will be included in production builds.
|
||||
|
||||
### `--ignore`
|
||||
|
||||
Ignore specific vulnerabilities by their advisory ID:
|
||||
|
||||
```bash
|
||||
# Ignore a single vulnerability
|
||||
$ bun audit --ignore 1002548
|
||||
|
||||
# Ignore multiple vulnerabilities
|
||||
$ bun audit --ignore 1002548,1003456,1004789
|
||||
```
|
||||
|
||||
Use this flag to suppress known vulnerabilities that have been assessed as acceptable risks for your project.
|
||||
|
||||
## Exit code
|
||||
|
||||
`bun audit` will exit with code `0` if no vulnerabilities are found and `1` if the report lists any vulnerabilities. This will still happen even if `--json` is passed.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Bun's package manager can scan packages for security vulnerabilities before installation, helping protect your applications from supply chain attacks and known vulnerabilities.
|
||||
Bun's package manager includes a Security Scanner API that allows scanning packages for security vulnerabilities before installation, helping protect your applications from supply chain attacks and known vulnerabilities.
|
||||
|
||||
## Quick Start
|
||||
|
||||
@@ -23,7 +23,18 @@ Security scanners analyze packages during `bun install`, `bun add`, and other pa
|
||||
- Known security vulnerabilities (CVEs)
|
||||
- Malicious packages
|
||||
- License compliance issues
|
||||
- ...and more!
|
||||
- Supply chain attacks
|
||||
- Suspicious package behaviors
|
||||
- Outdated dependencies with known issues
|
||||
|
||||
### Integration with Package Installation
|
||||
|
||||
The Security Scanner API integrates seamlessly with Bun's package installation process:
|
||||
|
||||
1. **Pre-installation scanning**: Packages are scanned before being added to your project
|
||||
2. **Dependency tree analysis**: Entire dependency chains are evaluated for security issues
|
||||
3. **Real-time vulnerability database**: Scanners can query up-to-date vulnerability databases
|
||||
4. **Policy enforcement**: Custom security policies can be enforced across installations
|
||||
|
||||
### Security Levels
|
||||
|
||||
|
||||
@@ -428,7 +428,7 @@ This helps ensure all your assertions run, especially in complex async code with
|
||||
|
||||
## Type Testing
|
||||
|
||||
Bun includes `expectTypeOf` for testing typescript types, compatible with Vitest.
|
||||
Bun includes `expectTypeOf` for testing TypeScript types, providing full compatibility with Vitest's type testing API.
|
||||
|
||||
### expectTypeOf
|
||||
|
||||
@@ -445,31 +445,125 @@ To test your types:
|
||||
1. Write your type assertions using `expectTypeOf`
|
||||
2. Run `bunx tsc --noEmit` to check that your types are correct
|
||||
|
||||
#### Type Equality
|
||||
|
||||
Use `toEqualTypeOf` for strict type equality checks:
|
||||
|
||||
```ts
|
||||
import { expectTypeOf } from "bun:test";
|
||||
|
||||
// Basic type assertions
|
||||
// Generic syntax
|
||||
expectTypeOf<string>().toEqualTypeOf<string>();
|
||||
expectTypeOf(123).toBeNumber();
|
||||
expectTypeOf("hello").toBeString();
|
||||
expectTypeOf<{ name: string; age: number }>().toEqualTypeOf<{
|
||||
name: string;
|
||||
age: number;
|
||||
}>();
|
||||
|
||||
// Object type matching
|
||||
expectTypeOf({ a: 1, b: "hello" }).toMatchObjectType<{ a: number }>();
|
||||
// Inferred syntax
|
||||
expectTypeOf("hello").toEqualTypeOf<string>();
|
||||
expectTypeOf({ name: "Alice", age: 30 }).toEqualTypeOf<{
|
||||
name: string;
|
||||
age: number;
|
||||
}>();
|
||||
|
||||
// Function types
|
||||
// Using with values for inference
|
||||
const user = { name: "Alice", age: 30 };
|
||||
expectTypeOf(user).toEqualTypeOf<{ name: string; age: number }>();
|
||||
```
|
||||
|
||||
#### Object Type Matching
|
||||
|
||||
For testing object shapes without requiring exact matches, use `toMatchObjectType`:
|
||||
|
||||
```ts
|
||||
interface User {
|
||||
name: string;
|
||||
age: number;
|
||||
email?: string;
|
||||
}
|
||||
|
||||
const user = { name: "Alice", age: 30, isActive: true };
|
||||
|
||||
// This passes - user has at least the required properties
|
||||
expectTypeOf(user).toMatchObjectType<{ name: string; age: number }>();
|
||||
|
||||
// This would fail - user doesn't have email property
|
||||
// expectTypeOf(user).toMatchObjectType<{ name: string; email: string }>();
|
||||
```
|
||||
|
||||
#### Function Types
|
||||
|
||||
Test function signatures, parameters, and return types:
|
||||
|
||||
```ts
|
||||
function greet(name: string): string {
|
||||
return `Hello ${name}`;
|
||||
}
|
||||
|
||||
async function fetchUser(id: number): Promise<User> {
|
||||
// implementation
|
||||
}
|
||||
|
||||
// Function type checks
|
||||
expectTypeOf(greet).toBeFunction();
|
||||
expectTypeOf(greet).parameters.toEqualTypeOf<[string]>();
|
||||
expectTypeOf(greet).returns.toEqualTypeOf<string>();
|
||||
|
||||
// Array types
|
||||
expectTypeOf([1, 2, 3]).items.toBeNumber();
|
||||
// Async function checks
|
||||
expectTypeOf(fetchUser).parameters.toEqualTypeOf<[number]>();
|
||||
expectTypeOf(fetchUser).returns.resolves.toMatchObjectType<User>();
|
||||
```
|
||||
|
||||
// Promise types
|
||||
#### Array and Promise Types
|
||||
|
||||
```ts
|
||||
// Array item types
|
||||
expectTypeOf([1, 2, 3]).items.toBeNumber();
|
||||
expectTypeOf(["a", "b", "c"]).items.toBeString();
|
||||
|
||||
// Promise resolution types
|
||||
expectTypeOf(Promise.resolve(42)).resolves.toBeNumber();
|
||||
expectTypeOf(Promise.resolve("hello")).resolves.toBeString();
|
||||
|
||||
// Array of promises
|
||||
expectTypeOf([
|
||||
Promise.resolve(1),
|
||||
Promise.resolve(2),
|
||||
]).items.resolves.toBeNumber();
|
||||
```
|
||||
|
||||
#### Negation with `.not`
|
||||
|
||||
Use `.not` to assert that types do NOT match:
|
||||
|
||||
```ts
|
||||
expectTypeOf("hello").not.toBeNumber();
|
||||
expectTypeOf(123).not.toBeString();
|
||||
expectTypeOf({ a: 1 }).not.toEqualTypeOf<{ a: string }>();
|
||||
```
|
||||
|
||||
#### Advanced Examples
|
||||
|
||||
```ts
|
||||
// Generic type testing
|
||||
function identity<T>(value: T): T {
|
||||
return value;
|
||||
}
|
||||
|
||||
expectTypeOf(identity).toBeCallableWith("hello");
|
||||
expectTypeOf(identity<string>).parameters.toEqualTypeOf<[string]>();
|
||||
expectTypeOf(identity<number>).returns.toEqualTypeOf<number>();
|
||||
|
||||
// Union types
|
||||
type Status = "loading" | "success" | "error";
|
||||
const status: Status = "loading";
|
||||
expectTypeOf(status).toMatchTypeOf<Status>();
|
||||
|
||||
// Branded types
|
||||
type UserId = string & { readonly brand: unique symbol };
|
||||
declare const userId: UserId;
|
||||
expectTypeOf(userId).toBeString();
|
||||
expectTypeOf(userId).not.toEqualTypeOf<string>();
|
||||
```
|
||||
|
||||
For full documentation on expectTypeOf matchers, see the [API Reference](/reference/bun/test/expectTypeOf)
|
||||
@@ -756,3 +850,181 @@ Bun implements the following matchers. Full Jest compatibility is on the roadmap
|
||||
- [`.toThrowErrorMatchingInlineSnapshot()`](https://jestjs.io/docs/expect#tothrowerrormatchinginlinesnapshotinlinesnapshot)
|
||||
|
||||
{% /table %}
|
||||
|
||||
## Mock Return Value Matchers
|
||||
|
||||
Bun provides several matchers specifically for testing mock function return values. These matchers are particularly useful when you need to verify that mocked functions returned specific values during execution.
|
||||
|
||||
### `.toHaveReturnedWith()`
|
||||
|
||||
Use `toHaveReturnedWith` to verify that a mock function returned a specific value at least once:
|
||||
|
||||
```ts
|
||||
import { expect, test, mock } from "bun:test";
|
||||
|
||||
test("mock return value testing", () => {
|
||||
const mockCalculate = mock((a: number, b: number) => a + b);
|
||||
|
||||
mockCalculate(2, 3);
|
||||
mockCalculate(10, 5);
|
||||
|
||||
// Verify the mock returned 5 at least once
|
||||
expect(mockCalculate).toHaveReturnedWith(5);
|
||||
|
||||
// Verify the mock returned 15 at least once
|
||||
expect(mockCalculate).toHaveReturnedWith(15);
|
||||
});
|
||||
```
|
||||
|
||||
### `.toHaveLastReturnedWith()`
|
||||
|
||||
Use `toHaveLastReturnedWith` to verify that a mock function's most recent call returned a specific value:
|
||||
|
||||
```ts
|
||||
import { expect, test, mock } from "bun:test";
|
||||
|
||||
test("last return value testing", () => {
|
||||
const mockGreet = mock((name: string) => `Hello, ${name}!`);
|
||||
|
||||
mockGreet("Alice");
|
||||
mockGreet("Bob");
|
||||
mockGreet("Charlie");
|
||||
|
||||
// Verify the most recent call returned "Hello, Charlie!"
|
||||
expect(mockGreet).toHaveLastReturnedWith("Hello, Charlie!");
|
||||
});
|
||||
```
|
||||
|
||||
### `.toHaveNthReturnedWith()`
|
||||
|
||||
Use `toHaveNthReturnedWith` to verify that a mock function returned a specific value on the nth call (1-indexed):
|
||||
|
||||
```ts
|
||||
import { expect, test, mock } from "bun:test";
|
||||
|
||||
test("nth return value testing", () => {
|
||||
const mockMultiply = mock((a: number, b: number) => a * b);
|
||||
|
||||
mockMultiply(2, 3); // 1st call returns 6
|
||||
mockMultiply(4, 5); // 2nd call returns 20
|
||||
mockMultiply(10, 2); // 3rd call returns 20
|
||||
|
||||
// Verify the 1st call returned 6
|
||||
expect(mockMultiply).toHaveNthReturnedWith(1, 6);
|
||||
|
||||
// Verify the 2nd call returned 20
|
||||
expect(mockMultiply).toHaveNthReturnedWith(2, 20);
|
||||
|
||||
// Verify the 3rd call returned 20
|
||||
expect(mockMultiply).toHaveNthReturnedWith(3, 20);
|
||||
});
|
||||
```
|
||||
|
||||
### Complex Return Value Testing
|
||||
|
||||
These matchers work with complex return values like objects and arrays:
|
||||
|
||||
```ts
|
||||
import { expect, test, mock } from "bun:test";
|
||||
|
||||
test("complex return values", () => {
|
||||
const mockCreateUser = mock((name: string, age: number) => ({
|
||||
name,
|
||||
age,
|
||||
id: Math.floor(Math.random() * 1000),
|
||||
}));
|
||||
|
||||
const user1 = mockCreateUser("Alice", 25);
|
||||
const user2 = mockCreateUser("Bob", 30);
|
||||
|
||||
// Test with objects using partial matching
|
||||
expect(mockCreateUser).toHaveReturnedWith(
|
||||
expect.objectContaining({ name: "Alice", age: 25 }),
|
||||
);
|
||||
|
||||
// Test the last returned value
|
||||
expect(mockCreateUser).toHaveLastReturnedWith(
|
||||
expect.objectContaining({ name: "Bob", age: 30 }),
|
||||
);
|
||||
|
||||
// Test specific call's return value
|
||||
expect(mockCreateUser).toHaveNthReturnedWith(
|
||||
1,
|
||||
expect.objectContaining({ name: "Alice", age: 25 }),
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
### Working with Async Functions
|
||||
|
||||
These matchers also work with async functions and promises:
|
||||
|
||||
```ts
|
||||
import { expect, test, mock } from "bun:test";
|
||||
|
||||
test("async mock return values", async () => {
|
||||
const mockFetchUser = mock(async (id: number) => ({
|
||||
id,
|
||||
name: `User ${id}`,
|
||||
email: `user${id}@example.com`,
|
||||
}));
|
||||
|
||||
await mockFetchUser(1);
|
||||
await mockFetchUser(2);
|
||||
|
||||
// Test resolved values
|
||||
await expect(mockFetchUser).toHaveReturnedWith(
|
||||
Promise.resolve(expect.objectContaining({ id: 1, name: "User 1" })),
|
||||
);
|
||||
|
||||
await expect(mockFetchUser).toHaveLastReturnedWith(
|
||||
Promise.resolve(expect.objectContaining({ id: 2, name: "User 2" })),
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
## Global Mock Management
|
||||
|
||||
Bun provides utilities for managing all your mocks at once, which is particularly useful in test setup and teardown.
|
||||
|
||||
### `mock.clearAllMocks()`
|
||||
|
||||
Reset all mock function state (calls, results, etc.) without restoring their original implementations:
|
||||
|
||||
```ts
|
||||
import { expect, mock, test } from "bun:test";
|
||||
|
||||
test("clearing all mocks", () => {
|
||||
const mockFn1 = mock(() => "result1");
|
||||
const mockFn2 = mock(() => "result2");
|
||||
|
||||
// Use the mocks
|
||||
mockFn1();
|
||||
mockFn2();
|
||||
|
||||
expect(mockFn1).toHaveBeenCalledTimes(1);
|
||||
expect(mockFn2).toHaveBeenCalledTimes(1);
|
||||
|
||||
// Clear all mock history
|
||||
mock.clearAllMocks();
|
||||
|
||||
// Call counts are reset
|
||||
expect(mockFn1).toHaveBeenCalledTimes(0);
|
||||
expect(mockFn2).toHaveBeenCalledTimes(0);
|
||||
|
||||
// But implementations are preserved
|
||||
expect(mockFn1()).toBe("result1");
|
||||
expect(mockFn2()).toBe("result2");
|
||||
});
|
||||
```
|
||||
|
||||
This is useful in test setup to ensure a clean state:
|
||||
|
||||
```ts
|
||||
import { mock, beforeEach } from "bun:test";
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset all mock state before each test
|
||||
mock.clearAllMocks();
|
||||
});
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user