wiregen

package module
v2.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 19, 2026 License: GPL-2.0, GPL-3.0 Imports: 13 Imported by: 0

README

wiregen

Go Reference Go version Test coverage Mutation OpenSSF Best Practices OpenSSF Scorecard

Generate TypeScript interfaces, decoders, and an SSE registry from Go types via AST analysis.

wiregen is a standalone Go library that, given a set of registered Go types and enum definitions, emits fully-typed TypeScript: interface declarations, runtime decoder functions with validation, and an SSE event→decoder registry. It analyzes your Go source with go/packages + go/types + go/ast, so it carries doc comments through to JSDoc on the generated interfaces. Its only build-time dependency is golang.org/x/tools; nothing it produces is a runtime dependency of your app.

Install

go get github.com/cplieger/wiregen/v2@latest

Upgrading from v1: the module path is now …/wiregen/v2, every per-file string generator returns (string, error) instead of panicking on config errors, non-omitempty map fields are now required in the emitted types (matching encoding/json), nested collection elements are validated recursively, and the validators module is library-owned generated output (see WithValidatorsFile).

Usage

Create a registry with NewRegistry (functional options configure behavior knobs), then set payload data via the exported fields:

package main

import "github.com/cplieger/wiregen/v2"

type Status string

type User struct {
	// ID is the user's unique identifier.
	ID     int    `json:"id"`
	Name   string `json:"name"`
	Status Status `json:"status"`
}

func main() {
	r := wiregen.NewRegistry(
		wiregen.WithValidatorsImport("./validators.js"),
		wiregen.WithBusImport("./bus.js"),
	)

	// PackagePaths is optional — derived from the registered types when omitted.
	// Types are registered by identity via TypeRef (no reflect.Type needed).
	r.Types = []wiregen.WireType{wiregen.TypeRef[User]()}
	// Enum Values are optional — auto-discovered from the type's const block.
	r.Enums = map[string]wiregen.EnumDef{"Status": {}}
	r.SSEEvents = []wiregen.SSERegEntry{
		{EventType: "user", TypeName: "User"},
	}

	if err := r.Generate("./wire"); err != nil {
		panic(err)
	}
}

The ID doc comment above becomes a /** ID is the user's unique identifier. */ JSDoc line on the generated User interface.

API

NewRegistry
func NewRegistry(opts ...Option) *Registry

Creates a *Registry with behavior configured via functional options. Payload data (types, enums, constants, mappings) is then assigned to the returned registry's exported fields.

Functional options
Option Description
WithValidatorsImport(v string) Required. Import path for the validators module.
WithBusImport(v string) Required (unless WithSelfContainedRegistry(true)). Import path for the bus module.
WithTransportImport(v string) Required with Endpoints. Transport-module import path for the client.
WithTypesImportPath(v string) Import path for the types file used in decoders (default: "./types.gen.js").
WithHeaderComment(v string) Header comment prepended to every generated file.
WithRegisterFuncName(v string) Function name imported from the bus module (default: "registerSSEDecoder").
WithRegistryFuncName(v string) Exported function name in the registry file (default: "registerAllSSEDecoders").
WithSelfContainedRegistry(v bool) Use a self-contained Map-based registry instead of importing from BusImport.
WithFilenames(types, decoders, registry, constants string) Override output filenames (pass "" to keep defaults).
WithClientFilename(v string) Override the generated client filename (default: "client.gen.ts").
WithValidatorsFile(v string) Write the library-owned validators module at this outDir-relative path on every run.
Registry fields (payload data)

Payload types are set via exported fields after construction:

Field Type Description
PackagePaths []string Import paths the AST engine loads + parses. Optional — derived from the registered types' packages when omitted.
Types []WireType Go types to generate TS interfaces and decoders for. Register via TypeRef[T]().
Enums map[string]EnumDef Named string enums (keyed by Go type name). Values is optional — auto-discovered from the type's const block (source order) when omitted; explicit Values win.
EnumTSName map[string]string Override the TS name for an enum (Go name → TS name).
TSNameOverride map[string]string Override the TS interface name for a struct (Go name → TS name).
PathNameOverride map[string]string Override the decoder path segment for a type (keyed by TS name).
TypeMappings map[string]string Custom Go type → TS type overrides, keyed by full importpath.Type (e.g. "…/uuid.UUID""string").
DecoderMappings map[string]string Custom Go type → decoder helper name (full importpath.Type key). When set, the decoder emits a validation call instead of a bare cast.
DiscriminatorMap map[string]map[string]string Per-union discriminator→variant decoder mapping; emit a union decoder for a sealed-interface union (see below).
SSEEvents []SSERegEntry Maps SSE event type strings to registered struct names.
Constants []WireConst Integer constants to emit into a constants file.
Endpoints []Endpoint HTTP endpoint table; when non-empty, Generate also emits a typed client (client.gen.ts) and enables GenerateGoPaths. See "Endpoint table + generated client".

Discriminated unions are declared in Go source with a directive on the sealed interface — //wiregen:union discriminator=type variants=A,B,C — which emits export type X = A | B | C. When DiscriminatorMap[X] is set, two runtime decoders are emitted: the 2-argument decodeX(disc: string, v: unknown): X (for callers that already extracted the discriminator, e.g. from an SSE event name) and the 1-argument payload adapter decodeXPayload: Decoder<X> (reads the discriminator key off the payload object itself). A union type can be registered in SSEEvents: the registry binds its payload adapter. Registering a union SSE event without a DiscriminatorMap entry fails Generate (there would be no runtime decoder to bind).

Methods

One error model across the whole surface: every generator returns an error on a config problem; nothing exported panics.

  • (*Registry).Generate(outDir string) error — writes all generated files to outDir with per-file atomicity (every file is staged to a temp sibling first, so a staging failure — e.g. disk full — leaves the directory untouched, and each rename is atomic; the rename pass itself is sequential, so a rename failure can leave a mix of old and new files — it is not a multi-file transaction). client.gen.ts is written only when Endpoints is non-empty; the validators module only when WithValidatorsFile is set. Returns an error and writes nothing when: a required import is missing (ValidatorsImport empty; BusImport empty while SSE events are registered and SelfContainedRegistry is false; TransportImport empty while endpoints are registered); a bare type name is registered twice (from the same or different packages — the engine keys types by bare name); two enums resolve to the same TS type name or const-array name; a registered WireConst's TSName sanitizes to an empty TS identifier; the endpoint table is structurally invalid (unknown method/kind/shape, duplicate or post-case-conversion-colliding names, malformed placeholders, unregistered request/response types); or a //wiregen:union type is registered in SSEEvents without a DiscriminatorMap entry.
  • (*Registry).GenerateTypes() (string, error) — types file content.
  • (*Registry).GenerateDecoders() (string, error) — decoders file content. Errors if ValidatorsImport is empty.
  • (*Registry).GenerateRegistry() (string, error) — registry file content. Errors if BusImport is empty while SelfContainedRegistry is false, or if SelfContainedRegistry is true while ValidatorsImport is empty.
  • (*Registry).GenerateConstants() (string, error) — constants file content. Errors on an unsanitizable TSName.
  • (*Registry).GenerateClient() (string, error) — typed-client file content. Errors if TransportImport or ValidatorsImport is empty or the endpoint table is invalid.
  • (*Registry).GenerateGoPaths(pkgName string) (string, error) — a gofmt-formatted Go file of Path* constants (one per endpoint). Errors on an invalid endpoint table or package name.
  • (*Registry).GenerateValidators() string — the library-owned validators module: the full 11-function contract (asObject, asArray, reqStr, reqNum, reqBool, optStr, optNum, optBool, reqOneOf<T>, decodeArray<T>, decodeRecord<T>) plus the Decoder<T> type, under the same DO-NOT-EDIT banner as every other generated file. Content is constant (registry-independent), so this method alone cannot fail. Prefer WithValidatorsFile so Generate keeps the file current on every run; never hand-edit the output. (The v1 "copy once, then own it" starter posture is retired.)
Types
// WireType identifies a registered Go type by package path + name.
type WireType struct {
    PkgPath string
    Name    string
}

// TypeRef registers a type by identity (the only use of reflect — for the
// {PkgPath, Name} pair; the field walk is done from source via the AST).
func TypeRef[T any]() WireType

type WireConst struct {
    TSName string
    Value  int
}

type EnumDef struct{ Values []string }

type UnionDef struct {
    Discriminator string
    Variants      []string
}

type SSERegEntry struct {
    EventType string
    TypeName  string
}

Endpoint table + generated client

Registering Endpoints makes the HTTP contract data in the same registry as the types. Generate then also emits client.gen.ts: one PATH_* constant per endpoint (placeholders kept verbatim — non-JSON flows are consumed exclusively through these) and, per KindJSON endpoint, a typed function pair — name(...): Promise<T | null> and nameRaw(...): Promise<ApiResult<T>> — with the response decoder bound when a Response type is registered (an endpoint without one gets an OK-flag Promise<boolean> flavor instead).

type Endpoint struct {
    Name      string       // TS function name + PATH_/Go constant base
    Method    string       // GET, POST, PUT, PATCH, DELETE
    Path      string       // "/api/scan/series/{id}" — {name} segments become typed args
    AuthGroup string       // opaque consumer tag for a routes-consistency check
    Kind      EndpointKind // "" = KindJSON; KindRaw / KindSSE emit only a PATH_ constant
    RespShape RespShape    // "" = RespObject; RespArray / RespRecord / RespStringArray
    Doc       string       // optional JSDoc line
    Request   WireType     // typed JSON request body (registered type)
    Response  WireType     // decoded 2xx response body (registered type)
    HasBody   bool         // untyped JSON body (body: unknown)
    Query     bool         // trailing query?: Record<string, QueryValue> argument
}

Validation happens before any file is written: unknown methods/kinds/shapes, duplicate names, names that collide after case conversion (configYaml vs configYAML would emit the same PATH_CONFIG_YAML / PathConfigYAML constant), malformed {placeholder} syntax, and request/response types that are not registered all fail Generate with a named error.

AuthGroup is never interpreted by wiregen — it exists so the consumer can write a consistency test comparing the table against its server's actual route registrations (the server stays authoritative for permissions).

Client-transport contract. The module at TransportImport must export:

  • clientRequest<T>(method, path, body, decoder, signal?): Promise<T | null>
  • clientRequestOK(method, path, body?, signal?): Promise<boolean>
  • clientRequestRaw<T>(method, path, body?, decoder?, signal?): Promise<ApiResult<T>>
  • interface ApiResult<T> (whatever envelope shape the consumer uses)

Go path constants. (*Registry).GenerateGoPaths(pkgName string) (string, error) returns a gofmt-formatted Go source file declaring one Path* string constant per endpoint, so a CLI in the same binary shares the exact path table the TS client was generated from. Errors on an invalid endpoint table or package name (matching the other generators).

Validators contract

The validators module (at ValidatorsImport) is library-owned generated output: set WithValidatorsFile and Generate writes it on every run, or scaffold it once with GenerateValidators() — either way, don't hand-edit it. The contract below is what the generated decoders import by name; it is also a stable, hand-written-decoder-friendly API (consumer code may import and build on these helpers freely). The module exports:

  • asObject(v: unknown, path: string): Record<string, unknown>
  • asArray(v: unknown, path: string): unknown[]
  • reqStr(o: Record<string, unknown>, key: string, path: string): string
  • reqNum(o: Record<string, unknown>, key: string, path: string): number
  • reqBool(o: Record<string, unknown>, key: string, path: string): boolean
  • optStr(o: Record<string, unknown>, key: string, path: string): string | undefined
  • optNum(o: Record<string, unknown>, key: string, path: string): number | undefined
  • optBool(o: Record<string, unknown>, key: string, path: string): boolean | undefined
  • reqOneOf<T extends string>(o: Record<string, unknown>, key: string, values: readonly T[], path: string): T
  • decodeArray<T>(v: unknown, decoder: Decoder<T>, path: string): T[]
  • decodeRecord<T>(v: unknown, decoder: Decoder<T>, path: string): Record<string, T>
  • type Decoder<T> = (v: unknown) => T

Behavior notes

  • Doc comments on registered structs and their fields are carried through to /** … */ JSDoc on the generated interfaces (the AST engine reads them from source).
  • Unexported fields are skipped (matching encoding/json behavior).
  • time.Time maps to string; json.RawMessage and interface{} map to unknown.
  • json.Number maps to number.
  • []byte maps to string (JSON encodes []byte as base64).
  • omitzero (Go 1.24+) is treated the same as omitempty — the field becomes optional.
  • Map fields keep their source optionality (pointer / omitempty / omitzero → optional, otherwise required), exactly like every other field kind. A required map's JSON null decodes to {} (below).
  • Nested collection elements are validated recursively. [][]T, map[string][]T, and deeper compositions decode with real per-level checks — each level accepts null as its empty value and validates its own elements; a malformed inner array/map throws with the element path.
  • JSON null decodes as the zero value, not an error. encoding/json marshals a nil pointer/slice/map (and a nil []byte) to null when the field lacks omitempty; the generated decoders accept that output — an optional field decodes present-null as undefined, a required slice/map decodes null as empty ([]/{}), and a required []byte decodes null as "". json.RawMessage and interface{} fields pass null through as data. There is no null-vs-absent distinction (nullable-vs-optional is a non-goal, below).
  • json:",string" causes the field to be typed as string and decoded with reqStr/optStr, matching encoding/json's string-wrapping behavior for numbers and booleans.
  • Map keys are always string in generated TS because JSON object keys are strings regardless of the Go map key type.
  • Embedded named structs are flattened into the embedding interface, and field promotion matches encoding/json's rules: the shallowest field wins, a tagged field dominates an untagged one at equal depth, and a field reachable through two sibling embeds at equal depth (a "diamond") is dropped as an ambiguous promotion.
  • Generated identifiers are always valid TypeScript. Consumer- or source-derived strings that land in an identifier position — struct/enum name overrides, the registry function-name knobs, a //wiregen:union discriminator, field wire names, and decoder local variables — are sanitized to a valid TS identifier (with a safe fallback when a value sanitizes to empty). A JSON key that isn't a valid identifier (e.g. content-type) is emitted as a quoted property and bracket access (out["content-type"]). Values that are already valid identifiers are emitted unchanged, so output stays byte-identical for the common case.
  • A zero-value enum (no discoverable const values and no explicit Values) emits export type X = never; rather than the invalid export type X = ;.
  • Generate writes types.gen.ts + decoders.gen.ts always; registry.gen.ts only when there are SSE events; constants.gen.ts only when there are constants.
  • PackagePaths defaults to the distinct packages of the registered types; set it explicitly only to load extra packages.
  • Enum Values are auto-discovered from the named type's const declarations (in source order) when left empty; provide them explicitly to override the set or order.

Unsupported by design

The following are intentionally not supported:

Feature Reason
Go generics (type parameters) The Go type system can't represent uninstantiated generic types here. Register concrete instantiations instead.
Nullable vs optional distinction T | null vs ?: — current consumers treat null and absent identically. Pointer/omitempty → optional only.
tstype struct tag hints TypeMappings provides the same escape hatch at the registry level.
Inline anonymous struct fields A field whose type is an inline struct { … } literal maps to unknown. Register it as a named type instead. (Embedded named structs are flattened, not unknown.)

Disclaimer

This project is built with care and follows security best practices, but it is intended for personal / self-hosted use. No guarantees of fitness for production environments. Use at your own risk.

This project was built with AI-assisted tooling using Claude Opus and Kiro. The human maintainer defines architecture, supervises implementation, and makes all final decisions.

License

GPL-3.0 — see LICENSE.

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 (
	"fmt"

	"github.com/cplieger/wiregen/v2"
	"github.com/cplieger/wiregen/v2/testdata/basic"
)

func main() {
	r := wiregen.NewRegistry(
		wiregen.WithValidatorsImport("./validators.js"),
		wiregen.WithBusImport("./bus.js"),
	)
	r.PackagePaths = []string{"github.com/cplieger/wiregen/v2/testdata/basic"}
	r.Types = []wiregen.WireType{wiregen.TypeRef[basic.Address]()}
	r.SSEEvents = []wiregen.SSERegEntry{
		{EventType: "addr", TypeName: "Address"},
	}

	ts, err := r.GenerateTypes()
	if err != nil {
		fmt.Println("generate:", err)
		return
	}
	fmt.Println(ts != "")
}
Output:
true

Index

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 Option

type Option func(*options)

Option configures optional behavior knobs on a Registry.

func WithBusImport

func WithBusImport(v string) Option

WithBusImport sets the import path for the SSE bus module.

func WithClientFilename

func WithClientFilename(v string) Option

WithClientFilename overrides the generated client filename (default "client.gen.ts").

func WithFilenames

func WithFilenames(types, decoders, registry, constants string) Option

WithFilenames overrides the output filenames for generated files.

func WithHeaderComment

func WithHeaderComment(v string) Option

WithHeaderComment sets the header comment prepended to every generated file.

func WithRegisterFuncName

func WithRegisterFuncName(v string) Option

WithRegisterFuncName sets the function name imported from the bus module.

func WithRegistryFuncName

func WithRegistryFuncName(v string) Option

WithRegistryFuncName sets the exported function name in the registry file.

func WithSelfContainedRegistry

func WithSelfContainedRegistry(v bool) Option

WithSelfContainedRegistry enables self-contained registry mode.

func WithTransportImport

func WithTransportImport(v string) Option

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

func WithTypesImportPath(v string) Option

WithTypesImportPath sets the import path used in decoders to reference types.

func WithValidatorsFile

func WithValidatorsFile(v string) Option

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

func WithValidatorsImport(v string) Option

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

func NewRegistry(opts ...Option) *Registry

NewRegistry creates a Registry with the given functional options applied.

func (*Registry) Generate

func (r *Registry) Generate(outDir string) error

Generate writes generated TS files to outDir using the AST engine.

Example

ExampleRegistry_Generate demonstrates basic wiregen usage.

package main

import (
	"fmt"

	"github.com/cplieger/wiregen/v2"
	"github.com/cplieger/wiregen/v2/testdata/basic"
)

func main() {
	r := wiregen.NewRegistry(
		wiregen.WithValidatorsImport("./validators.js"),
		wiregen.WithBusImport("./bus.js"),
	)
	r.PackagePaths = []string{"github.com/cplieger/wiregen/v2/testdata/basic"}
	r.Types = []wiregen.WireType{
		wiregen.TypeRef[basic.Address](),
	}

	ts, err := r.GenerateTypes()
	if err != nil {
		fmt.Println("generate:", err)
		return
	}
	fmt.Println(ts != "")
}
Output:
true

func (*Registry) GenerateClient

func (r *Registry) GenerateClient() (string, error)

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

func (r *Registry) GenerateConstants() (string, error)

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

func (r *Registry) GenerateDecoders() (string, error)

GenerateDecoders returns the decoders.gen.ts content as a string.

func (*Registry) GenerateGoPaths

func (r *Registry) GenerateGoPaths(pkgName string) (string, error)

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

func (r *Registry) GenerateRegistry() (string, error)

GenerateRegistry returns the registry.gen.ts content as a string.

func (*Registry) GenerateTypes

func (r *Registry) GenerateTypes() (string, error)

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.

func (*Registry) GenerateValidators

func (r *Registry) GenerateValidators() string

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

type SSERegEntry struct {
	EventType string
	TypeName  string
}

SSERegEntry maps an SSE event type to a registered struct name.

type UnionDef

type UnionDef struct {
	Discriminator string
	Variants      []string
}

UnionDef defines a discriminated union parsed from //wiregen:union directive.

type WireConst

type WireConst struct {
	TSName string
	Value  int
}

WireConst defines a named integer constant to emit into TypeScript.

type WireType

type WireType struct {
	PkgPath string
	Name    string
}

WireType is a compile-time-safe type reference captured by TypeRef[T]().

func TypeRef

func TypeRef[T any]() WireType

TypeRef registers a concrete Go type for TS generation. A typo or nonexistent type is a compile error — the generic constraint ensures T exists.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL