mcpField
B
bun-api

bun-api

github.com/dmythro開発7203 回インストール4 日前に更新
リポジトリ

bun-api について

bun-apiは、Bunプロジェクトに取り組む開発者やコーディングエージェント向けのスキルです。BunネイティブAPI、バージョンごとの挙動、複雑なコードを書く前に同梱ドキュメントを参照する方法を説明します。

主な機能

  1. 01BunネイティブAPIのガイド
  2. 02Bun 1.4.xのバージョン案内
  3. 03同梱APIドキュメントへの案内
  4. 04ランタイム固有の移行上の注意
  5. 05スクリプトやサービスのタスク案内

活用シーン

  1. 01プロジェクトのスクリプトで使うBun APIの選定
  2. 02Bunのパッチ間での挙動確認
  3. 03bun-types内のAPIリファレンス検索
  4. 04HTTP、ネットワーク、データベースコードの実装

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/dmythro/agent-skills --skill bun-api

インストール後、Claude Code で/bun-apiを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
file-io.md
hashing.md
http-server.md
image.md
migration-1.4.md
networking.md
redis-client.md
s3-client.md
shell-and-process.md
sql-client.md
sqlite-and-data.md
utilities.md
webview.md

詳細

Bun Runtime API

Bun は TypeScript をネイティブに実行します。tsc によるコンパイルも、ts-node も、ビルド手順も不要です。bun file.ts で任意の .ts ファイルを直接実行できます。実行時に型チェックは行われないため、型チェックには bun check(v1.4.3 以降。詳しくは bun-cli スキルを参照)を使用してください。Node.js の同等機能ではなく、Bun のネイティブ API を使用してください。より高速で使いやすく、追加の依存関係も不要です。

重要:Bun プロジェクト(bun.lock、bun.lockb、bunfig.toml のいずれかがある、または devDependencies に bun-types/@types/bun が含まれるプロジェクト)では、スクリプトの実行には必ず Bun を使用してください(node file.ts ではなく bun file.ts)。また、Node.js の同等機能よりも Bun のネイティブ API を優先してください。ランタイムを混在させると、気づきにくいバグや不要な再試行が発生します。

Bun v1.4.4 で検証済み(2026-10-22)。機能には導入されたバージョン(v1.4+、v1.4.1+、v1.4.2+、v1.4.3+、v1.4.4+)が記載されています。リリースで既存の動作が変更された場合は、古いプロジェクトでもこのスキルが正確であるよう、両方の動作を記載しています。バージョンが記載された項目に依存する前に、bun --version を確認してください。

バージョンガイド:各 1.4.x リリースの変更点

リリース追加機能既存コードの動作変更このバージョンにアップグレードするタイミング
1.4.0(2026-08-20)Bun.XML、TOML.stringify()、Bun.secrets、spawn({ cgroup })、{ dir } ルート、textStream()、fetch({ compress })、ML-DSA/ML-KEM、バックプレッシャー対応のネイティブ Web ストリームBun.cron がローカル時刻を読み取る、重複するヘッダーが ", " で結合される、Temporal が有効になる、Node 26 をターゲットにする(NODE_MODULE_VERSION 147)、Bun.connect/Bun.listen で rejectUnauthorized: true、MySQL の日付が UTC としてデコードされる、fetch のネットワークエラーが TypeError になる1.4 の API が必要な場合。まず cron のスケジュール、自己署名開発サーバー、MySQL の日付オフセットを監査してください
1.4.1(2026-09-04)Bun.serve({ http2 })、ストリーミング対応の Bun.write(path, response)、クライアントの WebSocket#pause()、crypto.argon2Sync()、Unix ソケットのキープアライブfetch() が Host ヘッダーではなく URL のホストに対して TLS を検証する、localhost がシステムリゾルバーを介さずに解決されるアップグレード先としては選ばないでください。AsyncLocalStorage の値が漏洩し、ワーカーの 'online' は最初のメッセージの後に発火します。1.4.2 以降を使用してください
1.4.2(2026-09-05)なし(バグ修正リリース).json() が JSON.parse のメッセージで拒否される、CMYK/YCCK JPEG をデコードできる1.4.1 を使用している場合
1.4.3(2026-10-10)Bun.FetchSession、Bun.ModuleGraph、CompressionStream の圧縮レベル、If-Range、fetch({ proxy: false })リクエストごとの checkServerIdentity によりリクエストごとに接続が必要になる、未 await の拒否された fetch() によりプロセスが 1 で終了する、ALL_PROXY とより広い NO_PROXY 構文が適用される、コード生成フラグが強制される、sql.begin() がロールバック済みのトランザクションを拒否するクライアントごとの TLS/プロキシ設定が必要な場合、または 1.4.1 時代のバグ(promisify(setTimeout)、キープアライブ時の ECONNRESET)に遭遇している場合
1.4.4(2026-10-22)bun:sqlite の関数と更新フック、SQL.camel による変換、sql.json()、動作する query.cancel()、PostgreSQL の COPY ストリーム、サーバーの ws.pause()、error(error, ws)、Bun.Glob の extglob、createWebSocketStream()WebSocket のクローズコード(1005、1006、1001)と ws イベント、*(...)/{1..3} の glob での意味、mTLS に requestCert が必要になる、複数文を含む SQLite のエラーがスローされる、データなしの Bun.hash() がスローされるbun:sqlite、Bun.SQL、ws、または WebSocket サーバーを使用している場合。JSONL をストリーミングする場合は 1.4.3 からアップグレードしてください

常に最新のパッチバージョンを使用してください。 各パッチはそれ以前のパッチのリグレッションを修正します(references/migration-1.4.md にリリースごとに記載)。そのため、「問題なく動作する」と分かっている古い 1.4.x に固定すると、既知のバグが残ります。コードベースをアップグレードする前に、その間にあるすべてのリリースについて「既存コードの動作変更」列を確認してください。アップグレードによって必要になる編集が記載されています。

まず Bun 自身のドキュメントを読む

Bun には、ランタイムと同じバージョンの完全なドキュメントが bun-types に含まれています。 bun-types または @types/bun がインストールされたプロジェクトでは、次の手順を実行してください。

node_modules/bun-types/docs/**/*.mdx   # full docs, plus ~180 task-shaped guides/
node_modules/bun-types/*.d.ts          # richest API surface (bun.d.ts, serve.d.ts, sql.d.ts)
node_modules/bun-types/CLAUDE.md       # Bun's own agent rules

複雑な Bun コードを書く前に、必ずドキュメントを参照してください。 このスキルでは、使用する API の選び方を説明します。付属のドキュメントでは、正確なシグネチャとオプションを確認できます。

  1. @types/bun ではなく bun-types を使用してください。 bun-types はすべての Bun リリースに含まれており、ドキュメントと型の両方を提供します。@types/bun は各リリースより遅れて更新され、多くの場合、1 日以上の遅れがあります。それにもかかわらず、bun init は latest として追加するため、最新の API で型チェックに失敗します(TS2339、TS2353)。@types/bun と並べて bun-types を追加しても、修正されるのはドキュメントの参照先だけです。型チェックでは引き続き、@types/bun にネストされた固定バージョンのコピーが使われます。両方を切り替えた後、bun --version と node_modules/bun-types/package.json を比較してください。

    bun remove @types/bun
    bun add -d bun-types@$(bun --version)   # then "types": ["bun-types"] in tsconfig.json
    
  2. 明示的なパスで開いてください。 Bun のグローバル仮想ストアが有効な場合、node_modules/bun-types はシンボリックリンクです。そのため、find node_modules -name '*.mdx' や rg <pattern> node_modules では何も見つかりませんが、find node_modules/bun-types/docs -name '*.mdx' は機能します。

  3. node_modules/ 内のファイルは絶対に編集しないでください。 グローバルストアでは、マシン上のすべてのプロジェクトが同じ inode を共有しているため、そこで書き込むとすべてのプロジェクトに影響します。bun patch を使用してください。

  4. インストールされていない場合はどうしますか? 同じパスをオンラインでも使用できます。docs/runtime/sql.mdx は https://bun.com/docs/runtime/sql にあります。

タスクドキュメントのパス(node_modules/bun-types/docs/ 以下)
HTTP サーバー、ルート、WebSocketruntime/http/server.mdx、runtime/http/routing.mdx、runtime/http/websockets.mdx
fetch、TCP、UDP、DNSruntime/networking/fetch.mdx、runtime/networking/tcp.mdx、runtime/networking/udp.mdx、runtime/networking/dns.mdx
ファイル I/O、ストリーム、バイナリデータruntime/file-io.mdx、runtime/streams.mdx、runtime/binary-data.mdx
シェル、サブプロセス、PTYruntime/shell.mdx、runtime/child-process.mdx
SQL、SQLite、Redis、S3runtime/sql.mdx、runtime/sqlite.mdx、runtime/redis.mdx、runtime/s3.mdx
パーサーruntime/json5.mdx、runtime/jsonl.mdx、runtime/xml.mdx、runtime/toml.mdx、runtime/yaml.mdx、runtime/markdown.mdx、runtime/file-types.mdx
画像、WebView、cron、シークレット、アーカイブruntime/image.mdx、runtime/webview.mdx、runtime/cron.mdx、runtime/secrets.mdx、runtime/archive.mdx
ハッシュ、ユーティリティ、semver、glob、Cookie、CSRFruntime/hashing.mdx、runtime/utils.mdx、runtime/semver.mdx、runtime/glob.mdx、runtime/cookies.mdx、runtime/csrf.mdx
アプリケーションインスタンス、文字列評価のロックダウン(v1.4.3 以降)runtime/module-graph.mdx、runtime/code-generation-from-strings.mdx
Node.js との互換性runtime/nodejs-compat.mdx

使用する場面

  • ファイルの生成、データの解析、マイグレーションの実行などのスクリプト
  • ファイル処理と変換のパイプライン
  • シェルスクリプトと自動化
  • SQLite(bun:sqlite)を使ったデータベース操作
  • 接続 URL を使ったデータベースクエリ — プロジェクトの .env または環境変数に DATABASE_URL がある場合(PostgreSQL、MySQL、Bun.sql() を使った SQLite)
  • S3 ストレージ操作 — プロジェクトに AWS_ACCESS_KEY_ID がある場合、または S3 互換ストレージ(Bun.s3)を使用する場合
  • Redis/Valkey のキャッシュと Pub/Sub — プロジェクトに REDIS_URL または VALKEY_URL がある場合(Bun.redis)
  • Bun プロジェクトで行うあらゆるスクリプト作業

HTTP サーバー(Bun.serve)

組み込みの HTTP サーバーです。Express、Fastify、http.createServer を置き換えます。

手作業で URL を解析するよりも routes を使用してください。パラメーター、メソッドごとのハンドラー、アロケーションのない静的レスポンスを利用できます。fetch は一致するリクエストがない場合のフォールバックです。

const server = Bun.serve({
  port: 3000,

  routes: {
    '/health': new Response('OK'),                    // static, zero-allocation
    '/api/users/:id': req => Response.json({ id: req.params.id }),
    '/api/posts': {                                   // per-method handlers
      GET: () => Response.json(listPosts()),
      POST: async req => Response.json(await req.json()),
    },
    '/static/*': { dir: './public' },                 // serve a directory (v1.4+)
  },

  fetch(req: Request): Response | Promise<Response> {  // unmatched requests
    return new Response('Not Found', { status: 404 })
  },

  error(error: Error): Response {
    return new Response(`Error: ${error.message}`, { status: 500 })
  },
})

console.log(`Listening on ${server.url}`)

ルートの優先順位は、完全一致 > :param > * > グローバルな /* です。登録された '/*' ルートは一致しないすべてのパスを受け取るため、'/*' ルートがない場合にのみ fetch が実行されます。フォールバックにはどちらか一方を使い、両方を使わないでください。ハンドラーには BunRequest(Request に params と cookies を加えたもの)が渡されます。

主なメソッド:server.stop()、server.reload()(ハンドラーのホットスワップ)、server.requestIP(req)、server.upgrade(req)(WebSocket)。

HTTP/2(v1.4.1 以降、実験的機能)。 http2: true を指定すると、同じポートで HTTP/2 と HTTP/1.1 を提供し、同じ routes と fetch を使用できます。TLS 接続では ALPN がプロトコルを選択し、HTTP/2 プリアンブルで開始するクリアテキスト接続(curl --http2-prior-knowledge、node:http2)では HTTP/2 が使用されます。http1: false を指定すると、HTTP/1.x クライアントを拒否します。server.upgrade()(WebSocket)とレスポンストレーラーは HTTP/1.1 専用のため、現時点では gRPC はこれを介して動作しません。

ファイルレスポンスの安全な再開(v1.4.3 以降)。 Bun.file() のボディと { dir } ルートはすでに Range に 206 で応答しますが、今回から If-Range にも対応します。If-Range が Last-Modified の日付、またはレスポンスに含まれる強い ETag と一致する場合にのみ範囲を送信します(Bun は Bun.file() のレスポンスに ETag を設定しないため、独自に追加してください)。それ以外の If-Range 値には全体を 200 で返します。{ dir } ルートの弱い ETag は一致しません。Bun 1.4.2 は If-Range を無視し、常に範囲を送信していました。

WebSocket(1.4.4 で変更)。 サーバーソケットでの ws.pause() / ws.resume() / ws.isPaused は、受信処理より速く送信するクライアントからの読み取りを停止し、アイドルタイムアウトを一時停止します。websocket.error(error, ws) には、ハンドラーが例外をスローしたソケットが渡されます(1.4.3 ではソケットが渡されませんでした)。すべてのハンドラーは省略可能です。クローズコードはプロトコルに従います。クライアントがコードを指定せずに close() すると、両端で 1005 が報告されます(1.4.3 では 1000)。一方、サーバー側の ws.close() は引き続き 1000 を送信し、server.stop(true) は 1001 Server closed を送信します(1.4.3 では 1006)。プロトコルエラーでは 1002 / 1007 / 1009 で接続を閉じます(リリースノート)。server.upgrade() の前に、Origin が許可リストに含まれているか確認してください。同一オリジンポリシーは WebSocket ハンドシェイクには適用されません。

mTLS(1.4.4 で変更)。 Bun.serve / Bun.listen / node:tls サーバーがクライアント証明書を要求するのは、requestCert: true の場合のみです。ca だけでは要求しなくなりました(1.4.3 では ca が設定されると常に証明書を要求していました)。相互 TLS を使用するには、両方を設定してください。

リファレンス:TLS、WebSocket のアップグレード、ストリーミングレスポンス、静的ファイルの提供、1.4 の動作変更については、references/http-server.md を参照してください。API 全体については、node_modules/bun-types/docs/runtime/http/server.mdx と runtime/http/routing.mdx を参照してください。

TCP / UDP ソケット

HTTP 以外のプロトコル向けの生ソケットです。TCP には Bun.listen() / Bun.connect()、UDP には Bun.udpSocket()、さらに組み込みの WebSocket クライアントと fetch() を使用します。

const server = Bun.listen({
  hostname: '127.0.0.1',
  port: 8080,
  socket: {
    open(socket) { socket.write('welcome\n') },
    data(socket, data) { /* Buffer */ },
  },
})

WebSocket クライアント(1.4.4 で変更)。 ブラウザーと同様に、close はサーバーの Close フレームを受信した後に発火します。スクリプトの最後で ws.close() を呼び出すと、終了までにもう 1 回のラウンドトリップが必要です。リリースノートによると、サーバーが応答しない場合は 30 秒後に 1006 が返されます(BUN_CONFIG_WS_CLOSE_TIMEOUT。ws.terminate() は即座に接続を閉じます)。接続に失敗すると、error(event.error.code に ECONNREFUSED などが設定されます)が発火し、その後 1006 と空の reason を伴って close が発火します。組み込みの ws パッケージは、npm の Node 用 ws と同じ動作になりました。'error' には .code を持つ Error が渡され、'close' には Buffer の reason が渡されます。リスナーのない 'error' はプロセスをクラッシュさせ、createWebSocketStream() が動作します。すべての ws ソケットに 'error' リスナーを追加してください。

リファレンス:TCP/UDP ハンドラー、Unix ソケット、WebSocket クライアント(ws+unix://、クローズコード、ws パッケージ)、fetch() のトランスポートオプション(HTTP/2、HTTP/3、プロキシ、システム CA)については、references/networking.md を参照してください。

fetch() セッションとプロキシ(v1.4.3 以降)

Bun.FetchSession を使うと、複数のリクエストに専用の TLS、プロキシ、キープアライブ設定と、プライベートな接続プールを持たせることができます。undici の Agent / dispatcher の代わりに使用してください。Bun に組み込まれている undici はこれらのクラスをエクスポートするためインポートは成功しますが、fetch() は dispatcher を無視します。

const session = new Bun.FetchSession({
  tls: { ca: await Bun.file('corp-ca.pem').text() },
  proxy: { url: 'http://proxy.internal:8080' },
  keepAlive: { idleTimeout: 30, maxIdleSockets: 8 },   // false: a new connection per request
})

const client = new SomeClient({ fetch: session.fetch }) // bound -- hand it to any client
await fetch('https://api.example.com/v1', { session })  // the same, through the global fetch
session.close()                                         // closes idle connections; stays usable
  • セッション同士、および通常の fetch() とセッションとの間で、接続が共有されることはありません。リクエストオプションはセッションの設定を上書きし、リクエストの tls はセッションの tls 全体を置き換えます。
  • 証明書のピン留めは、リクエストではなくセッションで行ってください。 リクエスト単位の tls.checkServerIdentity は専用の TLS 接続を確立し、レスポンス後に閉じます(3 件のリクエストならハンドシェイクは 3 回です。1.4.2 では接続が再利用されていました)。セッションでは接続ごとに 1 回実行され、その接続はプールされます。
  • session.fetch に preconnect はありません。オプションの型が typeof fetch の場合は、session.fetch as typeof fetch を渡してください。

プロキシの選択。 proxy: false を指定すると、HTTP_PROXY / HTTPS_PROXY / ALL_PROXY の設定にかかわらず直接接続します。スキーム固有の変数が未設定の場合に ALL_PROXY が適用されるようになりました(1.4.2 では無視されていました)。NO_PROXY は *.example.com、CIDR ブロック(10.0.0.0/8)、ポートなしの IPv6、host:port を受け付けます。また、明示的な proxy もバイパスします。ただし、respectNoProxy: false が設定されている場合を除きます。プロキシが CONNECT を拒否すると、fetch() は ERR_PROXY_TUNNEL で reject されます。1.4.2 では、プロキシの応答をオリジンからの応答として扱い、resolve していました。

try {
  await fetch(url, { proxy: { url: 'http://proxy.internal:8080', respectNoProxy: false } })
} catch (e: any) {
  if (e.code === 'ERR_PROXY_TUNNEL') console.error(e.status, e.headers.get('proxy-authenticate'))
}

リファレンス:セッションオプション、NO_PROXY の構文、checkServerIdentity のルールについては、references/networking.md および node_modules/bun-types/docs/runtime/networking/fetch.mdx を参照してください。

ファイル I/O

ファイルの読み込み
// Create a BunFile reference (lazy, no read yet)
const file = Bun.file('path/to/file.txt')

// Read contents
const text = await file.text()           // string
const json = await file.json()           // parsed JSON
const bytes = await file.arrayBuffer()   // ArrayBuffer
const stream = file.stream()             // ReadableStream
const blob = await file.blob()           // Blob

// File metadata
file.size                                // Size in bytes
file.type                                // MIME type (auto-detected)
file.name                                // File path
await file.exists()                      // Boolean

// Read from URL
const remote = Bun.file('https://example.com/data.json')
ファイルの書き込み
// Write string
await Bun.write('output.txt', 'content')

// Write from BunFile (efficient copy)
await Bun.write('copy.txt', Bun.file('original.txt'))

// Write JSON
await Bun.write('data.json', JSON.stringify(data, null, 2))

// Write Uint8Array / ArrayBuffer
await Bun.write('binary.dat', new Uint8Array([1, 2, 3]))

// Write a Response body -- streamed to disk (v1.4.1+; the whole body was buffered before)
await Bun.write('page.html', await fetch('https://example.com'))

// Write to stdout
await Bun.write(Bun.stdout, 'Hello\n')
標準入出力
Bun.stdin    // BunFile for stdin
Bun.stdout   // BunFile for stdout
Bun.stderr   // BunFile for stderr

// Read all of stdin
const input = await Bun.stdin.text()

// Stream stdin line by line
for await (const chunk of Bun.stdin.stream()) {
  // process chunk (Uint8Array)
}
よく使われるパターン
// JSON transform
const data = await Bun.file('input.json').json()
data.version = '2.0.0'
await Bun.write('output.json', JSON.stringify(data, null, 2))

// File generation from template
const template = await Bun.file('template.html').text()
const output = template.replace('{{title}}', 'My Page')
await Bun.write('index.html', output)

// Check if file exists before reading
const file = Bun.file('config.json')
if (await file.exists()) {
  const config = await file.json()
}

リファレンス:BunFile インターフェイス、write のオーバーロード、ストリーミング、MIME 検出、ファイル監視については、references/file-io.md を参照してください。

シェルとプロセスの実行

Bun.$(タグ付きテンプレートシェル)

シェルコマンドを実行する主な方法です。出力を含む Promise を返します。

import { $ } from 'bun'

// Basic execution
const result = await $`ls -la`
console.log(result.text())          // stdout as string

// With interpolation (auto-escaped)
const dir = 'my folder'
await $`ls ${dir}`                   // Safe: "my folder" is properly quoted

// Output methods
const output = await $`echo hello`
output.text()                        // "hello\n"
output.json()                        // Parse stdout as JSON
output.lines()                       // string[] (splits on newlines)
output.bytes()                       // Uint8Array
output.blob()                        // Blob
output.exitCode                      // number
output.stderr                        // Buffer

// Piping
await $`cat file.txt | grep pattern | wc -l`

// Quiet mode (suppress stdout)
await $`npm install`.quiet()

// No-throw mode (don't throw on non-zero exit)
const result = await $`command-that-might-fail`.nothrow()
if (result.exitCode !== 0) {
  console.error('Failed:', result.stderr.toString())
}

// Combined
await $`risky-command`.quiet().nothrow()

// Environment variables
await $`echo $HOME`.env({ HOME: '/custom' })

// Working directory
await $`ls`.cwd('/tmp')

// Redirect to file
await $`echo hello > output.txt`
await $`cat < input.txt`

// Pipe between commands
const input = Buffer.from('hello')
await $`cat`.stdin(input)
Bun.spawn(低レベル)

プロセスの実行をより細かく制御できます。

const proc = Bun.spawn(['command', 'arg1', 'arg2'], {
  cwd: '/path',
  env: { ...process.env, CUSTOM: 'value' },
  stdin: 'pipe',          // 'pipe' | 'inherit' | 'ignore' | BunFile | Blob | Response
  stdout: 'pipe',         // 'pipe' | 'inherit' | 'ignore' | BunFile
  stderr: 'pipe',         // 'pipe' | 'inherit' | 'ignore' | BunFile
  onExit(proc, exitCode, signalCode, error) {
    // Called when process exits
  },
})

// Write to stdin
proc.stdin.write('input data')
proc.stdin.end()

// Read stdout
const output = await new Response(proc.stdout).text()

// Wait for completion
await proc.exited                    // Promise<number> (exit code)

// Kill
proc.kill()                          // SIGTERM
proc.kill('SIGKILL')                 // Specific signal
Bun.spawnSync(同期)
const result = Bun.spawnSync(['command', 'arg1'], {
  cwd: '/path',
  env: { ...process.env },
})

result.exitCode     // number
result.stdout       // Buffer
result.stderr       // Buffer
result.success      // boolean

リファレンス:$ API 全般、spawn オプション、IPC、シグナル処理については、references/shell-and-process.md を参照してください。

Glob パターンマッチング

const glob = new Bun.Glob('**/*.ts')

// Async iteration
for await (const path of glob.scan({ cwd: './src', onlyFiles: true })) {
  console.log(path)
}

// Sync iteration
for (const path of glob.scanSync('./src')) {
  console.log(path)
}

// Test if a path matches
glob.match('src/index.ts')       // true
glob.match('README.md')          // false

// Scan options
glob.scan({
  cwd: './src',                  // Directory to scan (default: '.')
  dot: false,                    // Include dotfiles (default: false)
  onlyFiles: true,               // Skip directories (default: true)
  absolute: false,               // Return absolute paths (default: false)
  followSymlinks: false,         // Follow symlinks (default: false)
})

// Extglob and brace ranges (v1.4.4+)
new Bun.Glob('**/!(*.test).ts').match('src/cart.ts')      // true; src/cart.test.ts -> false
new Bun.Glob('src/@(app|lib)/**/*.ts').match('src/app/a.ts') // true
new Bun.Glob('shard-{1..3}.json').match('shard-2.json')   // true; also {01..10}, {a..e}, {1..9..2}

1.4.4 で変更 — glob 構文。 ?(...)、*(...)、+(...)、@(...)、!(...) は extglob 演算子で、{1..3} は範囲です。これは Bun が glob を使うすべての場所、つまり Bun.Glob、--filter、package.json の workspaces、files、sideEffects に適用されます("workspaces": ["packages/!(internal)"] が動作します)。1.4.3 ではこれらは文字列どおりにマッチしていたため、*(1).txt は copy(1).txt にマッチしましたが、現在は「1 が 0 回以上続き、その後に .txt が続く」という意味です。文字として指定するには *[(]1).txt と記述します。前置演算子のない括弧は文字列どおりに扱われ(app/(marketing)/**)、Bun Shell では引用符付きテキストと ${} の値は従来どおり文字列どおりに扱われます。また、{src/**,lib/**} は現在 src/a/b.ts にマッチします(1.4.3 では波括弧内の ** は * として扱われていました)。

環境変数と引数

Bun.env.NODE_ENV                 // Environment variable (same as process.env)
Bun.env.DATABASE_URL             // Typed access

Bun.argv                         // string[] — [bunPath, scriptPath, ...args]
// Equivalent: process.argv

Bun.main                         // Absolute path to the entry point script

import.meta.dir                  // Directory of current file
import.meta.file                 // Filename of current file
import.meta.path                 // Full path of current file
import.meta.dirname              // Same as import.meta.dir (Node.js compat)
import.meta.filename             // Same as import.meta.path (Node.js compat)

SQL クライアント(Bun.sql)— PostgreSQL、MySQL、SQLite

接続 URL を使ってデータベースをクエリする、組み込みの SQL クライアントです。依存関係は不要で、タグ付きテンプレートリテラル、自動プリペアドステートメント、コネクションプールに対応しています。プロジェクトの .env または環境変数に DATABASE_URL がある場合に使用してください。

import { sql, SQL } from "bun"

// Default instance -- auto-connects using DATABASE_URL from environment
const users = await sql`SELECT * FROM users WHERE active = ${true} LIMIT ${10}`

// Explicit connection
const db = new SQL("postgres://user:pass@localhost:5432/mydb")
const results = await db`SELECT * FROM users`

// MySQL
const mysql = new SQL("mysql://user:pass@localhost:3306/mydb")
オブジェクトヘルパーを使った挿入/更新
const user = { name: "Alice", email: "[email protected]" }

// Insert -- expands object to (column1, column2) VALUES (val1, val2)
const [newUser] = await sql`INSERT INTO users ${sql(user)} RETURNING *`

// Bulk insert
await sql`INSERT INTO users ${sql([user1, user2, user3])}`

// Update -- expands to SET column1 = val1, column2 = val2
await sql`UPDATE users SET ${sql(updates)} WHERE id = ${userId}`
トランザクション
await sql.begin(async (tx) => {
  const [user] = await tx`INSERT INTO users (name) VALUES (${"Alice"}) RETURNING *`
  await tx`INSERT INTO audit_log (action, user_id) VALUES ('created', ${user.id})`
})
// Auto-committed on success, rolled back on error
1.4.4 の新機能
import { sql, SQL } from "bun"

// snake_case columns, camelCase code -- both directions, every adapter
const db = new SQL({ url: process.env.DATABASE_URL, transform: SQL.camel })
await db`INSERT INTO users ${db({ firstName: "Alice" })}`   // INSERT INTO users ("first_name") ...
const [u] = await db`SELECT first_name FROM users`          // u.firstName === "Alice"

await sql`INSERT INTO settings (data) VALUES (${sql.json(42)})`   // JSON 42; a bare null stays SQL NULL
await sql`SELECT * FROM users WHERE id = ANY(${[1, 2, 3]})`       // PostgreSQL: arrays bind to array types

const q = sql`SELECT pg_sleep(30)`.execute()
setTimeout(() => q.cancel(), 100)               // PostgreSQL: the server stops it; q rejects

const r = await sql`SELECT id, tags FROM posts`
r.columns                                       // [{ name, type: <OID>, ... }]; null on SQLite
r.affectedRows                                  // rows written; 0 for a SELECT

// PostgreSQL COPY as web streams with backpressure
await Bun.file("users.csv").stream().pipeTo(sql`COPY users (id, name) FROM STDIN (FORMAT csv)`.writable())
const csv = new Response(sql`COPY users TO STDOUT (FORMAT csv, HEADER)`.readable())

1.4.4 で変更: Bun.SQL は PASSWORD 環境変数を読み取らなくなりました(PGPASSWORD、MYSQL_PASSWORD、URL、または password を使用してください)。new SQL({ filename }) は adapter がなくても SQLite を選択します(1.4.3 では PostgreSQL を試していました)。複数の文からなる SQLite の文字列はすべて実行され、パラメーターを指定できるのは最初の文だけです(1.4.3 では、先頭の PRAGMA 設定文も含め、行を返すものと判断した最初の文の後で停止していました)。affectedRows は SQLite と PostgreSQL で設定されます(常に null でした)。クエリが送信前にキャンセルされると、ERR_SQLITE_QUERY_CANCELLED/ERR_POSTGRES_QUERY_CANCELLED/ERR_MYSQL_QUERY_CANCELLED で reject されます(1.4.3 では処理が完了しませんでした)。また、SQLite では 2 回目の sql.begin() は cannot start a transaction within a transaction で失敗せず、待機します。PostgreSQL と MySQL の固有機能(配列バインディング、COPY、サーバー側キャンセル、channelBinding、bun --hot 実行時の接続再利用)はリリースノートに記載されています。確認に利用できるデータベースサーバーはありませんでした。

リファレンス:接続オプション、プール管理、セーブポイント、MySQL 固有機能、プリペアドステートメントの設定、変換、結果メタデータ、COPY、キャンセルについては、references/sql-client.md を参照してください。

S3 クライアント(Bun.s3)

Web 標準の Blob API を備えた組み込みの S3 クライアントです。依存関係は不要で、S3 互換サービス(AWS S3、Cloudflare R2、MinIO など)で動作します。プロジェクトの環境変数に AWS_ACCESS_KEY_ID または S3 互換の認証情報がある場合に使用してください。

import { s3, write } from "bun"

// Reads credentials from AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, etc.
const file = s3.file("data.json")              // Lazy reference, no network yet

// Read from S3
const data = await file.json()                  // Download and parse JSON
const text = await file.text()                  // Download as string
const stream = file.stream()                    // ReadableStream

// Upload to S3
await write(s3.file("output.json"), JSON.stringify(data))

// Presigned URLs (synchronous, no network request)
const url = s3.presign("report.pdf", {
  expiresIn: 3600,                              // 1 hour
  method: "PUT",                                // For uploads
  acl: "public-read",
})

// Delete
await file.delete()

リファレンス:カスタム S3Client、署名付き URL のオプション、マルチパートアップロード、Bun.serve からの配信については、references/s3-client.md を参照してください。

Redis クライアント(Bun.redis)

依存関係不要の、組み込み Redis/Valkey クライアントです。プロジェクトの環境変数に REDIS_URL または VALKEY_URL がある場合に使用してください。

import { redis, RedisClient } from "bun"

// Default client -- reads REDIS_URL from environment
await redis.set("key", "value")
const value = await redis.get("key")            // "value" | null

// With expiration
await redis.set("session", "data", "EX", 3600)

// Counter operations
await redis.incr("counter")
await redis.incrby("counter", 5)

// Hash operations
await redis.hset("user:1", "name", "Alice", "email", "[email protected]")
await redis.hget("user:1", "name")              // "Alice"

// Custom client
const client = new RedisClient("redis://user:pass@host:6379")

リファレンス:すべてのコマンド(文字列、ハッシュ、リスト、セット、ソート済みセット)、pub/sub、パイプライン、一般的なパターンについては、references/redis-client.md を参照してください。

アーカイブ(Bun.Archive)

オプションの gzip 圧縮を使って tarball を作成・展開します。

// Create archive
const archive = new Bun.Archive({
  "hello.txt": "Hello, World!",
  "config.json": JSON.stringify({ key: "value" }),
})
await Bun.write("archive.tar", archive)

// With gzip compression -- write the BYTES, not the Archive (see gotcha below)
const compressed = new Bun.Archive(
  { "hello.txt": "Hello, World!" },
  { compress: "gzip", level: 9 }        // level 1-12, default 6
)
await Bun.write("archive.tar.gz", await compressed.bytes())

// Extract (auto-detects gzip)
const tarball = await Bun.file("archive.tar.gz").bytes()
const extracted = new Bun.Archive(tarball)
await extracted.extract("./out")                   // -> number of entries
await extracted.extract("./out", { glob: ["src/**", "!**/*.test.ts"] })
const files = await extracted.files()              // -> Map<string, File>

注意点(v1.4.0 から v1.4.4 で確認済み): Bun.write(path, archive) はコンストラクターの compress オプションを無視し、.tar.gz というファイル名で非圧縮の tar を書き込みます。Bun のドキュメントでは Bun.write(path, archive) による圧縮が示されていますが、実際には圧縮されません。必ず await archive.bytes()(または await archive.blob())を渡してください。これらは compress オプションを正しく適用します(上流で追跡中:oven-sh/bun#30234)。

Archive は反復可能ではありません。for (const [name, contents] of archive) は例外になります。Map<string, File> を得るには await archive.files() を、展開するには await archive.extract(dir) を使用してください。

リファレンス:node_modules/bun-types/docs/runtime/archive.mdx

JSONC(コメント付き JSON)

コメントと末尾のカンマを含む JSON を解析します。jsonc-parser や json5 パッケージを置き換えます。

import { JSONC } from "bun"

const config = JSONC.parse(`{
  // Database config
  "host": "localhost",
  "port": 5432,  // default port
}`)

Bun は tsconfig.json、jsconfig.json、package.json、bun.lock の解析に JSONC を自動的に使用します。.jsonc ファイルは直接インポートできます:import config from "./config.jsonc"。

追加の解析機能とユーティリティ(v1.3+)

import { JSON5, JSONL, XML, TOML, markdown, cron, secrets } from "bun"

// JSON5 -- superset of JSON (comments, unquoted keys, trailing commas)
const config = JSON5.parse(`{ unquoted: 'value', /* comment */ }`)

// JSONL -- newline-delimited JSON
const records = JSONL.parse('{"a":1}\n{"a":2}\n')
JSONL.parseChunk(partial)                    // { values, read, done, error } for streams

// XML -- SIMD parser + serializer (v1.4+), replaces fast-xml-parser / xml2js
const order = XML.parse('<order id="A1"><item>Tea</item></order>')
// { order: { "@id": "A1", item: "Tea" } }   -- @attr / #text convention, values are strings
XML.parse(doc, { compact: false })           // { name, attributes, children } document tree

// TOML -- rewritten for TOML v1.1.0; stringify() added in v1.4
const cfg = TOML.parse('name = "app"')
TOML.stringify({ name: "app" })

// Markdown -- built-in CommonMark + GFM parser (replaces marked, remark, etc.)
const html = markdown.html("# Title\n\n**Bold** text.")
const ansi = markdown.ansi("# Title")        // ANSI terminal output (v1.3.12+)
markdown.react(readme)                       // React elements (v1.3.12+)
markdown.render(src, { heading: (c, { level }) => `<h${level}>${c}</h${level}>` })

// Cron -- OS-level jobs, in-process scheduler, and expression parser
const job = cron("0 9 * * 1-5", runReport)   // in-process (v1.3.12+)
const next = cron.parse("0 9 * * 1-5")       // -> Date | null  (NOT a string)

// Secrets -- OS credential store: Keychain / libsecret / Credential Manager (experimental)
await secrets.set({ service: "my-cli", name: "token", value: t })
const token = await secrets.get({ service: "my-cli", name: "token" })  // string | null

// ANSI-aware string utilities (replace wrap-ansi, slice-ansi npm packages)
const coloredText = "\x1b[31mHello, World!\x1b[0m"
Bun.wrapAnsi(coloredText, 80)              // Wrap to column width
Bun.sliceAnsi(coloredText, 0, 5)           // Grapheme-aware slice

1.4 での変更 — Bun.cron のタイムゾーン。 cron.parse() とプロセス内の cron(schedule, handler) は、スケジュールをプロセスのローカルタイムゾーンで読み取ります。1.4 より前は UTC を使用していました。以前の動作に戻すには、最後の引数として { tz: "UTC" } を渡します:

cron("0 9 * * *", handler, { tz: "UTC" })
cron.parse("0 9 * * *", Date.now(), { tz: "UTC" })

cron.parse() は Date を返します。式に一致する日時が 8 年以内にない場合(例:2 月 30 日)は null を返します。 cron.remove(title) には OS レベルのジョブの文字列タイトルを渡します。ジョブハンドルは受け付けません。 プロセス内のジョブは job.stop() または using で停止します。

1.4 での変更 — パーサーの厳格化。 TOML.parse() と bunfig.toml は、引用符で囲まれていない文字列値、 ペア間の改行不足、Number.MAX_SAFE_INTEGER を超える整数に対して SyntaxError をスローするようになりました。 JSONC.parse() は無効な入力と "" に対して SyntaxError をスローします(以前は {} を返していました)。 YAML.parse() は YAML 1.2 に準拠するため、yes/no/on/off はブール値ではなく文字列です。 GitHub Actions ワークフローの on: キーは "on" として解析されます。

リファレンス:すべての解析 API とユーティリティ API の詳細は、references/utilities.md を参照してください。


SQLite(bun:sqlite)

依存関係なしで使える、組み込みの SQLite3 です。組み込み/ローカルデータベース(ファイルベースまたはインメモリ)向けです。

import { Database } from 'bun:sqlite'

// Open database
const db = new Database('mydb.sqlite')
const db = new Database(':memory:')      // In-memory

// Enable WAL mode (recommended)
db.exec('PRAGMA journal_mode = WAL')

// Execute statements
db.exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)')

// Prepared statements
const insert = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)')
insert.run('Alice', '[email protected]')

// Query
const select = db.prepare('SELECT * FROM users WHERE name = ?')
const user = select.get('Alice')         // Single row or null
const users = select.all('Alice')        // All matching rows

// Named parameters
const stmt = db.prepare('SELECT * FROM users WHERE name = $name')
stmt.get({ $name: 'Alice' })

// Transactions
const insertMany = db.transaction((users) => {
  for (const user of users) {
    insert.run(user.name, user.email)
  }
})
insertMany([
  { name: 'Bob', email: '[email protected]' },
  { name: 'Carol', email: '[email protected]' },
])

// Close
db.close()
1.4.4 の新機能:JavaScript 関数と更新フック
db.function('add2', (a, b) => a + b)                       // SQL function; arity = fn.length
db.query('SELECT add2(12, 4) AS sum').get()                 // { sum: 16 }

db.run('CREATE TABLE expenses (category TEXT, dollars INTEGER)')
db.aggregate('add_all', { start: 0, step: (total, v) => total + v })   // like sum(); inverse -> window fn
db.query('SELECT category, add_all(dollars) AS total FROM expenses GROUP BY category').all()

db.onInsert = (_db, table, rowid) => console.log(`inserted ${table} ${rowid}`)   // also onUpdate, onDelete
db.onInsert = null                                          // remove

関数内でスローされたエラーは、そのクエリを実行した get()/all()/run() から表面化します。 シグネチャは better-sqlite3 により近くなり、関数もフックも自身の Database にクエリを実行できません (This database connection is busy executing a query)。stmt.reader/stmt.readonly は、文が行を返すか書き込みを行うかを示します。また、db[Symbol.for('sqlite-type')] は 'bun:sqlite' です。

1.4.4 での変更:

  • 名前付きパラメーターは、プレフィックスの有無にかかわらずバインドされます(どちらのモードでも):{ name: 'A' } は strict: true なしで $name に値を設定します(1.4.3 では NULL がバインドされていました)。また、{ $name: 'A' } は strict: true で動作します (1.4.3 では Missing parameter がスローされていました)。
  • 失敗した文があると、複数文の文字列に対する db.run()/db.exec() は停止してエラーをスローします。 1.4.3 では、最後以外の文で発生した UNIQUE 違反などの実行時エラーを無視し、残りの文を実行していました。
  • Date、Map、Promise のバインドは TypeError をスローします(以前は NULL がバインドされていました)。 また、{ readonly: true, create: true } は読み書きモードで開くのではなく、エラーをスローします。
  • db.transaction(fn) は、fn がすでに拒否された Promise を返すとロールバックします。 最初の await より前にスローする async 関数は、1.4.3 ではコミットされていました。トランザクション関数は同期処理にしてください。 await の後の処理はトランザクションの外で実行されます。
  • changes が数えるのは、その文自体が処理した行です。トリガーやカスケードによって書き込まれた行は含みません。

リファレンス:Database コンストラクター、Statement API、トランザクション、ユーザー定義関数、フック、列の型については、references/sqlite-and-data.md を参照してください。

ハッシュとパスワード

// Non-cryptographic (fast, for hash tables/checksums)
Bun.hash('input')                        // bigint (64-bit wyhash, fastest) -- not a number
Bun.hash.crc32('input')                  // number (CRC32)
Number(Bun.hash('user-123') % 16n)       // shard index 0..15: mix bigints, then convert

// Cryptographic
new Bun.CryptoHasher('sha256').update('data').digest('hex')

// Password hashing (async, bcrypt by default)
const hash = await Bun.password.hash('password')
const hash = await Bun.password.hash('password', { algorithm: 'argon2id' })
const valid = await Bun.password.verify('password', hash)

// Raw Argon2 tag via node:crypto (v1.4.1+) -- interop with hashes stored as bytes, not PHC strings
import { argon2Sync, randomBytes } from 'node:crypto'
argon2Sync('argon2id', { message: 'pw', nonce: randomBytes(16), parallelism: 1, tagLength: 32, memory: 65536, passes: 3 })  // Buffer

Bun.hash() とその 64 ビットアルゴリズムは bigint を返すため(1.4.3 と 1.4.4 で確認済み。@types/bun では 1.4.4 まで number | bigint と型付けされていました)、Bun.hash(key) % 16 は TypeError をスローします。v1.4.4 以降、 引数なし、undefined、null、または Bun.file()/S3 ファイルを指定した Bun.hash() は、""、"undefined"、"null"、または何もない値をハッシュ化する代わりに TypeError をスローします。先にファイルを読み取ってください (await file.bytes())。

リファレンス:すべてのハッシュアルゴリズム、CryptoHasher のストリーミング API、パスワードハッシュ化のオプション(bcrypt と argon2id の比較、コストパラメーター)については、references/hashing.md を参照してください。

圧縮

// Gzip
const compressed = Bun.gzipSync(data)         // Uint8Array → Uint8Array
const decompressed = Bun.gunzipSync(compressed)

// Deflate
const compressed = Bun.deflateSync(data)
const decompressed = Bun.inflateSync(compressed)

// Zstandard (zstd)
const compressed = Bun.zstdCompressSync(data)
const decompressed = Bun.zstdDecompressSync(compressed)

// With options
Bun.gzipSync(data, { level: 9, memLevel: 9 })
Bun.deflateSync(data, { level: 6 })
Bun.zstdCompressSync(data, { level: 3 })

すべての圧縮関数は Uint8Array | string | ArrayBuffer を受け取り、Uint8Array を返します。 memLevel と strategy は v1.4.4 以降で有効です。範囲外の値(memLevel が 1〜9 の範囲外、strategy が 0〜4 の範囲外)を指定すると RangeError がスローされます。1.4.3 ではどちらも無視され、デフォルト値で圧縮されていました。

ストリームの場合、CompressionStream では v1.4.3 以降、level を指定できます。それ以外では、brotli は品質 11 で実行されるため、大きな動的レスポンスでは時間がかかります。範囲は、gzip/deflate/deflate-raw が 0〜9、brotli が 0〜11、zstd が 1〜22 です。範囲外の値を指定すると RangeError がスローされます。Bun 1.4.2 ではオプションを受け付けますが、無視されます。

// Inside a Bun.serve handler
const body = Bun.file('big.json').stream().pipeThrough(new CompressionStream('brotli', { level: 4 }))
return new Response(body, { headers: { 'Content-Encoding': 'br' } })

ユーティリティ

// Which (find binary in PATH)
Bun.which('node')                        // '/usr/local/bin/node' or null
Bun.which('bun', { PATH: '/custom/bin' })

// Inspect (like console.log formatting)
Bun.inspect(obj)                         // string
Bun.inspect(obj, { depth: 4, colors: true })

// Module resolution
Bun.resolveSync('./module', '/from/dir')  // Resolved absolute path

// Deep equality
Bun.deepEquals(a, b)                     // boolean (structural equality)
Bun.deepEquals(a, b, true)              // Strict (differentiates 0 and -0)

// Sleep
await Bun.sleep(1000)                    // ms
await Bun.sleep(Bun.nanoseconds() + 1e9) // Until timestamp

// Timing
Bun.nanoseconds()                        // High-resolution timer (bigint)

// UUID
Bun.randomUUIDv7()                       // Time-ordered UUID v7

// String width (for terminal column alignment)
Bun.stringWidth('hello')                 // 5
Bun.stringWidth('你好')                  // 4 (CJK double-width)

// Peek at a promise without awaiting
const value = Bun.peek(promise)          // Returns value if resolved, promise if pending

// Color detection
Bun.color('red', 'css')                  // 'rgb(255, 0, 0)'
Bun.color('#ff0000', 'ansi')             // ANSI escape code
Bun.color('hsl(0, 100%, 50%)', 'number') // 0xff0000

リファレンス:ユーティリティ関数のシグネチャと使用例の全容については、references/utilities.md を参照してください。

Semver(Bun.semver)

組み込みの semver 操作機能です。npm パッケージ semver を置き換えます。

// Check if a version satisfies a range
Bun.semver.satisfies('1.2.3', '^1.0.0')     // true
Bun.semver.satisfies('2.0.0', '>=1.0 <2.0') // false
Bun.semver.satisfies('1.0.0-beta', '*')      // false (pre-release excluded by default)

// Sort versions (returns -1, 0, or 1)
Bun.semver.order('1.0.0', '2.0.0')          // -1 (a < b)
Bun.semver.order('2.0.0', '1.0.0')          // 1  (a > b)
Bun.semver.order('1.0.0', '1.0.0')          // 0  (equal)

// Sort an array of versions
const versions = ['3.0.0', '1.2.0', '2.1.0']
versions.sort(Bun.semver.order)              // ['1.2.0', '2.1.0', '3.0.0']

シリアライズ(bun:jsc)

効率的なシリアライズを実現するバイナリ構造化クローンです。

import { serialize, deserialize } from 'bun:jsc'

const data = { key: 'value', nested: [1, 2, 3] }
const bytes = serialize(data)              // Uint8Array
const restored = deserialize(bytes)        // Original structure

複雑なオブジェクトでは JSON.stringify/JSON.parse より高速です。Date、RegExp、Map、Set、ArrayBuffer など、JSON ではサポートされない型にも対応しています。

画像処理(Bun.Image)

組み込みの画像デコード/変換/エンコード機能(v1.3.14+)です。sharp と jimp を置き換えます。

const thumb = await Bun.file('upload.jpg')
  .image()
  .resize(400, 400, { fit: 'cover' })
  .rotate(90).flip().flop()
  .modulate({ brightness: 1.1 })
  .webp({ quality: 82 })
  .bytes()

await Bun.file('hero.jpg').image().resize(1024).webp().write('thumb.webp')
const { width, height, format } = await new Bun.Image(buffer).metadata()
const blur = await Bun.file('hero.jpg').image().placeholder()  // thumbhash data URL

const pasted = Bun.Image.fromClipboard()      // v1.4+, macOS/Windows only, null on Linux

フォーマットのサポート状況はプラットフォームによって異なります。同等の対応状況を前提にしないでください。

LinuxmacOSWindows
JPEG、PNG、WebP対応対応対応
GIF、BMP(デコードのみ)組み込みImageIOWIC
HEIC/AVIFERR_IMAGE_FORMAT_UNSUPPORTEDImageIO(AVIF のエンコードには Apple Silicon M3 以降が必要)WIC + Microsoft Store コーデック(HEIF Image Extensions/AV1 Video Extension)
TIFF デコード非対応ImageIOWIC
クリップボードnull を返す対応対応

JPEG/PNG/WebP は静的リンクされたコーデックを使用するため、エンコード結果はプラットフォーム間でバイト単位で一致します。HEIC/AVIF/TIFF(および macOS/Windows の GIF/BMP)は OS のバックエンドを経由します。.gif()/.bmp()/.tiff() のエンコーダーメソッドはありません。これらをデコードした画像は、JPEG/PNG/WebP として再エンコードしてください。CMYK および YCCK の JPEG(Photoshop や印刷用 PDF から書き出された印刷向け画像)は v1.4.2 以降でデコードでき、RGB に変換されるため、プラットフォームがサポートするすべての変換とエンコーダーを利用できます。1.4.1 以前では Image: decode failed で拒否されていました。v1.4.3 以降では、わずかに破損した JPEG(余分なバイト、終端マーカーの欠落、スキャンデータの切り詰め)もデコードでき、欠落ブロックは平坦なグレーで表示されます。1.4.2 では ERR_IMAGE_DECODE_FAILED で拒否されていました。

リファレンス:完全な互換性マトリックスについては、references/image.md および node_modules/bun-types/docs/runtime/image.mdx を参照してください。

ブラウザー自動化(Bun.WebView)

ヘッドレスブラウザー自動化機能(v1.3.12+)です。Playwright や Puppeteer を使わずに、ナビゲーション、クリック、入力、スクロール、JS の実行、スクリーンショットの撮影ができます(macOS ではシステムの WebKit、macOS、Linux、Windows ではインストール済みの Chrome/Chromium/Edge を使用します)。クリックとスクロールは実際のユーザー入力として処理されます。

await using view = new Bun.WebView({ width: 1280, height: 720 })
await view.navigate('https://bun.sh')
await view.click("a[href='/docs']")
const title = await view.evaluate('document.title')
await Bun.write('page.png', await view.screenshot())   // returns a Blob
await view.cdp('Page.captureScreenshot', {})           // raw CDP escape hatch

リファレンス:入力シミュレーションと CDP イベントについては、references/webview.md および node_modules/bun-types/docs/runtime/webview.mdx を参照してください。

Bun 1.4.x の新機能

簡潔なインデックスです。用途に合う機能があれば、コードを書く前にリンク先のドキュメントを確認してください。タグのない行は 1.4.0 で追加されました。

API用途ドキュメント(node_modules/bun-types/docs/)
Bun.XML.parse() / .stringify()fast-xml-parser/xml2js を使わずに XML を扱えます。.xml インポートはパース済みのドキュメントを返しますruntime/xml.mdx
Bun.TOML.stringify()TOML を書き込みます(パーサーは TOML v1.1.0 に準拠しました)runtime/toml.mdx
Bun.secretsドットファイルではなく OS のキーチェーンに認証情報を保存します(実験的)runtime/secrets.mdx
Bun.spawn({ cgroup })Linux で子プロセスの開始前にメモリ/PID 数の上限を設定しますruntime/child-process.mdx
Bun.Image.fromClipboard()システムのクリップボードから画像を読み取ります(macOS/Windows)runtime/image.mdx
res.textStream() / req.textStream()本文をバイト列ではなく、デコード済みの UTF-8 文字列として反復処理しますドキュメントページなし — bun-types/fetch.d.ts を参照
fetch(url, { compress: 'gzip' })リクエスト本文を圧縮し、Content-Encoding を設定しますruntime/networking/fetch.mdx
routes: { '/x/*': { dir: './public' } }ディレクトリを配信します。express.static/sirv の代わりになりますruntime/http/routing.mdx
process.on('memoryPressure', fn)OS からメモリ不足が報告されたときにキャッシュを破棄します。リスナーには 'warning' または 'critical' が渡されますドキュメントページなし — bun-types/overrides.d.ts を参照
Bun.isStandaloneExecutable--compile バイナリ内で、メモリ割り当てなしに処理を分岐しますbundler/executables.mdx
ML-DSA / ML-KEM耐量子署名と鍵カプセル化に使用しますruntime/nodejs-compat.mdx
Bun.serve({ http2: true }) (v1.4.1+)1 つのポートで HTTP/2 と HTTP/1.1 を使用します。HTTP/2 のみの場合は http1: false を指定しますruntime/http/server.mdx
Bun.write(path, response) のストリーム (v1.4.1+)本文をバッファリングせずにディスクへダウンロードしますruntime/file-io.mdx
WebSocket#pause() / resume() / isPaused (v1.4.1+)ピアに対するクライアント側のバックプレッシャーを制御します(Bun の拡張機能)ドキュメントページなし — bun-types/bun.d.ts を参照
crypto.argon2Sync() / コールバック版 argon2() (v1.4.1+)Node とバイト単位で一致する生の Argon2 タグを生成します。PHC 文字列には Bun.password を使用しますruntime/nodejs-compat.mdx
fetch(url, { unix }) のキープアライブ (v1.4.1+)Unix ソケット接続を再利用します。tls: { ca } も適用されますruntime/networking/fetch.mdx
ServerWebSocket の binaryType: "blob" (v1.4.1+)クライアントと同様に、バイナリフレームを Blob として受信しますruntime/http/websockets.mdx
import x from "./f" with { type: "text" } による型付きインポート (v1.4.1+)TypeScript 7.1+ でローダー型付きインポートを使用します(text、file、md、markdown、toml、yaml、jsonc、json5、xml、sqlite、html)bun-types/ts7.1/import-attributes.d.ts
Bun.FetchSession (v1.4.3+)プライベートプールを使って、クライアントごとの TLS、プロキシ、キープアライブ設定を行います。undici の Agent/dispatcher の代わりになりますruntime/networking/fetch.mdx
fetch(url, { proxy: false })、respectNoProxy (v1.4.3+)1 つのリクエストでプロキシ環境変数を無視するか、明示的なプロキシに対して NO_PROXY を無視しますruntime/networking/fetch.mdx
Bun.ModuleGraph (v1.4.3+、実験的)1 つのプロセスで同じアプリのインスタンスを複数実行し、それぞれに新しいモジュール状態、独自のタイマーと I/O を持たせます。サンドボックスではありませんruntime/module-graph.mdx
--disallow-code-generation-from-strings[=strict] (v1.4.3+)eval()/new Function() が EvalError をスローするようにします。=strict を指定すると、node:vm と data: インポートも対象になりますruntime/code-generation-from-strings.mdx
new CompressionStream(format, { level }) (v1.4.3+)ストリーム本文の圧縮率と速度のバランスを調整しますドキュメントページなし — bun-types/globals.d.ts を参照
Bun.serve の If-Range (v1.4.3+)ファイルが変更された場合に最初から再開する、レジューム可能なダウンロードを実現しますruntime/http/routing.mdx
Bun.secrets.set({ persist: "local" }) (v1.4.3+)Windows の認証情報をアカウントとともにローミングさせず、このマシンに保存しますruntime/secrets.mdx
Bun.unsafe.setJITPolicy() (v1.4.3+)--compile-jit-policy 実行ファイルが対話可能になった後、通常の JIT を復元しますbundler/executables.mdx
db.function() / db.aggregate() (v1.4.4+)bun:sqlite で JavaScript による SQL 関数、集約関数、ウィンドウ関数を定義しますruntime/sqlite.mdx
db.onInsert / onUpdate / onDelete (v1.4.4+)この Database が書き込む各行に反応します(フック内でクエリは実行できません)runtime/sqlite.mdx
new SQL({ transform: SQL.camel }) (v1.4.4+)すべてのアダプターで、first_name 列を読み書きの両方で firstName として扱います。SQL.pascal、SQL.kebab も使用できますruntime/sql.mdx
sql.json(value) (v1.4.4+)数値、文字列、真偽値、JSON の null を JSON として保存しますruntime/sql.mdx
query.cancel() (v1.4.4+、動作対応)実行中の PostgreSQL クエリを停止します。このメソッドは存在していましたが、何もしていませんでしたruntime/sql.mdx
query.writable() / query.readable() (v1.4.4+)PostgreSQL の COPY ... FROM STDIN/TO STDOUT を Web ストリームとして扱いますruntime/sql.mdx
result.columns / result.statement (v1.4.4+)PostgreSQL と MySQL で、列の型とステートメントのテキストを取得しますruntime/sql.mdx
ServerWebSocket#pause() / resume() / isPaused (v1.4.4+)送信が速すぎるクライアントに対するサーバー側のバックプレッシャーを制御しますruntime/http/websockets.mdx
websocket.error(error, ws) (v1.4.4+)ハンドラーが例外をスローしたソケットを閉じますruntime/http/websockets.mdx
new WebSocket(url, { proxy: { url, tls } }) (v1.4.4+)HTTPS プロキシとサーバーに個別の TLS オプションを設定しますドキュメントページなし — bun-types/bun.d.ts を参照
ws の createWebSocketStream() (v1.4.4+)ws ソケット上で Node の Duplex を使用します。「Not supported yet in Bun」とスローされていましたnpm の ws ドキュメント
Bun.Glob の extglob と {1..3} (v1.4.4+)!(*.test).ts、@(app|lib)、番号付きシャードを使用できます。workspaces と --filter でも利用できますruntime/glob.mdx
ReadableStream、WritableStream、TransformStreamは1.4からネイティブで利用でき、バックプレッシャーを自動的に処理します。ソケットがこれ以上受け入れられない場合、Bun.serveはリクエスト/レスポンスのボディを一時停止し、ボディを読み取る側がいない場合、fetch()はソケットを一時停止します。以前はペイロード全体をバッファリングしていたストリーミングコードも、パイプラインの各段階がバックプレッシャーに対応していれば、独自のスロットリング処理が不要になりました。

参考:1.4から1.4.4で変更された動作(URLホスト名に対するTLS検証、localhostのループバック解決、wsのArrayBufferフレーム、.json()のエラーメッセージ、リクエスト単位のcheckServerIdentityによるTLS接続、未処理のfetch()の拒否、WebSocketのクローズコード、glob構文、bun:sqliteのエラー処理、および各パッチで修正されたリグレッション)については、references/migration-1.4.mdを参照してください。Bunの公開ドキュメントでは現在の状態しか説明されていないため、これらは網羅されていません。

スクリプトのパターン

CLIスクリプトのテンプレート
#!/usr/bin/env bun

const args = Bun.argv.slice(2)
const command = args[0]

switch (command) {
  case 'generate':
    await generate(args.slice(1))
    break
  case 'process':
    await process(args.slice(1))
    break
  default:
    console.log('Usage: script <generate|process> [args]')
    process.exit(1)
}
ファイルジェネレーター
const glob = new Bun.Glob('**/*.schema.json')

for await (const path of glob.scan('./schemas')) {
  const schema = await Bun.file(`./schemas/${path}`).json()
  const code = generateTypeScript(schema)
  const outPath = path.replace('.schema.json', '.ts')
  await Bun.write(`./generated/${outPath}`, code)
}
データパイプライン
import { $ } from 'bun'
import { Database } from 'bun:sqlite'

// Fetch data
const data = await $`curl -s https://api.example.com/data`.json()

// Process and store
const db = new Database('output.sqlite')
db.exec('CREATE TABLE IF NOT EXISTS items (id TEXT PRIMARY KEY, value TEXT)')

const insert = db.prepare('INSERT OR REPLACE INTO items (id, value) VALUES (?, ?)')
const batch = db.transaction((items) => {
  for (const item of items) {
    insert.run(item.id, JSON.stringify(item))
  }
})

batch(data.items)
db.close()
ベストプラクティス
  1. fs.readFile/fs.writeFileよりもBun.file()+Bun.write()を優先してください
  2. child_processの代わりに、シェルコマンドにはBun.$を使ってください
  3. DATABASE_URLが利用可能な場合は、PostgreSQL/MySQLにBun.sql()を使ってください。依存関係が不要で、コネクションプーリングとタグ付きテンプレートを利用できます
  4. 外部パッケージの代わりに、組み込み/ローカルSQLiteデータベースにはbun:sqliteを使ってください
  5. glob npmパッケージの代わりに、Bun.Globを使ってください
  6. crypto.createHashの代わりに、Bun.CryptoHasherを使ってください
  7. bcrypt/argon2 npmパッケージの代わりに、Bun.passwordを使ってください
  8. zlibの代わりに、Bun.gzipSync/Bun.zstdCompressSyncを使ってください
  9. 環境変数にはBun.envを使ってください(process.envと同じですが、型が付いています)
  10. __dirnameの代わりにimport.meta.dirを使ってください(Node互換性にはimport.meta.dirnameを使ってください)
  11. which npmパッケージの代わりに、Bun.which()を使ってください
  12. S3操作には@aws-sdk/client-s3の代わりに、Bun.s3を使ってください
  13. ioredisまたはredis npmパッケージの代わりに、Bun.redisを使ってください
  14. tarballにはtarまたはarchiver npmパッケージの代わりに、Bun.Archiveを使ってください
  15. jsonc-parserパッケージの代わりに、JSONC.parse()を使ってください
  16. json5パッケージの代わりに、JSON5.parse()を使ってください
  17. JSON Linesを手動で改行分割する代わりに、JSONL.parse()を使ってください
  18. marked、remark、markdown-itパッケージの代わりに、markdown.html()/markdown.ansi()を使ってください
  19. wrap-ansi npmパッケージの代わりに、Bun.wrapAnsi()を使ってください
  20. slice-ansi npmパッケージの代わりに、Bun.sliceAnsi()を使ってください
  21. 画像処理にはsharpまたはjimpの代わりに、Bun.Imageを使ってください
  22. fast-xml-parserまたはxml2jsの代わりに、Bun.XMLを使ってください(v1.4+)
  23. 認証情報をドットファイルに書き込む代わりに、Bun.secretsを使ってください(v1.4+)
  24. 擬似端末にはnode-ptyの代わりに、Bun.Terminalを使ってください
  25. path-to-regexpの代わりに、URLPatternを使ってください
  26. ストリーミング圧縮にはCompressionStream/DecompressionStreamを使ってください。ホットパスでbrotliを使う場合は、levelを指定してください(v1.4.3+)
  27. Bunのコードを本格的に書く前に、node_modules/bun-types/docs/**/*.mdxを読み、明示的なパスで開いてください。node_modules/以下は編集しないでください
  28. undiciのAgent/dispatcherはBunのfetch()では無視されるため、クライアントごとのTLS、プロキシ、またはキープアライブ設定には、代わりにBun.FetchSessionを使ってください(v1.4.3+)
  29. リリースごとに遅れる@types/bunではなく、bun --versionに固定したbun-typesに依存してください。「まずBun独自のドキュメントを読む」を参照してください
  30. SQLiteが行ごとに実行すべきロジックには、行を読み出してJavaScriptで計算し、書き戻すのではなく、db.function()/db.aggregate()を使ってください(v1.4.4+)
  31. snake_caseの列を手動でマッピングする代わりに、transform: SQL.camelを使ってください(v1.4.4+)
  32. すべてのwsソケットに'error'リスナーを追加してください。1.4.4から、未処理のエラーはNodeと同様にプロセスをクラッシュさせます。また、server.upgrade()の前にOriginを確認してください

参考資料

  • references/migration-1.4.md -- 1.3 から 1.4.4 までの変更点(互換性を破る動作)
  • references/http-server.md -- Bun.serve のルート、TLS、WebSocket、静的ファイル
  • references/file-io.md、references/shell-and-process.md、references/networking.md
  • references/sql-client.md、references/sqlite-and-data.md、references/redis-client.md、references/s3-client.md
  • references/utilities.md、references/hashing.md、references/image.md、references/webview.md

コメント