Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

schema_en.md

maoxiaoyue edited this page May 14, 2026 · 1 revision

pkg/schema — Schema-first Route Registration (Multi-Protocol)

Attach metadata (input/output types, descriptions, tags) to routes so that AI can understand API behavior without tracing handler implementations. Supports REST, gRPC, Bot, MCP, WebSocket, and CLI protocols.

Design Philosophy

Traditional routes only tell the framework "which handler this URL maps to," requiring AI to read handler source code to understand the API. Schema-first routes attach metadata directly to routes:

Traditional: r.POST("/api/users", createUserHandler) <- AI needs to read handler source
Schema: r.Schema(Route{...}).Handle(handler) <- AI understands directly from metadata

Quick Start

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 a 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)

With Route Groups

api := r.NewGroup("/api/v1")
api.Schema(schema.Route{
 Method: "GET",
 Path: "/products",
 Summary: "Get product list",
 Tags: []string{"products"},
 Output: []ProductResponse{},
}).Handle(listProductsHandler)
// Route is automatically registered as GET /api/v1/products

Mixed Usage

Schema routes and traditional routes can coexist with full backward compatibility:

r.GET("/health", healthHandler) // Traditional route -- works as usual
r.Schema(schema.Route{...}).Handle(createHandler) // Schema route -- with metadata

Multi-Protocol Schema Registration

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:

// 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 the same Schema Registry and Manifest — AI reads one manifest to understand all APIs.

Core Types

Route (Multi-Protocol)

type Route struct {
 // Universal fields (all protocols)
 Protocol string // "rest"(default), "grpc", "bot", "mcp", "websocket", "cli"
 Command string // Non-REST command identifier
 Platform string // Bot-specific platform: "telegram", "line", "discord", "whatsapp"
 Summary string // One-line description (for AI and documentation)
 Description string // Detailed description
 Tags []string // Classification tags
 Input interface{} // Request Go struct (for validation)
 Output interface{} // Response Go struct (for validation)
 InputName string // Auto-populated, no manual setup needed
 OutputName string // Auto-populated, no manual setup needed
 // 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 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() returns true if this is a REST route

Supported Protocols

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

ParamSchema

type ParamSchema struct {
 Name string // Parameter name
 In string // "path", "query", "header"
 Required bool // Whether required
 Type string // "string", "int", "bool"
 Desc string // Description
}

ResponseSchema

type ResponseSchema struct {
 Description string // Response description
 Type interface{} // Go struct type (for Contract Testing validation)
 TypeName string // Auto-populated
}

Registry (Global Registry)

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()
// Reset (for testing)
schema.Global().Reset()

The Registry is thread-safe, protected by sync.RWMutex.

Reflection Utilities

Provides type introspection tools for use by Manifest and Contract Testing:

// Get type name
schema.TypeName(UserResponse{}) // -> "UserResponse"
// Get struct field information
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 (for automated testing)
data := schema.GenerateZeroJSON(CreateUserRequest{})
// -> {"name":"","email":""}

Required Field Rules

Condition Required
Name string \json:"name"`` Yes
Email string \json:"email,omitempty"`` No (omitempty)
Bio *string \json:"bio"`` No (pointer)
json:"-" Skipped (not present)

Architecture

pkg/schema/
├── schema.go Route (multi-protocol), SchemaRoute, ParamSchema type definitions
├── registry.go Global thread-safe Registry (supports RouteKey multi-protocol lookup)
├── helpers.go RegisterGRPC/Bot/MCP/WebSocket/CLI convenience functions
├── reflect.go TypeName, FieldsOf, ValidateJSON reflection utilities
└── schema_test.go Unit tests

Dependencies

pkg/schema <- Only depends on pkg/context (HandlerFunc type)
 <- Does not depend on pkg/router (avoids circular dependency)

The SchemaRegistrar interface is defined by schema, implemented by Router and Group, avoiding circular dependencies.

HypGo

繁體中文 | English


中文文件

設計文件

套件

AI 協作工具鏈

CLI 命令


English Docs

Design Docs

Packages

AI Collaboration Toolchain

CLI Commands

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /