Files
monitoring-app/CLAUDE.md
amaliadwiy d09a702d64 upd: swagger docs, api key auth, bug fixes
- tambah Elysia Swagger di /docs dengan deskripsi lengkap semua endpoint
- tambah API key auth (X-API-Key) untuk klien eksternal di POST /api/bugs
- tambah normalisasi BugSource: SYSTEM/USER untuk eksternal, QC/SYSTEM/USER untuk dashboard
- perbaiki source schema jadi optional string agar tidak reject nilai unknown dari klien lama
- hapus field status dari form create bug (selalu OPEN)
- perbaiki typo desa_plus → appId di apps.$appId.errors.tsx
- tambah toggle hide/show stack trace di bug-reports.tsx dan apps.$appId.errors.tsx
- perbaiki grafik desa (width(-1)/height(-1)) dengan minWidth: 0 pada grid item
- perbaiki error &[data-active] inline style di DashboardLayout → pindah ke CSS class
- update CLAUDE.md dengan arsitektur lengkap

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 17:30:07 +08:00

5.5 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Runtime

Default to Bun instead of Node.js everywhere:

  • bun <file> not node / ts-node
  • bun test not jest / vitest
  • bun install not npm install / yarn / pnpm
  • bun run <script> not npm run
  • bunx <pkg> not npx
  • Bun auto-loads .env — never use dotenv.

Common Commands

bun run dev          # dev server with hot reload (bun --watch src/serve.ts)
bun run build        # Vite production build
bun run start        # production server (NODE_ENV=production)
bun run typecheck    # tsc --noEmit
bun run lint         # biome check src/
bun run lint:fix     # biome check --write src/

# Database
bun run db:migrate   # prisma migrate dev
bun run db:seed      # seed demo data
bun run db:generate  # regenerate prisma client
bun run db:studio    # Prisma Studio GUI
bun run db:push      # push schema without migration

# Tests
bun run test              # all tests
bun run test:unit         # tests/unit/
bun run test:integration  # tests/integration/ — no server needed
bun run test:e2e          # tests/e2e/ — requires Lightpanda Docker

Run a single test file: bun test tests/integration/auth.test.ts

Architecture

Server

Elysia.js on Bun. All API routes are in src/app.ts as createApp() — testable via app.handle(request) without starting a server. src/index.tsx adds Vite middleware (dev) or static serving (prod) and calls .listen(). src/serve.ts is the dev entry point (dynamic import workaround for Bun EADDRINUSE race).

Database

PostgreSQL via Prisma v6. Client generated to ./generated/prisma (gitignored — run bun run db:generate after checkout or schema changes).

Schema models: User, Session, App, Log, Bug, BugImage, BugLog

Enums: Role (ADMIN, DEVELOPER), BugStatus (OPEN, ON_HOLD, IN_PROGRESS, RESOLVED, RELEASED, CLOSED), BugSource (QC, SYSTEM, USER), LogType (CREATE, UPDATE, DELETE, LOGIN, LOGOUT)

Import the singleton: import { prisma } from './lib/db'

Auth & Roles

Session-based auth with HttpOnly cookies stored in the DB (24h expiry). Two roles: DEVELOPER (super admin) and ADMIN. Users listed in SUPER_ADMIN_EMAIL env var are auto-promoted to DEVELOPER on login.

Endpoints: POST /api/auth/login, POST /api/auth/logout, GET /api/auth/session

Auth state on the frontend is managed via useSession() / useLogin() / useLogout() in src/frontend/hooks/useAuth.ts (TanStack Query).

Frontend

React 19 + Vite 8 (middleware mode in dev). TanStack Router with file-based routing in src/frontend/routes/. All routes are wrapped in DashboardLayout from src/frontend/components/DashboardLayout.tsx.

Route structure:

  • / → redirect
  • /login → login page
  • /dashboard → stats overview
  • /apps → app list
  • /apps/$appId → per-app layout with nested routes: index, errors, logs, users, villages, orders, products, payments
  • /users → operator management
  • /logs → system activity log
  • /bug-reports → cross-app bug reports
  • /profile → user profile

App configs are defined in src/frontend/config/appMenus.ts — each app has an ID and a menu list. Currently active: desa-plus. Add new app entries here to register them.

routeTree.gen.ts is auto-generated by the TanStack Router Vite plugin — never edit it manually.

UI: Mantine v8, dark theme forced (#242424). Charts use @mantine/charts (recharts under the hood). Icons from react-icons/tb.

API Structure

All API routes live in src/app.ts. Key groups:

  • /api/auth/* — authentication
  • /api/dashboard/* — stats and recent errors
  • /api/apps, /api/apps/:appId — app listing and detail
  • /api/bugs, /api/bugs/:id/status, /api/bugs/:id/feedback — bug report CRUD
  • /api/operators, /api/operators/:id — user management
  • /api/logs — system activity log
  • /api/system/status — health check with DB connectivity

Logging

createSystemLog(userId, type, message) from src/lib/logger.ts writes to the Log model. Call it for any significant user action (login/logout/CRUD). Logging errors are swallowed so they never break the main flow.

Environment Variables

Required: DATABASE_URL, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET Optional: PORT (default 3000), NODE_ENV, REACT_EDITOR, SUPER_ADMIN_EMAIL (comma-separated)

Validated at startup in src/lib/env.ts — missing required vars throw immediately.

Testing

  • Unit tests: env, DB connection, bcrypt — in tests/unit/
  • Integration tests: createApp().handle(new Request(...)) — no running server needed, use these for mutations
  • E2E tests: Lightpanda browser via CDP (ws://127.0.0.1:9222). App URLs use host.docker.internal from inside Docker. Lightpanda executes JS but POST fetch returns 407 — use integration tests for anything that writes data.
  • Helpers: tests/helpers.tscreateTestApp(), seedTestUser(), createTestSession(), cleanupTestData()

Dev Tools

  • Click-to-source: Ctrl+Shift+Cmd+C toggles inspector. Custom Vite plugin in src/vite.ts injects data-inspector-* attributes; reads original source from disk for accurate line numbers.
  • HMR: Vite 8 + @vitejs/plugin-react v6. dedupeRefreshPlugin in src/vite.ts prevents double React Refresh injection.
  • Editor: Set REACT_EDITOR env var. zed/subl use file:line:col; others get --goto file:line:col.
  • Playwright MCP: bun run mcp:playwright starts headless browser MCP server (config in .qwen/settings.json).