Support Go
May 13, 2026 ยท View on GitHub
Support Go
A collection of utility packages for Go with zero external dependencies.
Installation
Install the package using the go get command:
go get github.com/petaki/support-go
Packages
- CLI - Framework for building command-line applications
- File - File hashing utilities
- Forms - Form validation and JSON body decoding
- Vite - Vite asset management and HMR integration
CLI
The cli package provides a framework for building command-line applications with structured command groups, colored output, ASCII tables, and pre-configured loggers.
App, Group, and Command
Build a CLI application by defining groups and commands:
package main
import (
"fmt"
"github.com/petaki/support-go/cli"
)
func main() {
(&cli.App{
Name: "myapp",
Version: "1.0.0",
Groups: []*cli.Group{
{
Name: "serve",
Usage: "Server commands",
Commands: []*cli.Command{
{
Name: "start",
Usage: "Start the server",
Arguments: []string{"port"},
HandleFunc: func(group *cli.Group, command *cli.Command, arguments []string) int {
args, err := command.Parse(arguments)
if err != nil {
return command.PrintError(err)
}
fmt.Println("Starting on port", args[0])
return cli.Success
},
},
},
},
},
}).Execute()
}
Commands support flags via command.FlagSet(), which returns a standard *flag.FlagSet.
Colors
Color functions for terminal output (no-op on Windows):
cli.Red("error")
cli.Green("success")
cli.Yellow("warning")
cli.Blue("info")
cli.Purple("special")
cli.Cyan("note")
cli.Gray("muted")
cli.White("bright")
Table
Format data as an ASCII table:
table := &cli.Table{
Headers: []string{"Name", "Status"},
Rows: [][]string{
{"API", "Running"},
{"Worker", "Stopped"},
},
}
table.Print()
Loggers
Pre-configured loggers with colored prefixes:
cli.InfoLog.Println("server started") // cyan "INFO" prefix
cli.ErrorLog.Println("connection lost") // red "ERROR" prefix
File
The file package provides MD5 hash computation for files.
import "github.com/petaki/support-go/file"
// Hash a file on disk
hash, err := file.Hash("/path/to/file.txt")
// Hash a file from an fs.FS
hash, err := file.HashFromFS("static/app.js", embeddedFS)
Forms
The forms package provides form validation and JSON request body decoding for HTTP handlers.
Validation
import "github.com/petaki/support-go/forms"
form := forms.New(map[string]any{
"username": "john",
"email": "john@example.com",
"age": 25.0,
})
form.Required("username", "email")
form.MatchesPattern("username", forms.UsernameRegexp)
form.MatchesPattern("email", forms.EmailRegexp)
form.Min("age", 18)
form.Max("age", 120)
if !form.IsValid() {
// form.Errors contains validation errors per field
}
JSON Body Decoding
Decode JSON request bodies with detailed error handling (bad JSON, unknown fields, size limit of 1MB):
func handler(w http.ResponseWriter, r *http.Request) {
form, err := forms.NewFromRequest(w, r)
if err != nil {
// err is *forms.Error with Status and Msg
}
form.Required("name")
if !form.IsValid() {
// handle validation errors
}
}
You can also decode into a typed struct:
var input struct {
Name string `json:"name"`
Email string `json:"email"`
}
err := forms.DecodeBody(w, r, &input)
Vite
The vite package integrates Go applications with Vite for asset management and HMR.
import "github.com/petaki/support-go/vite"
// Create a Vite instance
v := vite.New("public", "build")
// Or with an embedded filesystem
v := vite.New("public", "build", embeddedFS)
// Check if Vite dev server is running
if v.IsRunningHot() {
// Assets are served from the dev server
}
// Resolve asset paths
jsPath, err := v.Asset("resources/js/app.js")
cssFiles, err := v.CSS("resources/js/app.js")
// Get manifest hash for cache busting
hash, err := v.ManifestHash()
// Get Inertia SSR URL
ssrURL, err := v.InertiaSSRURL("http://localhost:13714")
When the Vite dev server is running (detected via a public/hot file), assets are served from the dev server URL. In production, assets are resolved from manifest.json in the build directory.
Usage with Inertia
import (
"github.com/petaki/inertia-go"
"github.com/petaki/support-go/vite"
)
// Create Vite instance (use embedded FS in production)
var viteManager *vite.Vite
if debug {
viteManager = vite.New("static", "build")
} else {
viteManager = vite.New("static", "build", staticFiles)
}
// Use manifest hash as Inertia asset version
version, err := viteManager.ManifestHash()
// Set up Inertia with shared Vite helpers
inertiaManager := inertia.New(appURL, "app.gohtml", version, templates)
inertiaManager.ShareFunc("isRunningHot", viteManager.IsRunningHot)
inertiaManager.ShareFunc("asset", viteManager.Asset)
inertiaManager.ShareFunc("css", viteManager.CSS)
// Enable SSR
ssrURL, err := viteManager.InertiaSSRURL("http://127.0.0.1:13714/render")
inertiaManager.EnableSsr(ssrURL)
The root template (app.gohtml) uses the shared Vite functions:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
{{ range (css "resources/js/app.ts") }}
<link rel="stylesheet" href="{{ . }}">
{{ end }}
{{ if .ssr }}
{{ raw .ssr.Head }}
{{ end }}
</head>
<body>
{{ if not .ssr }}
<script data-page="app" type="application/json">{{ marshal .page }}</script>
<div id="app"></div>
{{ else }}
{{ raw .ssr.Body }}
{{ end }}
{{ if isRunningHot }}
<script type="module" src="{{ asset "@vite/client" }}"></script>
{{ end }}
<script type="module" src="{{ asset "resources/js/app.ts" }}"></script>
</body>
</html>
Contributors
- @monstergron for logo (ArtStation)
Reporting Issues
If you are facing a problem with this package or found any bug, please open an issue on GitHub.
License
The MIT License (MIT). Please see License File for more information.