Documentation
¶
Overview ¶
Package wiregen generates TypeScript interfaces, decoders, and an SSE registry from Go struct types using go/packages + go/types + ast.Inspect. Consumers register types via the compile-time-safe TypeRef[T]() helper and invoke Generate to emit TS files.
Example ¶
package main
import (
"context"
"fmt"
"github.com/cplieger/wiregen/v3"
"github.com/cplieger/wiregen/v3/testdata/basic"
)
func main() {
r := wiregen.NewRegistry(
wiregen.WithValidatorsImport("./validators.js"),
wiregen.WithBusImport("./bus.js"),
)
r.PackagePaths = []string{"github.com/cplieger/wiregen/v3/testdata/basic"}
r.Types = []wiregen.WireType{wiregen.TypeRef[basic.Address]()}
r.SSEEvents = []wiregen.SSERegEntry{
{EventType: "addr", TypeName: "Address"},
}
ts, err := r.GenerateTypes(context.Background())
if err != nil {
fmt.Println("generate:", err)
return
}
fmt.Println(ts != "")
}
Output: true
Index ¶
- type Endpoint
- type EndpointKind
- type EnumDef
- type Filenames
- type Option
- func WithBusImport(v string) Option
- func WithClientFilename(v string) Option
- func WithFilenames(names Filenames) Option
- func WithHeaderComment(v string) Option
- func WithRegisterFuncName(v string) Option
- func WithRegistryFuncName(v string) Option
- func WithSelfContainedRegistry(v bool) Option
- func WithTransportImport(v string) Option
- func WithTypesImportPath(v string) Option
- func WithValidatorsFile(v string) Option
- func WithValidatorsImport(v string) Option
- type Registry
- func (r *Registry) Generate(ctx context.Context, outDir string) error
- func (r *Registry) GenerateClient() (string, error)
- func (r *Registry) GenerateConstants() (string, error)
- func (r *Registry) GenerateDecoders(ctx context.Context) (string, error)
- func (r *Registry) GenerateGoPaths(pkgName string) (string, error)
- func (r *Registry) GenerateRegistry() (string, error)
- func (r *Registry) GenerateTypes(ctx context.Context) (string, error)
- func (r *Registry) GenerateValidators() string
- type RespShape
- type SSERegEntry
- type UnionDef
- type WireConst
- type WireType
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Endpoint ¶
type Endpoint struct {
// Name is the generated TS function name (KindJSON) and the base for the
// PATH_/Go path-constant names. Must be a valid TS identifier.
Name string
// Method is the HTTP method (GET, POST, PUT, PATCH, DELETE).
Method string
// Path is the URL path. Parameter segments use {name} placeholders
// (e.g. "/api/scan/series/{id}") and become typed function arguments.
Path string
// AuthGroup is an opaque consumer-defined tag (e.g. "admin",
// "userConfigured"). wiregen never interprets it; it exists so a
// consumer's consistency check can compare the table against the
// server's route registration.
AuthGroup string
// Kind classifies the payload flow; empty means KindJSON.
Kind EndpointKind
// RespShape refines Response decoding; empty means RespObject.
RespShape RespShape
// Doc is an optional JSDoc line emitted above the generated functions.
Doc string
// Request is the registered wire type of the JSON request body. Zero
// means no typed body; set HasBody for an untyped (unknown) body.
Request WireType
// Response is the registered wire type of the 2xx response body. Zero
// means the response is not decoded (the OK-flag function flavor is
// generated instead of the typed pair).
Response WireType
// HasBody marks an untyped JSON request body (body: unknown) for
// endpoints whose request has no registered Go struct.
HasBody bool
// Query adds a trailing optional query?: Record<string, QueryValue>
// argument, serialized with URLSearchParams (undefined values skipped).
Query bool
}
Endpoint describes one HTTP endpoint of the app's wire contract. The endpoint table is data: the server's route registration stays authoritative for permissions; consumers typically add a consistency test comparing the two (see the AuthGroup field).
type EndpointKind ¶
type EndpointKind string
EndpointKind classifies how an endpoint's payload flows through the generated client.
- KindJSON (the default): a typed client function pair is generated, decoder-bound when a Response is registered.
- KindRaw: a non-JSON escape hatch (file upload, YAML body, video stream, redirect flow). No client function is generated; the endpoint is emitted as a PATH_ constant and participates in consistency checks.
- KindSSE: an EventSource stream. Same emission as KindRaw; the kind tag documents why no function exists.
const ( KindJSON EndpointKind = "json" KindRaw EndpointKind = "raw" KindSSE EndpointKind = "sse" )
Endpoint kinds.
type EnumDef ¶
type EnumDef struct{ Values []string }
EnumDef defines a named string enum with its valid values.
type Filenames ¶
type Filenames struct {
// Types names the file holding the generated type declarations.
Types string
// Decoders names the file holding the generated decoders.
Decoders string
// Registry names the file holding the generated registry.
Registry string
// Constants names the file holding the generated constants.
Constants string
}
Filenames names the four generated output files whose names are otherwise interchangeable positionals. It is a struct rather than four positional strings because the four are same-typed and adjacent: a transposed pair compiled and wrote each file's content under another file's name, which a build only notices when an importer fails to find a symbol. Field names label each one at the call site.
An empty field keeps that file's default name, so a caller overriding one name sets one field and leaves the rest zero — the zero Filenames overrides nothing and is exactly equivalent to omitting WithFilenames.
Two generated files are named elsewhere, each for its own reason: the client by WithClientFilename (a lone string argument cannot be transposed), and the validators module by WithValidatorsFile (whose empty value means "do not write it at all", not "use the default name").
type Option ¶
type Option func(*options)
Option configures optional behavior knobs on a Registry.
func WithBusImport ¶
WithBusImport sets the import path for the SSE bus module.
func WithClientFilename ¶
WithClientFilename overrides the generated client filename (default "client.gen.ts"). It is a standalone option rather than a Filenames field because Filenames exists to label a RUN of same-typed positional arguments, which a single string does not have — and a fifth field would push the struct to 80 bytes, which gocritic's hugeParam correctly flags for a by-value parameter.
func WithFilenames ¶
WithFilenames overrides the output filenames for generated files. An empty field in names keeps that file's default (see Filenames).
func WithHeaderComment ¶
WithHeaderComment sets the header comment prepended to every generated file.
func WithRegisterFuncName ¶
WithRegisterFuncName sets the function name imported from the bus module.
func WithRegistryFuncName ¶
WithRegistryFuncName sets the exported function name in the registry file.
func WithSelfContainedRegistry ¶
WithSelfContainedRegistry enables self-contained registry mode.
func WithTransportImport ¶
WithTransportImport sets the import path for the transport module the generated client calls into. Required when endpoints are registered. The module must export clientRequest, clientRequestOK, clientRequestRaw, and the ApiResult type — see the client-transport contract in the README.
func WithTypesImportPath ¶
WithTypesImportPath sets the import path used in decoders to reference types.
func WithValidatorsFile ¶
WithValidatorsFile makes Generate write the library-owned validators module (the runtime the generated decoders import, with a DO-NOT-EDIT banner) at the given path relative to outDir on every run. The path may point outside outDir (e.g. "../validators.ts") so the module can live beside the consumer's hand-written source at the import path the decoders use. Empty (the default) writes nothing — but the module is wiregen-owned either way: scaffold it via GenerateValidators() and never hand-edit it.
func WithValidatorsImport ¶
WithValidatorsImport sets the import path for the validators module.
type Registry ¶
type Registry struct {
Enums map[string]EnumDef
EnumTSName map[string]string
TSNameOverride map[string]string
PathNameOverride map[string]string
TypeMappings map[string]string
DecoderMappings map[string]string
DiscriminatorMap map[string]map[string]string
ValidatorsImport string
TypesFilename string
ConstantsFilename string
RegistryFilename string
DecodersFilename string
ClientFilename string
ValidatorsFilename string
BusImport string
TransportImport string
TypesImportPath string
HeaderComment string
RegisterFuncName string
RegistryFuncName string
Types []WireType
PackagePaths []string
Constants []WireConst
SSEEvents []SSERegEntry
Endpoints []Endpoint
SelfContainedRegistry bool
// contains filtered or unexported fields
}
Registry holds all type registrations for code generation.
func NewRegistry ¶
NewRegistry creates a Registry with the given functional options applied.
func (*Registry) Generate ¶
Generate writes generated TS files to outDir using the AST engine. It loads and type-checks the registered packages, which runs the go command as a subprocess, so ctx bounds the whole pass: cancelling it aborts the load.
Example ¶
ExampleRegistry_Generate demonstrates basic wiregen usage.
package main
import (
"context"
"fmt"
"github.com/cplieger/wiregen/v3"
"github.com/cplieger/wiregen/v3/testdata/basic"
)
func main() {
r := wiregen.NewRegistry(
wiregen.WithValidatorsImport("./validators.js"),
wiregen.WithBusImport("./bus.js"),
)
r.PackagePaths = []string{"github.com/cplieger/wiregen/v3/testdata/basic"}
r.Types = []wiregen.WireType{
wiregen.TypeRef[basic.Address](),
}
ts, err := r.GenerateTypes(context.Background())
if err != nil {
fmt.Println("generate:", err)
return
}
fmt.Println(ts != "")
}
Output: true
func (*Registry) GenerateClient ¶
GenerateClient returns the client.gen.ts content as a string, rejecting a config error (missing TransportImport / ValidatorsImport, invalid endpoint table) with the same validation Generate applies.
func (*Registry) GenerateConstants ¶
GenerateConstants returns the constants.gen.ts content as a string, rejecting a registered constant whose TSName sanitizes to an empty TS identifier (the same validation Generate applies).
func (*Registry) GenerateDecoders ¶
GenerateDecoders returns the decoders.gen.ts content as a string. ctx bounds the package load, as in Registry.Generate.
func (*Registry) GenerateGoPaths ¶
GenerateGoPaths returns a generated Go source file declaring one Path* string constant per endpoint, for the consumer's CLI/server code to share the same path table as the TS client. pkgName is the target package name. Parameterized paths keep their {name} placeholders verbatim. The output is gofmt-formatted. Returns an error on an invalid endpoint table or package name (the same validation Generate applies).
func (*Registry) GenerateRegistry ¶
GenerateRegistry returns the registry.gen.ts content as a string.
func (*Registry) GenerateTypes ¶
GenerateTypes returns the types.gen.ts content as a string. Every per-file string generator returns an error on the same config problems Generate rejects — no exported generator panics.
ctx bounds the package load, as in Registry.Generate. The three generators that take one (Registry.Generate, this, and Registry.GenerateDecoders) are exactly the three that read the registered packages from source; the rest render from the registry alone and do no I/O.
func (*Registry) GenerateValidators ¶
GenerateValidators returns the library-owned validators module as a string: the implementation of the "Validators contract" (the 11 helper functions the generated decoders import — asObject, asArray, reqStr, reqNum, reqBool, optStr, optNum, optBool, reqOneOf, decodeArray, decodeRecord — plus the Decoder<T> type alias), under the same DO-NOT-EDIT banner as every other generated file (r.HeaderComment, or the default when unset).
The content is constant (it does not depend on the registered types). Consumers either set WithValidatorsFile so Generate writes it on every run, or call this directly from their driver — never hand-edit the output. The v1-era copy-once-then-own starter posture is retired.
type RespShape ¶
type RespShape string
RespShape describes the JSON shape of a KindJSON endpoint's 2xx response relative to its registered Response type.
const ( // RespObject decodes the body as one Response object (the default). RespObject RespShape = "object" // RespArray decodes the body as an array of Response objects. RespArray RespShape = "array" // RespRecord decodes the body as a string-keyed record of Response objects. RespRecord RespShape = "record" // RespStringArray decodes the body as a bare array of strings. Response // must be the zero WireType. RespStringArray RespShape = "stringArray" )
Response shapes.
type SSERegEntry ¶
SSERegEntry maps an SSE event type to a registered struct name.