AgentStack
SKILL verified MIT Self-run

Validator

skill-ngxtm-devkit-validator · by ngxtm

Struct validation using tags for Go.

No reviews yet
0 installs
16 views
0.0% view→install

Install

$ agentstack add skill-ngxtm-devkit-validator

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Validator? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Validator Standards

Basic Usage

import (
    "github.com/go-playground/validator/v10"
)

var validate = validator.New()

type User struct {
    Name     string `validate:"required,min=2,max=100"`
    Email    string `validate:"required,email"`
    Age      int    `validate:"gte=0,lte=120"`
    Password string `validate:"required,min=8"`
}

func ValidateUser(user User) error {
    return validate.Struct(user)
}

// Error handling
err := validate.Struct(user)
if err != nil {
    for _, err := range err.(validator.ValidationErrors) {
        fmt.Printf("Field: %s, Tag: %s, Value: %v\n",
            err.Field(), err.Tag(), err.Value())
    }
}

Common Validations

type Request struct {
    // Required
    Name string `validate:"required"`

    // String length
    Title string `validate:"min=1,max=100"`

    // Numbers
    Age   int     `validate:"gte=0,lte=150"`
    Price float64 `validate:"gt=0"`

    // Email, URL
    Email   string `validate:"email"`
    Website string `validate:"url"`

    // UUID
    ID string `validate:"uuid4"`

    // Enum
    Status string `validate:"oneof=pending active completed"`

    // Contains
    Code string `validate:"contains=PREFIX"`

    // Regex (alpha, alphanum, numeric, etc.)
    Username string `validate:"alphanum,min=3,max=20"`

    // Date/Time
    StartDate string `validate:"datetime=2006-01-02"`
}

Nested Structs

type Address struct {
    Street  string `validate:"required"`
    City    string `validate:"required"`
    ZipCode string `validate:"required,len=5"`
}

type User struct {
    Name    string  `validate:"required"`
    Address Address `validate:"required"`  // Validates nested
}

type Company struct {
    Employees []User `validate:"required,min=1,dive"` // Validates each element
}

type Config struct {
    Settings map[string]string `validate:"required,dive,keys,required,endkeys,required"`
}

Cross-Field Validation

type DateRange struct {
    StartDate time.Time `validate:"required"`
    EndDate   time.Time `validate:"required,gtfield=StartDate"`
}

type PasswordChange struct {
    Password        string `validate:"required,min=8"`
    ConfirmPassword string `validate:"required,eqfield=Password"`
}

type Transfer struct {
    FromAccount string `validate:"required"`
    ToAccount   string `validate:"required,nefield=FromAccount"`
}

Custom Validators

func init() {
    validate.RegisterValidation("nowhitespace", noWhitespaceValidator)
    validate.RegisterValidation("strongpassword", strongPasswordValidator)
}

func noWhitespaceValidator(fl validator.FieldLevel) bool {
    return !strings.Contains(fl.Field().String(), " ")
}

func strongPasswordValidator(fl validator.FieldLevel) bool {
    password := fl.Field().String()
    hasUpper := regexp.MustCompile(`[A-Z]`).MatchString(password)
    hasLower := regexp.MustCompile(`[a-z]`).MatchString(password)
    hasNumber := regexp.MustCompile(`[0-9]`).MatchString(password)
    hasSpecial := regexp.MustCompile(`[!@#$%^&*]`).MatchString(password)
    return hasUpper && hasLower && hasNumber && hasSpecial
}

type User struct {
    Username string `validate:"required,nowhitespace"`
    Password string `validate:"required,min=8,strongpassword"`
}

Conditional Validation

type User struct {
    Type  string `validate:"required,oneof=personal business"`
    TaxID string `validate:"required_if=Type business"`
}

type Order struct {
    PaymentMethod string `validate:"required,oneof=card cash"`
    CardNumber    string `validate:"required_if=PaymentMethod card"`
}

// Other conditional tags:
// required_unless, required_with, required_without
// required_with_all, required_without_all

Gin Integration

import (
    "github.com/gin-gonic/gin"
    "github.com/gin-gonic/gin/binding"
    "github.com/go-playground/validator/v10"
)

func init() {
    if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
        v.RegisterValidation("customtag", customValidator)
    }
}

type CreateUserRequest struct {
    Name  string `json:"name" binding:"required,min=2"`
    Email string `json:"email" binding:"required,email"`
}

func CreateUser(c *gin.Context) {
    var req CreateUserRequest
    if err := c.ShouldBindJSON(&req); err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }
    // req is validated
}

Error Translation

import (
    "github.com/go-playground/locales/en"
    ut "github.com/go-playground/universal-translator"
    en_translations "github.com/go-playground/validator/v10/translations/en"
)

var (
    uni      *ut.UniversalTranslator
    trans    ut.Translator
    validate *validator.Validate
)

func init() {
    en := en.New()
    uni = ut.New(en, en)
    trans, _ = uni.GetTranslator("en")

    validate = validator.New()
    en_translations.RegisterDefaultTranslations(validate, trans)
}

func translateError(err error) []string {
    var messages []string
    for _, e := range err.(validator.ValidationErrors) {
        messages = append(messages, e.Translate(trans))
    }
    return messages
}

Best Practices

  1. Singleton: Create one validator instance
  2. Custom validators: Register at init time
  3. Dive: Use for slices and maps
  4. Translations: Provide user-friendly messages
  5. Gin: Use binding tags for automatic validation

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.