Imported from firmanJS/bun-hono-service (
AGENTS.md). Install upstream withnpx skills add firmanJS/bun-hono-service. Copyright stays with the author.
AGENTS.md — rnd-auth Hono Service
Context
Part of rnd-auth monorepo. Sibling services:
| Directory | Tech | Container name | Port |
|---|---|---|---|
gateway/ |
KrakenD 2.13.7 | gateway_rnd |
8081 |
rust-service/ |
Axum + MySQL | rust_service |
3000 |
hono-service/ |
Hono + Bun + MySQL | hono_service |
4000 |
All services share the gateway_rnd Docker bridge network for inter-container communication.
Architecture
Hono (TypeScript) with layered modular pattern:
src/
index.ts # entrypoint — validates env, starts Bun.serve
app.ts # Hono app factory, middleware wiring → registerRoutes
config/
environment.ts # env-based config (HOST, PORT, DATABASE_URL, …)
database/
connection.ts # Drizzle (MySQL2) pool
migrate.ts # programmatic migration runner (imported from CLI if needed)
middleware/
request-id.ts # crypto.randomUUID() → X-Request-Id header + context
logger.ts # Pino: requestId, ip, method, url, status, ms, headers, query, params, body
security.ts # security headers (configurable by env)
error.ts # AppError class + error/notFound handlers (includes requestId in response)
shared/
logger.ts # Pino instance (stdout with pretty-print or file destination)
redact.ts # sensitive field scrubber (password, token, secret, …)
response.ts # success() / error() helpers (status, message, data)
routes/
index.ts # route registry — import + mount all feature routers
modules/bank/ # self-contained feature module
schema.ts → repository.ts
handler.ts → service.ts → MySQL
types.ts # Valibot-inferred request/response types
- Handler — HTTP layer, Valibot validation, delegates to service
- Service — business logic, uniqueness checks, throws AppError
- Repository — Drizzle ORM queries (no raw SQL)
- Soft delete via
deleted_attimestamp
Commands
make dev # bun run --watch (hot reload)
make start # bun run (production)
make check # tsc --noEmit
make db-generate # drizzle-kit generate (after schema change)
make db-migrate # drizzle-kit migrate
make docker-build # build + start Docker container
Network
- Container:
hono_serviceongateway_rndbridge network - Gateway reaches this service as
hono_service:3000 - From macOS host via Docker:
host.docker.internal:3000
Conventions
.envis gitignored; copy.env.examplefor required vars- Docker Compose at
docker/docker-compose.yml— loads env from../.envviaenv_file - Database is external (MySQL): set
DATABASE_URLin.env - Migrations: generate with
make db-generate, apply withmake db-migrate(manual, not on startup) - API responses always
{ status: boolean, message: string, data: T | null }; errors includerequestIdindata - Every response gets
X-Request-Idheader (UUIDv4) for traceability - Logging via Pino: headers, query, params, body logged on every request; sensitive fields (password, token, secret, authorization, …) auto-redacted
LOG_OUTPUT=stdoutprints pretty-print to terminal;LOG_OUTPUT=filewrites structured JSON toLOG_FILEpath- Each module owns its Drizzle schema (
schema.ts) — no centralschema.ts - New modules: copy
src/module/bank/structure (schema, types, handler, service, repository), register route insrc/modules/index.ts, app.ts untouched