|
388 | 388 | go run cmd/routes/main.go --json | jq '.routes[].Name' | grep -q "api.users.index" |
389 | 389 | ``` |
390 | 390 |
|
391 | | -### 4. Documentation Generation |
| 391 | +### 4. Listing Routes Without Real Handler Dependencies |
| 392 | + |
| 393 | +In larger applications, handlers are often constructed with live dependencies (database |
| 394 | +connections, service clients, config, etc.) that are unavailable or expensive to build in a |
| 395 | +standalone CLI tool. The recommended pattern is to extract route registration into a shared |
| 396 | +function that accepts a handler interface, then provide a stub implementation backed by |
| 397 | +`teapot.NoopHandler` when listing: |
| 398 | + |
| 399 | +```go |
| 400 | +// Handlers defines the contract your route registration depends on. |
| 401 | +type Handlers interface { |
| 402 | + ListUsers() http.Handler |
| 403 | + ShowUser() http.Handler |
| 404 | + CreateUser() http.Handler |
| 405 | +} |
| 406 | + |
| 407 | +// RegisterRoutes is the single source of truth for all routes. |
| 408 | +// It is used by both the real server and the listing tool. |
| 409 | +func RegisterRoutes(r *teapot.Router, h Handlers) { |
| 410 | + r.GET("/users", h.ListUsers()).Name("users.index") |
| 411 | + r.GET("/users/{id}", h.ShowUser()).Name("users.show") |
| 412 | + r.POST("/users", h.CreateUser()).Name("users.store") |
| 413 | +} |
| 414 | + |
| 415 | +// Real implementation — constructed with live dependencies in main.go. |
| 416 | +type appHandlers struct{ db *sql.DB } |
| 417 | +func (h *appHandlers) ListUsers() http.Handler { return NewListUsersHandler(h.db) } |
| 418 | +func (h *appHandlers) ShowUser() http.Handler { return NewShowUserHandler(h.db) } |
| 419 | +func (h *appHandlers) CreateUser() http.Handler { return NewCreateUserHandler(h.db) } |
| 420 | + |
| 421 | +// Stub implementation — no dependencies required. |
| 422 | +type stubHandlers struct{} |
| 423 | +func (stubHandlers) ListUsers() http.Handler { return teapot.NoopHandler } |
| 424 | +func (stubHandlers) ShowUser() http.Handler { return teapot.NoopHandler } |
| 425 | +func (stubHandlers) CreateUser() http.Handler { return teapot.NoopHandler } |
| 426 | + |
| 427 | +// cmd/routes/main.go — prints routes with zero real dependencies. |
| 428 | +func main() { |
| 429 | + r := teapot.New() |
| 430 | + RegisterRoutes(r, stubHandlers{}) |
| 431 | + teapot.FormatRoutesTable(os.Stdout, r.Routes()) |
| 432 | +} |
| 433 | +``` |
| 434 | + |
| 435 | +Because the stub satisfies the same interface as the real implementation, adding a new route |
| 436 | +to `RegisterRoutes` will cause a compile error until `stubHandlers` is updated — keeping |
| 437 | +the listing tool automatically in sync. |
| 438 | + |
| 439 | +### 5. Documentation Generation |
392 | 440 |
|
393 | 441 | Generate route documentation from routes: |
394 | 442 |
|
|
0 commit comments