Go Bindings
Typed Go binding workflow for vxt document-mode templates.
Go Bindings
The bind package generates typed Go wrappers for document-mode .vxt
templates. Generated bindings are useful when application code should call a
template with a typed Input struct instead of raw map[string]any values.
Bindings are library-only. They are generated by Go code that calls
github.com/vandordev/vxt/bind; vxt does not provide a CLI.
When to Use Bindings
Use generated bindings when:
- one document template is part of a Go module
- callers should get compile-time field names for template input
- generated code should wrap compile, validate, plan, and write calls
- local
@usedefinitions should be embedded into the generated package
Use the raw runtime API when:
- templates are loaded dynamically
- input shape is not known at build time
- the caller wants direct control over every runtime stage
Current bindings are document-mode only. Single-file bindings are not implemented.
Generated Package Shape
For a document named service, bind.Generate emits one Go source file under
.vxt/service_gen.go. The generated package name is the PackageName from the
generation request.
Generated code includes:
- an
Inputstruct matching document@inputdeclarations - public Go structs for document
@typedeclarations - embedded main document source
- embedded local
@usesource documents supplied in the request - wrapper functions for
Compile,Validate,Plan, andWrite
Example consumer code:
plan, err := servicevxt.Plan(servicevxt.Input{
Entity: servicevxt.Entity{
Name: "User",
PackageName: "user",
HasRepository: true,
},
})
if err != nil {
panic(err)
}The generated Plan wrapper returns a runtime.Plan. The generated Write
wrapper writes through a caller-provided output target.
Generate Bindings
Call bind.Generate with a package name, the main document source, and any
local @use sources.
out, err := bind.Generate(bind.Request{
PackageName: "servicevxt",
Document: source.Source{
ID: "service.vxt",
Path: "service.vxt",
Text: serviceTemplate,
},
Uses: map[string]source.Source{
"./schema.vxt": {
ID: "schema.vxt",
Path: "schema.vxt",
Text: schemaTemplate,
},
},
})
if err != nil {
panic(err)
}Output.Files contains generated files. Each file has a path and content. The
path currently uses the .vxt/ prefix.
Write Generated Output
Use bind.WriteOutput when you already have a generated bind.Output and want
to write it into a specific directory:
report, err := bind.WriteOutput(out, ".vxt", bind.WriteOptions{})
if err != nil {
panic(err)
}
_ = reportUse bind.GenerateToDir to generate and write in one call:
report, err := bind.GenerateToDir(bind.Request{
PackageName: "servicevxt",
Document: mainSource,
Uses: useSources,
}, ".vxt", bind.WriteOptions{})
if err != nil {
panic(err)
}The write report records created, overwritten, and removed files. Stale generated files owned by the same binding can be removed during reconciliation.
Dry Run
Set bind.WriteOptions{DryRun: true} to report planned write actions without
creating the output directory or writing files.
report, err := bind.GenerateToDir(bind.Request{
PackageName: "servicevxt",
Document: mainSource,
Uses: useSources,
}, ".vxt", bind.WriteOptions{DryRun: true})
if err != nil {
panic(err)
}
fmt.Println(report.DryRun)
fmt.Println(report.Actions)Dry-run reports use the same planning path as normal writes, but stop before filesystem mutation.
Local @use Embedding
When a document has @use "./schema.vxt", the caller must provide that source
in bind.Request.Uses under the same path string.
The generator compiles the main document, collects local use paths, recompiles
with a resolver, and embeds the resolved sources into the generated package.
This lets the generated package compile and plan without reading schema.vxt
from disk at runtime.
Current behavior is local-source embedding only. There is no package-style
@use, registry lookup, or network resolution.
Current Limitations
- Bindings are generated for document mode only.
- Single-file binding generation is not implemented.
- Generated bindings are Go-only.
@usesupport is local-path source embedding supplied by the caller.- The generator does not define trust policy or hook execution policy.
- Generated source is intended to be committed with the consuming Go module.
