Skip to main content

bunjs

Use when building Bun.js/Hono applications, implementing HTTP endpoints, setting up Prisma/SQLite, writing Zod validation, or using Bun's test runner. See bunjs-architecture for layered patterns, bunjs-production for deployment.

ソース情報

リポジトリ
MadAppGang/claude-code
ソースの最終更新活動
2026年1月20日 08:16
検出された SKILL.md の言語
英語
スター
284
フォーク
25

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
bunjs
version
2.0.0
description
Use when building Bun.js/Hono applications, implementing HTTP endpoints, setting up Prisma/SQLite, writing Zod validation, or using Bun's test runner. See bunjs-architecture for layered patterns, bunjs-production for deployment.
keywords
["Bun","Hono","TypeScript","Prisma","Zod","SQLite","PostgreSQL","Bun test","WebSocket","file operations"]
plugin
dev
updated
2026-01-20T00:00:00.000Z
# Bun.js Backend Patterns ## Overview Bun runtime patterns for building fast TypeScript backend services. This skill covers core Bun features, HTTP servers with Hono, database access with Prisma, validation with Zod, error handling, testing, and configuration patterns. **When to use this skill:** - Implementing basic HTTP endpoints and route handlers - Setting up middleware patterns (CORS, logging, auth) - Working with SQLite or PostgreSQL databases - Implementing request validation with Zod - Writing tests with Bun's native test runner - Basic file operations and WebSocket handling **For advanced topics, see:** - **dev:bunjs-architecture** - Layered architecture, clean code patterns, camelCase conventions - **dev:bunjs-production** - Docker, AWS, Redis caching, security, CI/CD - **dev:bunjs-apidog** - OpenAPI specs and Apidog integration ## Why Bun Bun fundamentally transforms TypeScript backend development by: - **Native TypeScript execution** - No build steps in development - **Lightning-fast performance** - 3-4x faster than Node.js for many operations - **Unified toolkit** - Built-in test runner, bundler, and transpiler - **Drop-in compatibility** - Most Node.js APIs and npm packages work - **Developer experience** - Hot reload with `--hot`, instant feedback ## Stack Overview - **Bun 1.x** (runtime, package manager, test runner, bundler) - **TypeScript 5.7** (strict mode) - **Hono 4.6** (ultra-fast web framework, TypeScript-first) - **Prisma 6.2** (type-safe ORM) - **Biome 2.3** (formatting + linting, replaces ESLint + Prettier) - **Zod** (runtime validation) - **PostgreSQL 17 / SQLite** (database) ## Project Structure ``` project-root/ ├── src/ │ ├── server.ts # Entry point (starts server) │ ├── app.ts # Hono app initialization & middleware │ ├── config.ts # Environment configuration │ ├── core/ # Core utilities (errors, logger, responses) │ ├── database/ │ │ ├── client.ts # Prisma client setup │ │ └── repositories/ # Data access layer (Prisma queries) │ ├── services/ # Business logic layer │ ├── controllers/ # HTTP handlers (calls services) │ ├── middleware/ # Hono middleware (auth, validation, etc.) │ ├── routes/ # API route definitions │ ├── schemas/ # Zod validation schemas │ ├── types/ # TypeScript type definitions │ └── utils/ # Utility functions ├── tests/ │ ├── unit/ # Unit tests │ └── integration/ # Integration tests (API + DB) ├── prisma/ # Prisma schema & migrations ├── tsconfig.json # TypeScript config ├── biome.json # Biome config ├── package.json # Bun-managed dependencies └── bun.lockb # Bun lockfile ``` **Key Principles:** - Structure by **technical capability**, not by feature - Each layer has **single responsibility** - No HTTP handling in services, no business logic in controllers - Easy to test components in isolation ## Quick Start ```bash # Initialize project bun init # Install dependencies bun add hono @hono/node-server zod @prisma/client bcrypt jsonwebtoken bun add -d @types/node @types/jsonwebtoken @types/bcrypt typescript prisma @biomejs/biome @types/bun # Initialize tools bunx tsc --init bunx prisma init bunx @biomejs/biome init ``` **package.json scripts:** ```json { "scripts": { "dev": "bun --hot src/server.ts", "start": "NODE_ENV=production bun src/server.ts", "build": "bun build src/server.ts --target bun --outdir dist", "test": "bun test", "test:watch": "bun test --watch", "lint": "biome lint --write", "format": "biome format --write", "check": "biome check --write", "typecheck": "tsc --noEmit", "db:generate": "prisma generate", "db:migrate": "prisma migrate dev", "db:studio": "prisma studio" } } ``` ## TypeScript Configuration **tsconfig.json (key settings):** ```json { "compilerOptions": { "target": "ES2022", "module": "ESNext", "lib": ["ES2022"], "moduleResolution": "bundler", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "types": ["bun-types"], "baseUrl": ".", "paths": { "@core/*": ["src/core/*"], "@database/*": ["src/database/*"], "@services/*": ["src/services/*"], "@/*": ["src/*"] } } } ``` **Critical settings:** - `"strict": true` - Enable all strict checks - `"moduleResolution": "bundler"` - Aligns with Bun's resolver - Use `paths` for clean imports (`@core/*`, `@services/*`) ## HTTP Server with Hono ### Basic Server Setup **Entry point (src/server.ts):** ```typescript import { serve } from '@hono/node-server'; import { app } from './app'; const PORT = Number(process.env.PORT) || 3000; serve({ fetch: app.fetch, port: PORT }); console.log(`🚀 Server running on port ${PORT}`); ``` **App initialization (src/app.ts):** ```typescript import { Hono } from 'hono'; import { logger } from 'hono/logger'; import { cors } from 'hono/cors'; import userRouter from './routes/user.routes'; export const app = new Hono(); // Global middleware app.use('*', logger()); app.use('*', cors({ origin: ['http://localhost:3000'], allowHeaders: ['Content-Type', 'Authorization'], allowMethods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'], credentials: true })); // Health check app.get('/health', (c) => c.json({ status: 'ok' })); // API routes app.route('/api/users', userRouter); ``` ### Route Handlers **Routes (src/routes/user.routes.ts):** ```typescript import { Hono } from 'hono'; import * as userController from '../controllers/user.controller'; import { validate } from '../middleware/validator'; import { createUserSchema } from '../schemas/user.schema'; const userRouter = new Hono(); userRouter.get('/', userController.getUsers); userRouter.get('/:id', userController.getUserById); userRouter.post('/', validate(createUserSchema), userController.createUser); userRouter.put('/:id', userController.updateUser); userRouter.delete('/:id', userController.deleteUser); export default userRouter; ``` **Controllers (src/controllers/user.controller.ts):** ```typescript import type { Context } from 'hono'; import * as userService from '../services/user.service'; export const createUser = async (c: Context) => { const data = c.get('validatedData'); const user = await userService.createUser(data); return c.json(user, 201); }; export const getUserById = async (c: Context) => { const id = c.req.param('id'); const user = await userService.getUserById(id); return c.json(user); }; export const getUsers = async (c: Context) => { const page = Number(c.req.query('page')) || 1; const limit = Number(c.req.query('limit')) || 20; const result = await userService.getUsers({ page, limit }); return c.json(result); }; export const updateUser = async (c: Context) => { const id = c.req.param('id'); const data = await c.req.json(); const user = await userService.updateUser(id, data); return c.json(user); }; export const deleteUser = async (c: Context) => { const id = c.req.param('id'); await userService.deleteUser(id); return c.json({ message: 'User deleted' }); }; ``` ## Middleware Patterns ### Validation Middleware **src/middleware/validator.ts:** ```typescript import { z, ZodSchema } from 'zod'; import type { Context, Next } from 'hono'; export const validate = (schema: ZodSchema) => async (c: Context, next: Next) => { try { const body = await c.req.json(); c.set('validatedData', schema.parse(body)); await next(); } catch (e) { if (e instanceof z.ZodError) { return c.json({ error: 'Validation failed', details: e.issues }, 422); } throw e; } }; export const validateQuery = (schema: ZodSchema) => async (c: Context, next: Next) => { try { c.set('validatedQuery', schema.parse(c.req.query())); await next(); } catch (e) { if (e instanceof z.ZodError) { return c.json({ error: 'Invalid query parameters', details: e.issues }, 422); } throw e; } }; ``` ### Authentication Middleware **src/middleware/auth.ts:** ```typescript import type { Context, Next } from 'hono'; import { verifyToken } from '../services/auth.service'; export const authenticate = async (c: Context, next: Next) => { const header = c.req.header('Authorization'); if (!header?.startsWith('Bearer ')) { return c.json({ error: 'Missing or invalid token' }, 401); } try { const token = header.slice(7); const payload = await verifyToken(token); c.set('user', payload); await next(); } catch { return c.json({ error: 'Invalid or expired token' }, 401); } }; export const authorize = (...roles: string[]) => async (c: Context, next: Next) => { const user = c.get('user') as { role: string } | undefined; if (!user) { return c.json({ error: 'Authentication required' }, 401); } if (!roles.includes(user.role)) { return c.json({ error: 'Insufficient permissions' }, 403); } await next(); }; ``` ### Logging Middleware **src/middleware/requestLogger.ts:** ```typescript import type { Context, Next } from 'hono'; export const requestLogger = async (c: Context, next: Next) => { const start = Date.now(); const requestId = crypto.randomUUID(); c.set('requestId', requestId); console.log(`[${requestId}] ${c.req.method} ${c.req.path}`); await next(); const duration = Date.now() - start; console.log(`[${requestId}] ${c.res.status} ${duration}ms`); }; ``` ## Database Access ### SQLite with Bun ```typescript import { Database } from 'bun:sqlite'; const db = new Database('app.db'); // Enable WAL mode for better performance db.exec('PRAGMA journal_mode = WAL'); // Prepared statements const findUserById = db.prepare<{ id: string }, [string]>( 'SELECT * FROM users WHERE id = ?' ); const createUser = db.prepare<void, [string, string, string]>( 'INSERT INTO users (id, name, email) VALUES (?, ?, ?)' ); // Repository export const userRepository = { findById(id: string) { return findUserById.get(id); }, create(user: { id: string; name: string; email: string }) {
GitHubで見る
この SKILL.md は非常に大きいため、SkillsMP では最初のセクションだけを表示しています。 GitHubで見る