router

package
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 24, 2026 License: MIT Imports: 26 Imported by: 0

Documentation

Overview

Package router implements file-based routing for Vango.

The router provides:

  • File-system based route discovery from app/routes/
  • Radix tree for efficient route matching
  • Parameter extraction with type coercion
  • Layout composition and middleware chains
  • Code generation for compile-time route registration

File Structure Convention

Routes are defined by Go files in the app/routes/ directory:

app/routes/
├── index.go           → GET /
├── about.go           → GET /about
├── layout.go          → Layout for all routes
├── projects/
│   ├── index.go       → GET /projects
│   ├── [id].go        → GET /projects/:id
│   └── layout.go      → Layout for /projects/*
└── api/
    └── users.go       → GET/POST /api/users

Note: Bracket notation is allowed in filenames (e.g. [id].go), but NOT recommended for directory names (e.g. projects/[id]/index.go) because Go import paths cannot contain '[' or ']'. For nested param routes, prefer the Go-friendly directory segment: projects/id_/index.go.

Parameters

Dynamic route segments are defined with brackets:

[id].go        → :id (string by default)
[id:int].go    → :id (parsed as int)
[...slug].go   → *slug (catch-all, []string)

Route Files

Each route file can export specific functions:

func Page(ctx server.Ctx, params Params) vdom.Component  // Page handler
func Layout(ctx server.Ctx, children Slot) *vdom.VNode   // Layout wrapper (Slot is opaque)
func Meta(ctx server.Ctx, params Params) PageMeta        // Page metadata
func Middleware() []Middleware                           // Route middleware
func GET(ctx server.Ctx, params Params) (any, error)     // API handlers
func POST(ctx server.Ctx, params Params, body T) (any, error)

Usage

scanner := router.NewScanner("app/routes")
routes, err := scanner.Scan()

r := router.NewRouter()
for _, route := range routes {
    r.AddPage(route.Path, pageHandler)
}

result, ok := r.Match("GET", "/projects/123")
if ok {
    // result.Params["id"] == "123"
    // result.PageHandler, result.Layouts, result.Middleware available
}

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidPath           = routepath.ErrInvalidPath
	ErrBackslashInPath       = routepath.ErrBackslashInPath
	ErrNullByteInPath        = routepath.ErrNullByteInPath
	ErrInvalidPercentEscape  = routepath.ErrInvalidPercentEscape
	ErrPathEscapesRoot       = routepath.ErrPathEscapesRoot
	ErrEncodedSlashInSegment = routepath.ErrEncodedSlashInSegment
)

Path canonicalization errors.

View Source
var ErrRateLimited = errors.New("rate limit exceeded")

ErrRateLimited is returned when the rate limit is exceeded.

Functions

func ActiveLink(href string, activeClass string, exactMatch bool, children ...any) *vdom.VNode

ActiveLink creates a link with custom active class handling via data attributes. This is for power users who need custom active class names or client-side active state detection.

For most use cases, prefer el.NavLink(ctx, path, children...) which uses server-side path matching to add the "active" class directly.

The activeClass is set via data-active-class attribute. The exactMatch parameter controls whether the match must be exact (data-active-exact).

func CanonicalizeAndValidateNavPath

func CanonicalizeAndValidateNavPath(path string) (string, error)

CanonicalizeAndValidateNavPath canonicalizes and validates a navigation path.

func ComposeMiddleware

func ComposeMiddleware(ctx server.Ctx, mw []Middleware, handler func() error) error

ComposeMiddleware builds a handler chain from middleware and a final handler. Middleware is executed in order (first to last), with the handler at the end.

func DataLink() vdom.Attr

DataLink creates an anchor attribute that enables client-side navigation.

Deprecated: Use VangoLink() instead. This function is kept for backwards compatibility but will be removed in a future version.

func DecodePathSegments

func DecodePathSegments(path string) ([]string, error)

DecodePathSegments decodes all segments of a path.

func DecodeSegment

func DecodeSegment(segment string, isCatchAll bool) (string, error)

DecodeSegment decodes a single path segment.

func FormatValidationError

func FormatValidationError(err ValidationError) string

FormatValidationError formats a validation error for display. Per the spec, errors should be formatted clearly:

ERROR: Duplicate route detected
  /projects/[id].go → /projects/:id
  /projects/id_.go → /projects/:id
func Link(href string, children ...any) *vdom.VNode

Link creates an anchor element with SPA navigation enabled. When clicked, the thin client intercepts and sends a navigate event to the server instead of performing a full page reload.

Deprecated: Use el.Link() instead. With the dot import of el, this is simply Link("/path", Text("label")). This function remains for backwards compatibility but will be removed in a future version.

func LinkWithPrefetch deprecated

func LinkWithPrefetch(href string, children ...any) *vdom.VNode

LinkWithPrefetch creates a link that prefetches the target page on hover. This provides faster navigation by loading the target page before the user clicks.

Deprecated: Use el.LinkPrefetch() instead. With the dot import of el, this is simply LinkPrefetch("/path", Text("label")). This function remains for backwards compatibility but will be removed in a future version.

func NavLink(href string, children ...any) *vdom.VNode

NavLink creates a link with default active class handling.

Deprecated: Use el.NavLink(ctx, path, children...) instead. The new NavLink uses server-side path matching which works with SSR and doesn't require client-side JavaScript. This function remains for backwards compatibility but will be removed in a future version.

func Prefetch

func Prefetch() vdom.Attr

Prefetch creates a prefetch attribute for links. Add this to any anchor element to enable hover prefetching.

Example:

A(Href("/about"), Prefetch(), Text("About"))

func Redirect

func Redirect(ctx server.Ctx, path string, code int)

Redirect sends an HTTP redirect response (relative paths only). This should only be used for initial page loads, not WebSocket navigations.

func RedirectExternal

func RedirectExternal(ctx server.Ctx, url string, code int)

RedirectExternal sends an HTTP redirect to an external URL. External redirects require an explicit allowlist.

func SortBySpecificity

func SortBySpecificity(routes []ScannedRoute)

SortBySpecificity sorts routes by specificity for proper matching order. Per Section 1.3.1:

  • Static segments > typed parameters > plain parameters > catch-all
  • More specific routes should be matched first

Order (most specific first):

  1. Static routes (/users/profile)
  2. Routes with typed params (/users/:id where id is int)
  3. Routes with plain params (/users/:id where id is string)
  4. Catch-all routes (/users/*path)

func SplitPathAndQuery

func SplitPathAndQuery(input string) (path, query string)

SplitPathAndQuery splits a path into path and query components. The query is returned without the leading "?".

func ValidateInt

func ValidateInt(value string) error

ValidateInt validates that a string is a valid integer.

func ValidateParam

func ValidateParam(value, paramType string) error

ValidateParam validates a parameter value against its expected type.

func ValidateUUID

func ValidateUUID(value string) error

ValidateUUID validates that a string is a valid UUID.

func VangoLink() vdom.Attr

VangoLink creates an anchor attribute that enables client-side navigation. This is the canonical marker for SPA navigation.

Example:

A(Href("/about"), VangoLink(), Text("About"))

Types

type APIEndpoint

type APIEndpoint struct {
	Path         string
	Method       string
	FuncName     string
	Package      string
	Description  string
	Params       []ParamDef
	RequestType  *TypeInfo
	ResponseType *TypeInfo
}

APIEndpoint represents a discovered API endpoint.

type APIHandler

type APIHandler func(ctx server.Ctx, params any, body any) (any, error)

APIHandler handles an API request, returning data or an error. The params parameter is a typed params struct, body is the decoded request body.

type CanonicalizeResult

type CanonicalizeResult = routepath.CanonicalizeResult

CanonicalizeResult contains the result of path canonicalization.

func CanonicalizePath

func CanonicalizePath(input string) (CanonicalizeResult, error)

CanonicalizePath normalizes a URL path according to the routing contract.

type ErrorHandler

type ErrorHandler func(ctx server.Ctx, err error) *vdom.VNode

ErrorHandler handles error pages.

type FieldInfo

type FieldInfo struct {
	Name     string
	Type     string
	JSONName string
	Required bool
}

FieldInfo contains information about a struct field.

type FileDiff

type FileDiff struct {
	// Path is the relative path to the file
	Path string `json:"path"`

	// Status is one of: "missing", "changed"
	Status string `json:"status"`
}

FileDiff describes a mismatch between generated and existing files.

type GenerationResult

type GenerationResult struct {
	// OutputFile is the path to the generated file
	OutputFile string `json:"outputFile"`

	// RouteCount is the total number of routes discovered
	RouteCount int `json:"routeCount"`

	// PageCount is the number of page routes
	PageCount int `json:"pageCount"`

	// APICount is the number of API routes
	APICount int `json:"apiCount"`

	// LayoutCount is the number of layouts
	LayoutCount int `json:"layoutCount"`

	// MiddlewareCount is the number of middleware registrations
	MiddlewareCount int `json:"middlewareCount"`
}

GenerationResult contains the results of route generation.

type Generator

type Generator struct {
	// contains filtered or unexported fields
}

Generator generates Go code for registering routes.

func NewGenerator

func NewGenerator(routes []ScannedRoute, modulePath string) *Generator

NewGenerator creates a new code generator.

func (*Generator) Generate

func (g *Generator) Generate() ([]byte, error)

Generate produces the routes_gen.go file content. The output is deterministic - same input produces identical output.

type GeneratorConfig

type GeneratorConfig struct {
	// RoutesDir is the directory to scan for route files (e.g., "app/routes")
	RoutesDir string

	// ModulePath is the Go module path (e.g., "github.com/example/myapp")
	ModulePath string

	// OutputPath is the output file path (default: {RoutesDir}/routes_gen.go)
	OutputPath string
}

GeneratorConfig configures the route code generator.

type GeneratorWithConfig

type GeneratorWithConfig struct {
	// contains filtered or unexported fields
}

GeneratorWithConfig holds configuration and state for code generation. Use this for verification workflows; use NewGenerator for simple generation.

func NewGeneratorWithConfig

func NewGeneratorWithConfig(config GeneratorConfig) *GeneratorWithConfig

NewGeneratorWithConfig creates a new generator from configuration.

func (*GeneratorWithConfig) Generate

func (g *GeneratorWithConfig) Generate() (*GenerationResult, error)

Generate scans routes (if needed) and generates the routes_gen.go file.

func (*GeneratorWithConfig) GenerateToPath

func (g *GeneratorWithConfig) GenerateToPath(outputPath string) (*GenerationResult, error)

GenerateToPath generates routes to a specific output path.

func (*GeneratorWithConfig) Routes

func (g *GeneratorWithConfig) Routes() []ScannedRoute

Routes returns the scanned routes.

func (*GeneratorWithConfig) Scan

func (g *GeneratorWithConfig) Scan() error

Scan populates routes by scanning the configured routes directory.

func (*GeneratorWithConfig) VerifyUpToDate

func (g *GeneratorWithConfig) VerifyUpToDate() (*VerifyResult, error)

VerifyUpToDate checks whether generated routes match the current source files. Returns an error with code VANGO.ROUTES.OUT_OF_DATE if routes are stale.

type Handler

type Handler func(ctx server.Ctx) error

Handler is a function that handles a request context. This is the base type for all route handlers in middleware chains. It's compatible with the signature expected by middleware patterns.

type HandlerFunc

type HandlerFunc = Handler

HandlerFunc is an alias for Handler for naming consistency with http.HandlerFunc.

type HandlerRegistry

type HandlerRegistry struct {
	Pages   map[string]PageHandler
	Layouts map[string]LayoutHandler
	APIs    map[string]map[string]APIHandler // path -> method -> handler
	MW      map[string][]Middleware
}

BuildFromScanned builds the router from scanned routes and a handler registry. The registry maps file paths to handler functions.

type LayoutHandler

type LayoutHandler func(ctx server.Ctx, children Slot) *vdom.VNode

LayoutHandler wraps child content in a layout.

type MatchResult

type MatchResult struct {
	// PageHandler is the handler for page routes
	PageHandler PageHandler

	// APIHandler is the handler for API routes
	APIHandler APIHandler

	// Layouts are hierarchical layouts collected from app.Layout() calls (root to leaf)
	Layouts []LayoutHandler

	// PageLayouts are explicit layouts from app.Page(..., layouts)
	// These are NOT inherited - they replace hierarchical layouts when HasPageLayouts is true
	PageLayouts []LayoutHandler

	// HasPageLayouts distinguishes "unset" vs "explicitly empty"
	// When true, PageLayouts should be used instead of Layouts
	HasPageLayouts bool

	// Middleware is the combined middleware chain
	Middleware []Middleware

	// Params are the extracted route parameters
	Params map[string]string

	// Route is the matched route definition
	Route *ScannedRoute

	// MethodNotAllowed indicates the path matched an API route, but the requested
	// method did not match any registered handler.
	MethodNotAllowed bool

	// AllowedMethods is the set of allowed HTTP methods for the matched API path.
	// Only meaningful when MethodNotAllowed is true.
	AllowedMethods []string
}

MatchResult contains the result of matching a path against the router. Implements server.RouteMatch interface.

func (*MatchResult) GetLayoutHandlers

func (m *MatchResult) GetLayoutHandlers() []server.LayoutHandler

GetLayoutHandlers implements server.RouteMatch.

func (*MatchResult) GetMiddleware

func (m *MatchResult) GetMiddleware() []server.RouteMiddleware

GetMiddleware implements server.RouteMatch.

func (*MatchResult) GetPageHandler

func (m *MatchResult) GetPageHandler() server.PageHandler

GetPageHandler implements server.RouteMatch.

func (*MatchResult) GetParams

func (m *MatchResult) GetParams() map[string]string

GetParams implements server.RouteMatch.

type Middleware

type Middleware interface {
	// Handle processes the request and optionally calls next.
	// Return an error to stop the chain and report an error.
	// Return nil without calling next to stop the chain without error.
	Handle(ctx server.Ctx, next func() error) error
}

Middleware processes requests before they reach the handler.

func Chain

func Chain(middleware ...Middleware) Middleware

Chain creates a middleware that combines multiple middleware in order.

func Logger

func Logger(logger *slog.Logger) Middleware

Logger returns middleware that logs each event with timing information. This is for Vango event-loop logging (Layer 2), not HTTP request logging.

func Only

func Only(condition func(ctx server.Ctx) bool, mw Middleware) Middleware

Only is a middleware that runs only if a condition is true.

func RateLimit

func RateLimit(maxPerSecond int) Middleware

RateLimit returns middleware that limits events per session. maxPerSecond specifies the maximum number of events allowed per second. Exceeding the limit returns ErrRateLimited.

func Recover

func Recover(onPanic func(ctx server.Ctx, recovered any)) Middleware

Recover returns middleware that recovers from panics. The onPanic callback is called with the recovered value and can log or handle it.

func Skip

func Skip(condition func(ctx server.Ctx) bool, mw Middleware) Middleware

Skip is a middleware that skips to the next middleware based on a condition.

func Timeout

func Timeout(duration time.Duration) Middleware

Timeout returns middleware that times out after the specified duration. Note: This only affects the handler execution, not the full event processing.

func WithValue

func WithValue(key, value any) Middleware

WithValue returns middleware that sets a context value for the request. The value is available to subsequent middleware and handlers via ctx.Value().

type MiddlewareFunc

type MiddlewareFunc func(ctx server.Ctx, next func() error) error

MiddlewareFunc is a function adapter for Middleware.

func (MiddlewareFunc) Handle

func (f MiddlewareFunc) Handle(ctx server.Ctx, next func() error) error

Handle implements Middleware.

type MultiValidationError

type MultiValidationError struct {
	Errors []ValidationError
}

MultiValidationError wraps multiple validation errors.

func (*MultiValidationError) Error

func (e *MultiValidationError) Error() string
type NavigateOption func(*NavigateOptions)

NavigateOption is a functional option for Navigate.

func WithParams

func WithParams(params map[string]any) NavigateOption

WithParams adds query parameters to the navigation URL.

func WithPrefetch

func WithPrefetch() NavigateOption

WithPrefetch enables prefetching for this navigation.

func WithReplace

func WithReplace() NavigateOption

WithReplace replaces the current history entry instead of pushing.

func WithoutScroll

func WithoutScroll() NavigateOption

WithoutScroll disables scrolling to top after navigation.

type NavigateOptions struct {
	// Replace replaces the current history entry instead of pushing.
	Replace bool

	// Params are query parameters to add to the URL.
	Params map[string]any

	// Scroll controls whether to scroll to top after navigation.
	// Defaults to true.
	Scroll bool

	// Prefetch indicates this path should be prefetched.
	Prefetch bool
}

NavigateOptions configures navigation behavior.

type NavigationRequest struct {
	Path    string
	Options NavigateOptions
}

NavigationRequest represents a pending navigation.

func (nr *NavigationRequest) BuildURL() (string, error)

BuildURL constructs the full URL for a navigation request.

type Navigator interface {
	// Navigate performs a client-side navigation to the given path.
	Navigate(path string, opts ...NavigateOption)

	// Back navigates back in browser history.
	Back()

	// Forward navigates forward in browser history.
	Forward()
}

Navigator handles client-side navigation. It is typically obtained from the request context.

func NewNavigator

func NewNavigator(ctx server.Ctx) Navigator

NewNavigator creates a new navigator for the given context.

type OpenAPIComponents

type OpenAPIComponents struct {
	Schemas map[string]*OpenAPISchema `json:"schemas,omitempty"`
}

OpenAPIComponents contains reusable components.

type OpenAPIGenerator

type OpenAPIGenerator struct {
	// contains filtered or unexported fields
}

OpenAPIGenerator generates OpenAPI 3.0 specifications from API routes.

func NewOpenAPIGenerator

func NewOpenAPIGenerator(routesDir, modulePath string, info OpenAPIInfo) *OpenAPIGenerator

NewOpenAPIGenerator creates a new OpenAPI generator.

func (*OpenAPIGenerator) Generate

func (g *OpenAPIGenerator) Generate() ([]byte, error)

Generate creates an OpenAPI specification from the API routes.

type OpenAPIInfo

type OpenAPIInfo struct {
	Title       string
	Description string
	Version     string
}

OpenAPIInfo contains API metadata.

type OpenAPIMediaType

type OpenAPIMediaType struct {
	Schema *OpenAPISchema `json:"schema,omitempty"`
}

OpenAPIMediaType represents media type content.

type OpenAPIOperation

type OpenAPIOperation struct {
	Summary     string                     `json:"summary,omitempty"`
	Description string                     `json:"description,omitempty"`
	OperationID string                     `json:"operationId,omitempty"`
	Tags        []string                   `json:"tags,omitempty"`
	Parameters  []OpenAPIParameter         `json:"parameters,omitempty"`
	RequestBody *OpenAPIRequestBody        `json:"requestBody,omitempty"`
	Responses   map[string]OpenAPIResponse `json:"responses"`
}

OpenAPIOperation represents an HTTP operation.

type OpenAPIParameter

type OpenAPIParameter struct {
	Name        string         `json:"name"`
	In          string         `json:"in"` // path, query, header
	Description string         `json:"description,omitempty"`
	Required    bool           `json:"required,omitempty"`
	Schema      *OpenAPISchema `json:"schema"`
}

OpenAPIParameter represents a request parameter.

type OpenAPIPath

type OpenAPIPath map[string]*OpenAPIOperation

OpenAPIPath represents path operations.

type OpenAPIRequestBody

type OpenAPIRequestBody struct {
	Description string                      `json:"description,omitempty"`
	Required    bool                        `json:"required,omitempty"`
	Content     map[string]OpenAPIMediaType `json:"content"`
}

OpenAPIRequestBody represents a request body.

type OpenAPIResponse

type OpenAPIResponse struct {
	Description string                      `json:"description"`
	Content     map[string]OpenAPIMediaType `json:"content,omitempty"`
}

OpenAPIResponse represents a response.

type OpenAPISchema

type OpenAPISchema struct {
	Type       string                    `json:"type,omitempty"`
	Format     string                    `json:"format,omitempty"`
	Items      *OpenAPISchema            `json:"items,omitempty"`
	Properties map[string]*OpenAPISchema `json:"properties,omitempty"`
	Required   []string                  `json:"required,omitempty"`
	Ref        string                    `json:"$ref,omitempty"`
}

OpenAPISchema represents a JSON schema.

type OpenAPISpec

type OpenAPISpec struct {
	OpenAPI    string                 `json:"openapi"`
	Info       OpenAPISpecInfo        `json:"info"`
	Paths      map[string]OpenAPIPath `json:"paths"`
	Components *OpenAPIComponents     `json:"components,omitempty"`
}

OpenAPISpec represents an OpenAPI 3.0 specification.

type OpenAPISpecInfo

type OpenAPISpecInfo struct {
	Title       string `json:"title"`
	Description string `json:"description,omitempty"`
	Version     string `json:"version"`
}

OpenAPISpecInfo contains API info.

type PageHandler

type PageHandler func(ctx server.Ctx, params any) vdom.Component

PageHandler handles a page request, returning a component to render.

type PageMeta

type PageMeta struct {
	Title       string
	Description string
	Keywords    []string
	OGImage     string
	OGTitle     string
	OGDesc      string
	Canonical   string
	Robots      string
}

PageMeta contains page metadata for SEO.

type ParamDef

type ParamDef struct {
	// Name is the parameter name (e.g., "id")
	Name string

	// Type is the parameter type (e.g., "int", "string", "uuid")
	Type string

	// ExplicitType is the explicit type annotation from the route segment, if any.
	// Example: "[id:int]" -> "int". Empty means the type was inferred by convention.
	ExplicitType string

	// Segment is the original segment (e.g., "[id]", "[id:int]")
	Segment string
}

ParamDef defines a route parameter.

type ParamParser

type ParamParser struct{}

ParamParser parses string parameters into typed struct fields.

func NewParamParser

func NewParamParser() *ParamParser

NewParamParser creates a new parameter parser.

func (*ParamParser) Parse

func (p *ParamParser) Parse(params map[string]string, target any) error

Parse populates a struct with values from the params map. The target must be a pointer to a struct with `param` tags.

type RouteNode

type RouteNode struct {
	// contains filtered or unexported fields
}

RouteNode is a node in the radix tree.

type RouteOption

type RouteOption func(*routeOptions)

RouteOption configures route registration. Used for param type constraints, page layouts, etc.

func WithPageLayouts

func WithPageLayouts(layouts ...LayoutHandler) RouteOption

WithPageLayouts sets explicit layouts for a page (not inherited). When set, these layouts are used instead of hierarchical layouts from app.Layout() calls. This allows different sections of an app to use different layouts.

Example:

// Marketing pages use MarketingLayout
r.Page("/", HomePage, router.WithPageLayouts(MarketingLayout))

// App pages use AppLayout (completely different)
r.Page("/app/dashboard", DashboardPage, router.WithPageLayouts(AppLayout))

func WithParamType

func WithParamType(param, typ string) RouteOption

WithParamType specifies the type constraint for a route parameter. This allows specifying the type separately from the path pattern.

Example:

r.Page("/users/:id", users.ShowPage, router.WithParamType("id", "int"))

This is equivalent to using the inline type syntax:

r.Page("/users/:id:int", users.ShowPage)

func WithParamValidator

func WithParamValidator(param string, fn func(string) error) RouteOption

WithParamValidator sets a validation function for a route parameter. When set, the validator is used during route matching to determine whether a parameter segment is considered a match (return nil) or rejected (return error).

type Router

type Router struct {
	// contains filtered or unexported fields
}

Router manages route matching and handler dispatch.

func NewRouter

func NewRouter() *Router

NewRouter creates a new router.

func (*Router) API

func (r *Router) API(method, path string, handler APIHandler, opts ...RouteOption)

API registers an API handler for a method and path. This is the spec-compliant alias for AddAPI. Note: method comes first to match natural reading order ("GET /api/health").

Example:

r.API("GET", "/api/health", api.HealthGET)
r.API("POST", "/api/users", api.UsersPOST)

func (*Router) AddAPI

func (r *Router) AddAPI(path, method string, handler APIHandler)

AddAPI registers an API handler for a path and method.

func (*Router) AddLayout

func (r *Router) AddLayout(path string, handler LayoutHandler)

AddLayout registers a layout handler for a path.

func (*Router) AddMiddleware

func (r *Router) AddMiddleware(path string, mw ...Middleware)

AddMiddleware adds middleware to a specific path.

func (*Router) AddPage

func (r *Router) AddPage(path string, handler PageHandler)

AddPage registers a page handler for a path.

func (*Router) BuildFromScanned

func (r *Router) BuildFromScanned(routes []ScannedRoute, registry *HandlerRegistry)

BuildFromScanned populates the router from scanned routes.

func (*Router) ErrorPage

func (r *Router) ErrorPage() ErrorHandler

ErrorPage returns the error page handler.

func (*Router) Layout

func (r *Router) Layout(path string, handler LayoutHandler)

Layout registers a layout handler for a path. This is the spec-compliant alias for AddLayout.

func (*Router) Match

func (r *Router) Match(method, path string) (*MatchResult, bool)

Match finds the handler for a path.

func (*Router) Middleware

func (r *Router) Middleware(path string, mw ...Middleware)

Middleware adds middleware to a specific path. This is the spec-compliant alias for AddMiddleware.

func (*Router) MiddlewareForPath

func (r *Router) MiddlewareForPath(path string) []server.RouteMiddleware

MiddlewareForPath returns the route middleware chain that applies to path. This includes global middleware and middleware on the longest matching route prefix. Unlike Match, this does not require a terminal page/API handler.

func (*Router) NotFound

func (r *Router) NotFound() PageHandler

NotFound returns the 404 handler.

func (*Router) Page

func (r *Router) Page(path string, handler PageHandler, opts ...RouteOption)

Page registers a page handler for a path. This is the spec-compliant alias for AddPage. Optional RouteOption arguments can specify parameter type constraints or page layouts.

Example:

r.Page("/users/:id", users.ShowPage)
r.Page("/users/:id", users.ShowPage, router.WithParamType("id", "int"))
r.Page("/app/dashboard", DashboardPage, router.WithPageLayouts(AppLayout))

func (*Router) ServeHTTP

func (r *Router) ServeHTTP(ctx server.Ctx) (*MatchResult, bool)

ServeHTTP implements http.Handler for the router. This provides basic HTTP routing without WebSocket features.

func (*Router) SetErrorPage

func (r *Router) SetErrorPage(handler ErrorHandler)

SetErrorPage sets the error page handler.

func (*Router) SetNotFound

func (r *Router) SetNotFound(handler PageHandler)

SetNotFound sets the 404 handler.

func (*Router) Use

func (r *Router) Use(mw ...Middleware)

Use adds global middleware that applies to all routes.

type RouterAdapter

type RouterAdapter struct {
	*Router
}

RouterAdapter wraps Router to implement server.Router interface. This adapter is needed because the server package defines its own PageHandler type to avoid import cycles.

func NewRouterAdapter

func NewRouterAdapter(r *Router) *RouterAdapter

NewRouterAdapter creates a new adapter for use with server.Session.SetRouter().

func (*RouterAdapter) Match

func (a *RouterAdapter) Match(method, path string) (server.RouteMatch, bool)

Match implements server.Router interface.

func (*RouterAdapter) NotFound

func (a *RouterAdapter) NotFound() server.PageHandler

NotFound implements server.Router interface.

type ScanOptions

type ScanOptions struct {
	// Validate enables route validation (duplicate detection, constraint conflicts, etc.)
	Validate bool

	// Sort enables specificity sorting (static > typed > plain > catch-all)
	Sort bool
}

ScanOptions configures scanning behavior.

type ScannedRoute

type ScannedRoute struct {
	// Path is the URL pattern (e.g., "/projects/:id")
	Path string

	// FilePath is the source file path
	FilePath string

	// Package is the Go package name
	Package string

	// Params are the route parameters
	Params []ParamDef

	// ParamStructTypes maps route param name -> canonical type derived from the
	// handler's params struct (when available). Used for validation.
	ParamStructTypes map[string]string

	// HasPage indicates the file exports a page handler function (e.g., IndexPage)
	HasPage bool

	// HandlerName is the actual name of the page handler function (e.g., "IndexPage", "ShowPage")
	HandlerName string

	// HasLayout indicates the file exports a Layout function
	HasLayout bool

	// HasMeta indicates the file exports a Meta function
	HasMeta bool

	// HasMiddleware indicates the file exports a Middleware variable or function
	HasMiddleware bool

	// MiddlewareIsFunc indicates the route exports a Middleware() function.
	MiddlewareIsFunc bool

	// MiddlewareIsVar indicates the route exports a Middleware variable.
	MiddlewareIsVar bool

	// Methods lists HTTP methods for API routes (GET, POST, etc.)
	Methods []string

	// APIHandlers maps HTTP method to the exported Go function name.
	// Example: {"GET": "GET"} or {"GET": "HealthGET"}.
	APIHandlers map[string]string

	// IsAPI indicates this is an API route (returns JSON)
	IsAPI bool

	// IsCatchAll indicates this is a catch-all route ([...slug])
	IsCatchAll bool
}

ScannedRoute represents a route discovered by the scanner.

func ValidateAndSort

func ValidateAndSort(routes []ScannedRoute) ([]ScannedRoute, error)

ValidateAndSort validates routes and sorts them by specificity. This is the main entry point for the scanner to call.

type Scanner

type Scanner struct {
	// contains filtered or unexported fields
}

Scanner scans a directory for route files.

func NewScanner

func NewScanner(rootDir string) *Scanner

NewScanner creates a new route scanner.

func (*Scanner) Scan

func (s *Scanner) Scan() ([]ScannedRoute, error)

Scan reads all route files and returns route definitions. Routes are validated and sorted by specificity.

func (*Scanner) ScanWithOptions

func (s *Scanner) ScanWithOptions(opts ScanOptions) ([]ScannedRoute, error)

ScanWithOptions reads all route files with configurable validation and sorting.

type Slot

type Slot = corevango.Slot

Slot represents the child content passed to a layout. It is an opaque container that can be rendered by VDOM elements.

type TypeInfo

type TypeInfo struct {
	Name      string
	Package   string
	Fields    []FieldInfo
	IsSlice   bool
	IsPointer bool
}

TypeInfo contains information about a Go type.

type ValidationError

type ValidationError struct {
	// Type is the error category
	Type ValidationErrorType

	// Message is the human-readable error message
	Message string

	// Files are the source files involved
	Files []string

	// Path is the conflicting URL pattern
	Path string

	// Details contains additional error-specific information
	Details string
}

ValidationError represents a route validation error.

func (ValidationError) Error

func (e ValidationError) Error() string

type ValidationErrorType

type ValidationErrorType string

ValidationErrorType categorizes validation errors.

const (
	// ErrorInvalidGoFilename indicates a route file won't be compiled by Go.
	// The Go toolchain ignores files whose basename starts with '_' or '.'.
	ErrorInvalidGoFilename ValidationErrorType = "INVALID_GO_FILENAME"

	// ErrorInvalidGoImportPath indicates a route directory name will produce an
	// invalid Go import path in generated routes_gen.go (e.g. directories containing '[' or ']').
	ErrorInvalidGoImportPath ValidationErrorType = "INVALID_GO_IMPORT_PATH"

	// ErrorDuplicateRoute indicates multiple files resolve to the same URL pattern.
	// Example: [id].go and id_.go both resolve to /:id
	ErrorDuplicateRoute ValidationErrorType = "DUPLICATE_ROUTE"

	// ErrorParamConstraintConflict indicates the same param has different type constraints.
	// Example: [id:int].go and [id].go at the same path
	ErrorParamConstraintConflict ValidationErrorType = "PARAM_CONSTRAINT_CONFLICT"

	// ErrorAPIAmbiguity indicates both bare (GET) and prefixed (HealthGET) handlers exist.
	// Example: Both GET() and HealthGET() exported in /api/health.go
	ErrorAPIAmbiguity ValidationErrorType = "API_AMBIGUITY"

	// ErrorMiddlewareAmbiguity indicates both Middleware() and Middleware var exist.
	// Example: middleware.go exports both `func Middleware()` and `var Middleware`.
	ErrorMiddlewareAmbiguity ValidationErrorType = "MIDDLEWARE_AMBIGUITY"

	// ErrorParamTypeMismatch indicates annotation type differs from Params struct field type.
	// Example: [id:int].go but Params struct has id as string
	ErrorParamTypeMismatch ValidationErrorType = "PARAM_TYPE_MISMATCH"
)

type Validator

type Validator struct {
	// contains filtered or unexported fields
}

Validator validates scanned routes for conflicts and errors. Per Section 1.3 and 1.6 of the Routing Spec.

func NewValidator

func NewValidator(routes []ScannedRoute) *Validator

NewValidator creates a new route validator.

func (*Validator) Validate

func (v *Validator) Validate() error

Validate checks all routes for conflicts and errors. Returns nil if all routes are valid, or a MultiValidationError with all errors.

type VerifyResult

type VerifyResult struct {
	// Current is true if the generated routes match the existing file
	Current bool `json:"current"`

	// Differences lists files that differ from expected
	Differences []FileDiff `json:"differences,omitempty"`
}

VerifyResult contains the result of routes verification.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL