rdev/internal/adapter/templates/templates/skeleton/pkg/httpresponse/envelope.go.tmpl
jordan 8282d60c69 feat: implement composable monorepo template system with component architecture
Adds the composable monorepo template system that generates project skeletons
with pluggable components (service, worker, app-react, app-astro, cli).

Key changes:
- Monorepo skeleton templates with shared pkg/, scripts/, and git hooks
- Component templates (service, worker, app-react, app-astro, cli) with
  Dockerfiles, CI steps, and component.yaml manifests
- Component domain model with validation and dependency resolution
- Component handler endpoints for CRUD and composition
- Template provider extended with BuildComposableProject and component assembly
- Deployer extended with composable project deployment support
- Handler timeout constants (TimeoutFastLookup through TimeoutLongRunning)
- envutil package for centralized env var reads with defaults
- api.DecodeJSON helper for standardized request body decoding
- Standardized response helpers (WriteBadRequest, WriteNotFound, etc.)
- Replaced fullstack-app cookbook with composable-app cookbook
- Hardened handler timeouts, logging, and error responses across all handlers

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 19:11:42 -07:00

76 lines
1.9 KiB
Cheetah

// Package httpresponse provides standard HTTP response types and helpers.
//
// This package implements an envelope pattern for consistent API responses:
//
// {
// "data": {...}, // Present on success
// "error": {...}, // Present on error
// "meta": {
// "request_id": "...",
// "trace_id": "...",
// "timestamp": "..."
// }
// }
//
// Usage:
//
// func GetUser(w http.ResponseWriter, r *http.Request) {
// user, err := svc.Get(ctx, id)
// if err != nil {
// httpresponse.NotFound(w, r, "user not found")
// return
// }
// httpresponse.OK(w, r, user)
// }
package httpresponse
import (
"net/http"
"time"
"{{GO_MODULE}}/pkg/httpcontext"
)
// Response is the standard envelope for all API responses.
type Response struct {
Data any `json:"data,omitempty"`
Error *Error `json:"error,omitempty"`
Meta Meta `json:"meta"`
}
// Error represents an API error in the response envelope.
type Error struct {
Code string `json:"code"`
Message string `json:"message"`
Details any `json:"details,omitempty"`
}
// Meta contains response metadata.
type Meta struct {
RequestID string `json:"request_id,omitempty"`
TraceID string `json:"trace_id,omitempty"`
Timestamp string `json:"timestamp"`
}
// newMeta creates a Meta with current timestamp, request ID, and trace ID from context.
func newMeta(r *http.Request) Meta {
requestID, _ := httpcontext.GetRequestID(r.Context())
traceID, _ := httpcontext.GetTraceID(r.Context())
return Meta{
RequestID: requestID,
TraceID: traceID,
Timestamp: time.Now().UTC().Format(time.RFC3339),
}
}
// Error codes for machine-readable error classification.
const (
CodeBadRequest = "BAD_REQUEST"
CodeUnauthorized = "UNAUTHORIZED"
CodeForbidden = "FORBIDDEN"
CodeNotFound = "NOT_FOUND"
CodeConflict = "CONFLICT"
CodeInternal = "INTERNAL_ERROR"
CodeValidation = "VALIDATION_ERROR"
)