bun-dev
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBun Development
Bun开发
Bun runtime → native APIs → zero-dependency patterns.
<when_to_use>
- Bun runtime development
- SQLite database with bun:sqlite
- HTTP server with Bun.serve
- Testing with bun:test
- File operations with Bun.file/Bun.write
- Shell operations with $ template
- Password hashing with Bun.password
- Environment variable handling
- Building and bundling
NOT for: Node.js-only patterns, cross-runtime libraries, non-Bun projects
</when_to_use>
<runtime_basics>
Package management:
bash
bun install # Install deps
bun add zod # Add package
bun remove zod # Remove package
bun update # Update allScript execution:
bash
bun run dev # Run package.json script
bun run src/index.ts # Execute TypeScript directly
bun --watch index.ts # Watch modeTesting:
bash
bun test # All tests
bun test src/ # Directory
bun test --watch # Watch mode
bun test --coverage # With coverageBuilding:
bash
bun build ./index.ts --outfile dist/bundle.js
bun build ./index.ts --compile --outfile myapp # Standalone executable</runtime_basics>
Bun runtime → 原生API → 零依赖开发模式.
<when_to_use>
- Bun runtime开发
- 使用bun:sqlite的SQLite数据库开发
- 使用Bun.serve的HTTP服务器开发
- 使用bun:test进行测试
- 使用Bun.file/Bun.write进行文件操作
- 使用$模板进行Shell操作
- 使用Bun.password进行密码哈希
- 环境变量处理
- 构建与打包
不适用于:仅Node.js的开发模式、跨运行时库、非Bun项目
</when_to_use>
<runtime_basics>
包管理:
bash
bun install # 安装依赖
bun add zod # 添加包
bun remove zod # 移除包
bun update # 更新所有依赖脚本执行:
bash
bun run dev # 运行package.json中的脚本
bun run src/index.ts # 直接执行TypeScript文件
bun --watch index.ts # 监听模式测试:
bash
bun test # 运行所有测试
bun test src/ # 运行指定目录下的测试
bun test --watch # 监听模式
bun test --coverage # 生成测试覆盖率报告构建:
bash
bun build ./index.ts --outfile dist/bundle.js
bun build ./index.ts --compile --outfile myapp # 生成独立可执行文件</runtime_basics>
File Operations
文件操作
<file_operations>
typescript
// Read file (lazy, efficient)
const file = Bun.file('./data.json');
if (!(await file.exists())) throw new Error('File not found');
// Read formats
const text = await file.text();
const json = await file.json();
const buffer = await file.arrayBuffer();
const stream = file.stream(); // Large files
// Metadata
console.log(file.size, file.type);
// Write
await Bun.write('./output.txt', 'content');
await Bun.write('./data.json', JSON.stringify(data));
await Bun.write('./blob.txt', new Blob(['data']));</file_operations>
<file_operations>
typescript
// 读取文件(懒加载,高效)
const file = Bun.file('./data.json');
if (!(await file.exists())) throw new Error('文件未找到');
// 读取不同格式
const text = await file.text();
const json = await file.json();
const buffer = await file.arrayBuffer();
const stream = file.stream(); // 处理大文件
// 获取元数据
console.log(file.size, file.type);
// 写入文件
await Bun.write('./output.txt', 'content');
await Bun.write('./data.json', JSON.stringify(data));
await Bun.write('./blob.txt', new Blob(['data']));</file_operations>
SQLite (bun:sqlite)
SQLite (bun:sqlite)
<sqlite>
typescript
import { Database } from 'bun:sqlite';
const db = new Database('app.db', { create: true, readwrite: true, strict: true });
// Create tables
db.run(`
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
)
`);
// Prepared statements (always use these)
const getUser = db.prepare('SELECT * FROM users WHERE id = ?');
const createUser = db.prepare('INSERT INTO users (id, email, name) VALUES (?, ?, ?) RETURNING *');
// Execution
const user = getUser.get('user-123'); // Single row
const all = db.prepare('SELECT * FROM users').all(); // All rows
db.prepare('DELETE FROM users WHERE id = ?').run('id'); // No return
// Named parameters
const stmt = db.prepare('SELECT * FROM users WHERE email = $email');
stmt.get({ $email: 'alice@example.com' });
// Transactions (atomic, auto-rollback on error)
const transfer = db.transaction((fromId: string, toId: string, amount: number) => {
db.run('UPDATE accounts SET balance = balance - ? WHERE id = ?', [amount, fromId]);
db.run('UPDATE accounts SET balance = balance + ? WHERE id = ?', [amount, toId]);
});
transfer('alice', 'bob', 100);
db.close(); // When doneSee sqlite-patterns.md for migrations, pooling, repository pattern.
</sqlite><sqlite>
typescript
import { Database } from 'bun:sqlite';
const db = new Database('app.db', { create: true, readwrite: true, strict: true });
// 创建表
db.run(`
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
)
`);
// 预编译语句(推荐始终使用)
const getUser = db.prepare('SELECT * FROM users WHERE id = ?');
const createUser = db.prepare('INSERT INTO users (id, email, name) VALUES (?, ?, ?) RETURNING *');
// 执行语句
const user = getUser.get('user-123'); // 获取单行数据
const all = db.prepare('SELECT * FROM users').all(); // 获取所有行数据
db.prepare('DELETE FROM users WHERE id = ?').run('id'); // 无返回结果
// 命名参数
const stmt = db.prepare('SELECT * FROM users WHERE email = $email');
stmt.get({ $email: 'alice@example.com' });
// 事务(原子操作,出错时自动回滚)
const transfer = db.transaction((fromId: string, toId: string, amount: number) => {
db.run('UPDATE accounts SET balance = balance - ? WHERE id = ?', [amount, fromId]);
db.run('UPDATE accounts SET balance = balance + ? WHERE id = ?', [amount, toId]);
});
transfer('alice', 'bob', 100);
db.close(); // 使用完毕后关闭连接查看 sqlite-patterns.md 了解迁移、连接池、仓库模式等内容。
</sqlite>Password Hashing
密码哈希
<password>
</password>
typescript
// Hash (argon2id recommended)
const hash = await Bun.password.hash('password123', {
algorithm: 'argon2id',
memoryCost: 65536, // 64 MB
timeCost: 3
});
// Or bcrypt
const bcryptHash = await Bun.password.hash('password123', {
algorithm: 'bcrypt',
cost: 12
});
// Verify
const isValid = await Bun.password.verify('password123', hash);
if (!isValid) throw new Error('Invalid password');Auth flow example:
typescript
app.post('/auth/register', zValidator('json', RegisterSchema), async (c) => {
const { email, password } = c.req.valid('json');
const db = c.get('db');
if (db.prepare('SELECT id FROM users WHERE email = ?').get(email)) {
throw new HTTPException(409, { message: 'Email already registered' });
}
const hashedPassword = await Bun.password.hash(password, { algorithm: 'argon2id' });
const user = db.prepare(`
INSERT INTO users (id, email, password) VALUES (?, ?, ?) RETURNING id, email
`).get(crypto.randomUUID(), email, hashedPassword);
return c.json({ user }, 201);
});<password>
</password>
typescript
// 哈希(推荐使用argon2id算法)
const hash = await Bun.password.hash('password123', {
algorithm: 'argon2id',
memoryCost: 65536, // 64 MB
timeCost: 3
});
// 或者使用bcrypt算法
const bcryptHash = await Bun.password.hash('password123', {
algorithm: 'bcrypt',
cost: 12
});
// 验证密码
const isValid = await Bun.password.verify('password123', hash);
if (!isValid) throw new Error('密码无效');认证流程示例:
typescript
app.post('/auth/register', zValidator('json', RegisterSchema), async (c) => {
const { email, password } = c.req.valid('json');
const db = c.get('db');
if (db.prepare('SELECT id FROM users WHERE email = ?').get(email)) {
throw new HTTPException(409, { message: '该邮箱已注册' });
}
const hashedPassword = await Bun.password.hash(password, { algorithm: 'argon2id' });
const user = db.prepare(`
INSERT INTO users (id, email, password) VALUES (?, ?, ?) RETURNING id, email
`).get(crypto.randomUUID(), email, hashedPassword);
return c.json({ user }, 201);
});HTTP Server
HTTP服务器
<http_server>
typescript
Bun.serve({
port: 3000,
fetch(req) {
const url = new URL(req.url);
if (url.pathname === '/') return new Response('Hello');
if (url.pathname === '/json') return Response.json({ ok: true });
return new Response('Not found', { status: 404 });
},
error(err) {
return new Response(`Error: ${err.message}`, { status: 500 });
}
});With Hono (recommended for APIs):
typescript
import { Hono } from 'hono';
const app = new Hono()
.get('/', (c) => c.text('Hello'))
.get('/json', (c) => c.json({ ok: true }));
Bun.serve({ port: 3000, fetch: app.fetch });See server-patterns.md for routing, middleware, file serving, streaming.
</http_server>
<http_server>
typescript
Bun.serve({
port: 3000,
fetch(req) {
const url = new URL(req.url);
if (url.pathname === '/') return new Response('Hello');
if (url.pathname === '/json') return Response.json({ ok: true });
return new Response('未找到', { status: 404 });
},
error(err) {
return new Response(`错误: ${err.message}`, { status: 500 });
}
});搭配Hono使用(API开发推荐):
typescript
import { Hono } from 'hono';
const app = new Hono()
.get('/', (c) => c.text('Hello'))
.get('/json', (c) => c.json({ ok: true }));
Bun.serve({ port: 3000, fetch: app.fetch });查看 server-patterns.md 了解路由、中间件、文件服务、流处理等内容。
</http_server>
WebSocket
WebSocket
<websocket>
typescript
import type { ServerWebSocket } from 'bun';
type WsData = { userId: string };
Bun.serve<WsData>({
port: 3000,
fetch(req, server) {
const url = new URL(req.url);
if (url.pathname === '/ws') {
const userId = url.searchParams.get('userId') || 'anon';
return server.upgrade(req, { data: { userId } }) ? undefined
: new Response('Upgrade failed', { status: 400 });
}
return new Response('Hello');
},
websocket: {
open(ws: ServerWebSocket<WsData>) {
ws.subscribe('chat');
ws.send(JSON.stringify({ type: 'connected' }));
},
message(ws: ServerWebSocket<WsData>, msg: string | Buffer) {
ws.publish('chat', msg);
},
close(ws: ServerWebSocket<WsData>) {
ws.unsubscribe('chat');
}
}
});See server-patterns.md for client tracking, rooms, reconnection.
</websocket><websocket>
typescript
import type { ServerWebSocket } from 'bun';
type WsData = { userId: string };
Bun.serve<WsData>({
port: 3000,
fetch(req, server) {
const url = new URL(req.url);
if (url.pathname === '/ws') {
const userId = url.searchParams.get('userId') || 'anon';
return server.upgrade(req, { data: { userId } }) ? undefined
: new Response('升级失败', { status: 400 });
}
return new Response('Hello');
},
websocket: {
open(ws: ServerWebSocket<WsData>) {
ws.subscribe('chat');
ws.send(JSON.stringify({ type: 'connected' }));
},
message(ws: ServerWebSocket<WsData>, msg: string | Buffer) {
ws.publish('chat', msg);
},
close(ws: ServerWebSocket<WsData>) {
ws.unsubscribe('chat');
}
}
});查看 server-patterns.md 了解客户端跟踪、房间管理、重连等内容。
</websocket>Shell Operations
Shell操作
<shell>
</shell>
typescript
import { $ } from 'bun';
// Run commands
const result = await $`ls -la`;
console.log(result.text());
// Variables (auto-escaped)
const dir = './src';
await $`find ${dir} -name "*.ts"`;
// Check exit code
const { exitCode } = await $`npm test`.nothrow();
if (exitCode !== 0) console.error('Tests failed');
// Spawn process
const proc = Bun.spawn(['ls', '-la']);
await proc.exited;
// Capture output
const proc2 = Bun.spawn(['echo', 'Hello'], { stdout: 'pipe' });
const output = await new Response(proc2.stdout).text();<shell>
</shell>
typescript
import { $ } from 'bun';
// 运行命令
const result = await $`ls -la`;
console.log(result.text());
// 变量(自动转义)
const dir = './src';
await $`find ${dir} -name "*.ts"`;
// 检查退出码
const { exitCode } = await $`npm test`.nothrow();
if (exitCode !== 0) console.error('测试失败');
// 启动进程
const proc = Bun.spawn(['ls', '-la']);
await proc.exited;
// 捕获输出
const proc2 = Bun.spawn(['echo', 'Hello'], { stdout: 'pipe' });
const output = await new Response(proc2.stdout).text();Testing (bun:test)
测试(bun:test)
<testing>
typescript
import { describe, test, expect, beforeEach, afterEach } from 'bun:test';
describe('feature', () => {
let db: Database;
beforeEach(() => { db = new Database(':memory:'); });
afterEach(() => { db.close(); });
test('behavior', () => {
expect(result).toBe(expected);
expect(arr).toContain(item);
expect(fn).toThrow();
expect(obj).toEqual({ foo: 'bar' });
});
test('async', async () => {
const result = await asyncFn();
expect(result).toBeDefined();
});
test.todo('pending feature');
test.skip('temporarily disabled');
});bash
bun test # All tests
bun test src/api.test.ts # Specific file
bun test --watch # Watch mode
bun test --coverage # With coverageSee testing.md for assertions, mocking, snapshots, best practices.
</testing><testing>
typescript
import { describe, test, expect, beforeEach, afterEach } from 'bun:test';
describe('功能', () => {
let db: Database;
beforeEach(() => { db = new Database(':memory:'); });
afterEach(() => { db.close(); });
test('行为验证', () => {
expect(result).toBe(expected);
expect(arr).toContain(item);
expect(fn).toThrow();
expect(obj).toEqual({ foo: 'bar' });
});
test('异步测试', async () => {
const result = await asyncFn();
expect(result).toBeDefined();
});
test.todo('待实现功能');
test.skip('临时禁用');
});bash
bun test # 运行所有测试
bun test src/api.test.ts # 运行指定文件的测试
bun test --watch # 监听模式
bun test --coverage # 生成测试覆盖率报告查看 testing.md 了解断言、模拟、快照、最佳实践等内容。
</testing>Environment Variables
环境变量
<environment>
typescript
// Access
console.log(Bun.env.NODE_ENV);
console.log(Bun.env.DATABASE_URL);
// Zod validation
import { z } from 'zod';
const EnvSchema = z.object({
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
DATABASE_URL: z.string(),
PORT: z.coerce.number().int().positive().default(3000),
API_KEY: z.string().min(32)
});
export const env = EnvSchema.parse(Bun.env);Bun auto-loads , , .
</environment>.env.env.local.env.production<environment>
typescript
// 访问环境变量
console.log(Bun.env.NODE_ENV);
console.log(Bun.env.DATABASE_URL);
// Zod验证
import { z } from 'zod';
const EnvSchema = z.object({
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
DATABASE_URL: z.string(),
PORT: z.coerce.number().int().positive().default(3000),
API_KEY: z.string().min(32)
});
export const env = EnvSchema.parse(Bun.env);Bun会自动加载 、、 文件。
</environment>.env.env.local.env.productionPerformance Utilities
性能工具
<performance>
</performance>
typescript
// High-resolution timing
const start = Bun.nanoseconds();
await doWork();
console.log(`Took ${(Bun.nanoseconds() - start) / 1_000_000}ms`);
// Hashing
const hash = Bun.hash(data);
const crc32 = Bun.hash.crc32(data);
const sha256 = Bun.CryptoHasher.hash('sha256', data);
// Sleep
await Bun.sleep(1000);
// Memory
const { rss, heapUsed } = process.memoryUsage();
console.log('RSS:', rss / 1024 / 1024, 'MB');<performance>
</performance>
typescript
// 高分辨率计时
const start = Bun.nanoseconds();
await doWork();
console.log(`耗时 ${(Bun.nanoseconds() - start) / 1_000_000}ms`);
// 哈希计算
const hash = Bun.hash(data);
const crc32 = Bun.hash.crc32(data);
const sha256 = Bun.CryptoHasher.hash('sha256', data);
// 休眠
await Bun.sleep(1000);
// 内存使用情况
const { rss, heapUsed } = process.memoryUsage();
console.log('RSS:', rss / 1024 / 1024, 'MB');Building & Bundling
构建与打包
<building>
bash
undefined<building>
bash
undefinedProduction bundle
生产环境打包
bun build ./index.ts --outfile dist/bundle.js --minify --sourcemap
bun build ./index.ts --outfile dist/bundle.js --minify --sourcemap
External deps
排除外部依赖
bun build ./index.ts --outfile dist/bundle.js --external hono --external zod
bun build ./index.ts --outfile dist/bundle.js --external hono --external zod
Standalone executable
生成独立可执行文件
bun build ./index.ts --compile --outfile myapp
bun build ./index.ts --compile --outfile myapp
Cross-compile
跨平台编译
bun build ./index.ts --compile --target=bun-linux-x64 --outfile myapp-linux
bun build ./index.ts --compile --target=bun-darwin-arm64 --outfile myapp-macos
bun build ./index.ts --compile --target=bun-windows-x64 --outfile myapp.exe
</building>
<rules>
ALWAYS:
- Use Bun APIs when available (faster, native)
- Prepared statements for database queries
- Transactions for multi-statement operations
- argon2id for password hashing
- Validate environment variables at startup
- Close database connections when done
NEVER:
- String interpolation in SQL (use parameters)
- Plaintext passwords
- Ignore async disposal cleanup
- Deprecated Node.js APIs when Bun native exists
PREFER:
- Bun.file over fs.readFile
- Bun.write over fs.writeFile
- bun:sqlite over external SQLite libraries
- Bun.password over bcrypt/argon2 packages
- $ shell template over child_process
</rules>
<references>
- [sqlite-patterns.md](references/sqlite-patterns.md) — migrations, pooling, repository, FTS
- [server-patterns.md](references/server-patterns.md) — HTTP, WebSocket, streaming, compression
- [testing.md](references/testing.md) — assertions, mocking, snapshots, best practices
**Examples:**
- [database-crud.md](examples/database-crud.md) — SQLite CRUD patterns
- [file-uploads.md](examples/file-uploads.md) — streaming file handling
</references>bun build ./index.ts --compile --target=bun-linux-x64 --outfile myapp-linux
bun build ./index.ts --compile --target=bun-darwin-arm64 --outfile myapp-macos
bun build ./index.ts --compile --target=bun-windows-x64 --outfile myapp.exe
</building>
<rules>
必须遵守:
- 优先使用Bun原生API(更快、原生支持)
- 数据库查询使用预编译语句
- 多语句操作使用事务
- 密码哈希使用argon2id算法
- 启动时验证环境变量
- 使用完毕后关闭数据库连接
禁止:
- SQL语句中使用字符串插值(使用参数化查询)
- 明文存储密码
- 忽略异步资源清理
- 当有Bun原生API时使用已废弃的Node.js API
推荐:
- 使用Bun.file替代fs.readFile
- 使用Bun.write替代fs.writeFile
- 使用bun:sqlite替代外部SQLite库
- 使用Bun.password替代bcrypt/argon2包
- 使用$ Shell模板替代child_process
</rules>
<references>
- [sqlite-patterns.md](references/sqlite-patterns.md) — 迁移、连接池、仓库模式、全文搜索
- [server-patterns.md](references/server-patterns.md) — HTTP、WebSocket、流处理、压缩
- [testing.md](references/testing.md) — 断言、模拟、快照、最佳实践
**示例**:
- [database-crud.md](examples/database-crud.md) — SQLite增删改查模式
- [file-uploads.md](examples/file-uploads.md) — 流处理文件上传
</references>