slate-test-1770505673/services/preferences-api/internal/api/spec.go
rdev-worker 868f79c67a
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
build: /implement-feature user-preferences
2026-02-07 23:47:42 +00:00

73 lines
3.4 KiB
Go

package api
import "git.threesix.ai/jordan/slate-test-1770505673/pkg/openapi"
// NewServiceSpec builds the OpenAPI specification for the preferences-api service.
func NewServiceSpec() *openapi.OpenAPISpec {
spec := openapi.NewOpenAPISpec("preferences-api API", "1.0.0").
WithDescription("REST API for user preferences management").
WithBearerSecurity("bearer", "JWT authentication token").
WithTag("Health", "Service health endpoints").
WithTag("Preferences", "User preference endpoints")
// Reusable schemas
spec.WithSchema("PreferencesMap", openapi.Object(map[string]openapi.Schema{
"theme": openapi.StringEnum("light", "dark", "system").WithDescription("UI theme preference"),
"language": openapi.String().WithPattern("^[a-z]{2}$").WithDescription("ISO 639-1 language code"),
"notifications_enabled": openapi.StringEnum("true", "false").WithDescription("Notification toggle"),
}))
spec.WithSchema("UpdatePreferencesRequest", openapi.Object(map[string]openapi.Schema{
"theme": openapi.StringEnum("light", "dark", "system").WithDescription("UI theme preference"),
"language": openapi.String().WithPattern("^[a-z]{2}$").WithDescription("ISO 639-1 language code"),
"notifications_enabled": openapi.StringEnum("true", "false").WithDescription("Notification toggle"),
}))
userIDParam := openapi.PathParamWithSchema("user_id", "User UUID", openapi.UUID())
// Health
spec.AddPath("/api/preferences-api/health", "get", map[string]any{
"summary": "Health check",
"tags": []string{"Health"},
"responses": map[string]any{
"200": openapi.OpResponse("Service is healthy", openapi.Object(map[string]openapi.Schema{
"service": openapi.String(),
"status": openapi.String(),
})),
},
})
// GET /preferences/{user_id}
spec.AddPath("/api/preferences-api/preferences/{user_id}", "get", map[string]any{
"summary": "Get user preferences",
"description": "Returns all preferences for a user. Returns empty object if no preferences are set.",
"tags": []string{"Preferences"},
"security": []map[string][]string{{"bearer": {}}},
"parameters": []any{userIDParam},
"responses": map[string]any{
"200": openapi.OpResponse("Success", openapi.ResponseSchema(openapi.Ref("PreferencesMap"))),
"400": openapi.OpResponse("Invalid user ID", openapi.ErrorResponseSchema()),
"401": openapi.OpResponse("Unauthorized", openapi.ErrorResponseSchema()),
"403": openapi.OpResponse("Forbidden", openapi.ErrorResponseSchema()),
},
})
// PUT /preferences/{user_id}
spec.AddPath("/api/preferences-api/preferences/{user_id}", "put", map[string]any{
"summary": "Update user preferences",
"description": "Creates or updates preferences for a user (partial upsert). Returns the full preference set after the update.",
"tags": []string{"Preferences"},
"security": []map[string][]string{{"bearer": {}}},
"parameters": []any{userIDParam},
"requestBody": openapi.RequestBody(openapi.Ref("UpdatePreferencesRequest"), true),
"responses": map[string]any{
"200": openapi.OpResponse("Updated", openapi.ResponseSchema(openapi.Ref("PreferencesMap"))),
"400": openapi.OpResponse("Bad request", openapi.ErrorResponseSchema()),
"401": openapi.OpResponse("Unauthorized", openapi.ErrorResponseSchema()),
"403": openapi.OpResponse("Forbidden", openapi.ErrorResponseSchema()),
},
})
return spec
}