Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 156 additions & 0 deletions examples/constraints/api.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
openapi: 3.0.0
info:
title: Constraints Demo API
version: 1.0.0
description: Demo API to showcase constraint constants generation for both schemas and inline parameters

paths:
/users:
get:
operationId: listUsers
summary: List users with pagination and filtering
description: Demonstrates inline parameter constraints generating constants
parameters:
- in: query
name: limit
description: Maximum number of items to return
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- in: query
name: offset
description: Number of items to skip
schema:
type: integer
minimum: 0
- in: query
name: search
description: Search query string
schema:
type: string
minLength: 3
maxLength: 50
- in: query
name: minScore
description: Minimum score filter
schema:
type: number
format: float
minimum: 0.0
maximum: 100.0
responses:
"200":
description: List of users
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/User"
post:
operationId: createUser
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/User"
responses:
"201":
description: User created
content:
application/json:
schema:
$ref: "#/components/schemas/User"

/users/{userId}:
get:
operationId: getUser
summary: Get a specific user by ID
parameters:
- in: path
name: userId
required: true
description: User ID (UUID format)
schema:
type: string
minLength: 36
maxLength: 36
responses:
"200":
description: User details
content:
application/json:
schema:
$ref: "#/components/schemas/User"

components:
schemas:
# These are defined as standalone types so constraints become constants
Username:
type: string
minLength: 3
maxLength: 20
default: "guest"
description: Username must be between 3 and 20 characters

Age:
type: integer
minimum: 0
maximum: 150
default: 18
description: User's age in years

UserScore:
type: number
format: float
minimum: 0.0
maximum: 100.0
default: 50.0
description: User score between 0 and 100

Port:
type: integer
format: int32
minimum: 1024
maximum: 65535
default: 8080
description: Preferred port number

IsActive:
type: boolean
default: true
description: Whether the account is active

UserTags:
type: array
items:
type: string
minItems: 1
maxItems: 10
description: User tags (1-10 items)

User:
type: object
required:
- username
- age
properties:
username:
$ref: "#/components/schemas/Username"
age:
$ref: "#/components/schemas/Age"
email:
type: string
format: email
maxLength: 100
isActive:
$ref: "#/components/schemas/IsActive"
score:
$ref: "#/components/schemas/UserScore"
port:
$ref: "#/components/schemas/Port"
tags:
$ref: "#/components/schemas/UserTags"
8 changes: 8 additions & 0 deletions examples/constraints/cfg.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# yaml-language-server: $schema=../../configuration-schema.json
package: constraints
output: gen.go
generate:
models: true
echo-server: true
output-options:
skip-prune: true
178 changes: 178 additions & 0 deletions examples/constraints/example.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
package constraints

import (
"fmt"
"net/http"

"github.com/labstack/echo/v4"
)

// Example implementation showing how to use the generated constraint constants for both schema types and inline parameters
type Server struct{}

func NewServer() *Server {
return &Server{}
}

// ListUsers demonstrates using constraint constants from inline parameters
func (s *Server) ListUsers(ctx echo.Context, params ListUsersParams) error {
// Validate limit parameter using generated constants
if params.Limit != nil {
if *params.Limit < ListUsersLimitMinimum || *params.Limit > ListUsersLimitMaximum {
return echo.NewHTTPError(http.StatusBadRequest,
fmt.Sprintf("Limit must be between %d and %d", ListUsersLimitMinimum, ListUsersLimitMaximum))
}
} else {
// Use the generated default constant
defaultLimit := ListUsersLimitDefault
params.Limit = &defaultLimit
}

// Validate offset parameter
if params.Offset != nil {
if *params.Offset < ListUsersOffsetMinimum {
return echo.NewHTTPError(http.StatusBadRequest,
fmt.Sprintf("Offset must be at least %d", ListUsersOffsetMinimum))
}
}

// Validate search parameter length
if params.Search != nil {
searchLen := uint64(len(*params.Search))
if searchLen < ListUsersSearchMinLength {
return echo.NewHTTPError(http.StatusBadRequest,
fmt.Sprintf("Search must be at least %d characters", ListUsersSearchMinLength))
}
if searchLen > ListUsersSearchMaxLength {
return echo.NewHTTPError(http.StatusBadRequest,
fmt.Sprintf("Search must not exceed %d characters", ListUsersSearchMaxLength))
}
}

// Validate minScore parameter
if params.MinScore != nil {
if *params.MinScore < ListUsersMinScoreMinimum || *params.MinScore > ListUsersMinScoreMaximum {
return echo.NewHTTPError(http.StatusBadRequest,
fmt.Sprintf("MinScore must be between %.1f and %.1f", ListUsersMinScoreMinimum, ListUsersMinScoreMaximum))
}
}

fmt.Printf("Listing users with limit=%d, offset=%d\n", *params.Limit, *params.Offset)

// Return mock data (implementation not shown)
users := []User{}
return ctx.JSON(http.StatusOK, users)
}

// GetUser demonstrates using constraint constants from path parameters
func (s *Server) GetUser(ctx echo.Context, userId string) error {
// Validate userId length using generated constants
userIdLen := uint64(len(userId))
if userIdLen < GetUserUserIdMinLength || userIdLen > GetUserUserIdMaxLength {
return echo.NewHTTPError(http.StatusBadRequest,
fmt.Sprintf("UserId must be exactly %d characters", GetUserUserIdMinLength))
}

fmt.Printf("Getting user: %s\n", userId)

// Return mock data (implementation not shown)
user := User{Username: UsernameDefault, Age: AgeDefault}
return ctx.JSON(http.StatusOK, user)
}

// CreateUser demonstrates using the generated constraint constants for validation
func (s *Server) CreateUser(ctx echo.Context) error {
var user User
if err := ctx.Bind(&user); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}

// Use the generated constraint constants for validation!

// Validate age constraints
if user.Age < AgeMinimum || user.Age > AgeMaximum {
return echo.NewHTTPError(http.StatusBadRequest,
fmt.Sprintf("Age must be between %d and %d", AgeMinimum, AgeMaximum))
}

// Validate username length constraints
if uint64(len(user.Username)) < UsernameMinLength {
return echo.NewHTTPError(http.StatusBadRequest,
fmt.Sprintf("Username must be at least %d characters", UsernameMinLength))
}
if uint64(len(user.Username)) > UsernameMaxLength {
return echo.NewHTTPError(http.StatusBadRequest,
fmt.Sprintf("Username must not exceed %d characters", UsernameMaxLength))
}

// Validate port constraints (if provided)
if user.Port != nil {
if *user.Port < PortMinimum || *user.Port > PortMaximum {
return echo.NewHTTPError(http.StatusBadRequest,
fmt.Sprintf("Port must be between %d and %d", PortMinimum, PortMaximum))
}
}

// Validate user score constraints (if provided)
if user.Score != nil {
if *user.Score < UserScoreMinimum || *user.Score > UserScoreMaximum {
return echo.NewHTTPError(http.StatusBadRequest,
fmt.Sprintf("Score must be between %.1f and %.1f", UserScoreMinimum, UserScoreMaximum))
}
}

// Validate tags constraints (if provided)
if user.Tags != nil {
if uint64(len(*user.Tags)) < UserTagsMinItems {
return echo.NewHTTPError(http.StatusBadRequest,
fmt.Sprintf("Must provide at least %d tags", UserTagsMinItems))
}
if uint64(len(*user.Tags)) > UserTagsMaxItems {
return echo.NewHTTPError(http.StatusBadRequest,
fmt.Sprintf("Cannot exceed %d tags", UserTagsMaxItems))
}
}

// Use default values where appropriate
if user.IsActive == nil {
defaultActive := IsActiveDefault
user.IsActive = &defaultActive
}
if user.Port == nil {
defaultPort := PortDefault
user.Port = &defaultPort
}
if user.Score == nil {
defaultScore := UserScoreDefault
user.Score = &defaultScore
}

// Create the user (implementation not shown)
fmt.Printf("Creating user: %+v\n", user)

return ctx.JSON(http.StatusCreated, user)
}

// Example usage in main function
func Example() {
e := echo.New()
server := NewServer()
RegisterHandlers(e, server)

fmt.Println("=== Schema Constraint Constants ===")
fmt.Printf("Age range: %d-%d (default: %d)\n", AgeMinimum, AgeMaximum, AgeDefault)
fmt.Printf("Username length: %d-%d (default: %s)\n", UsernameMinLength, UsernameMaxLength, UsernameDefault)
fmt.Printf("Port range: %d-%d (default: %d)\n", PortMinimum, PortMaximum, PortDefault)
fmt.Printf("Score range: %.1f-%.1f (default: %.1f)\n", UserScoreMinimum, UserScoreMaximum, UserScoreDefault)
fmt.Printf("Tags count: %d-%d\n", UserTagsMinItems, UserTagsMaxItems)
fmt.Printf("Is active default: %v\n", IsActiveDefault)

fmt.Println("\n=== Inline Parameter Constraint Constants ===")
fmt.Printf("ListUsers limit: %d-%d (default: %d)\n", ListUsersLimitMinimum, ListUsersLimitMaximum, ListUsersLimitDefault)
fmt.Printf("ListUsers offset: minimum %d\n", ListUsersOffsetMinimum)
fmt.Printf("ListUsers search length: %d-%d\n", ListUsersSearchMinLength, ListUsersSearchMaxLength)
fmt.Printf("ListUsers minScore: %.1f-%.1f\n", ListUsersMinScoreMinimum, ListUsersMinScoreMaximum)
fmt.Printf("GetUser userId length: %d-%d\n", GetUserUserIdMinLength, GetUserUserIdMaxLength)

e.Logger.Fatal(e.Start(":8080"))
}
Loading