|
| 1 | +# Bun Backend API |
| 2 | + |
| 3 | +HaloLight Bun Backend API, a high-performance backend service built with Bun + Hono + Drizzle ORM, sharing the same database (PostgreSQL/Neon) and API specification with NestJS/Java versions. |
| 4 | + |
| 5 | +## Features |
| 6 | + |
| 7 | +- ⚡ **Bun 1.1+** - JavaScript runtime 4x faster than Node.js |
| 8 | +- 🔥 **Hono 4.x** - Ultra-lightweight, high-performance web framework (~14KB) |
| 9 | +- 🗄️ **Drizzle ORM** - TypeScript-first SQL ORM with zero runtime overhead |
| 10 | +- 🔐 **JWT Dual Token** - AccessToken + RefreshToken authentication |
| 11 | +- 🛡️ **RBAC Authorization** - Role-based access control system |
| 12 | +- 📚 **Swagger Docs** - Dynamically generated OpenAPI specification |
| 13 | +- ✅ **Zod Validation** - Type-safe request data validation |
| 14 | +- 🧪 **Complete Testing** - Bun Test unit tests + E2E tests |
| 15 | + |
| 16 | +## Tech Stack |
| 17 | + |
| 18 | +| Category | Technology | |
| 19 | +|----------|------------| |
| 20 | +| Runtime | Bun 1.1+ | |
| 21 | +| Framework | Hono 4.x | |
| 22 | +| Language | TypeScript 5.x | |
| 23 | +| Database | PostgreSQL 15+ / Neon | |
| 24 | +| ORM | Drizzle ORM 0.36+ | |
| 25 | +| Authentication | JWT (jose) | |
| 26 | +| Validation | Zod 3.x + @hono/zod-validator | |
| 27 | +| Documentation | Swagger/OpenAPI | |
| 28 | +| Testing | Bun Test | |
| 29 | +| Package Manager | pnpm | |
| 30 | + |
| 31 | +## Performance Comparison |
| 32 | + |
| 33 | +| Metric | Bun | Node.js | Improvement | |
| 34 | +|--------|-----|---------|-------------| |
| 35 | +| Startup Time | ~100ms | ~500ms | **4x** | |
| 36 | +| HTTP Throughput | ~50,000 req/s | ~20,000 req/s | **2.5x** | |
| 37 | +| Memory Usage | ~30MB | ~50MB+ | **40%** | |
| 38 | + |
| 39 | +## Quick Start |
| 40 | + |
| 41 | +```bash |
| 42 | +# Clone repository |
| 43 | +git clone https://github.com/halolight/halolight-api-bun.git |
| 44 | +cd halolight-api-bun |
| 45 | + |
| 46 | +# Install dependencies |
| 47 | +pnpm install |
| 48 | + |
| 49 | +# Configure environment variables |
| 50 | +cp .env.example .env |
| 51 | +# Edit .env with your database connection string and JWT secret |
| 52 | + |
| 53 | +# Push database schema |
| 54 | +bun run db:push |
| 55 | + |
| 56 | +# Seed test data (optional) |
| 57 | +bun run db:seed |
| 58 | + |
| 59 | +# Start development server |
| 60 | +bun run dev |
| 61 | + |
| 62 | +# Build for production |
| 63 | +bun run build |
| 64 | +bun run start |
| 65 | +``` |
| 66 | + |
| 67 | +## Environment Variables |
| 68 | + |
| 69 | +| Variable | Description | Default | |
| 70 | +|----------|-------------|---------| |
| 71 | +| `DATABASE_URL` | PostgreSQL connection string | - | |
| 72 | +| `JWT_SECRET` | JWT signing secret (≥32 chars) | - | |
| 73 | +| `JWT_REFRESH_SECRET` | RefreshToken secret | - | |
| 74 | +| `PORT` | Server port | `3002` | |
| 75 | +| `NODE_ENV` | Runtime environment | `development` | |
| 76 | +| `CORS_ORIGIN` | CORS allowed origins (comma-separated) | `http://localhost:3000` | |
| 77 | +| `API_PREFIX` | API route prefix | `/api` | |
| 78 | +| `JWT_EXPIRES_IN` | AccessToken expiration | `15m` | |
| 79 | +| `JWT_REFRESH_EXPIRES_IN` | RefreshToken expiration | `7d` | |
| 80 | +| `SWAGGER_ENABLED` | Enable Swagger | `true` | |
| 81 | +| `SWAGGER_PATH` | Swagger UI path | `/swagger` | |
| 82 | + |
| 83 | +## Project Structure |
| 84 | + |
| 85 | +``` |
| 86 | +halolight-api-bun/ |
| 87 | +├── src/ |
| 88 | +│ ├── db/ |
| 89 | +│ │ ├── schema.ts # Drizzle ORM Schema (17 entities) |
| 90 | +│ │ ├── index.ts # Database connection pool |
| 91 | +│ │ ├── migrate.ts # Migration script |
| 92 | +│ │ └── seed.ts # Seed data script |
| 93 | +│ ├── middleware/ |
| 94 | +│ │ ├── auth.ts # JWT authentication middleware |
| 95 | +│ │ ├── cors.ts # CORS configuration |
| 96 | +│ │ ├── error.ts # Global error handler |
| 97 | +│ │ └── logger.ts # Request logging middleware |
| 98 | +│ ├── routes/ # Route layer (Controllers) |
| 99 | +│ │ ├── auth.ts # Auth endpoints |
| 100 | +│ │ ├── users.ts # User management |
| 101 | +│ │ ├── roles.ts # Role management |
| 102 | +│ │ ├── permissions.ts # Permission management |
| 103 | +│ │ ├── teams.ts # Team management |
| 104 | +│ │ ├── documents.ts # Document management |
| 105 | +│ │ ├── notifications.ts # Notification management |
| 106 | +│ │ ├── dashboard.ts # Dashboard statistics |
| 107 | +│ │ └── index.ts # Route aggregation |
| 108 | +│ ├── services/ # Business logic layer |
| 109 | +│ │ ├── auth.service.ts |
| 110 | +│ │ ├── user.service.ts |
| 111 | +│ │ ├── role.service.ts |
| 112 | +│ │ ├── permission.service.ts |
| 113 | +│ │ ├── team.service.ts |
| 114 | +│ │ ├── document.service.ts |
| 115 | +│ │ ├── notification.service.ts |
| 116 | +│ │ └── dashboard.service.ts |
| 117 | +│ ├── swagger/ # Swagger documentation |
| 118 | +│ │ ├── openapi.ts # Dynamic OpenAPI spec generation |
| 119 | +│ │ ├── zod-to-json.ts # Zod Schema to JSON Schema |
| 120 | +│ │ └── index.ts # Swagger UI routes |
| 121 | +│ ├── pages/ |
| 122 | +│ │ └── home.ts # Homepage HTML template |
| 123 | +│ ├── utils/ # Utility functions |
| 124 | +│ │ ├── env.ts # Environment variable validation (Zod) |
| 125 | +│ │ ├── jwt.ts # JWT sign/verify |
| 126 | +│ │ ├── hash.ts # Password hashing (Bun.password) |
| 127 | +│ │ └── response.ts # Unified response format |
| 128 | +│ └── index.ts # Application entry point |
| 129 | +├── test/ |
| 130 | +│ ├── unit/ # Unit tests |
| 131 | +│ └── e2e/ # E2E tests |
| 132 | +├── drizzle.config.ts # Drizzle configuration |
| 133 | +└── package.json |
| 134 | +``` |
| 135 | + |
| 136 | +## API Modules |
| 137 | + |
| 138 | +The project covers **9 core business modules** with **50+ RESTful API endpoints**: |
| 139 | + |
| 140 | +| Module | Endpoints | Description | |
| 141 | +|--------|-----------|-------------| |
| 142 | +| **Auth** | 5 | Authentication (login, register, refresh token, get current user, logout) | |
| 143 | +| **Users** | 7 | User management (CRUD, pagination, search, status update, batch delete) | |
| 144 | +| **Roles** | 5 | Role management (CRUD + permission assignment) | |
| 145 | +| **Permissions** | 4 | Permission management | |
| 146 | +| **Teams** | 6 | Team management (CRUD, member management) | |
| 147 | +| **Documents** | 5 | Document management (CRUD) | |
| 148 | +| **Notifications** | 5 | Notification management (list, unread count, mark as read) | |
| 149 | +| **Dashboard** | 9 | Dashboard statistics (overview, trends, chart data) | |
| 150 | + |
| 151 | +### Authentication Endpoints |
| 152 | + |
| 153 | +| Method | Path | Description | Auth | |
| 154 | +|--------|------|-------------|------| |
| 155 | +| POST | `/api/auth/login` | User login | Public | |
| 156 | +| POST | `/api/auth/register` | User registration | Public | |
| 157 | +| POST | `/api/auth/refresh` | Refresh token | Public | |
| 158 | +| GET | `/api/auth/me` | Get current user | JWT Required | |
| 159 | +| POST | `/api/auth/logout` | User logout | JWT Required | |
| 160 | + |
| 161 | +### User Management Endpoints |
| 162 | + |
| 163 | +| Method | Path | Description | Auth | |
| 164 | +|--------|------|-------------|------| |
| 165 | +| GET | `/api/users` | Get user list (pagination, search, status filter) | JWT Required | |
| 166 | +| GET | `/api/users/:id` | Get user details | JWT Required | |
| 167 | +| POST | `/api/users` | Create user | JWT Required | |
| 168 | +| PATCH | `/api/users/:id` | Update user | JWT Required | |
| 169 | +| PATCH | `/api/users/:id/status` | Update user status | JWT Required | |
| 170 | +| POST | `/api/users/batch-delete` | Batch delete users | JWT Required | |
| 171 | +| DELETE | `/api/users/:id` | Delete user | JWT Required | |
| 172 | + |
| 173 | +### Role Management Endpoints |
| 174 | + |
| 175 | +| Method | Path | Description | Auth | |
| 176 | +|--------|------|-------------|------| |
| 177 | +| GET | `/api/roles` | Get role list | JWT Required | |
| 178 | +| GET | `/api/roles/:id` | Get role details | JWT Required | |
| 179 | +| POST | `/api/roles` | Create role | JWT Required | |
| 180 | +| PATCH | `/api/roles/:id` | Update role | JWT Required | |
| 181 | +| DELETE | `/api/roles/:id` | Delete role | JWT Required | |
| 182 | + |
| 183 | +### Team Management Endpoints |
| 184 | + |
| 185 | +| Method | Path | Description | Auth | |
| 186 | +|--------|------|-------------|------| |
| 187 | +| GET | `/api/teams` | Get team list | JWT Required | |
| 188 | +| GET | `/api/teams/:id` | Get team details | JWT Required | |
| 189 | +| POST | `/api/teams` | Create team | JWT Required | |
| 190 | +| PATCH | `/api/teams/:id` | Update team | JWT Required | |
| 191 | +| DELETE | `/api/teams/:id` | Delete team | JWT Required | |
| 192 | +| POST | `/api/teams/:id/members` | Add team member | JWT Required | |
| 193 | + |
| 194 | +### Dashboard Endpoints |
| 195 | + |
| 196 | +| Method | Path | Description | Auth | |
| 197 | +|--------|------|-------------|------| |
| 198 | +| GET | `/api/dashboard/stats` | Get statistics | JWT Required | |
| 199 | +| GET | `/api/dashboard/visits` | Get visit trends | JWT Required | |
| 200 | +| GET | `/api/dashboard/sales` | Get sales trends | JWT Required | |
| 201 | +| GET | `/api/dashboard/products` | Get product statistics | JWT Required | |
| 202 | +| GET | `/api/dashboard/orders` | Get order statistics | JWT Required | |
| 203 | +| GET | `/api/dashboard/activities` | Get activity logs | JWT Required | |
| 204 | +| GET | `/api/dashboard/system` | Get system overview | JWT Required | |
| 205 | +| GET | `/api/dashboard/pie` | Get pie chart data | JWT Required | |
| 206 | +| GET | `/api/dashboard/tasks` | Get pending tasks | JWT Required | |
| 207 | + |
| 208 | +## Database Models |
| 209 | + |
| 210 | +17 core entities defined with Drizzle ORM: |
| 211 | + |
| 212 | +- **User Auth**: `users`, `refresh_tokens` |
| 213 | +- **RBAC Authorization**: `roles`, `permissions`, `role_permissions`, `user_roles` |
| 214 | +- **Team Collaboration**: `teams`, `team_members` |
| 215 | +- **Document Management**: `documents`, `document_shares`, `document_tags`, `tags` |
| 216 | +- **File System**: `files`, `folders` |
| 217 | +- **Calendar**: `calendar_events`, `event_attendees`, `event_reminders` |
| 218 | +- **Messaging**: `conversations`, `conversation_participants`, `messages` |
| 219 | +- **Notifications**: `notifications` |
| 220 | +- **Audit Logs**: `activity_logs` |
| 221 | + |
| 222 | +## Authentication Mechanism |
| 223 | + |
| 224 | +### JWT Dual Token Strategy |
| 225 | + |
| 226 | +``` |
| 227 | +┌─────────────┐ Login ┌─────────────┐ |
| 228 | +│ Client │ ─────────────> │ Server │ |
| 229 | +└─────────────┘ └─────────────┘ |
| 230 | + │ │ |
| 231 | + │ <── AccessToken (15m) ─── │ |
| 232 | + │ <── RefreshToken (7d) ─── │ |
| 233 | + │ │ |
| 234 | + │ ─── API Request ──────────> │ |
| 235 | + │ ─── Authorization: Bearer │ |
| 236 | + │ │ |
| 237 | +``` |
| 238 | + |
| 239 | +- **AccessToken**: Short-lived token (15 minutes) for API request authentication |
| 240 | +- **RefreshToken**: Long-lived token (7 days) for refreshing AccessToken, supports Token Rotation |
| 241 | + |
| 242 | +### Response Format |
| 243 | + |
| 244 | +Success response: |
| 245 | +```json |
| 246 | +{ |
| 247 | + "success": true, |
| 248 | + "data": { |
| 249 | + "user": { |
| 250 | + "id": "xxx", |
| 251 | + "email": "admin@example.com", |
| 252 | + "name": "System Admin", |
| 253 | + "status": "ACTIVE", |
| 254 | + "roles": ["admin"], |
| 255 | + "permissions": ["*:*"] |
| 256 | + }, |
| 257 | + "accessToken": "eyJ...", |
| 258 | + "refreshToken": "eyJ..." |
| 259 | + } |
| 260 | +} |
| 261 | +``` |
| 262 | + |
| 263 | +Error response: |
| 264 | +```json |
| 265 | +{ |
| 266 | + "success": false, |
| 267 | + "error": { |
| 268 | + "code": "UNAUTHORIZED", |
| 269 | + "message": "Invalid credentials" |
| 270 | + } |
| 271 | +} |
| 272 | +``` |
| 273 | + |
| 274 | +## Common Commands |
| 275 | + |
| 276 | +```bash |
| 277 | +# Development |
| 278 | +bun run dev # Start dev server (hot reload) |
| 279 | +bun run build # Production build |
| 280 | +bun run start # Run production build |
| 281 | + |
| 282 | +# Code Quality |
| 283 | +bun run lint # ESLint check |
| 284 | +bun run lint:fix # ESLint auto-fix |
| 285 | +bun run type-check # TypeScript type check |
| 286 | +bun run format # Prettier format |
| 287 | + |
| 288 | +# Testing |
| 289 | +bun test # Run unit tests |
| 290 | +bun test --watch # Watch mode |
| 291 | +bun test --coverage # Generate coverage report |
| 292 | + |
| 293 | +# Database |
| 294 | +bun run db:generate # Generate Drizzle migration files |
| 295 | +bun run db:migrate # Run database migrations |
| 296 | +bun run db:push # Push schema to database |
| 297 | +bun run db:studio # Open Drizzle Studio |
| 298 | +bun run db:seed # Seed test data |
| 299 | +``` |
| 300 | + |
| 301 | +## Bun-Specific Features |
| 302 | + |
| 303 | +Leveraging Bun's built-in APIs for better performance: |
| 304 | + |
| 305 | +```typescript |
| 306 | +// Password hashing (faster than bcrypt package) |
| 307 | +const hash = await Bun.password.hash(password, { algorithm: 'bcrypt', cost: 10 }); |
| 308 | +const isValid = await Bun.password.verify(password, hash, 'bcrypt'); |
| 309 | + |
| 310 | +// File operations |
| 311 | +const file = Bun.file('./path/to/file'); |
| 312 | +const content = await file.text(); |
| 313 | + |
| 314 | +// Fast hashing |
| 315 | +const hash = Bun.hash(data); |
| 316 | +``` |
| 317 | + |
| 318 | +## Frontend Integration |
| 319 | + |
| 320 | +Configure frontend API URL: |
| 321 | + |
| 322 | +```env |
| 323 | +# Next.js |
| 324 | +NEXT_PUBLIC_API_URL=http://localhost:3002/api |
| 325 | +
|
| 326 | +# Vue/Vite |
| 327 | +VITE_API_URL=http://localhost:3002/api |
| 328 | +
|
| 329 | +# Angular |
| 330 | +API_URL=http://localhost:3002/api |
| 331 | +``` |
| 332 | + |
| 333 | +## Access URLs |
| 334 | + |
| 335 | +- **API**: http://localhost:3002/api |
| 336 | +- **Swagger UI**: http://localhost:3002/swagger |
| 337 | +- **Homepage**: http://localhost:3002 |
| 338 | +- **API Info**: http://localhost:3002/info |
| 339 | + |
| 340 | +## Related Links |
| 341 | + |
| 342 | +- [GitHub Repository](https://github.com/halolight/halolight-api-bun) |
| 343 | +- [Bun Documentation](https://bun.sh/docs) |
| 344 | +- [Hono Documentation](https://hono.dev/docs) |
| 345 | +- [Drizzle ORM Documentation](https://orm.drizzle.team/docs/overview) |
0 commit comments