-
Notifications
You must be signed in to change notification settings - Fork 0
docs\en\how_to_schema.md
Attach metadata (input/output types, descriptions, tags) directly to routes so AI understands API behavior without reading handler source code. Supports six protocols: REST, gRPC, Bot, MCP, WebSocket, and CLI.
Traditional routing tells the framework only "this URL maps to this handler" — AI must read the handler source to understand the API. Schema-first routing embeds metadata at registration time:
Traditional: r.POST("/api/users", createUserHandler) ← AI must read handler source
Schema: r.Schema(Route{...}).Handle(handler) ← AI reads metadata directly
import "github.com/maoxiaoyue/hypgo/pkg/schema"
// Define request/response types
type CreateUserRequest struct {
Name string `json:"name"`
Email string `json:"email"`
}
type UserResponse struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
// Register route with schema
r := router.New()
r.Schema(schema.Route{
Method: "POST",
Path: "/api/users",
Summary: "Create user",
Tags: []string{"users"},
Input: CreateUserRequest{},
Output: UserResponse{},
Responses: map[int]schema.ResponseSchema{
201: {Description: "User created"},
400: {Description: "Invalid input"},
},
}).Handle(createUserHandler)api := r.NewGroup("/api/v1")
api.Schema(schema.Route{
Method: "GET",
Path: "/products",
Summary: "List products",
Tags: []string{"products"},
Output: []ProductResponse{},
}).Handle(listProductsHandler)
// Route is automatically registered as GET /api/v1/productsSchema routes and traditional routes can coexist — fully backward compatible:
r.GET("/health", healthHandler) // Traditional route — works as usual
r.Schema(schema.Route{...}).Handle(createHandler) // Schema route — carries metadata
v0.8.5+Multi-protocol support (gRPC / Bot / MCP / WebSocket / CLI) is new in v0.8.5. v0.8.1 supports REST only.
Beyond REST, Schema supports registering command contracts for other protocols directly:
// gRPC
schema.RegisterGRPC("UserService/CreateUser", "Create user", CreateUserReq{}, UserResp{})
// Bot (Telegram, Line, Discord, WhatsApp, etc.)
schema.RegisterBot("/start", "Start the bot", nil, WelcomeMsg{})
schema.RegisterBotPlatform("telegram", "/game", "Start game", GameOpts{}, GameState{})
schema.RegisterBotPlatform("discord", "!play", "Play music", PlayReq{}, PlayResp{})
// MCP (Model Context Protocol)
schema.RegisterMCP("search_repos", "Search repos", SearchInput{}, SearchOutput{})
// WebSocket message types
schema.RegisterWebSocket("join_room", "Join room", JoinReq{}, JoinResp{})
// CLI subcommands
schema.RegisterCLI("process", "Process data", ProcessFlags{}, ProcessResult{})All protocols share a single Schema Registry and Manifest — AI reads one manifest to understand all APIs.
type Route struct {
// Common fields (shared across all protocols)
Protocol string // "rest"(default), "grpc", "bot", "mcp", "websocket", "cli"
Command string // Non-REST command identifier (gRPC method, bot command, MCP tool...)
Platform string // Bot-specific platform: "telegram", "line", "discord", "whatsapp"
Summary string // One-line description (for AI and documentation)
Description string // Detailed description
Tags []string // Category tags
Input interface{} // Request Go struct (used for validation)
Output interface{} // Response Go struct (used for validation)
InputName string // Auto-populated, no need to set manually
OutputName string // Auto-populated, no need to set manually
// REST-specific (backward compatible)
Method string // HTTP method (GET, POST, PUT, DELETE...)
Path string // Route path (supports :param and *catchall)
Params []ParamSchema // Path/query parameter descriptions
Headers []HeaderSchema // Required request header descriptions
Responses map[int]ResponseSchema // Response descriptions per status code
}
// RouteKey() returns the Registry lookup key:
// REST: "rest|POST /api/users"
// gRPC: "grpc|UserService/CreateUser"
// Bot: "bot|/start"
// MCP: "mcp|search_repos"
// IsREST() reports whether this is a REST route| Protocol | Command Format | Example |
|---|---|---|
rest |
Method + Path (auto) |
POST /api/users |
grpc |
Service/Method |
UserService/CreateUser |
bot |
/command or event name |
/start, follow, !play
|
mcp |
tool_name |
search_repos, create_issue
|
websocket |
message_type |
join_room, send_message
|
cli |
command_name |
process, export
|
type ParamSchema struct {
Name string // Parameter name
In string // "path", "query", "header"
Required bool // Whether required
Type string // "string", "int", "bool"
Desc string // Description
}type ResponseSchema struct {
Description string // Response description
Type interface{} // Go struct type (used for Contract Testing validation)
TypeName string // Auto-populated
}All routes registered via Schema() or Register*() are stored in the global Registry:
// Query REST route (backward compatible)
route, ok := schema.Global().Get("POST", "/api/users")
// Query by full key (any protocol)
route, ok := schema.Global().GetByKey("grpc|UserService/CreateUser")
route, ok := schema.Global().GetByKey("bot|/start")
// Filter by protocol
grpcRoutes := schema.Global().GetByProtocol("grpc")
botRoutes := schema.Global().GetByProtocol("bot")
// Get all registered schemas (all protocols)
all := schema.Global().All()
// Check registered count
count := schema.Global().Len()
// Clear (for testing)
schema.Global().Reset()The Registry is thread-safe, protected by sync.RWMutex.
Type introspection tools used by Manifest and Contract Testing:
// Get type name
schema.TypeName(UserResponse{}) // → "UserResponse"
// Get struct field info
fields := schema.FieldsOf(UserResponse{})
// → [{Name:"id", Type:"integer", Required:true}, ...]
// Validate JSON against struct (including required field checks)
err := schema.ValidateJSON([]byte(`{"name":"alice"}`), CreateUserRequest{})
// Generate zero-value JSON (used for automatic testing)
data := schema.GenerateZeroJSON(CreateUserRequest{})
// → {"name":"","email":""}| Condition | Required |
|---|---|
Name string \json:"name"`` |
✅ Yes |
Email string \json:"email,omitempty"`` |
❌ No (omitempty) |
Bio *string \json:"bio"`` |
❌ No (pointer) |
json:"-" |
Skipped (not present) |
pkg/schema/
├── schema.go Route (multi-protocol), SchemaRoute, ParamSchema type definitions
├── registry.go Global thread-safe Registry (supports RouteKey multi-protocol queries)
├── helpers.go RegisterGRPC/Bot/MCP/WebSocket/CLI convenience functions
├── reflect.go TypeName, FieldsOf, ValidateJSON reflection utilities
└── schema_test.go Unit tests
pkg/schema ← depends only on pkg/context (HandlerFunc type)
← does NOT depend on pkg/router (avoids circular dependency)
The SchemaRegistrar interface is defined in schema, implemented by Router and Group, avoiding circular dependencies.
由 台灣卯小月 用 ❤️ 製作 · MIT License And Wiki is written by Claude
設計文件
套件
- config — 設定
- context — 請求上下文
- router — 路由器
- server — 伺服器
- middleware — 中介層
- websocket — WebSocket
- hidb — 資料庫 ORM
- hidb/cassandra — Cassandra
- logger — 日誌
- json — JSON 處理
- grpc — gRPC
AI 協作工具鏈
- schema — Schema-first 路由
- manifest — 專案 Manifest
- contract — Contract Testing
- errors — Typed Error Catalog
- migrate — Migration Diff
- scaffold — 智慧 Scaffold
- airules — AI Rules
CLI 命令
- hyp 總覽
- hyp new
- hyp api
- hyp run
- hyp restart
- hyp generate
- hyp migrate
- hyp context
- hyp ai-rules
- hyp chkcomment
- hyp impact
- hyp docker
- hyp health
- hyp version
- hyp difflog
Design Docs
Packages
- config — Configuration
- context — Request Context
- router — Router
- server — Server
- middleware — Middleware
- websocket — WebSocket
- hidb — Database ORM
- hidb/cassandra - Cassandra 5.0
- logger — Logger
- json — JSON
- grpc — gRPC
AI Collaboration Toolchain
- schema — Schema-first Routing
- manifest — Project Manifest
- contract — Contract Testing
- errors — Typed Error Catalog
- migrate — Migration Diff
- scaffold — Smart Scaffold
- airules — AI Rules
CLI Commands