generator

package
v0.5.26 Latest Latest
Warning

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

Go to latest
Published: Aug 25, 2026 License: Apache-2.0 Imports: 43 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ExtensionGo  = "go"
	ExtensionCSS = "css"
	ExtensionJS  = "js"
)

Artifact extensions, without a leading dot.

View Source
const (
	// DynamoPage issues one request and returns a page.
	DynamoPage = dynamobind.Page
	// DynamoMany iterates every page.
	DynamoMany = dynamobind.Many
)
View Source
const (
	DynamoEqual          = dynamobind.OpEqual
	DynamoLess           = dynamobind.OpLess
	DynamoLessOrEqual    = dynamobind.OpLessOrEqual
	DynamoGreater        = dynamobind.OpGreater
	DynamoGreaterOrEqual = dynamobind.OpGreaterOrEqual
	DynamoBetween        = dynamobind.OpBetween
	DynamoBeginsWith     = dynamobind.OpBeginsWith
)
View Source
const (
	// FirestoreBatch issues one request and returns a page.
	FirestoreBatch = firestorebind.Batch
	// FirestoreMany iterates every batch.
	FirestoreMany = firestorebind.Many
	// FirestoreCount runs an aggregation query.
	FirestoreCount = firestorebind.Count
	// FirestoreKeys runs a keys-only query.
	FirestoreKeys = firestorebind.Keys
)
View Source
const (
	FirestoreEqual          = firestorebind.OpEqual
	FirestoreNotEqual       = firestorebind.OpNotEqual
	FirestoreLess           = firestorebind.OpLess
	FirestoreLessOrEqual    = firestorebind.OpLessOrEqual
	FirestoreGreater        = firestorebind.OpGreater
	FirestoreGreaterOrEqual = firestorebind.OpGreaterOrEqual
	FirestoreIn             = firestorebind.OpIn
	FirestoreNotIn          = firestorebind.OpNotIn
)
View Source
const (
	FirestoreAscending  = firestorebind.Ascending
	FirestoreDescending = firestorebind.Descending
)
View Source
const (
	FirestoreAnd = firestorebind.JunctionAnd
	FirestoreOr  = firestorebind.JunctionOr
)
View Source
const (
	// DefaultPublicDir receives extracted static assets when a project
	// configures no directory. Extraction always happens, so a
	// zero-configuration project still gets working asset URLs.
	DefaultPublicDir = "public/generated"
	// DefaultPublicURLBase serves those files when a project configures no URL
	// base.
	DefaultPublicURLBase = htmlbind.DefaultPublicURLBase
)
View Source
const (
	KindRestAny = "rest_any" // map[string]any with payload:"*"
	KindRestRaw = "rest_raw" // map[string]json.RawMessage with payload:"*"
	KindStruct  = "struct"
	KindSlice   = "slice"
	// KindArray is a fixed-length Go array field, which is a different kind
	// from KindSlice because the two decode differently: a slice is built and
	// assigned, while an array is filled in place against a length the type
	// already states. Encoding is the one place they agree, and both arms say
	// so by sharing it.
	KindArray = "array"
	// KindBytes is a slice or a fixed-length array of bytes, which is one kind
	// rather than an element kind because its wire form has nothing to do with
	// the uint8 it is made of: a base64 string in JSON and a byte string in
	// CBOR. ArrayLen tells the two spellings apart, exactly as it does for
	// KindArray.
	KindBytes = "bytes"
	KindMap   = "map"
	// KindForeign is a field whose type is declared in another package and
	// carries its own JSON codec through the jsonbind interfaces.
	//
	// Such a field used to be dropped from the plan without a word, because
	// analysis is per package and a qualified type name resolves to nothing it
	// can walk. It still resolves to nothing this run can walk; what changed is
	// that the type can say it does not need walking.
	KindForeign = "foreign"
)

Composite and special field kinds.

View Source
const (
	DefaultTemplatesName       = "tinybind_templates_gen.go"
	DefaultHTMLTemplatePattern = "*.tb.html"
	DefaultSQLTemplatePattern  = "*.tb.sql"
)
View Source
const DefaultDynamoTemplatePattern = dynamobind.DefaultTemplatePattern

DefaultDynamoTemplatePattern is the base-name glob for query declarations, beside the HTML and SQL template patterns.

View Source
const DefaultFirestoreTemplatePattern = firestorebind.DefaultTemplatePattern

DefaultFirestoreTemplatePattern is the base-name glob for query declarations.

Variables

View Source
var ErrDerivedAssetDir = errors.New(
	"generator: a reference hook produced a file but DerivedAssetDir is not set; " +
		"it is not derived from PublicDir, because a transform chooses the URL it rewrites to " +
		"and only the caller knows which directory is served there")

ErrDerivedAssetDir reports a hook that produced a file with nowhere to put it. Discarding it silently would leave the rewritten reference dangling, which is the one property this seam exists to guarantee.

View Source
var ErrFeatureDisabled = errors.New("generator: feature disabled")

ErrFeatureDisabled is returned when a disabled generator artifact is invoked directly.

View Source
var ErrNothingToGenerate = errors.New("generator: nothing to generate")

ErrNothingToGenerate reports a package with no enabled artifacts.

View Source
var ErrPublicAssetPairing = errors.New(
	"generator: PublicDir and PublicURLBase must be set together; " +
		"neither is derived from the other, so configure both or leave both empty for " +
		DefaultPublicDir + " and " + DefaultPublicURLBase)

ErrPublicAssetPairing reports a public asset configuration that sets only one of the two independent options.

Functions

func AnalyzeConfigBind added in v0.1.5

func AnalyzeConfigBind(dir string) (pkgName string, specs []cbcg.Spec, err error)

AnalyzeConfigBind discovers default Bind[T](prefix) registrations.

func AnalyzeConfigBindWithOptions added in v0.1.12

func AnalyzeConfigBindWithOptions(dir string, options Options) (pkgName string, specs []cbcg.Spec, err error)

AnalyzeConfigBindWithOptions discovers configured config-bind calls.

func Emit

func Emit(plan *PackagePlan) ([]byte, error)

Emit generates Go source for type-specific binders, writers, and JSON codecs. The output does not import "reflect".

func EmitCacheKeys added in v0.5.9

func EmitCacheKeys(plan *CacheKeyPackagePlan) ([]byte, error)

EmitCacheKeys generates the key method for every plan in the package.

func EmitDynamoItems added in v0.2.8

func EmitDynamoItems(plan *DynamoPackagePlan, emitTable bool) ([]byte, error)

EmitDynamoItems generates the item codec for every plan in the package.

func EmitDynamoQueries added in v0.2.9

func EmitDynamoQueries(pkg string, plans []DynamoQueryPlan) ([]byte, error)

EmitDynamoQueries generates one function per checked declaration, in the Context form.

func EmitDynamoQueriesWithOptions added in v0.3.7

func EmitDynamoQueriesWithOptions(pkg string, plans []DynamoQueryPlan, opts DynamoQueryOptions) ([]byte, error)

EmitDynamoQueriesWithOptions is EmitDynamoQueries in the mode opts selects.

func EmitFirestoreEntities added in v0.3.6

func EmitFirestoreEntities(plan *FirestorePackagePlan) ([]byte, error)

EmitFirestoreEntities generates the entity codec for every plan in the package.

func EmitFirestoreQueries added in v0.3.6

func EmitFirestoreQueries(pkg string, plans []FirestoreQueryPlan) ([]byte, error)

EmitFirestoreQueries generates one function per checked declaration, in the Context form.

func EmitFirestoreQueriesWithOptions added in v0.3.7

func EmitFirestoreQueriesWithOptions(pkg string, plans []FirestoreQueryPlan, opts FirestoreQueryOptions) ([]byte, error)

EmitFirestoreQueriesWithOptions is EmitFirestoreQueries in the mode opts selects.

func EmitOpenAPI

func EmitOpenAPI(pkg string, doc Document) ([]byte, error)

EmitOpenAPI produces Go source for a package-named fragment. Prefer EmitOpenAPIFragment when the package import path is available.

func EmitOpenAPIFragment added in v0.1.11

func EmitOpenAPIFragment(pkg, packagePath string, doc Document) ([]byte, error)

EmitOpenAPIFragment produces Go source embedding and registering one package-local OpenAPI fragment.

func Generate

func Generate(dir, outDir, outName string) (string, error)

Generate analyzes dir and writes <outName> (default: tinybind_gen.go) into outDir (default: dir). Returns the absolute path of the written file.

func GenerateOpenAPI

func GenerateOpenAPI(dir, outDir, outName string) (string, error)

GenerateOpenAPI builds OpenAPI 3.1 from Go sources in dir and writes a generated file that embeds the document and registers it with httpbind for serving.

func Main

func Main(set CommandSet)

Main owns only the outer process boundary.

func ResolveTemplatePositions added in v0.5.17

func ResolveTemplatePositions(content []byte, fileName string) []byte

ResolveTemplatePositions names the file an artifact is written as, in the line directives requirement:template-source-positions emitted into it.

A mapped span ends with a directive returning positions to the generated file, and that directive has to state the file's name and the physical line the reader is on. This package knows the line, because the bytes are final; it does not know the name, because Artifact states a suggested base and the caller chooses the suffix it writes. A caller writing artifacts under its own name calls this with that name before writing:

content := generator.ResolveTemplatePositions(artifact.Content, artifact.OutputBase+"_pw_gen.go")

For an Artifact only the name is filled in, because the line numbers were already correct when the artifact was built: they describe bytes nothing has moved since. Content taken straight out of a template package's own Generate entry point, which cannot know the name either, has both filled in here.

It is a no-op on content holding no such directive, so it is safe to call on whatever the run generated and whether or not Options.TemplateLineDirectives is set. Skipping it leaves the directives naming a synthetic file that does not exist, which misreports the position of generated scaffolding and nothing else: a template position is unaffected.

func TemplateFiles added in v0.1.5

func TemplateFiles(dir string) ([]string, error)

TemplateFiles returns the .tb.html and .tb.sql files directly contained in dir. A generator invocation targets one Go package and therefore does not descend into child package directories.

func TemplateFilesWithPatterns added in v0.1.13

func TemplateFilesWithPatterns(dir, htmlPattern, sqlPattern string) ([]string, error)

TemplateFilesWithPatterns returns files directly contained in dir whose base names match the filepath.Match patterns for HTML and SQL templates.

Types

type Artifact added in v0.1.13

type Artifact struct {
	// SourcePath is the real on-disk path of the owning source. It is empty for
	// package-wide artifacts.
	SourcePath  string
	Kind        ArtifactKind
	Destination ArtifactDestination
	// OutputBase is the suggested output base name, without directory,
	// extension, or generated-file suffix.
	OutputBase string
	// Extension is the output file extension without a dot.
	Extension string
	// PackageName is meaningful for a go_package destination only.
	PackageName string
	Content     []byte
	// PublicPath is the URL a public asset is referenced by. It is empty for a
	// go_package destination.
	PublicPath string
}

Artifact is one generated output unit and the source file that owns it. The caller maps OutputBase to its own generated file name; nothing is written to disk by the API that produces Artifacts.

Go formatting and import correctness apply to a go_package destination only; a public asset is written verbatim.

type ArtifactDestination added in v0.2.9

type ArtifactDestination string

ArtifactDestination says where an artifact is written, because a stylesheet is served, not compiled.

const (
	DestinationGoPackage   ArtifactDestination = "go_package"
	DestinationPublicAsset ArtifactDestination = "public_asset"
)

type ArtifactKind added in v0.1.13

type ArtifactKind string

ArtifactKind classifies one generated output unit.

const (
	ArtifactHTMLTemplate ArtifactKind = "html_template"
	ArtifactSQLTemplate  ArtifactKind = "sql_template"
	ArtifactBinding      ArtifactKind = "binding"
	ArtifactConfigBind   ArtifactKind = "configbind"
	ArtifactDynamoItem   ArtifactKind = "dynamo_item"
	ArtifactDynamoQuery  ArtifactKind = "dynamo_query"

	ArtifactFirestoreEntity ArtifactKind = "firestore_entity"
	ArtifactFirestoreQuery  ArtifactKind = "firestore_query"
	ArtifactOpenAPI         ArtifactKind = "openapi"
	// ArtifactStylesheet is the component CSS extracted from one template.
	ArtifactStylesheet ArtifactKind = "stylesheet"
	// ArtifactScript is the component JavaScript extracted from one template.
	ArtifactScript ArtifactKind = "script"
	// ArtifactDerivedAsset is a file a reference hook transform produced from an
	// authored source the template points at.
	ArtifactDerivedAsset ArtifactKind = "derived_asset"
	// ArtifactTransport is the other transport's copy of the package's
	// handlers, derived from the authored net/http source.
	ArtifactTransport ArtifactKind = "transport"
	// ArtifactTransportBinding is the derived backend's binder registry. The
	// runtime's Bind reads a registry the generated init fills, so a package
	// missing this file compiles and fails on the first request instead.
	ArtifactTransportBinding ArtifactKind = "transport_binding"
	// ArtifactTransportRoutes registers the derived handlers on the router
	// TransformOptions.Router names.
	ArtifactTransportRoutes ArtifactKind = "transport_routes"
)

type CBORHTTPProfile added in v0.5.19

type CBORHTTPProfile struct {
	// RejectFloats refuses floats in both directions: a float64 field becomes
	// a generation error naming the field, and a float arriving in a request
	// body is a decode error. For a service carrying scaled integers.
	RejectFloats bool
	// RequireSortedKeys emits map members in RFC 8949 section 4.2.1 bytewise
	// order, computed at generation time, for a client that checks
	// deterministic encoding. A runtime map field cannot promise that order
	// and becomes a generation error while this is set.
	RequireSortedKeys bool
}

CBORHTTPProfile is the CBOR subset the HTTP codecs of EnableCBORHTTP are generated for. It is this generator's own type rather than the driver's Profile, because the generator never imports the driver; the restrictions named here become code in the emitted file. Both ends of the protocol must agree on it, which hashing it into the generation fingerprint enforces for every regeneration.

type CacheKeyFieldPlan added in v0.5.9

type CacheKeyFieldPlan struct {
	Name string
	Type CacheKeyType
}

CacheKeyFieldPlan is one field that participates in a key.

type CacheKeyKind added in v0.5.9

type CacheKeyKind string

CacheKeyKind is how one Go type is framed into a cache key.

const (
	CacheKeyString   CacheKeyKind = "string"
	CacheKeyBool     CacheKeyKind = "bool"
	CacheKeyInt      CacheKeyKind = "int"
	CacheKeyUint     CacheKeyKind = "uint"
	CacheKeyFloat    CacheKeyKind = "float"
	CacheKeyBytes    CacheKeyKind = "bytes"
	CacheKeyTime     CacheKeyKind = "time"
	CacheKeyOptional CacheKeyKind = "optional"
	CacheKeyArray    CacheKeyKind = "array"
)

type CacheKeyPackagePlan added in v0.5.9

type CacheKeyPackagePlan struct {
	Package     string
	PackagePath string
	Keys        []CacheKeyPlan
}

CacheKeyPackagePlan is every key plan in one package.

func AnalyzeCacheKeys added in v0.5.9

func AnalyzeCacheKeys(dir string) (*CacheKeyPackagePlan, error)

AnalyzeCacheKeys builds key plans for the types a package uses as cache keys.

func AnalyzeCacheKeysWithOptions added in v0.5.9

func AnalyzeCacheKeysWithOptions(dir string, opts Options) (*CacheKeyPackagePlan, error)

AnalyzeCacheKeysWithOptions is AnalyzeCacheKeys with custom discovery.

type CacheKeyPlan added in v0.5.9

type CacheKeyPlan struct {
	Name       string
	Fields     []CacheKeyFieldPlan
	SourcePath string
}

CacheKeyPlan is the key plan for one struct type.

func (CacheKeyPlan) Identity added in v0.5.9

func (p CacheKeyPlan) Identity(packagePath string) string

Identity is the prefix that separates this type's entries from every other type's. It is wholly derived: the package path and name are unique by construction while one struct yields one key, so nothing here is declared and nothing can be forgotten.

There is deliberately no author-declared version. Invalidating on a meaning change is a deployment's job, and api:cache-store already states that the runtime never invalidates entries.

type CacheKeyType added in v0.5.9

type CacheKeyType struct {
	Kind CacheKeyKind
	// Go is the type as it must be written inside the generated package. It is
	// needed for the closure parameter an optional or an array frames through.
	Go string
	// Elem is the element of a pointer or a slice.
	Elem *CacheKeyType
}

CacheKeyType is how one Go type reaches a framing helper.

type CallOperation added in v0.1.12

type CallOperation string

CallOperation identifies the generator meaning of a configured wrapper call.

const (
	OperationRequestBind         CallOperation = "request_bind"
	OperationResponseWrite       CallOperation = "response_write"
	OperationResponseWriteStatus CallOperation = "response_write_status"
	OperationStreamCreate        CallOperation = "stream_create"
	OperationSocketReceive       CallOperation = "socket_receive"
	OperationSocketSend          CallOperation = "socket_send"
	OperationJSONDecode          CallOperation = "json_decode"
	OperationJSONEncode          CallOperation = "json_encode"
	// The two declaration operations below name a codec an annotation asked for
	// rather than one a call site implied. They are separate from the two above
	// because they carry a second meaning: the codec is also published as a
	// method, which a discovered call never asks for.
	//
	// There is one per direction and no third for both, so that each is gated
	// by the codec feature it carries. An annotation asking for both registers
	// both patterns against its one target, which is the same shape the socket
	// entry already has.
	OperationJSONEncoderDeclare CallOperation = "json_encoder_declare"
	OperationJSONDecoderDeclare CallOperation = "json_decoder_declare"
	// The four CBOR codec operations, one per container shape and direction.
	// The shape is in the entry point's name rather than in an argument,
	// because discovery reads a call's symbol and its type arguments and never
	// an argument's value; two names are two symbols and cost nothing.
	//
	// One operation per direction, not one per shape, so rule:generator-feature
	// -disable can remove a direction and leave the other standing -- the same
	// lesson the JSON declaration learned when a both-directions operation
	// turned out not to be half-removable.
	OperationCBORArrayEncode CallOperation = "cbor_array_encode"
	OperationCBORArrayDecode CallOperation = "cbor_array_decode"
	OperationCBORMapEncode   CallOperation = "cbor_map_encode"
	OperationCBORMapDecode   CallOperation = "cbor_map_decode"
	OperationRowsScan        CallOperation = "rows_scan"
	OperationItemEncode      CallOperation = "item_encode"
	OperationItemDecode      CallOperation = "item_decode"
	OperationItemKey         CallOperation = "item_key"
	// OperationItemEncodeDecode is a write that reads back what it replaced, and
	// OperationItemKeyDecode a delete that does. One call needs two generated
	// methods, and a call target carries exactly one operation, so the pair gets
	// its own operation rather than two patterns for one function.
	OperationItemEncodeDecode CallOperation = "item_encode_decode"
	OperationItemKeyDecode    CallOperation = "item_key_decode"
	// The Firestore entity operations. They are separate from the DynamoDB item
	// ones rather than shared, because the two runtimes emit different methods
	// onto the same struct and a call has to say which.
	OperationEntityEncode CallOperation = "entity_encode"
	OperationEntityDecode CallOperation = "entity_decode"
	OperationEntityKey    CallOperation = "entity_key"
	// OperationCacheKey marks the argument a cache reads a key from. It selects
	// an argument type rather than a type parameter, because the value passed is
	// the key itself and a framework's memo call is generic over the result.
	OperationCacheKey         CallOperation = "cache_key"
	OperationConfigBind       CallOperation = "config_bind"
	OperationConfigSubCommand CallOperation = "config_subcommand"
	OperationRouteRegister    CallOperation = "route_register"
	OperationErrorResponse    CallOperation = "error_response"
	// OperationTransportOnly carries transport slots and nothing else. It exists
	// for calls the transform has to recognize but discovery reads nothing from:
	// WriteError and the request accessors take a writer or a request, yet name
	// no model. Without a pattern they would look like any unrecognized call and
	// refuse every handler that makes one.
	OperationTransportOnly CallOperation = "transport_only"
)

type CallPattern added in v0.1.12

type CallPattern struct {
	Target        CallTarget
	Operation     CallOperation
	TypeRoles     map[string]TypeSource
	ArgumentRoles map[string]ValueSource
	Transport     TransportSlots
}

CallPattern maps a framework call identity onto one generator operation.

func CBORArrayDecodeCall added in v0.5.23

func CBORArrayDecodeCall(target CallTarget, options ...CallPatternOption) CallPattern

CBORArrayDecodeCall declares the array-shaped CBOR decoder entry point.

func CBORArrayEncodeCall added in v0.5.23

func CBORArrayEncodeCall(target CallTarget, options ...CallPatternOption) CallPattern

CBORArrayEncodeCall declares the array-shaped CBOR encoder entry point.

func CBORMapDecodeCall added in v0.5.23

func CBORMapDecodeCall(target CallTarget, options ...CallPatternOption) CallPattern

CBORMapDecodeCall declares the map-shaped CBOR decoder entry point.

func CBORMapEncodeCall added in v0.5.23

func CBORMapEncodeCall(target CallTarget, options ...CallPatternOption) CallPattern

CBORMapEncodeCall declares the map-shaped CBOR encoder entry point.

func CacheKeyCall added in v0.5.9

func CacheKeyCall(target CallTarget, options ...CallPatternOption) CallPattern

CacheKeyCall declares a wrapper that reads a cache key from an argument.

The key role takes ArgumentType rather than GenericType: a memo call is generic over the result it caches, and the key is the value beside it.

func Call added in v0.1.12

func Call(operation CallOperation, target CallTarget, options ...CallPatternOption) CallPattern

Call constructs a semantic wrapper call pattern.

func ConfigBindCall added in v0.1.12

func ConfigBindCall(target CallTarget, options ...CallPatternOption) CallPattern

ConfigBindCall declares a configbind registration wrapper.

func ConfigSubCommandCall added in v0.1.12

func ConfigSubCommandCall(target CallTarget, options ...CallPatternOption) CallPattern

ConfigSubCommandCall declares a configbind subcommand registration wrapper.

func EntityDecodeCall added in v0.3.6

func EntityDecodeCall(target CallTarget, options ...CallPatternOption) CallPattern

EntityDecodeCall declares a Firestore entity reader wrapper.

func EntityEncodeCall added in v0.3.6

func EntityEncodeCall(target CallTarget, options ...CallPatternOption) CallPattern

EntityEncodeCall declares a Firestore entity writer wrapper.

func EntityKeyCall added in v0.3.6

func EntityKeyCall(target CallTarget, options ...CallPatternOption) CallPattern

EntityKeyCall declares a wrapper that needs only a type's key.

func ErrorResponseCall added in v0.1.12

func ErrorResponseCall(target CallTarget, options ...CallPatternOption) CallPattern

ErrorResponseCall declares an error constructor with a fixed HTTP status.

func ItemDecodeCall added in v0.2.8

func ItemDecodeCall(target CallTarget, options ...CallPatternOption) CallPattern

ItemDecodeCall declares a DynamoDB item reader wrapper.

func ItemEncodeCall added in v0.2.8

func ItemEncodeCall(target CallTarget, options ...CallPatternOption) CallPattern

ItemEncodeCall declares a DynamoDB item writer wrapper.

func ItemEncodeDecodeCall added in v0.2.8

func ItemEncodeDecodeCall(target CallTarget, options ...CallPatternOption) CallPattern

ItemEncodeDecodeCall declares a wrapper that writes an item and decodes the item it replaced.

func ItemKeyCall added in v0.2.8

func ItemKeyCall(target CallTarget, options ...CallPatternOption) CallPattern

ItemKeyCall declares a wrapper that needs only a type's primary key.

func ItemKeyDecodeCall added in v0.2.8

func ItemKeyDecodeCall(target CallTarget, options ...CallPatternOption) CallPattern

ItemKeyDecodeCall declares a wrapper that deletes by key and decodes the item it deleted.

func JSONDecodeCall added in v0.1.12

func JSONDecodeCall(target CallTarget, options ...CallPatternOption) CallPattern

JSONDecodeCall declares a standalone JSON decoder wrapper.

func JSONDecoderDeclareCall added in v0.5.10

func JSONDecoderDeclareCall(target CallTarget, options ...CallPatternOption) CallPattern

JSONDecoderDeclareCall declares the annotation asking for the decoder alone.

func JSONEncodeCall added in v0.1.12

func JSONEncodeCall(target CallTarget, options ...CallPatternOption) CallPattern

JSONEncodeCall declares a standalone JSON encoder wrapper.

func JSONEncoderDeclareCall added in v0.5.10

func JSONEncoderDeclareCall(target CallTarget, options ...CallPatternOption) CallPattern

JSONEncoderDeclareCall declares the annotation asking for the encoder alone.

func RequestBindCall added in v0.1.12

func RequestBindCall(target CallTarget, options ...CallPatternOption) CallPattern

RequestBindCall declares a request-model binding wrapper.

func ResponseWriteCall added in v0.1.12

func ResponseWriteCall(target CallTarget, options ...CallPatternOption) CallPattern

ResponseWriteCall declares a default-status response writer wrapper.

func ResponseWriteStatusCall added in v0.1.12

func ResponseWriteStatusCall(target CallTarget, options ...CallPatternOption) CallPattern

ResponseWriteStatusCall declares a response writer wrapper with a status role.

func RouteRegisterCall added in v0.1.12

func RouteRegisterCall(target CallTarget, options ...CallPatternOption) CallPattern

RouteRegisterCall declares an HTTP route registration wrapper.

func RowsScanCall added in v0.1.12

func RowsScanCall(target CallTarget, options ...CallPatternOption) CallPattern

RowsScanCall declares a SQL row scanner wrapper.

func SocketReceiveCall added in v0.5.4

func SocketReceiveCall(target CallTarget, options ...CallPatternOption) CallPattern

SocketReceiveCall declares the inbound half of a WebSocket entry. It is paired with SocketSendCall against the same target: the two type arguments run in opposite directions, so one pattern cannot stand for both.

func SocketSendCall added in v0.5.4

func SocketSendCall(target CallTarget, options ...CallPatternOption) CallPattern

SocketSendCall declares the outbound half of a WebSocket entry.

func StreamCreateCall added in v0.1.12

func StreamCreateCall(target CallTarget, options ...CallPatternOption) CallPattern

StreamCreateCall declares a streaming response constructor wrapper.

func TransportCall added in v0.4.9

func TransportCall(target CallTarget, options ...CallPatternOption) CallPattern

TransportCall declares a call that takes a transport value and yields no model. Discovery ignores it; the transform needs it, so that a handler calling one is not refused for making an ordinary runtime call.

type CallPatternOption added in v0.1.12

type CallPatternOption func(*CallPattern)

CallPatternOption adds one semantic role source to a CallPattern.

func Argument added in v0.1.12

func Argument(role string, index int) CallPatternOption

Argument reads a value role from a zero-based value argument index.

func ArgumentType added in v0.1.12

func ArgumentType(role string, index int) CallPatternOption

ArgumentType reads a type role from a zero-based value argument index.

func Constant added in v0.1.12

func Constant(role string, value any) CallPatternOption

Constant provides a fixed semantic value hidden by a wrapper.

func GenericType added in v0.1.12

func GenericType(role string, index int) CallPatternOption

GenericType reads a type role from a zero-based generic argument index.

func RequestArgument added in v0.4.9

func RequestArgument(index int) CallPatternOption

RequestArgument names the zero-based argument holding the request.

func WriterArgument added in v0.4.9

func WriterArgument(index int) CallPatternOption

WriterArgument names the zero-based argument holding the response writer. Declare it on any wrapper that takes one, so a single-value transport knows which argument disappears.

type CallRegistry added in v0.1.12

type CallRegistry struct {
	// contains filtered or unexported fields
}

CallRegistry accumulates framework wrapper declarations without global state.

func NewCallRegistry added in v0.1.12

func NewCallRegistry() *CallRegistry

NewCallRegistry creates an empty framework-local call registry.

func (*CallRegistry) Options added in v0.1.12

func (registry *CallRegistry) Options(base Options) (Options, error)

Options returns an immutable options snapshot containing defaults and wrappers.

func (*CallRegistry) Register added in v0.1.12

func (registry *CallRegistry) Register(patterns ...CallPattern) error

Register validates and adds call patterns.

type CallTarget added in v0.1.12

type CallTarget struct {
	Function *SymbolPattern
	Method   *MethodPattern
}

CallTarget identifies either a package function or a named-receiver method.

func Function added in v0.1.12

func Function(packagePath, name string) CallTarget

Function identifies a package function used as a generator call target.

func Method added in v0.1.12

func Method(packagePath, name, receiverPackagePath, receiverType string) CallTarget

Method identifies a method used as a generator call target.

type CheckRules

type CheckRules struct {
	Required bool
	Min      *float64
	Max      *float64
	MinLen   *int
	MaxLen   *int
	Len      *int
	Pattern  string
	Email    bool
	UUID     bool
	Date     bool
	Time     bool
	DateTime bool
}

CheckRules is the structured form of a field's check tag (codegen only).

func ParseCheckTag

func ParseCheckTag(raw, kind string) (CheckRules, error)

ParseCheckTag parses a check tag value for a field of the given Go kind. Invalid syntax, unknown rules, type mismatches, and invalid patterns fail here.

func (CheckRules) HasValidation added in v0.1.6

func (c CheckRules) HasValidation() bool

HasValidation reports whether the check rules can reject a bound value. Every check rule can; defaults live in DefaultRule precisely because they cannot. Enums can too, but are their own tag: see FieldPlan.HasValidation.

type Command added in v0.1.12

type Command struct {
	Name    string
	Summary string
	Run     func(context.Context, []string, CommandIO) int
}

Command is one independently testable subcommand.

func FormatCommand added in v0.3.1

func FormatCommand(options Options) Command

FormatCommand creates the tinybind fmt subcommand, per api:template-format-command. Everything it does is available as a library through templatefmt; this is the process boundary around it.

func GenerateCommand added in v0.1.12

func GenerateCommand(options Options) Command

GenerateCommand creates the tinybind generate subcommand.

type CommandIO added in v0.1.12

type CommandIO struct {
	Stdin            io.Reader
	Stdout           io.Writer
	Stderr           io.Writer
	WorkingDirectory string
	Environment      []string
}

CommandIO contains process state injected into a command execution.

type CommandSet added in v0.1.12

type CommandSet struct {
	// contains filtered or unexported fields
}

CommandSet is an immutable command dispatcher.

func MustCommandSet added in v0.1.12

func MustCommandSet(commands ...Command) CommandSet

MustCommandSet is NewCommandSet for process setup code and panics on invalid commands.

func NewCommandSet added in v0.1.12

func NewCommandSet(commands ...Command) (CommandSet, error)

NewCommandSet validates commands and constructs an immutable dispatcher.

func (CommandSet) Run added in v0.1.12

func (set CommandSet) Run(ctx context.Context, args []string, streams CommandIO) int

Run dispatches one command without reading process globals or terminating the process.

type ConfigBindBinding added in v0.1.5

type ConfigBindBinding struct {
	TypeName   string
	Prefix     string
	SubCommand bool
	Name       string
	Help       string
	// SourcePath is the Go file containing the discovered call.
	SourcePath string
}

ConfigBindBinding is one discovered configbind.Bind[T](prefix) call.

type ConfigBindSpec added in v0.1.13

type ConfigBindSpec struct {
	SourcePath string
	Spec       cbcg.Spec
}

ConfigBindSpec pairs one generated config definition with the source file whose call declared it.

func AnalyzeConfigBindSources added in v0.1.13

func AnalyzeConfigBindSources(dir string, options Options) (pkgName string, specs []ConfigBindSpec, err error)

AnalyzeConfigBindSources is AnalyzeConfigBindWithOptions with the owning source file retained for every discovered definition.

type DefaultRule added in v0.2.0

type DefaultRule struct {
	Value string
	Set   bool
}

DefaultRule is the parsed default tag of a field (codegen only). A default is not a constraint: it never rejects a value, it only fills in one that never arrived, which is why it lives outside the check tag.

func ParseDefaultTag added in v0.2.0

func ParseDefaultTag(raw, kind string) (DefaultRule, error)

ParseDefaultTag parses a default tag value for a field of the given Go kind. Callers pass only tags that are actually present, so default:"" stays distinguishable from a missing tag. Unsupported kinds and values that cannot be converted to the field type fail here.

type DiscoverySymbol

type DiscoverySymbol struct {
	PackagePath         string
	Name                string
	ReceiverPackagePath string
	ReceiverType        string
	Usage               Usage
	TypeArgument        int
	ArgumentType        *int
}

DiscoverySymbol identifies a generic function and the entry point it needs. PackagePath is matched by go/types identity, so import aliases are supported.

type Document

type Document map[string]any

Document is an OpenAPI 3.1 document represented as ordered JSON-friendly maps. Keys under paths/operations/components are sorted for deterministic output.

func BuildOpenAPI

func BuildOpenAPI(dir string) (Document, error)

BuildOpenAPI analyzes dir with the route parser and field planner and returns an OpenAPI 3.1 document derived only from Go source (not from handwritten YAML).

func (Document) JSON

func (d Document) JSON() ([]byte, error)

JSON is an alias for MarshalJSON bytes for callers.

func (Document) MarshalJSON

func (d Document) MarshalJSON() ([]byte, error)

MarshalJSON returns deterministic indented OpenAPI JSON.

type DynamoFieldPlan added in v0.2.8

type DynamoFieldPlan struct {
	Name      string
	Attribute string
	OmitEmpty bool
	// Key is "", "partition" or "sort".
	Key  string
	Type DynamoType
}

DynamoFieldPlan is one struct field and the attribute it maps to.

type DynamoItemPlan added in v0.2.8

type DynamoItemPlan struct {
	Name       string
	SourcePath string
	Doc        string
	Fields     []DynamoFieldPlan
	Usage      DynamoUsage
}

DynamoItemPlan is the item codec plan for one struct type.

func (DynamoItemPlan) PartitionKey added in v0.2.8

func (p DynamoItemPlan) PartitionKey() (DynamoFieldPlan, bool)

PartitionKey returns the partition key field, if the type declares one.

func (DynamoItemPlan) SortKey added in v0.2.8

func (p DynamoItemPlan) SortKey() (DynamoFieldPlan, bool)

SortKey returns the sort key field, if the type declares one.

type DynamoKind added in v0.2.8

type DynamoKind string

DynamoKind is how one Go type maps onto a DynamoDB attribute.

const (
	DynamoString    DynamoKind = "S"
	DynamoInt       DynamoKind = "N.int"
	DynamoUint      DynamoKind = "N.uint"
	DynamoFloat     DynamoKind = "N.float"
	DynamoBool      DynamoKind = "BOOL"
	DynamoBytes     DynamoKind = "B"
	DynamoTime      DynamoKind = "S.time"
	DynamoUnixTime  DynamoKind = "N.time"
	DynamoList      DynamoKind = "L"
	DynamoMap       DynamoKind = "M"
	DynamoStruct    DynamoKind = "M.struct"
	DynamoPointer   DynamoKind = "ptr"
	DynamoStringSet DynamoKind = "SS"
	DynamoNumberSet DynamoKind = "NS"
	DynamoBinarySet DynamoKind = "BS"
	// DynamoRaw is a dynamodb.AttributeValue field, stored as it stands. It is
	// the escape hatch for what the table above cannot express.
	DynamoRaw DynamoKind = "AV"
)

type DynamoOp added in v0.2.9

type DynamoOp = dynamobind.Op

DynamoOp is a key condition operator.

type DynamoPackagePlan added in v0.2.8

type DynamoPackagePlan struct {
	Package     string
	PackagePath string
	Items       []DynamoItemPlan
}

DynamoPackagePlan is every item plan in one package.

func AnalyzeDynamoItems added in v0.2.8

func AnalyzeDynamoItems(dir string) (*DynamoPackagePlan, error)

AnalyzeDynamoItems builds item plans for the types a package binds to DynamoDB, discovered from dynamobind call sites.

func AnalyzeDynamoItemsWithOptions added in v0.2.8

func AnalyzeDynamoItemsWithOptions(dir string, opts Options) (*DynamoPackagePlan, error)

AnalyzeDynamoItemsWithOptions is AnalyzeDynamoItems with custom discovery.

type DynamoPredicate added in v0.2.9

type DynamoPredicate = dynamobind.Predicate

DynamoPredicate is one comparison in a key clause.

type DynamoQueryDecl added in v0.2.9

type DynamoQueryDecl = dynamobind.QueryDecl

DynamoQueryDecl is one declared access pattern.

type DynamoQueryOptions added in v0.3.7

type DynamoQueryOptions struct {
	// ParameterAPI gives each function a leading dynamobind.Handle parameter.
	ParameterAPI bool
	// HandleResolver names a framework function answering a dynamobind.Handle
	// for one Context. ParameterAPI takes precedence over it.
	HandleResolver *SymbolPattern
	// LineDirectives maps each generated query function back to the declaration
	// that produced it, so a compile error and a runtime stack frame both name
	// the .tb.dynamo file.
	//
	// The mapping is per declaration and line only: a parsed declaration carries
	// a source path and a line and no column, so there is nothing finer to map.
	LineDirectives bool
	// OutputName is the base name of the Go file this output becomes, needed to
	// end a mapped span. Empty leaves the restore directives unresolved for a
	// caller that combines several results and calls
	// [ResolveTemplatePositions] on the combined file.
	OutputName string
}

DynamoQueryOptions selects which of the three client-supply modes the generated functions use. The zero value is the Context form, which is the default and what every run that sets nothing generates.

type DynamoQueryParam added in v0.2.9

type DynamoQueryParam = dynamobind.QueryParam

DynamoQueryParam is one declared parameter of a query function.

type DynamoQueryPlan added in v0.2.9

type DynamoQueryPlan struct {
	Decl DynamoQueryDecl
	// Item is the type the query decodes into.
	Item DynamoItemPlan
	// Expression is the KeyConditionExpression, written with aliases.
	Expression string
	// Names maps each alias to the attribute it stands for.
	Names map[string]string
	// Values pairs each ":v" placeholder with the parameter and attribute that
	// fill it, in emission order.
	Values []DynamoQueryValue
}

DynamoQueryPlan is one checked declaration, ready to emit. Every name in it has been matched against the bound type's tags, so the emitter looks nothing up.

type DynamoQueryValue added in v0.2.9

type DynamoQueryValue struct {
	Placeholder string
	Param       DynamoQueryParam
	Attribute   DynamoFieldPlan
}

DynamoQueryValue is one bound placeholder.

type DynamoResultShape added in v0.2.9

type DynamoResultShape = dynamobind.ResultShape

DynamoResultShape is what a declaration asks the generated function to return.

type DynamoType added in v0.2.8

type DynamoType struct {
	Kind DynamoKind
	// Go is the type as it must be written inside the generated package.
	Go string
	// Elem is the element of a slice, map or pointer.
	Elem *DynamoType
	// MapKey is the key type of a map attribute, written as the generated
	// package must spell it. DynamoDB map keys are strings, so it is always a
	// string-kinded type.
	MapKey string
	// Struct is the named struct type of a nested item, always declared in the
	// same package as its parent.
	Struct string
	// Bits is the width a number is parsed at: 8, 16, 32 or 64, and 0 for int
	// and uint, which strconv reads as the platform width. Parsing at the
	// field's own width turns a value it cannot hold into an error instead of a
	// silent wrap.
	Bits int
}

DynamoType describes one Go type in attribute terms.

type DynamoUsage added in v0.2.8

type DynamoUsage uint8

DynamoUsage selects which generated item methods a type needs.

const (
	// DynamoEncode emits EncodeItem.
	DynamoEncode DynamoUsage = 1 << iota
	// DynamoDecode emits DecodeItem.
	DynamoDecode
	// DynamoKey emits ItemKey and the table definition.
	DynamoKey
)

type EnumRule added in v0.2.0

type EnumRule struct {
	Values []string
	Set    bool
}

EnumRule is the parsed enum tag of a field (codegen only). Unlike a default, an enum can reject a value, so it counts as validation; it lives outside the check tag only because config structs already spell it this way.

func ParseEnumTag added in v0.2.0

func ParseEnumTag(raw, kind string) (EnumRule, error)

ParseEnumTag parses an enum tag value for a field of the given Go kind. Values are comma-separated, which means a value cannot contain a comma — the same limit the check tag had, where commas separated rules.

type Feature

type Feature string

Feature identifies a generator capability that can be permanently disabled.

const (
	FeatureRouteDiscovery Feature = "route-discovery"
	FeatureOpenAPI        Feature = "openapi"
	FeatureBind           Feature = "bind"
	FeatureWrite          Feature = "write"
	FeatureWriteStatus    Feature = "write-status"
	FeatureDecodeJSON     Feature = "decode-json"
	FeatureEncodeJSON     Feature = "encode-json"
	FeatureStreaming      Feature = "streaming"
	FeatureWebSocket      Feature = "websocket"
	FeatureScanRows       Feature = "scan-rows"
	FeatureMultipartFile  Feature = "multipart-file"
	// FeatureItemCodec turns off DynamoDB item codec generation entirely.
	FeatureItemCodec Feature = "item-codec"
	// FeatureItemTable turns off only the generated table definition, leaving
	// the codec and the key builder in place. Emitting it is the default,
	// because it is what makes a key name single-source; a project that manages
	// tables with IaC and never creates one in Go can drop it.
	FeatureItemTable Feature = "item-table"
	// FeatureEntityCodec turns off Firestore entity codec generation entirely.
	FeatureEntityCodec Feature = "entity-codec"
	// FeatureCBORArrayCodec and FeatureCBORMapCodec turn off one CBOR container
	// shape. They are two features rather than one because a project may want
	// the evolvable shape and not the compact one, and each direction is its
	// own pattern under them.
	FeatureCBORArrayCodec Feature = "cbor-array-codec"
	FeatureCBORMapCodec   Feature = "cbor-map-codec"
	// FeatureCacheKey turns off cache key generation entirely.
	FeatureCacheKey Feature = "cache-key"
	// FeatureHelpBackfill writes help tags derived from godoc into config
	// structs. Disable it to keep hand-written sources untouched.
	FeatureHelpBackfill Feature = "help-backfill"
)

type FieldPlan

type FieldPlan struct {
	Name      string      // Go field name
	Wire      string      // wire / tag name ("*" for payload rest)
	Source    FieldSource // input|query|payload|path|header|cookie|method
	Kind      string      // string|int|int64|bool|float64|file|rest_*|struct|slice|map
	JSON      string      // json name for encode/document keys
	JSONSkip  bool        // json:"-": the JSON codec neither writes nor reads it
	OmitEmpty bool        // json:",omitempty": skip when it would encode as "", [] or {}
	OmitZero  bool        // json:",omitzero": skip when the field holds the Go zero value
	Check     CheckRules  // from check:"" tag; empty if absent
	Enum      EnumRule    // from enum:"" tag; unset if absent
	Default   DefaultRule // from default:"" tag; unset if absent
	TypeName  string      // KindStruct name, or element struct name for slice/map of struct
	// Named is the declared type of a field whose Kind was resolved from that
	// type's underlying kind, such as UserID for a named string. It is empty
	// for a field written as a predeclared type.
	//
	// Generated code converts across it in both directions, because the codec
	// works in the underlying kind and the field is declared in the named one.
	Named string
	// Foreign is which codec halves a KindForeign field's type carries. It is
	// the zero value for every other kind.
	Foreign  ForeignCodec
	ElemKind string // for slice/array/map: string|int|int64|bool|float64|struct
	// ElemNamed is the declared type of a collection element whose ElemKind was
	// resolved from that type's underlying kind, such as Mark for a []Mark over
	// uint. It is the element's half of Named, and empty when the element is
	// written as a predeclared type.
	ElemNamed string
	// ArrayLen is a KindArray field's length exactly as it was written, so a
	// generated type spells [boardSize]Cell the way the source did rather than
	// resolving the constant behind the author's back. It is empty for every
	// other kind.
	ArrayLen string
	DB       string // SQL result column (db tag or snake_case field name)
	GroupKey bool   // groupkey tag presence
	Doc      string // godoc of the field (doc or line comment)
}

FieldPlan is one struct field mapping plan (compile-time).

func (FieldPlan) BindsFromString added in v0.5.24

func (f FieldPlan) BindsFromString() bool

BindsFromString reports a field a query, path, header or cookie value can fill: every scalar, plus a byte sequence, which is the one composite that has a string form.

func (FieldPlan) BindsRepeatedFromQuery added in v0.5.26

func (f FieldPlan) BindsRepeatedFromQuery() bool

BindsRepeatedFromQuery reports a field one repeated query key fills: a slice of scalars. A URL carries a key many times natively and an urlencoded form submits a checkbox group exactly that way, so this is the one composite besides a byte sequence that a query string has a spelling for.

A slice of struct is not one: an object still needs a document.

func (FieldPlan) BytesRead added in v0.5.24

func (f FieldPlan) BytesRead(expr string) string

BytesRead renders a KindBytes field as the []byte every helper takes, which for a fixed-length field means slicing it.

func (FieldPlan) ElemGoType added in v0.5.24

func (f FieldPlan) ElemGoType() string

ElemGoType is the Go type of one element, as generated code has to spell it.

func (FieldPlan) ElemPlan added in v0.5.24

func (f FieldPlan) ElemPlan() FieldPlan

ElemPlan is the collection element as a field of its own, which is what lets the scalar emitters serve an element without knowing they are inside a collection. It carries the element's declared name, so the conversions Read and Write spell for a named field are the same ones an element gets.

func (FieldPlan) GoType

func (f FieldPlan) GoType() string

GoType returns a Go type string for generated code (e.g. NestedCustomer, []string).

func (FieldPlan) HasValidation added in v0.2.0

func (f FieldPlan) HasValidation() bool

HasValidation reports whether anything about the field can reject a bound value, across every tag that carries a constraint.

func (FieldPlan) IsComposite

func (f FieldPlan) IsComposite() bool

IsComposite reports nested struct/slice/map kinds.

A foreign field counts, because it is read from the document body through a raw sub-slice exactly as a nested struct is, and never from the query.

func (FieldPlan) IsFixedBytes added in v0.5.24

func (f FieldPlan) IsFixedBytes() bool

IsFixedBytes reports a KindBytes field declared as [N]byte rather than []byte, which is the one thing the two spellings decode differently.

func (FieldPlan) IsRest

func (f FieldPlan) IsRest() bool

IsRest reports whether f is a payload rest map field.

func (FieldPlan) NeedsPresence added in v0.2.0

func (f FieldPlan) NeedsPresence() bool

NeedsPresence is true when codegen must track whether the field was present: validation has to skip absent optional values, and a default only applies to a field nobody supplied.

func (FieldPlan) Read added in v0.5.10

func (f FieldPlan) Read(expr string) string

Read renders an expression yielding the field's value in its underlying kind, so a codec working in that kind can consume it.

A field declared as a predeclared type reads as itself; one declared as a named type is converted, because Go has no implicit conversion between the two and generated code that omitted it would not compile.

func (FieldPlan) Write added in v0.5.10

func (f FieldPlan) Write(expr string) string

Write renders an expression converting a value of the underlying kind back to the field's declared type, for the assigning direction.

type FieldSource

type FieldSource string

FieldSource is where a request field is read from.

const (
	SourceInput   FieldSource = "input"
	SourceQuery   FieldSource = "query"
	SourcePayload FieldSource = "payload"
	SourcePath    FieldSource = "path"
	SourceHeader  FieldSource = "header"
	SourceCookie  FieldSource = "cookie"
	SourceMethod  FieldSource = "method"
)

type FirestoreBound added in v0.3.6

type FirestoreBound = firestorebind.Bound

FirestoreBound is a limit or an offset.

type FirestoreCondition added in v0.3.6

type FirestoreCondition = firestorebind.Condition

FirestoreCondition is one node of a where clause.

type FirestoreDirection added in v0.3.6

type FirestoreDirection = firestorebind.Direction

FirestoreDirection is a sort direction.

type FirestoreEntityPlan added in v0.3.6

type FirestoreEntityPlan struct {
	Name       string
	Kind       string
	SourcePath string
	Fields     []FirestoreFieldPlan
	Usage      FirestoreUsage
}

FirestoreEntityPlan is the entity codec plan for one struct type.

func (FirestoreEntityPlan) Expiry added in v0.3.6

Expiry returns the field a TTL policy is meant to expire this kind by. It changes nothing about how the property is written; it is declared so a deployment can be told which property to point a policy at.

func (FirestoreEntityPlan) Identity added in v0.3.6

Identity returns the field that supplies the key's name or id.

func (FirestoreEntityPlan) Parent added in v0.3.6

Parent returns the field that supplies the ancestor path.

func (FirestoreEntityPlan) Properties added in v0.3.6

func (p FirestoreEntityPlan) Properties() []FirestoreFieldPlan

Properties returns the fields that become entity properties, which excludes the identity fields the key carries instead.

func (FirestoreEntityPlan) Version added in v0.3.6

Version returns the field that receives Entity.Version.

type FirestoreFieldPlan added in v0.3.6

type FirestoreFieldPlan struct {
	Name     string
	Property string
	// Role is "", "name", "id", "parent", "version" or "ttl". A field with a
	// role other than "", "version" and "ttl" carries identity rather than a
	// property; a ttl field is an ordinary property that a policy also reads.
	Role      string
	OmitEmpty bool
	NoIndex   bool
	// Stored reports whether the field also becomes a property. It is false for
	// an identity field unless the tag gave it a real property name.
	Stored bool
	Type   FirestoreType
}

FirestoreFieldPlan is one struct field and the property it maps to.

type FirestoreIndexProperty added in v0.3.6

type FirestoreIndexProperty = firestorebind.IndexProperty

FirestoreIndexProperty is one property of a declared composite index.

type FirestoreJunction added in v0.3.6

type FirestoreJunction = firestorebind.Junction

FirestoreJunction is how a condition joins its operands.

type FirestoreKind added in v0.3.6

type FirestoreKind string

FirestoreKind is how one Go type maps onto a Datastore property value.

const (
	FirestoreString  FirestoreKind = "string"
	FirestoreInt     FirestoreKind = "integer.int"
	FirestoreUint    FirestoreKind = "integer.uint"
	FirestoreDouble  FirestoreKind = "double"
	FirestoreBool    FirestoreKind = "boolean"
	FirestoreBlob    FirestoreKind = "blob"
	FirestoreTime    FirestoreKind = "timestamp"
	FirestoreKeyRef  FirestoreKind = "key"
	FirestoreGeo     FirestoreKind = "geoPoint"
	FirestoreArray   FirestoreKind = "array"
	FirestoreStruct  FirestoreKind = "entity"
	FirestorePointer FirestoreKind = "ptr"
	// FirestoreRaw is a datastore.Value field, stored as it stands. It is the
	// escape hatch for what the table above cannot express, including the
	// dynamic property names a map would have needed.
	FirestoreRaw FirestoreKind = "value"
)

type FirestoreOp added in v0.3.6

type FirestoreOp = firestorebind.Op

FirestoreOp is a property filter comparison.

type FirestoreOrder added in v0.3.6

type FirestoreOrder = firestorebind.Order

FirestoreOrder is one sort key of an order clause.

type FirestorePackagePlan added in v0.3.6

type FirestorePackagePlan struct {
	Package     string
	PackagePath string
	Entities    []FirestoreEntityPlan
}

FirestorePackagePlan is every entity plan in one package.

func AnalyzeFirestoreEntities added in v0.3.6

func AnalyzeFirestoreEntities(dir string) (*FirestorePackagePlan, error)

AnalyzeFirestoreEntities builds entity plans for the types a package binds to Firestore, discovered from firestorebind call sites.

func AnalyzeFirestoreEntitiesWithOptions added in v0.3.6

func AnalyzeFirestoreEntitiesWithOptions(dir string, opts Options) (*FirestorePackagePlan, error)

AnalyzeFirestoreEntitiesWithOptions is AnalyzeFirestoreEntities with custom discovery.

type FirestorePredicate added in v0.3.6

type FirestorePredicate = firestorebind.Predicate

FirestorePredicate is one comparison in a where clause.

type FirestoreProjection added in v0.3.6

type FirestoreProjection = firestorebind.Projection

FirestoreProjection is one property a select or distinct clause names.

type FirestoreQueryDecl added in v0.3.6

type FirestoreQueryDecl = firestorebind.QueryDecl

FirestoreQueryDecl is one declared access pattern.

type FirestoreQueryFilter added in v0.3.6

type FirestoreQueryFilter struct {
	Predicate FirestorePredicate
	Field     FirestoreFieldPlan
	Param     FirestoreQueryParam
}

FirestoreQueryFilter is one checked predicate.

type FirestoreQueryOptions added in v0.3.7

type FirestoreQueryOptions struct {
	// ParameterAPI gives each function a leading firestorebind.Handle parameter.
	ParameterAPI bool
	// HandleResolver names a framework function answering a firestorebind.Handle
	// for one Context. ParameterAPI takes precedence over it.
	HandleResolver *SymbolPattern
	// LineDirectives maps each generated query function back to the declaration
	// that produced it, on the same terms as [DynamoQueryOptions.LineDirectives]:
	// per declaration and line only, because that is all a parsed declaration
	// carries.
	LineDirectives bool
	// OutputName is the base name of the Go file this output becomes, needed to
	// end a mapped span. Empty leaves the restore directives unresolved for a
	// caller that combines several results and calls
	// [ResolveTemplatePositions] on the combined file.
	OutputName string
}

FirestoreQueryOptions selects which of the three client-supply modes the generated functions use. The zero value is the Context form, which is the default and what every run that sets nothing generates.

The transactional twin takes a *firestorebind.Tx, which already carries the client and the tenancy, so no mode changes it.

type FirestoreQueryOrder added in v0.3.6

type FirestoreQueryOrder struct {
	Order FirestoreOrder
	Field FirestoreFieldPlan
}

FirestoreQueryOrder is one checked sort key.

type FirestoreQueryParam added in v0.3.6

type FirestoreQueryParam = firestorebind.QueryParam

FirestoreQueryParam is one declared parameter of a query function.

type FirestoreQueryPlan added in v0.3.6

type FirestoreQueryPlan struct {
	Decl FirestoreQueryDecl
	// Entity is the type the query decodes into, and whose Kind the query runs
	// against.
	Entity FirestoreEntityPlan
	// Filters pairs each predicate with the field it names and the parameter
	// that fills it, in the order the source wrote them.
	Filters []FirestoreQueryFilter
	// Where is the checked filter tree, or nil when there is no where clause.
	// Filters is its leaves; the tree is what the emitter walks when the
	// declaration uses or.
	Where *FirestoreCondition
	// HasOr reports whether the tree needs datastore.Where at all. Without it
	// the emitter keeps to the per-predicate Filter calls it always wrote.
	HasOr bool
	// Orders are the checked sort keys.
	Orders []FirestoreQueryOrder
	// Ancestor is the parameter holding the ancestor key, or "".
	Ancestor string
	// Select and Distinct are the checked property names, resolved to what the
	// tags call them.
	Select   []string
	Distinct []string
	// ProjectsAnArray reports whether any projected property is a slice, which
	// makes the service return one result per element rather than one per
	// entity. The godoc says so; nothing here can prevent it.
	ProjectsAnArray bool
	// Start and End are the parameters holding the cursors.
	Start string
	End   string
}

FirestoreQueryPlan is one checked declaration, ready to emit. Every name in it has been matched against the bound type's tags, so the emitter looks nothing up.

type FirestoreResultShape added in v0.3.6

type FirestoreResultShape = firestorebind.ResultShape

FirestoreResultShape is what a declaration asks the generated function to return.

type FirestoreType added in v0.3.6

type FirestoreType struct {
	Kind FirestoreKind
	// Go is the type as it must be written inside the generated package.
	Go string
	// Elem is the element of a slice or pointer.
	Elem *FirestoreType
	// Struct is the named struct type of a nested entity, always declared in the
	// same package as its parent.
	Struct string
	// Bits is the width a number is parsed at: 8, 16, 32 or 64, and 0 for int
	// and uint, which strconv reads as the platform width.
	Bits int
}

FirestoreType describes one Go type in property terms.

type FirestoreUsage added in v0.3.6

type FirestoreUsage uint8

FirestoreUsage selects which generated entity methods a type needs.

const (
	// FirestoreEncode emits EncodeEntity.
	FirestoreEncode FirestoreUsage = 1 << iota
	// FirestoreDecode emits DecodeEntity.
	FirestoreDecode
	// FirestoreKey emits EntityKey.
	FirestoreKey
)

type ForeignCodec added in v0.5.10

type ForeignCodec struct {
	// Append is AppendJSONTo on the value, so the field can be encoded.
	Append bool
	// Decode is DecodeJSONFrom on the pointer, so the field can be read.
	Decode bool
}

ForeignCodec records which halves of the jsonbind codec contract a foreign field's type carries.

A type carrying one half is usable in that direction alone. Which halves a field needs is a property of its parent's usage, which is not known while the field is being admitted, so both are recorded and the requirement is checked at emission by checkForeignFieldDirections.

func (ForeignCodec) Any added in v0.5.10

func (c ForeignCodec) Any() bool

Any reports whether either half is present, which is what admits the field at all.

type GenerateRequest added in v0.1.12

type GenerateRequest struct {
	Dir           string
	Out           string
	Name          string
	OpenAPI       bool
	OpenAPIName   string
	TemplatesName string
	// HTMLTemplatePattern and SQLTemplatePattern override template discovery
	// globs. Empty values retain the generator options.
	HTMLTemplatePattern string
	SQLTemplatePattern  string
	// SQLDialect overrides the generator option for this run. An empty value
	// retains it.
	SQLDialect     string
	ConfigBindName string
	// TransportName is the generated transport output file. Empty uses the
	// default; it is written only when Options.Transform selects a backend.
	TransportName string
	// FastBindersName is the selected backend's binder and writer output file.
	FastBindersName string
	// RoutesName is the selected backend's route registration output file.
	RoutesName string
	// DynamoName is the DynamoDB item codec output file.
	DynamoName string
	// DynamoQueryName is the generated DynamoDB query output file.
	DynamoQueryName string
	// FirestoreName is the Firestore entity codec output file.
	FirestoreName string
	// FirestoreQueryName is the generated Firestore query output file.
	FirestoreQueryName string
	// CacheKeyName is the generated cache key output file.
	CacheKeyName string
	// PublicDir and PublicURLBase override where extracted static assets are
	// written and how they are referenced. Empty values retain the generator
	// options; setting one requires setting the other.
	PublicDir     string
	PublicURLBase string
	Check         bool
	GenerateAll   bool
	// Force regenerates even when the generated files record the current input
	// hash. Use it after a change the hash does not cover, such as an edit in
	// another package of the module.
	Force         bool
	SQLContextAPI bool
	// SQLContextOnlyAPI enables the context-only SQL API for this run. It can
	// turn the option on, never off.
	SQLContextOnlyAPI bool
	// DynamoParameterAPI and FirestoreParameterAPI put the runtime Handle in
	// each generated query's signature for this run. Like the SQL switches they
	// can turn the option on, never off.
	DynamoParameterAPI    bool
	FirestoreParameterAPI bool

	// Packages supplies the type-checked package for Dir out of a load the
	// caller already performed with LoadPackages, so a caller generating many
	// directories checks the dependencies they share once instead of once per
	// directory. A nil set, or a set not covering Dir, loads the directory
	// here, which is what every run did before there was a set.
	//
	// GenerateArtifacts and GenerateArtifactsWithRoutes read it. GeneratePackage
	// does not, and cannot: it writes the generated templates into the directory
	// and then type-checks the package they have joined, so the tree it analyzes
	// is by construction not the tree any set was built from.
	Packages *PackageSet
}

GenerateRequest configures one package-local generation execution.

type GenerateResult added in v0.1.12

type GenerateResult struct {
	BinderPath         string
	ConfigBindPath     string
	DynamoPath         string
	DynamoQueryPath    string
	FirestorePath      string
	FirestoreQueryPath string
	CacheKeyPath       string
	OpenAPIPath        string
	TemplatesPath      string
	// AssetPaths holds the static files extracted from component style and
	// script blocks, then the files reference hook conversions produced, in
	// generation order.
	AssetPaths []string
	// Rewrites reports what the reference hooks did, including what they
	// declined and why. An author cannot see a build-time rewrite by reading
	// the template, so the build is the only place it is visible.
	//
	// It reports rather than interprets: whether a converted file is small
	// enough is the caller's judgment, and a caller measuring sizes owns its
	// own transform and can measure inside it.
	Rewrites []htmlbind.Rewrite
	// ReadSet holds every authored file the run depended on through a hook: the
	// sources each cache key named, plus whatever each transform reported
	// reading beyond them, sorted. A transform that under-reports produces a
	// stale output on the next run, which is the one correctness property this
	// package cannot verify for the caller.
	ReadSet []string
	// DynamicReferences are the attributes a hook was registered for whose
	// value is a template expression, and so could not be rewritten.
	DynamicReferences []htmlbind.DynamicReference
	// DepsPath is the recorded read set, written only when a transform reported
	// reading something. The next run verifies it before trusting its own skip,
	// because a file read by a transform is not otherwise a hashed input.
	DepsPath string
	// TransportPath is the derived other-transport source, written only when a
	// backend is selected.
	TransportPath string
	// FastBindersPath is the selected backend's binders and writers.
	FastBindersPath string
	// RoutesPath is the selected backend's route registration.
	RoutesPath string
	// LayoutWarnings name authored files a build tag cannot cleanly exclude,
	// because they hold transport handlers beside declarations both builds need.
	LayoutWarnings []string
	Diagnostics    []parser.Diagnostic
	// Routes is the run's route analysis: resolved registrations with their
	// sites, plus unresolved route-like sites as diagnostics. It is nil on
	// Check, report-only, and Cached results, which run no fresh analysis.
	Routes *parser.Result
	// Cached reports that the paths were left untouched because the generated
	// files already record the current input hash.
	Cached bool
}

GenerateResult records generated artifacts or check diagnostics.

func (GenerateResult) Paths added in v0.1.12

func (result GenerateResult) Paths() []string

Paths returns non-empty artifact paths in generation order.

type Generator

type Generator struct{ Options Options }

Generator is a reusable, configurable code generator.

A *Generator is safe for concurrent use over distinct directories. It holds the run's options and no run state: each call derives everything it needs from the directory it was handed, so generation stays a pure function of a directory and scheduling cannot change what comes out. A caller generating a tree of packages may therefore run its directories at once.

Loading is what that concurrency overlaps, and LoadPackages is what removes it: a caller with a set of directories to generate can type-check them together and hand each generation its package through GenerateRequest.

Two obligations stay with the caller, because only the caller can meet them. A ReferenceHook or ContentHook registered in Options is called from several goroutines at once, so it must be safe for concurrent use in the sense ConversionWorkers describes. And the help backfill rewrites the hand-written sources of the package it generates. That write is atomic, so no reader can catch the file half-written, but what a reader sees still depends on whether it has happened: a package binding a config type another package declares reads that type's tags, and the backfill is what puts them there. Generate a directory declaring config before, rather than beside, the directories that import it - or turn FeatureHelpBackfill off, which removes the write.

func New

func New(opts Options) *Generator

New constructs a usage-directed generator. Set GenerateAll for legacy output.

func (*Generator) Analyze

func (g *Generator) Analyze(dir string) (*PackagePlan, error)

Analyze analyzes a package using this generator's discovery symbols.

func (*Generator) BuildOpenAPI

func (g *Generator) BuildOpenAPI(dir string) (Document, error)

BuildOpenAPI builds a document using this generator's discovery identities.

func (*Generator) EmitDynamoQueriesFor added in v0.2.9

func (g *Generator) EmitDynamoQueriesFor(dir string) ([]byte, error)

EmitDynamoQueriesFor analyzes dir and returns the generated query source without writing it, which is what a check needs.

func (*Generator) EmitFirestoreQueriesFor added in v0.3.6

func (g *Generator) EmitFirestoreQueriesFor(dir string) ([]byte, error)

EmitFirestoreQueriesFor analyzes dir and returns the generated query source without writing it, which is what a check needs.

func (*Generator) Generate

func (g *Generator) Generate(dir, outDir, outName string) (string, error)

Generate analyzes dir and writes generated source.

func (*Generator) GenerateArtifacts added in v0.1.13

func (g *Generator) GenerateArtifacts(ctx context.Context, request GenerateRequest) ([]Artifact, error)

GenerateArtifacts runs every enabled generation phase and returns the result as per-source artifacts. It writes no file, so the same call serves both generation and --check.

func (*Generator) GenerateArtifactsWithRoutes added in v0.5.18

func (g *Generator) GenerateArtifactsWithRoutes(ctx context.Context, request GenerateRequest) ([]Artifact, *parser.Result, error)

GenerateArtifactsWithRoutes is GenerateArtifacts plus the route analysis the run performed: resolved registrations with their sites, and unresolved route-like sites as diagnostics. The run parses once and every phase reads that result, so asking for it adds no second analysis; when no phase needed routes the parse happens for the return value alone. Like GenerateArtifacts it writes no file.

func (*Generator) GenerateCacheKeys added in v0.5.9

func (g *Generator) GenerateCacheKeys(dir, outDir, outName string) (string, error)

GenerateCacheKeys analyzes dir and writes the cache key methods. It returns "" when the package uses no type as a cache key.

func (*Generator) GenerateConfigBind added in v0.1.5

func (g *Generator) GenerateConfigBind(dir, outDir, outName string) (string, error)

GenerateConfigBind analyzes dir for configbind.Bind usage and writes configbind_gen.go. Returns the absolute path written, or "" if no Bind calls found.

func (*Generator) GenerateDynamoItems added in v0.2.8

func (g *Generator) GenerateDynamoItems(dir, outDir, outName string) (string, error)

GenerateDynamoItems analyzes dir and writes the DynamoDB item codec. It returns "" when the package binds no type to DynamoDB.

func (*Generator) GenerateDynamoQueries added in v0.2.9

func (g *Generator) GenerateDynamoQueries(dir, outDir, outName string) (string, error)

GenerateDynamoQueries analyzes dir and writes the generated query functions. It returns "" when the package declares none.

func (*Generator) GenerateFirestoreEntities added in v0.3.6

func (g *Generator) GenerateFirestoreEntities(dir, outDir, outName string) (string, error)

GenerateFirestoreEntities analyzes dir and writes the Firestore entity codec. It returns "" when the package binds no type to Firestore.

func (*Generator) GenerateFirestoreQueries added in v0.3.6

func (g *Generator) GenerateFirestoreQueries(dir, outDir, outName string) (string, error)

GenerateFirestoreQueries analyzes dir and writes the generated query functions. It returns "" when the package declares none.

func (*Generator) GenerateOpenAPI

func (g *Generator) GenerateOpenAPI(dir, outDir, outName string) (string, error)

GenerateOpenAPI writes OpenAPI generated with this generator's identities.

func (*Generator) GeneratePackage added in v0.1.12

func (g *Generator) GeneratePackage(ctx context.Context, request GenerateRequest) (GenerateResult, error)

GeneratePackage executes every enabled generator phase without CLI or process ownership.

func (*Generator) GenerateTemplates added in v0.1.5

func (g *Generator) GenerateTemplates(dir, outDir, outName string) (string, error)

GenerateTemplates discovers files using the configured template patterns and writes one Go file containing all generated declarations, plus the static files extracted from component style and script blocks. It returns an empty path when no templates exist.

type MethodPattern

type MethodPattern struct {
	PackagePath         string
	Name                string
	ReceiverPackagePath string
	ReceiverType        string
}

MethodPattern identifies a method and its receiver type.

type NamedKind added in v0.5.10

type NamedKind struct {
	// Kind is the bind kind the underlying type supports: one of the scalar
	// names, or KindStruct. Empty means the underlying type is one this
	// generator cannot place.
	Kind string
	// Underlying is the underlying type as written, for the diagnostic that
	// reports a type nothing can be done with.
	Underlying string
	// Declared is the name generated code spells for this field's type: the
	// name of the *types.Named the identifier resolves to once every alias
	// layer is peeled away. It is "" when nothing resolves to a same-package
	// *types.Named at all -- a predeclared scalar, or an alias of one -- which
	// is what lets such a field read and write with no conversion at all,
	// identical to declaring it with the predeclared type directly.
	Declared string
	// ForeignPackage is the import path an alias resolved into when it is not
	// this package's own. Set only when Kind and Underlying are both unset:
	// this package's run is the only thing that will ever generate a
	// decode<Name>JSON, so a struct declared elsewhere cannot be planned here,
	// and neither can a scalar whose identity this generator would have to
	// spell with an import it does not manage.
	ForeignPackage string
}

NamedKind is what a same-package named type resolves to underneath.

A named type is not a struct just because it is not a predeclared scalar, which is what the field analysis assumed before this: it mapped every same-package identifier to a nested struct, and a named scalar then had a codec named for it that nothing emitted, because only struct declarations enter the plan.

type Options

type Options struct {
	ServeMuxes      PatternSet[TypePattern]
	RouteMethods    PatternSet[MethodPattern]
	RouteFunctions  PatternSet[SymbolPattern]
	RuntimePackages PatternSet[string]
	Calls           PatternSet[CallPattern]
	FileTypes       PatternSet[TypePattern]
	// HTMLTemplatePattern and SQLTemplatePattern are filepath.Match patterns
	// applied to file base names. Empty values use the standard patterns.
	HTMLTemplatePattern string
	SQLTemplatePattern  string
	// DynamoTemplatePattern is the base-name glob for DynamoDB query
	// declarations. An empty value uses DefaultDynamoTemplatePattern.
	DynamoTemplatePattern string
	// FirestoreTemplatePattern is the base-name glob for Firestore query
	// declarations. An empty value uses DefaultFirestoreTemplatePattern.
	FirestoreTemplatePattern string
	// SQLDialect names the target database for SQL templates: "postgresql",
	// "mysql", or "sqlite". A run that discovers a SQL template must set it.
	// There is no default, because an assumed dialect emits placeholders the
	// target engine rejects, and nothing about the templates reveals the
	// mistake.
	SQLDialect string
	// SQLContextAPI adds Context-resolved wrappers for exported SQL templates.
	SQLContextAPI bool
	// SQLContextOnlyAPI publishes only the Context-resolved SQL surface under
	// the name declared in the template. The executor-taking function becomes
	// unexported and no <Component>Context wrapper is generated. It implies
	// SQLContextAPI.
	SQLContextOnlyAPI bool
	// SQLExecutorResolver selects a framework-specific Context resolver and
	// implies SQLContextAPI. Nil uses sqlbind.SQLExecutorFromContext.
	SQLExecutorResolver *SymbolPattern
	// DynamoParameterAPI gives every generated DynamoDB query a leading
	// dynamobind.Handle parameter instead of resolving one from the Context.
	// The declared name is unchanged; only the signature moves. False keeps the
	// Context form, which is the default and what every existing run generates.
	DynamoParameterAPI bool
	// DynamoHandleResolver selects a framework function that answers a
	// dynamobind.Handle for one Context, so generated code reads the
	// framework's own Context value instead of the one dynamobind installs.
	// It is how a framework carrying every value it manages in one struct
	// serves generated queries with a single lookup.
	//
	// The signature is func(context.Context) (dynamobind.Handle, error). Nil
	// uses dynamobind's own Context key. DynamoParameterAPI takes precedence:
	// a signature that already carries the Handle resolves nothing.
	DynamoHandleResolver *SymbolPattern
	// FirestoreParameterAPI is DynamoParameterAPI for Firestore queries,
	// giving each a leading firestorebind.Handle parameter.
	FirestoreParameterAPI bool
	// FirestoreHandleResolver is DynamoHandleResolver for Firestore queries.
	// The signature is func(context.Context) (firestorebind.Handle, error).
	FirestoreHandleResolver *SymbolPattern
	// DataAttributePrefix names the data attributes generated HTML uses for
	// partial update boundaries. Empty uses the standard prefix. A project
	// overriding it must use a browser runtime built for the same prefix,
	// because the runtime hardcodes it rather than discovering it.
	DataAttributePrefix string
	// Transform selects the source transform and names its target backend. Nil
	// generates the authored net/http backend alone, which is the default and
	// what keeps a run predating this feature byte-identical.
	//
	// Set it to DefaultTransformOptions() for the fasthttp backend this module
	// ships, or to a value carrying your own ImportRewrites for a framework
	// providing the same helper names over the other transport.
	Transform *TransformOptions

	// GeneratedHeaders names header prefixes, beside this module's own, whose
	// files every discovery pass must skip. A framework generating with tinybind
	// and branding its output writes a header nothing here recognizes on its own,
	// and an unrecognized generated registry is analyzed as if a user had written
	// it: its page registrations become routes, and an HTML page enters an OpenAPI
	// document. Each entry still requires the conventional "DO NOT EDIT." ending.
	GeneratedHeaders []string
	// PreserveTemplateWhitespace keeps the authoring indentation and newlines of
	// HTML templates in generated static output instead of collapsing each run
	// to one space. The default collapses, which renders identically and drops
	// every indentation byte from the generated source and the binary.
	PreserveTemplateWhitespace bool
	// TemplateLineDirectives maps generated template code back to the template
	// line that produced it, with Go //line directives. A compile error in a
	// template expression then names the .tb.html or .tb.sql file, and a panic
	// inside a generated SQL statement function names it in the stack frame.
	//
	// It is off by default, because turning it on rewrites every generated file
	// carrying a template and makes a covered test run report lines that do not
	// exist in the file it names. See requirement:template-source-positions and
	// rule:line-directive-emission.
	TemplateLineDirectives bool

	// PublicDir is the filesystem directory receiving the static files
	// extracted from component style and script blocks. Empty uses
	// DefaultPublicDir.
	PublicDir string
	// PublicURLBase is the URL prefix under which those files are served. It is
	// either an absolute URL path or a full URL, and is used verbatim either
	// way, so a CDN base changes the reference and nothing else. Empty uses
	// DefaultPublicURLBase.
	//
	// Neither option is derived from the other, and setting one explicitly
	// requires setting the other.
	PublicURLBase string

	// ReferenceHooks rewrite the static values of the attributes they are
	// registered for, at generation time, and declare the conversions those
	// rewrites depend on. They are how a build converts a file a template points
	// at, such as an image to a modern format or a TypeScript entry point to
	// JavaScript.
	//
	// A hook converts and returns the bytes, so the rewrite may depend on how
	// the conversion turned out; an encode larger than its source is worth
	// declining, and only the converted bytes can say so.
	ReferenceHooks []htmlbind.ReferenceHook
	// ContentHooks compile the component script blocks whose lang attribute
	// they claim. A block marked lang="ts" reaches the browser as JavaScript
	// through the transform registered here, so the compiler is this command's
	// dependency and never the module's.
	ContentHooks []htmlbind.ContentHook
	// ImplicitBindings are the names an embedder puts in every HTML template's
	// scope, so an application does not thread a framework value through every
	// component and every layout in a chain.
	//
	// They reach every compile path this command drives. That is a
	// checklist item rather than a consequence: the same field on the
	// context-external seam once reached one path and not the other, which
	// shipped a feature that was simply absent on filesystem routes. See
	// .knowledge requirement:route-package-context-externals.
	ImplicitBindings []htmlbind.ImplicitBinding
	// Messages maps a resolved message id to the Go symbol it calls, and
	// MessageContextBinding names the ImplicitBindings entry supplying those
	// symbols' leading argument.
	//
	// The mapping is data because an id is not a Go identifier; whoever owns
	// the catalog decides how a slug becomes a symbol. [htmlbind.MessageRefs]
	// reports what a template needs before this can be filled.
	Messages              map[string]htmlbind.MessageSymbol
	MessageContextBinding string
	// ConversionCacheDir stores the outcome of each conversion, keyed by what
	// the hook's CacheKey declared it depends on. An unchanged asset then costs
	// a digest instead of an encode, and a source that once lost a size
	// comparison is never re-encoded to rediscover it.
	//
	// Empty converts every build, which is correct and slow. It is a plain
	// directory of generated data: deleting it costs time and nothing else.
	ConversionCacheDir string
	// DerivedAssetDir receives the files those conversions produce. It is
	// deliberately not derived from PublicDir: a hook chooses the URL it rewrites
	// to, and only the caller knows which directory is served there.
	//
	// A produced file with no directory configured is a configuration error
	// rather than a silent discard.
	DerivedAssetDir string
	// ConversionWorkers converts what the compile is about to ask for ahead of
	// it, on this many goroutines, instead of one encode at a time inside a
	// sequential compile. It changes wall clock and nothing else: the same
	// bytes, the same produced files, and the same diagnostics in the same
	// order.
	//
	// Zero or one keeps every transform on one goroutine, which is the default
	// because concurrency is a promise about the caller's transform that only
	// the caller can make. Being a pure function of what it reads is necessary
	// and not sufficient: a transform holding a shared scratch buffer is pure by
	// that definition and unsafe by this one. Set this only once Transform is
	// safe for concurrent use.
	//
	// A warm cache converts nothing and starts nothing whatever this says.
	//
	// It is excluded from the hashed options deliberately. Every other field
	// here can change what is generated, and this one cannot: it says how many
	// goroutines do the same work. Hashing it would stamp the machine that ran
	// the build into the output, so a four-core laptop and a sixteen-core runner
	// would disagree on bytes that are identical in every way that matters, and
	// `--check` would fail on the difference between two correct builds.
	ConversionWorkers int `json:"-"`

	// EnableCBORHTTP emits application/cbor negotiation into every generated
	// binder and writer: a request carrying application/cbor binds its payload
	// fields from one CBOR map, and a response answers CBOR when the Accept
	// header asks for it. Off by default, and project-wide on purpose — which
	// media types a service accepts is a property of the service, not of one
	// route, so there is no per-route or per-type spelling. A run leaving it
	// off regenerates today's bytes exactly and links no CBOR code.
	EnableCBORHTTP bool
	// CBORHTTPProfile tunes the CBOR subset the HTTP codecs are generated for.
	// The zero value is the default profile: floats are ordinary values and
	// members come out in struct field order. It is read only when
	// EnableCBORHTTP is set.
	CBORHTTPProfile CBORHTTPProfile

	DisableFeatures []Feature
	GenerateAll     bool

	// ServerActions are the typed server actions to emit an entry point for in
	// the package being generated.
	//
	// They are supplied rather than discovered because the annotation admitting
	// one is read by routetree, which parses a route package before that
	// package can compile. This phase type-checks, which is why the argument
	// struct and the codecs are built here and the declaration is read there.
	ServerActions []ServerAction `json:"-"`
}

Options configures discovery identities and generated template APIs. A zero Options value intentionally discovers nothing and disables optional wrappers; use DefaultOptions for standard behavior.

func DefaultOptions

func DefaultOptions() Options

DefaultOptions returns the standard tinybind runtime setup.

func (Options) WithServerActionsFor added in v0.5.10

func (o Options) WithServerActionsFor(actions []routetree.Action, relDir string) Options

WithServerActionsFor is Options carrying the typed actions of one route package, which is what a caller generating over a whole tree needs per package.

type PackagePlan

type PackagePlan struct {
	Package     string
	PackagePath string
	Types       []TypePlan
	// ServerActions are the typed server actions this package emits an entry
	// point for, carried from Options so emission needs no second input.
	ServerActions []ServerAction
	// CBORHTTP and CBORHTTPProfile carry Options.EnableCBORHTTP and its profile
	// into emission, the way ServerActions travels: emission takes a plan and a
	// transport target and no Options.
	CBORHTTP        bool
	CBORHTTPProfile CBORHTTPProfile
	// Discovered lists type names referenced by configured generic call sites.
	Discovered []string
}

PackagePlan is all type plans in a package.

func AnalyzePackage

func AnalyzePackage(dir string) (*PackagePlan, error)

AnalyzePackage builds field plans for all package-level structs with exported fields. Generic call discovery (Bind/Write/DecodeJSON/EncodeJSON) uses go/types symbol identity.

func AnalyzePackageWithOptions

func AnalyzePackageWithOptions(dir string, opts Options) (*PackagePlan, error)

AnalyzePackageWithOptions is AnalyzePackage with customizable call targets.

type PackageSet added in v0.5.22

type PackageSet struct {
	// contains filtered or unexported fields
}

PackageSet holds several directories type-checked in one go/packages call.

It is read-only once returned, so the directories it covers may generate concurrently, which is the pairing it exists for: one load, then whatever concurrency the caller wants over the generation that follows.

A set describes the tree as it was when the set was built, and nothing here is incremental. A caller that writes generated files and then generates directories which type-check them must build a new set in between - which is why a run staged around what it writes builds one set per stage rather than one per run.

func LoadPackages added in v0.5.22

func LoadPackages(ctx context.Context, dirs []string) (*PackageSet, error)

LoadPackages type-checks dirs, and the dependency closure they share, in one go/packages call.

The result covers every directory that resolved to one analyzable package. A directory that did not is left out rather than reported, because leaving it out is what preserves the diagnostic: its generation loads it alone and fails the way it fails today, naming that directory instead of the batch. The same goes for a directory outside the module the others are in, which one load cannot reach.

An error is returned only when the load itself could not run.

func (*PackageSet) Len added in v0.5.22

func (set *PackageSet) Len() int

Len reports how many directories the set covers, so a caller can log what a load reached without reaching into it.

type PatternSet

type PatternSet[T any] struct {
	Set      []T
	Disabled bool
}

PatternSet is an authoritative set of discovery identities. Set replaces, rather than extends, any defaults. Disabled suppresses the feature entirely.

type RouterTarget added in v0.4.9

type RouterTarget struct {
	// Import is the package supplying the router, and Qualifier the name the
	// generated file refers to it by.
	Import    string
	Qualifier string
	// Type is the parameter type of the generated registration function,
	// written verbatim so an interface needs no pointer.
	Type string
	// RegisterFunc is the name of the generated registration function.
	RegisterFunc string
	// CatchAllSuffix replaces the net/http "..." catch-all marker inside a
	// pattern segment. Empty rejects catch-all routes instead of guessing.
	CatchAllSuffix string
}

RouterTarget names the router generated registration installs on.

func DefaultRouterTarget added in v0.4.9

func DefaultRouterTarget() RouterTarget

DefaultRouterTarget targets the fasthttp/router fork that tinygodriver carries beside its fasthttp fork.

It has to be that one rather than upstream: a handler taking the fork's RequestCtx is not a handler taking valyala/fasthttp's, so the upstream router will not accept generated code. An application on upstream fasthttp points Import at github.com/fasthttp/router instead; the two share an API and a pattern syntax, so nothing else in the target changes.

type ServerAction added in v0.5.10

type ServerAction struct {
	// Func is the declared Go function name, which may be unexported: the
	// wrapper sits beside it in the same package.
	Func string
	// Wrapper is the exported entry point to emit. Empty derives one from Func.
	Wrapper string
	// Params are the declared inputs after any leading context was trimmed.
	Params []ServerActionParam
	// TakesContext passes the request's context as the first argument.
	TakesContext bool
	// Result is the type of the single non-error result. Empty means the
	// function returns only an error, and the entry point answers no content.
	Result string
	// SourcePath is the file declaring the function.
	//
	// Generation is per source file: the argument struct, its decoder and the
	// entry point all belong to the artifact of the file the action was
	// declared in. Without it the struct grouped under the empty path while the
	// entry point was written into every artifact, so the wrapper named a
	// decoder emitted into a different file.
	SourcePath string
}

ServerAction is one typed server action to generate an entry point for.

It is an input rather than something discovered here, because the annotation that admits it is read by routetree, which parses the route package before it can compile. This phase does type-check, which is why the argument struct and the codecs are built here rather than there.

func ServerActionsFor added in v0.5.10

func ServerActionsFor(actions []routetree.Action, relDir string) []ServerAction

ServerActionsFor selects the typed server actions declared in one route package and converts them to what this phase takes.

The two halves of a typed action are built by different phases: routetree reads the declaration, because it parses a route package before that package can compile, and this phase builds the argument struct and the codecs, because it type-checks. The conversion is here rather than in a caller so the wrapper name, the parameter list and the context flag cannot drift between what the registry registers and what the wrapper is emitted as.

relDir selects the package: it is routetree.Action.RelDir, empty for the route root. Raw handlers are skipped, since nothing is generated around one.

func (ServerAction) WrapperName added in v0.5.10

func (a ServerAction) WrapperName() string

WrapperName is the exported entry point emitted for this action.

type ServerActionParam added in v0.5.10

type ServerActionParam struct {
	Name string
	Type string
	// JSON is the member the caller writes it as. Empty derives it from Name
	// the way an untagged struct field's wire name is derived.
	JSON string
}

ServerActionParam is one declared input of a typed server action: the Go parameter name, and the source text of its type.

type SymbolPattern

type SymbolPattern struct{ PackagePath, Name string }

SymbolPattern identifies a package-level declaration by go/types identity.

type TransformCandidate added in v0.4.9

type TransformCandidate struct {
	Name string
	Decl *ast.FuncDecl
	// TransportParams are the parameter names holding the writer and the
	// request, in declaration order. They collapse into one context parameter.
	TransportParams []string
	// contains filtered or unexported fields
}

TransformCandidate is one function the transform considered.

type TransformOptions added in v0.4.9

type TransformOptions struct {
	// ImportRewrites maps an import path in the authored source to the path the
	// generated source imports instead. The local name is preserved, so a call
	// selector in a rewritten body is untouched: only the import line moves.
	//
	// A framework providing the same helper names over the other transport
	// registers its own pair here. Nothing about the mapping is built in beyond
	// the defaults below.
	ImportRewrites map[string]string

	// ContextType is the type the collapsed parameter takes, written verbatim,
	// and ContextImport the package supplying it.
	ContextType   string
	ContextImport string

	// ContextName is the preferred identifier for the collapsed parameter. A
	// function already using the name gets a fresh one instead.
	ContextName string

	// RequestSelectorRewrites maps a method or field named on the request to
	// the expression replacing the whole selector. "$ctx" stands for the
	// context identifier.
	//
	// Enumerated one entry at a time on purpose: the size of this map is the
	// honest measure of how much net/http semantics the transform claims to
	// reproduce, and a general rule would hide that.
	RequestSelectorRewrites map[string]string

	// Router names the router the generated route registration installs on.
	// The zero value uses DefaultRouterTarget.
	Router RouterTarget

	// Calls are the recognized calls whose transport arguments are dropped.
	// Empty uses the canonical set for the default runtime packages.
	Calls []CallPattern

	// ReportOnly lists what a transformed build would refuse and writes
	// nothing. Adoption is all-or-nothing per decision:backend-build-tag-mode,
	// so an application needs to see the whole cost before committing to the
	// migration rather than one refusal at a time after it.
	ReportOnly bool

	// GeneratedHeaders names header prefixes, beside this module's own, whose
	// files the transform skips. It carries Options.GeneratedHeaders to a
	// direct AnalyzeTransform caller, and a Generator fills it from there.
	//
	// The transform reads the whole loaded package, so a framework branding its
	// generated output writes a header nothing here recognizes on its own, and
	// its generated code is classified as if a user had authored it. Each entry
	// still requires the conventional "DO NOT EDIT." ending.
	GeneratedHeaders []string
}

TransformOptions configures the source transform.

func DefaultTransformOptions added in v0.4.9

func DefaultTransformOptions() TransformOptions

DefaultTransformOptions targets the fasthttp runtime this module ships.

func (TransformOptions) RewriteImport added in v0.4.9

func (o TransformOptions) RewriteImport(from string) (string, bool)

RewriteImport returns the path that replaces from, and whether it changes.

type TransformOutput added in v0.4.9

type TransformOutput struct {
	Source []byte
	// LayoutWarnings name authored files the tag cannot cleanly exclude. See
	// checkLayout for why that is the application's problem to fix.
	LayoutWarnings []string
}

TransformOutput is the generated fasthttp source and what the run wants the caller to know about it.

func RewriteTransform added in v0.4.9

func RewriteTransform(pkg *packages.Package, plan *TransformPlan, options TransformOptions) (*TransformOutput, error)

RewriteTransform emits the fasthttp source for every admitted function.

The rewrite is textual over the original bytes rather than a mutated syntax tree: comments and formatting survive without being reconstructed, and the loaded package's AST stays usable by the other generator phases, which share one type check.

type TransformPlan added in v0.4.9

type TransformPlan struct {
	Admitted []*TransformCandidate
	Refusals TransformRefusals
}

TransformPlan is the analysis result: what can be rewritten and what cannot.

func AnalyzeTransform added in v0.4.9

func AnalyzeTransform(pkg *packages.Package, options TransformOptions) (*TransformPlan, error)

AnalyzeTransform classifies every same-package function taking a transport value, per rule:transform-eligibility.

Every such function is a candidate, not only the discovered handlers: with no adapter to fall back to, a shared helper that stays net/http would refuse every handler that calls it, so the admission set closes over the call graph.

type TransformRefusal added in v0.4.9

type TransformRefusal struct {
	Function string
	Kind     TransformRefusalKind
	Position token.Position
	Detail   string
	// Chain runs from this function to the occurrence that caused the refusal.
	// It is empty when the occurrence is in this function's own body.
	Chain []TransformRefusalHop
}

TransformRefusal reports one function the transform will not rewrite.

func (TransformRefusal) Error added in v0.4.9

func (r TransformRefusal) Error() string

Error renders the refusal the way requirement:transform-diagnostics asks: the position of the occurrence rather than of the declaration, the classification, every hop that inherited it, and the remedy.

type TransformRefusalHop added in v0.4.9

type TransformRefusalHop struct {
	Function string
	Position token.Position
	Detail   string
}

TransformRefusalHop is one step from the handler to the occurrence.

type TransformRefusalKind added in v0.4.9

type TransformRefusalKind string

TransformRefusalKind names why a function cannot be rewritten. It is the classification requirement:transform-diagnostics prints, so each value maps to one remedy a reader can act on.

const (
	// RefusalUnknownCall passes a transport value to a call the generator does
	// not recognize. The common shape of tracing, metrics and session libraries.
	RefusalUnknownCall TransformRefusalKind = "unknown_call"
	// RefusalUnknownSelector names a method or field absent from the rewrite table.
	RefusalUnknownSelector TransformRefusalKind = "unknown_selector"
	// RefusalEscapes assigns, stores, captures, returns or takes the address of
	// a transport value.
	RefusalEscapes TransformRefusalKind = "escapes"
	// RefusalTypeAssertion reaches for Flusher, Hijacker or another capability
	// the other transport does not present the same way.
	RefusalTypeAssertion TransformRefusalKind = "type_assertion"
	// RefusalInheritedFromCallee is refused only because something it calls is.
	RefusalInheritedFromCallee TransformRefusalKind = "inherited"
)

func (TransformRefusalKind) Remedy added in v0.4.9

func (k TransformRefusalKind) Remedy() string

Remedy is the action that clears this kind of refusal.

type TransformRefusals added in v0.4.9

type TransformRefusals []TransformRefusal

TransformRefusals is every refusal in one package, reported together so a shared helper's refusal and the handlers that inherited it arrive in one run.

func (TransformRefusals) Diagnostics added in v0.4.9

func (rs TransformRefusals) Diagnostics() []parser.Diagnostic

Diagnostics renders the refusals the way the rest of the generator reports what it could not analyze, so a report-only run rides the same rail as --check instead of inventing a second one.

func (TransformRefusals) Error added in v0.4.9

func (rs TransformRefusals) Error() string

type TransportSlots added in v0.4.9

type TransportSlots struct {
	Writer  *int
	Request *int
}

TransportSlots names the argument positions holding the transport values a call receives: the response writer and the request.

The other roles say where a semantic value is read from. These say the opposite — which arguments carry nothing semantic and exist only because the net/http shape passes both halves separately. A backend carrying both in one value drops exactly these positions, so a call whose slots are undeclared is one the transform cannot rewrite.

func (TransportSlots) Declared added in v0.4.9

func (s TransportSlots) Declared() bool

Declared reports whether either slot was named.

func (TransportSlots) Drops added in v0.4.9

func (s TransportSlots) Drops(index int) bool

Drops reports whether the zero-based argument index is a transport slot, and so is removed when the call is rewritten for a single-value transport.

type TypePattern

type TypePattern struct{ PackagePath, Name string }

TypePattern identifies a named type by go/types identity.

type TypePlan

type TypePlan struct {
	Name string
	// SourcePath is the Go file that declares the type. It is the owning source
	// of every artifact generated for this type.
	SourcePath string
	Fields     []FieldPlan
	// Doc is the godoc of the type declaration.
	Doc string
	// Usage records which generated entry points are referenced by source code.
	// Zero means the type is unused and emits no mapping paths.
	Usage Usage
	// DirectUsage excludes usage inherited from containing structs.
	DirectUsage Usage
}

TypePlan is the mapping plan for one struct type.

type TypeSource added in v0.1.12

type TypeSource struct {
	GenericArgument *int
	ArgumentType    *int
}

TypeSource selects a semantic type from a generic argument or value argument.

type Usage

type Usage uint32

Usage selects generated mapping entry points.

const (
	UsageBind Usage = 1 << iota
	UsageWrite
	UsageDecodeJSON
	UsageEncodeJSON
	UsageScanRows
	UsageEncodeItem
	UsageDecodeItem
	UsageItemKey
	UsageEncodeEntity
	UsageDecodeEntity
	UsageEntityKey
	UsageCacheKey
	// UsageAppendMethod and UsageDecodeMethod publish a type's JSON codec as
	// the Appender and Decoder methods of the jsonbind package, so a consumer
	// that never analyzed the type can still encode and decode it.
	//
	// Only a jsonbind annotation sets them, and each direction is its own bit
	// because the annotation names the direction. Reading the direction off the
	// type's overall usage instead would publish both methods for a type that
	// asked for one, since GenerateAll gives every type every codec.
	//
	// They stay out of UsageAll for the reason UsageItem does: a type reached
	// by an ordinary call site should not acquire a public method it never
	// asked for, since that is code size in every binary carrying the type.
	UsageAppendMethod
	UsageDecodeMethod
	// The four CBOR codec bits, one per container shape and direction, set by
	// the cborbind entry point a call site named. They stay out of UsageAll and
	// have no generate-all rule at all: a CBOR codec is a protocol, so giving
	// every struct in a package one would publish a wire format nobody asked
	// for. The item and entity codecs each have a tag-driven generate-all; this
	// has none, because there is no tag that means "this is a message".
	UsageCBORArrayEncode
	UsageCBORArrayDecode
	UsageCBORMapEncode
	UsageCBORMapDecode
	UsageAll = UsageBind | UsageWrite | UsageDecodeJSON | UsageEncodeJSON
	// UsageJSONMethods is either published method, for a caller asking whether
	// a type publishes any.
	UsageJSONMethods = UsageAppendMethod | UsageDecodeMethod
	// UsageItem is every DynamoDB item entry point. It stays out of UsageAll:
	// the item codec has its own generate-all rule, which requires a dynamo tag,
	// so an unrelated request struct never acquires one.
	UsageItem = UsageEncodeItem | UsageDecodeItem | UsageItemKey
	// UsageEntity is every Firestore entity entry point, and stays out of
	// UsageAll for the same reason, requiring a firestore tag instead.
	UsageEntity = UsageEncodeEntity | UsageDecodeEntity | UsageEntityKey
	// UsageCBORArray and UsageCBORMap are one shape's two directions, and
	// UsageCBOR is every CBOR bit, for a caller asking whether a type has a
	// codec of that shape at all.
	UsageCBORArray = UsageCBORArrayEncode | UsageCBORArrayDecode
	UsageCBORMap   = UsageCBORMapEncode | UsageCBORMapDecode
	UsageCBOR      = UsageCBORArray | UsageCBORMap
)

type ValueSource added in v0.1.12

type ValueSource struct {
	Argument   *int
	Constant   any
	IsConstant bool
}

ValueSource selects a semantic value from a value argument or a fixed constant.

Jump to

Keyboard shortcuts

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