chore: add GSD codebase map with 7 analysis documents
Parallel analysis of tech stack, architecture, structure, conventions, testing patterns, integrations, and concerns. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
198
.planning/codebase/CONVENTIONS.md
Normal file
198
.planning/codebase/CONVENTIONS.md
Normal file
@@ -0,0 +1,198 @@
|
||||
# Coding Conventions
|
||||
|
||||
**Analysis Date:** 2026-03-23
|
||||
|
||||
## Naming Patterns
|
||||
|
||||
**Go Files:**
|
||||
- Package-level source files use the package name: `diunwebhook.go`
|
||||
- Test files follow Go convention: `diunwebhook_test.go`
|
||||
- Test-only export files: `export_test.go`
|
||||
- Entry point: `main.go` inside `cmd/diunwebhook/`
|
||||
|
||||
**Go Functions:**
|
||||
- PascalCase for exported functions: `WebhookHandler`, `UpdateEvent`, `InitDB`, `GetUpdates`
|
||||
- Handler functions are named `<Noun>Handler`: `WebhookHandler`, `UpdatesHandler`, `DismissHandler`, `TagsHandler`, `TagByIDHandler`, `TagAssignmentHandler`
|
||||
- Test functions use `Test<FunctionName>_<Scenario>`: `TestWebhookHandler_BadRequest`, `TestDismissHandler_NotFound`
|
||||
|
||||
**Go Types:**
|
||||
- PascalCase structs: `DiunEvent`, `UpdateEntry`, `Tag`
|
||||
- JSON tags use snake_case: `json:"diun_version"`, `json:"hub_link"`, `json:"received_at"`
|
||||
|
||||
**Go Variables:**
|
||||
- Package-level unexported variables use short names: `mu`, `db`, `webhookSecret`
|
||||
- Local variables use short idiomatic Go names: `w`, `r`, `err`, `res`, `n`, `e`
|
||||
|
||||
**TypeScript Files:**
|
||||
- Components: PascalCase `.tsx` files: `ServiceCard.tsx`, `AcknowledgeButton.tsx`, `Header.tsx`, `TagSection.tsx`
|
||||
- Hooks: camelCase with `use` prefix: `useUpdates.ts`, `useTags.ts`
|
||||
- Types: camelCase `.ts` files: `diun.ts`
|
||||
- Utilities: camelCase `.ts` files: `utils.ts`, `time.ts`, `serviceIcons.ts`
|
||||
- UI primitives (shadcn): lowercase `.tsx` files: `badge.tsx`, `button.tsx`, `card.tsx`, `tooltip.tsx`
|
||||
|
||||
**TypeScript Functions:**
|
||||
- camelCase for regular functions and hooks: `fetchUpdates`, `useUpdates`, `getServiceIcon`
|
||||
- PascalCase for React components: `ServiceCard`, `StatCard`, `AcknowledgeButton`
|
||||
- Helper functions within components use camelCase: `getInitials`, `getTag`, `getShortName`
|
||||
- Event handlers prefixed with `handle`: `handleDragEnd`, `handleNewGroupSubmit`
|
||||
|
||||
**TypeScript Types:**
|
||||
- PascalCase interfaces: `DiunEvent`, `UpdateEntry`, `Tag`, `ServiceCardProps`
|
||||
- Type aliases: PascalCase: `UpdatesMap`
|
||||
- Interface properties use snake_case matching the Go JSON tags: `diun_version`, `hub_link`
|
||||
|
||||
## Code Style
|
||||
|
||||
**Go Formatting:**
|
||||
- `gofmt` enforced in CI (formatting check fails the build)
|
||||
- No additional Go linter (golangci-lint) configured
|
||||
- `go vet` runs in CI
|
||||
- Standard Go formatting: tabs for indentation
|
||||
|
||||
**TypeScript Formatting:**
|
||||
- No ESLint or Prettier configured in the frontend
|
||||
- No formatting enforcement in CI for frontend code
|
||||
- Consistent 2-space indentation observed in all `.tsx` and `.ts` files
|
||||
- Single quotes for strings in TypeScript
|
||||
- No semicolons (observed in all frontend files)
|
||||
- Trailing commas used in multi-line constructs
|
||||
|
||||
**TypeScript Strictness:**
|
||||
- `strict: true` in `tsconfig.app.json`
|
||||
- `noUnusedLocals: true`
|
||||
- `noUnusedParameters: true`
|
||||
- `noFallthroughCasesInSwitch: true`
|
||||
- `noUncheckedSideEffectImports: true`
|
||||
|
||||
## Import Organization
|
||||
|
||||
**Go Import Order:**
|
||||
Standard library imports come first, followed by a blank line, then the project import using the module alias:
|
||||
|
||||
```go
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
diun "awesomeProject/pkg/diunwebhook"
|
||||
)
|
||||
```
|
||||
|
||||
- The project module is aliased as `diun` in both `main.go` and test files
|
||||
- The blank-import pattern `_ "modernc.org/sqlite"` is used for the SQLite driver in `pkg/diunwebhook/diunwebhook.go`
|
||||
|
||||
**TypeScript Import Order:**
|
||||
1. React and framework imports (`react`, `@dnd-kit/core`)
|
||||
2. Internal imports using `@/` path alias (`@/hooks/useUpdates`, `@/components/Header`)
|
||||
3. Type-only imports: `import type { Tag, UpdatesMap } from '@/types/diun'`
|
||||
|
||||
**Path Aliases:**
|
||||
- `@/` maps to `frontend/src/` (configured in `vite.config.ts` and `tsconfig.app.json`)
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Go Patterns:**
|
||||
- Handlers use `http.Error(w, message, statusCode)` for all error responses
|
||||
- Error messages are lowercase: `"bad request"`, `"internal error"`, `"not found"`, `"method not allowed"`
|
||||
- Internal errors are logged with `log.Printf` before returning HTTP 500
|
||||
- Decode errors include context: `log.Printf("WebhookHandler: failed to decode request: %v", err)`
|
||||
- Fatal errors in `main.go` use `log.Fatalf`
|
||||
- `errors.Is()` used for sentinel error comparison (e.g., `http.ErrServerClosed`)
|
||||
- String matching used for SQLite constraint errors: `strings.Contains(err.Error(), "UNIQUE")`
|
||||
|
||||
**TypeScript Patterns:**
|
||||
- API errors throw with HTTP status: `throw new Error(\`HTTP ${res.status}\`)`
|
||||
- Catch blocks use `console.error` for logging
|
||||
- Error state stored in hook state: `setError(e instanceof Error ? e.message : 'Failed to fetch updates')`
|
||||
- Optimistic updates used for tag assignment (update UI first, then call API)
|
||||
|
||||
## Logging
|
||||
|
||||
**Framework:** Go standard `log` package
|
||||
|
||||
**Patterns:**
|
||||
- Startup messages: `log.Printf("Listening on :%s", port)`
|
||||
- Warnings: `log.Println("WARNING: WEBHOOK_SECRET not set ...")`
|
||||
- Request logging on success: `log.Printf("Update received: %s (%s)", event.Image, event.Status)`
|
||||
- Error logging before HTTP error response: `log.Printf("WebhookHandler: failed to store event: %v", err)`
|
||||
- Handler name prefixed to log messages: `"WebhookHandler: ..."`, `"UpdatesHandler: ..."`
|
||||
|
||||
**Frontend:** `console.error` for API failures, no structured logging
|
||||
|
||||
## Comments
|
||||
|
||||
**When to Comment:**
|
||||
- Comments are sparse in the Go codebase
|
||||
- Handler functions have short doc comments describing the routes they handle:
|
||||
```go
|
||||
// TagsHandler handles GET /api/tags and POST /api/tags
|
||||
// TagByIDHandler handles DELETE /api/tags/{id}
|
||||
// TagAssignmentHandler handles PUT /api/tag-assignments and DELETE /api/tag-assignments
|
||||
```
|
||||
- Inline comments used for non-obvious behavior: `// Migration: add acknowledged_at to existing databases`
|
||||
- No JSDoc/TSDoc in the frontend codebase
|
||||
|
||||
## Function Design
|
||||
|
||||
**Go Handler Pattern:**
|
||||
- Each handler is a standalone `func(http.ResponseWriter, *http.Request)`
|
||||
- Method checking done at the top of each handler (not via middleware)
|
||||
- Multi-method handlers use `switch r.Method`
|
||||
- URL path parameters extracted via `strings.TrimPrefix`
|
||||
- Request bodies decoded with `json.NewDecoder(r.Body).Decode(&target)`
|
||||
- Responses written with `json.NewEncoder(w).Encode(data)` or `w.WriteHeader(status)`
|
||||
- Mutex (`mu`) used around write operations to SQLite
|
||||
|
||||
**TypeScript Hook Pattern:**
|
||||
- Custom hooks return object with state and action functions
|
||||
- `useCallback` wraps all action functions
|
||||
- `useEffect` for side effects (polling, initial fetch)
|
||||
- State updates use functional form: `setUpdates(prev => { ... })`
|
||||
|
||||
## Module Design
|
||||
|
||||
**Go Exports:**
|
||||
- Single package `diunwebhook` exports all types and handler functions
|
||||
- No barrel files; single source file `diunwebhook.go` contains everything
|
||||
- Test helpers exposed via `export_test.go` (only visible to `_test` packages)
|
||||
|
||||
**TypeScript Exports:**
|
||||
- Named exports for all components, hooks, and utilities
|
||||
- Default export only for the root `App` component (`export default function App()`)
|
||||
- Type exports use `export interface` or `export type`
|
||||
- `@/components/ui/` contains shadcn primitives (`badge.tsx`, `button.tsx`, etc.)
|
||||
|
||||
## Git Commit Message Conventions
|
||||
|
||||
**Format:** Conventional Commits with bold markdown formatting
|
||||
|
||||
**Pattern:** `**<type>(<scope>):** <description>`
|
||||
|
||||
**Types observed:**
|
||||
- `feat` - new features
|
||||
- `fix` - bug fixes
|
||||
- `docs` - documentation changes
|
||||
- `chore` - maintenance tasks (deps, config)
|
||||
- `refactor` - code restructuring
|
||||
- `style` - UI/styling changes
|
||||
- `test` - test additions
|
||||
|
||||
**Scopes observed:** `docs`, `compose`, `webhook`, `ci`, `ui`, `main`, `errors`, `sql`, `api`, `deps`, `stats`
|
||||
|
||||
**Examples:**
|
||||
```
|
||||
**feat(webhook):** add `WEBHOOK_SECRET` for token authentication support
|
||||
**fix(ci):** improve version bump script for robustness and compatibility
|
||||
**docs:** expand `index.md` with architecture, quick start, and tech stack
|
||||
**chore(docs):** add `.gitignore` for `docs` and introduce `bun.lock` file
|
||||
```
|
||||
|
||||
**Multi-change commits:** Use bullet list with each item prefixed by `- **type(scope):**`
|
||||
|
||||
---
|
||||
|
||||
*Convention analysis: 2026-03-23*
|
||||
Reference in New Issue
Block a user