contract

package
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Jul 16, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package contract drives the four *_gen.go files (mock, middleware, tracing, metrics) emitted from a single hand-written contract.go.

The behavioural surface is a single Service. Data carriers (ContractFile, InterfaceDef, MethodDef, ParamDef) remain plain types.

Package contract parses Go interface definitions from contract.go files and generates mock_gen.go (function-field mock pattern) in the same directory.

Earlier versions of this package also emitted middleware_gen.go, tracing_gen.go and metrics_gen.go — per-method wrappers around every contract.go interface. Those were removed in favour of Connect interceptors at the handler boundary (forge/pkg/observe) plus opt-in helpers (observe.LogCall, observe.TraceCall, observe.NewCallMetrics) for users who want internal-package observability. The mock stays codegen because the per-method MockX struct is a real grep target — "show me MockUserService's methods" is a tight feedback loop that generic reflection can't replace.

Code generated by forge. DO NOT EDIT. forge:hash=bebcefa8e8969a2afdc41af0650f57fbcf0833407df2e03ce432c9df6824ad05 forge-owned: regenerated every run — do not edit (forge disown to take ownership) Source: contract.go in this package.

To customize: edit contract.go (the interface IS the public surface) and re-run "forge generate". This file is regenerated unconditionally.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Generate

func Generate(contractPath string) error

Generate parses contractPath and writes mock_gen.go next to it.

In addition to (re)writing mock_gen.go, Generate sweeps any stale observability wrappers (middleware_gen.go, tracing_gen.go, metrics_gen.go) from the same directory — these were emitted by previous forge versions and are now superseded by the forge/pkg/observe Connect interceptors. Removing them here (rather than relying on the audit "orphan" report) keeps `forge generate` idempotent and gives the user a clear signal in the build output: either the file is present and current, or it's gone.

func GenerateWithOptions

func GenerateWithOptions(contractPath string, opts Options) error

GenerateWithOptions is Generate with project-level extension hooks (currently: ExtraInterfaceTypes). New plumbing should go through this entry point; the bare Generate is preserved for call sites that don't need the extension surface.

Types

type ContractFile

type ContractFile struct {
	Package    string
	Imports    map[string]string // alias/name → import path (e.g. "sql" → "database/sql")
	Interfaces []InterfaceDef
	// InterfaceNames is the set of interface type names defined in this file.
	// Used by the zero-value generator to emit "nil" for interface-typed
	// returns instead of the invalid composite literal "T{}".
	InterfaceNames map[string]bool
	// PrimitiveAliases maps a named type (e.g. "BalanceCapReason") to its
	// underlying primitive kind (e.g. "string"). Populated by scanning
	// contract.go and its sibling .go files for `type X <primitive>`
	// declarations. Used by the zero-value generator to emit the
	// underlying primitive's zero (`""`, `0`, `false`) instead of the
	// invalid composite literal `BalanceCapReason{}`.
	PrimitiveAliases map[string]string
}

ContractFile holds everything extracted from a single contract.go.

func ParseContract

func ParseContract(path string) (*ContractFile, error)

ParseContract parses a contract.go file and extracts all interface definitions.

Sibling .go files in the same package directory are also scanned (parse-only, no method extraction) to populate InterfaceNames so the mock generator can emit "nil" for interface-typed returns whose declaration lives outside contract.go (e.g. internal/debug defines Service in contract.go and Debugger in debugger.go).

type Deps

type Deps struct{}

Deps is the dependency set for the contract Service. Empty today.

type InterfaceDef

type InterfaceDef struct {
	Name    string
	Methods []MethodDef
}

InterfaceDef represents a parsed Go interface.

type MethodDef

type MethodDef struct {
	Name    string
	Params  []ParamDef
	Results []ParamDef
}

MethodDef represents a single method on an interface.

func (MethodDef) CallArgs

func (m MethodDef) CallArgs() string

CallArgs returns the argument list for delegating to the inner implementation, e.g. "ctx, id" or "ctx, query, args...".

func (MethodDef) ContextParamName

func (m MethodDef) ContextParamName() string

ContextParamName returns the name of the context.Context parameter, or empty string.

func (MethodDef) ErrorResultName

func (m MethodDef) ErrorResultName() string

ErrorResultName returns the placeholder name for the error result (last result).

func (MethodDef) FuncFieldType

func (m MethodDef) FuncFieldType() string

FuncFieldType returns the func type for mock function fields, e.g. "func(context.Context, string) (string, error)".

func (MethodDef) HasContext

func (m MethodDef) HasContext() bool

HasContext returns true if the method has a context.Context parameter.

func (MethodDef) HasResults

func (m MethodDef) HasResults() bool

ResultNamesReturn returns "r0, r1" or "return r0, r1".

func (MethodDef) LastResultIsError

func (m MethodDef) LastResultIsError() bool

LastResultIsError returns true if the last result type is "error".

func (MethodDef) ParamSignature

func (m MethodDef) ParamSignature() string

ParamSignature returns the Go parameter list for a method, e.g. "ctx context.Context, id string".

func (MethodDef) RecordArgs

func (m MethodDef) RecordArgs() string

RecordArgs returns the argument list to pass to the embedded contractkit.Recorder.Record. Variadic params are passed verbatim (no "..." suffix) so the recorder receives the slice as a single any value — this is what callers want when asserting on captured arguments. If the method has no parameters, returns the empty string and the template emits Record("Method") with no extra args.

func (MethodDef) ResultNames

func (m MethodDef) ResultNames() string

ResultNames returns placeholder variable names for capturing results, e.g. "r0, r1" for two return values.

func (MethodDef) ResultSignature

func (m MethodDef) ResultSignature() string

ResultSignature returns the Go result type list, e.g. "(string, error)" or "error".

func (MethodDef) ZeroResults

func (m MethodDef) ZeroResults(mockName string, interfaceNames map[string]bool, primitiveAliases map[string]string) string

ZeroResults returns the zero-value expression for the result types, for use in mock fallback returns. E.g. "nil, contractkit.MockNotSet(...)".

interfaceNames is the set of locally-defined interface names from the parsed contract; passed through to zeroValue so interface-typed returns emit "nil" rather than the invalid composite literal "T{}".

primitiveAliases maps locally-declared named primitive types (e.g. `type BalanceCapReason string`) to their underlying kind; passed through so the mock emits the primitive's zero value ("") rather than the invalid composite literal `BalanceCapReason{}`.

The trailing error result is rendered as contractkit.MockNotSet so the canonical "Mock<Iface>.<Method>Func not set" error string lives in the library; bumping the format is now a one-place change.

type MockService

type MockService struct {
	contractkit.Recorder
	GenerateFunc      func(string) error
	ParseContractFunc func(string) (*ContractFile, error)
}

MockService is a test mock for the Service interface.

The embedded contractkit.Recorder records every call so tests can assert call counts and captured arguments. Set XxxFunc fields to override per-method behaviour; unset methods return the canonical "MockService.<Method>Func not set" error.

func (*MockService) Generate

func (m *MockService) Generate(contractPath string) error

func (*MockService) ParseContract

func (m *MockService) ParseContract(path string) (*ContractFile, error)

type Options

type Options struct {
	// ExtraInterfaceTypes is a project-supplied allow-list of cross-package
	// interface types the mock generator should treat as mockable. The
	// rendered type expression of a method's return (e.g.
	// "billing.MeterClient") is matched against this set during zero-value
	// emission; matches produce "nil" instead of the invalid composite
	// literal "T{}".
	//
	// Sourced from forge.yaml's `contracts.interface_types` at the CLI
	// layer; nil / empty is the no-op default.
	ExtraInterfaceTypes map[string]bool

	// ProjectRoot + Checksums route the mock write through the
	// checksums.WriteGeneratedFile chokepoint so the emitted
	// internal/<pkg>/mock_gen.go is recorded in the manifest AND in
	// the per-run WrittenThisRun set. Without this, the stale-artifact
	// sweep saw every manifest-tracked mock_gen.go as "tracked but not
	// re-emitted this run" and flagged it for deletion on every
	// `forge generate` — and `--force-cleanup` would actually delete
	// live mocks (kalshi-trader FORGE_BACKLOG #15).
	//
	// ProjectRoot is the project root (the directory containing .forge/);
	// relative manifest paths are computed against it. Both fields nil
	// /empty preserve the legacy raw-os.WriteFile behavior for callers
	// without a manifest in scope (e.g. the `forge add package` stub
	// emit — its mock is adopted into the manifest on the next full
	// generate).
	ProjectRoot string
	Checksums   *checksums.FileChecksums
}

Options controls optional aspects of mock generation. The zero value is equivalent to plain Generate(contractPath) — every field is opt-in and backwards compatible.

type ParamDef

type ParamDef struct {
	Name     string
	TypeExpr string // rendered Go type expression, e.g. "context.Context", "*sql.Rows", "...any"
	Variadic bool
}

ParamDef represents a method parameter or return value.

type Service

type Service interface {
	Generate(contractPath string) error
	ParseContract(path string) (*ContractFile, error)
}

Service drives contract.go → *_gen.go generation. Generate parses the contract, applies the four generators, and writes results next to the input. ParseContract is exposed for callers that want the AST without emitting files (e.g. docs).

func New

func New(_ Deps) Service

New constructs a contract.Service.

Jump to

Keyboard shortcuts

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