generator

package
v0.8.3 Latest Latest
Warning

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

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

Documentation

Index

Constants

View Source
const Version = "0.8.3"

Version is the proto2type generator version stamped into output files.

Variables

This section is empty.

Functions

This section is empty.

Types

type DomainEnum added in v0.4.0

type DomainEnum struct {
	// Name is the PascalCase type name. For nested enums this is prefixed
	// with the parent message name (e.g. "UserSettings_Theme").
	Name string
	// FullName is the fully-qualified proto name (e.g. "test.v1.UserStatus").
	FullName string
	// Comment is the leading proto comment.
	Comment string
	// Values in declaration order.
	Values []*DomainEnumValue
}

DomainEnum is the IR for a proto enum.

type DomainEnumValue added in v0.4.0

type DomainEnumValue struct {
	// Name is the PascalCase, prefix-stripped name (e.g. "Active").
	Name string
	// ProtoName is the original UPPER_SNAKE proto name (e.g. "USER_STATUS_ACTIVE").
	ProtoName string
	// Number is the proto enum numeric value.
	Number int32
	// IsDefault is true when Number == 0 and this is the first value.
	IsDefault bool
	// Comment is the leading proto comment.
	Comment string
}

DomainEnumValue is a single enum value.

type DomainField added in v0.4.0

type DomainField struct {
	// Name is the original proto field name (snake_case).
	Name string
	// PascalName is the PascalCase version of Name (e.g. "DisplayName").
	PascalName string
	// CamelName is the lowerCamelCase version of Name (e.g. "displayName").
	CamelName string
	// ProtoNumber is the proto field number, used for stable ordering.
	ProtoNumber int

	// Kind classifies the field (scalar, message, timestamp, enum, etc.).
	Kind FieldKind
	// ScalarKind is the proto scalar kind (only meaningful when Kind == FieldKindScalar).
	ScalarKind protoreflect.Kind

	// MessageTypeName is the PascalCase IR type name for message-typed fields.
	// Empty for scalars and WKTs.
	MessageTypeName string
	// MessageSourcePath is the proto file path of the referenced message type.
	// Empty when the message is in the same file.
	MessageSourcePath string
	// NeedsBox is true when a message-typed field requires heap allocation
	// (Box<T> in Rust) because the type is part of a recursive cycle.
	// False for non-recursive message fields (which can use Option<T> directly).
	NeedsBox bool
	// EnumTypeName is the PascalCase IR enum type name for enum-typed fields.
	// Empty for non-enum fields.
	EnumTypeName string
	// EnumFullName is the fully qualified proto enum name.
	EnumFullName string
	// EnumSourcePath is the proto file path of the referenced enum type.
	// Empty when the enum is in the same file.
	EnumSourcePath string
	// EnumDefaultName is the proto name of the first (zero-value) enum value.
	// Used by backends with explicit defaults (Kotlin, Python) when EnumAsString is true.
	EnumDefaultName string

	// Optional is true for proto3 `optional` scalar fields.
	Optional bool
	// Repeated is true for `repeated` fields (but NOT maps).
	Repeated bool
	// IsMap is true for `map<K,V>` fields.
	IsMap bool

	// MapKey describes the key kind and scalar type (only set when IsMap is true).
	MapKey *MapTypeInfo
	// MapValue describes the value kind and type info (only set when IsMap is true).
	MapValue *MapTypeInfo

	// DocID is true when (proto2type.field).document_id = true.
	DocID bool
	// ServerTimestamp is true when (proto2type.field).server_timestamp = true.
	ServerTimestamp bool
	// FieldSkip is true when (proto2type.field).skip = true (this field was already
	// excluded from Fields, but we keep the flag for edge-case introspection).
	FieldSkip bool
	// NameOverride is the (proto2type.field).name value, or empty.
	NameOverride string
	// Inline is true when (proto2type.field).inline = true.
	Inline bool
	// EnumAsString is true when the enum should be serialised as its string name.
	EnumAsString bool
	// Omitempty is the resolved omitempty flag for this field.
	Omitempty bool
	// Deprecated is true when the field has the deprecated option set.
	Deprecated bool
	// Proto2DefaultValue is the string representation of a proto2 custom default.
	// Empty for proto3 fields (which always use zero-value defaults).
	// TODO: Wire into TS/Go/Rust backends when proto2 support is needed.
	// Currently populated from descriptor but not consumed by any backend.
	Proto2DefaultValue string

	// FieldBehaviors from google.api.field_behavior annotations.
	// nil means no annotation present.
	FieldBehaviors []annotations.FieldBehavior

	// ValidateConstraints from buf/validate field annotations.
	// nil means no constraints annotated.
	ValidateConstraints *ValidateConstraints

	// Comment is the leading proto comment for this field, cleaned.
	Comment string

	// OneofName is the oneof group name when this field is a oneof variant.
	// Empty for non-oneof fields. (In the main Fields slice, oneof members
	// are NOT present; they appear only in DomainOneof.Variants.)
	OneofName string

	// IsOneof is true when this field represents a collapsed oneof group
	// in the Fields slice (inserted at the proto declaration position).
	IsOneof bool
	// OneofTypeName is the IR type name of the oneof enum (e.g. "UserContactMethod").
	// Only set when IsOneof is true.
	OneofTypeName string

	// ProtoGoName is the Go field name in the generated proto struct (field.GoName).
	// May differ from PascalName (e.g. proto generates "Id" for "id").
	ProtoGoName string
	// ProtoEnumGoIdent is the protogen.GoIdent for enum types.
	// Used for QualifiedGoIdent to resolve e.g. pb.UserStatus.
	ProtoEnumGoIdent protogen.GoIdent
	// ProtoMessageGoIdent is the protogen.GoIdent for message types.
	// Used for QualifiedGoIdent to resolve e.g. pb.Tag.
	ProtoMessageGoIdent protogen.GoIdent
}

DomainField is the IR for a single message field.

func (*DomainField) IsImmutable added in v0.5.0

func (f *DomainField) IsImmutable() bool

func (*DomainField) IsInputOnly added in v0.5.0

func (f *DomainField) IsInputOnly() bool

func (*DomainField) IsOutputOnly added in v0.5.0

func (f *DomainField) IsOutputOnly() bool

func (*DomainField) IsRequired added in v0.5.0

func (f *DomainField) IsRequired() bool

type DomainFile added in v0.4.0

type DomainFile struct {
	// SourcePath is the proto file path (e.g. "user.proto").
	SourcePath string
	// Package is the proto package name (e.g. "test.v1").
	Package string
	// Enums are the top-level enum definitions.
	Enums []*DomainEnum
	// Messages are the top-level message definitions.
	Messages []*DomainMessage
}

DomainFile is the top-level IR node for a single .proto source file.

func BuildDomainFile added in v0.4.0

func BuildDomainFile(file *protogen.File, opts *Options) (*DomainFile, error)

BuildDomainFile builds the IR for a single proto source file. It consolidates the scanning/walking logic that was previously duplicated across go_domain.go and rust_domain.go.

NOTE: Cross-package type references (PB-3) are not yet handled. The IR currently processes one file at a time and uses bare PascalCase names for MessageTypeName/EnumTypeName. When multi-file IR support is added, irMessageNameFromDesc and irEnumNameFromDesc will need package-qualified names to disambiguate types from different proto packages.

type DomainMessage added in v0.4.0

type DomainMessage struct {
	// Name is the PascalCase type name (e.g. "ModelCatalogEntry").
	// For nested messages this is flattened: Parent_Child.
	Name string
	// FullName is the fully-qualified proto name (e.g. "test.v1.User").
	FullName string
	// Comment is the leading proto comment, if any.
	Comment string
	// Fields in declaration order (excludes skipped fields and oneof members).
	Fields []*DomainField
	// Oneofs in declaration order.
	Oneofs []*DomainOneof
	// Enums defined inside this message.
	NestedEnums []*DomainEnum
	// Messages defined inside this message (excluding map-entry synthetics).
	NestedMessages []*DomainMessage
	// Skip is true when the message has (proto2type.message).skip = true.
	Skip bool
	// HasDocID is true when at least one field has (proto2type.field).document_id = true.
	HasDocID bool
	// ProtoGoIdent is the protogen.GoIdent for the proto message type.
	// Used by Go converters to emit qualified proto types (e.g. pb.User).
	ProtoGoIdent protogen.GoIdent
	// HasNonSyntheticOneof is true if the message has real (non-synthetic) oneofs.
	HasNonSyntheticOneof bool
}

DomainMessage is the IR for a single proto message.

type DomainOneof added in v0.4.0

type DomainOneof struct {
	// Name is MessageName + PascalCase(oneof_name), e.g. "UserContactMethod".
	Name string
	// FieldName is the snake_case oneof field name (e.g. "contact_method").
	FieldName string
	// Variants in declaration order.
	Variants []*OneofVariant
	// ProtoGoName is the Go field name for this oneof in the generated proto struct.
	// e.g. "ContactMethod" — used in ToProto as out.ContactMethod = ...
	ProtoGoName string
}

DomainOneof is the IR for a proto oneof group.

type FieldKind added in v0.4.0

type FieldKind int

FieldKind classifies a proto field into a language-agnostic category. Backends use this to select the correct type mapping and serialisation logic.

const (
	// FieldKindScalar is a primitive type (bool, int32, string, bytes, etc.).
	FieldKindScalar FieldKind = iota
	// FieldKindEnum is a protobuf enum.
	FieldKindEnum
	// FieldKindMessage is a user-defined message (not a WKT).
	FieldKindMessage
	// FieldKindTimestamp is google.protobuf.Timestamp.
	FieldKindTimestamp
	// FieldKindDuration is google.protobuf.Duration.
	FieldKindDuration
	// FieldKindWrapperBool is google.protobuf.BoolValue.
	FieldKindWrapperBool
	// FieldKindWrapperInt32 is google.protobuf.Int32Value.
	FieldKindWrapperInt32
	// FieldKindWrapperInt64 is google.protobuf.Int64Value.
	FieldKindWrapperInt64
	// FieldKindWrapperUInt32 is google.protobuf.UInt32Value.
	FieldKindWrapperUInt32
	// FieldKindWrapperUInt64 is google.protobuf.UInt64Value.
	FieldKindWrapperUInt64
	// FieldKindWrapperFloat is google.protobuf.FloatValue.
	FieldKindWrapperFloat
	// FieldKindWrapperDouble is google.protobuf.DoubleValue.
	FieldKindWrapperDouble
	// FieldKindWrapperString is google.protobuf.StringValue.
	FieldKindWrapperString
	// FieldKindWrapperBytes is google.protobuf.BytesValue.
	FieldKindWrapperBytes
	// FieldKindStruct is google.protobuf.Struct.
	FieldKindStruct
	// FieldKindValue is google.protobuf.Value.
	FieldKindValue
	// FieldKindListValue is google.protobuf.ListValue.
	FieldKindListValue
	// FieldKindFieldMask is google.protobuf.FieldMask.
	FieldKindFieldMask
	// FieldKindEmpty is google.protobuf.Empty.
	FieldKindEmpty
	// FieldKindAny is google.protobuf.Any.
	FieldKindAny
)

func (FieldKind) IsWrapper added in v0.4.0

func (k FieldKind) IsWrapper() bool

IsWrapper returns true if the kind is one of the google.protobuf wrapper types.

func (FieldKind) String added in v0.4.0

func (k FieldKind) String() string

String returns the human-readable name of a FieldKind.

type MapTypeInfo added in v0.4.0

type MapTypeInfo struct {
	Kind            FieldKind
	ScalarKind      protoreflect.Kind
	MessageTypeName string
	EnumTypeName    string
	EnumFullName    string // Fully qualified proto enum name, for WKT detection (e.g. "google.protobuf.NullValue").
	SourcePath      string // ADD THIS: proto file path for cross-file import resolution

	// ProtoGoIdent is the protogen.GoIdent for the map value message type.
	// Used by Go backend converters for QualifiedGoIdent (e.g. pb.Settings).
	ProtoGoIdent protogen.GoIdent
}

MapTypeInfo captures the kind and type name of a map key or value.

type OneofVariant added in v0.4.0

type OneofVariant struct {
	// Name is the PascalCase variant name (e.g. "ContactEmail").
	Name string
	// ProtoName is the original proto field name (e.g. "contact_email").
	ProtoName string
	// Kind classifies the variant (scalar, message, timestamp, enum, etc.).
	Kind FieldKind
	// ScalarKind is set when Kind == FieldKindScalar.
	ScalarKind protoreflect.Kind
	// TypeName is the resolved type name for message/enum variants.
	TypeName string
	// SourcePath is the proto file path of the referenced type. Empty when same file.
	SourcePath string
	// EnumAsString is true when the enum should be serialised as its string name.
	EnumAsString bool
	// EnumFullName is the fully qualified proto enum name, for WKT detection (e.g. "google.protobuf.NullValue").
	EnumFullName string
	// NeedsBox is true when a message-typed variant requires heap allocation
	// because the type is part of a recursive cycle.
	NeedsBox bool
	// ProtoGoIdent is the protogen.GoIdent for the oneof wrapper struct.
	// e.g. GoIdent for User_ContactEmail — used in ToProto/FromProto.
	ProtoGoIdent protogen.GoIdent
	// ProtoGoName is the Go field name in the proto wrapper struct.
	// e.g. "ContactEmail" — used to access the value inside the wrapper.
	ProtoGoName string
	// ProtoEnumGoIdent is the protogen.GoIdent for enum types.
	// Used for QualifiedGoIdent to resolve e.g. pb.Priority.
	ProtoEnumGoIdent protogen.GoIdent
	// ProtoMessageGoIdent is the protogen.GoIdent for message types.
	// Used for QualifiedGoIdent to resolve e.g. pb.Settings.
	ProtoMessageGoIdent protogen.GoIdent
	// ValidateConstraints holds buf/validate rules for this variant field.
	ValidateConstraints *ValidateConstraints
}

OneofVariant is a single variant inside a oneof group.

type Options

type Options struct {
	// Lang is the target language (go, python, kotlin, typescript).
	Lang string

	// Backend is the storage backend (firestore, mongo, dynamodb, datastore, spanner).
	// Empty string means no storage types are generated.
	Backend string

	// Domain controls whether domain types and proto converters are generated.
	Domain bool

	// OutputFile overrides the default output filename.
	OutputFile string

	// EnumAsString stores enums as string names instead of int32.
	EnumAsString bool

	// OmitemptyDefault controls whether optional/zero-value fields get omitempty by default.
	OmitemptyDefault bool

	// GoPackage overrides the Go package name for generated types.
	// When set, generated types use this as their Go import path and the converters
	// import the proto types from the original go_package in the .proto file.
	GoPackage string

	// RustExhaustive controls whether Rust structs are generated as exhaustive (omitting #[non_exhaustive]).
	// Default: false. Set to true for vendored codegen where the consumer owns the types.
	RustExhaustive bool

	// BufModule is the Rust module path where buffa-generated proto types live.
	// Required for backend=buffa (e.g. "crate::proto::candela::harness::v1").
	BufModule string

	// Validate selects the validation strategy for code generation.
	// When non-empty, enables validation code generation from buf.validate constraints.
	// When empty (default), no validation code is generated.
	//
	// Supported values ("true" selects the default strategy per language):
	//
	//   Go:     "true" → protovalidate delegation via Validate() method.
	//           "native" → pure Go checks in Validate(), zero external deps.
	//   Rust:   "true" | "validator" → validator crate (#[derive(Validate)]).
	//   Kotlin: "true" | "native"   → hand-rolled validate(): List<String>.
	//   Python: constraints are always emitted via Pydantic Field() args.
	//
	// Oneof mutual-exclusion checks (Go) are always generated regardless of this flag.
	//
	// NOTE: length validation counts characters (Unicode scalar values), not bytes.
	// This differs from proto's min_len/max_len which count bytes, but matches
	// user expectations and is consistent with Python/Pydantic.
	Validate string

	// BufOneofPrefix is an optional module prefix inserted between the buffa module
	// and the "oneof" submodule in generated Rust code.
	// When empty (default), oneof paths are: __buffa_mod::oneof::<msg>::<Variant>
	// When set (e.g. "__buffa"), paths become: __buffa_mod::__buffa::oneof::<msg>::<Variant>
	// connectrpc-build uses "__buffa" as its prefix.
	BufOneofPrefix string

	// DomainModule is an optional Rust module path for domain type imports in buffa output.
	// When empty (default), generates: use super::*;
	// When set (e.g. "candela_core::harness"), generates: use candela_core::harness::*;
	// This allows generated buffa converters to be placed in any module, not just
	// as a sibling of the domain type definitions.
	DomainModule string

	// PythonBaseClass overrides the Pydantic base class (default: "BaseModel").
	PythonBaseClass string

	// PythonAliasGenerator adds model_config with alias generation ("camel" for to_camel).
	PythonAliasGenerator string

	// PythonEnumStyle controls enum generation: "" (default, prefix-stripped lowercase)
	// or "raw" (original proto names with UNSPECIFIED).
	PythonEnumStyle string

	// PythonPreset applies preset configurations ("a2a" sets alias_generator=camel + enum_style=raw).
	PythonPreset string

	// PythonDescription overrides module-level docstring.
	PythonDescription string

	// PythonStripProtoSuffix uses base.py instead of base_pb2_pydantic.py (Python only).
	PythonStripProtoSuffix bool

	// TSInt64Style controls int64/uint64 representation in TypeScript:
	// "string" (default, JSON-safe) or "bigint".
	TSInt64Style string

	// TSEnumStyle controls enum representation in TypeScript:
	// "enum" (default, z.enum) or "native" (z.nativeEnum with const object).
	TSEnumStyle string

	// TSExplicitTypes emits explicit export interface alongside z.infer
	// for improved IDE performance in large codebases.
	TSExplicitTypes bool

	// TSZodImport controls the zod import path (default "zod").
	TSZodImport string

	// TSTypesOnly emits plain TypeScript interfaces and type aliases without
	// Zod schemas or runtime dependencies. Incompatible with validate.
	TSTypesOnly bool

	// TSStrict appends .strict() to all generated Zod object schemas,
	// rejecting unknown fields per ProtoJSON spec. Default: false.
	TSStrict bool

	// TSPreset applies preset configurations for TypeScript.
	TSPreset string

	// TSOutputSuffix overrides the default TypeScript output file extension.
	TSOutputSuffix string

	// GoConstructor generates NewXxx() constructor functions for domain types
	// that have required fields (google.api.field_behavior=REQUIRED or
	// buf.validate.field.required=true). OUTPUT_ONLY fields are excluded.
	// Default: true.
	GoConstructor bool

	// Debug emits IR debug information to stderr when set.
	Debug bool
}

Options holds the plugin configuration parsed from command-line flags.

func (*Options) ValidateEnabled added in v0.6.0

func (o *Options) ValidateEnabled() bool

ValidateEnabled returns true if any validation strategy is configured.

func (*Options) ValidateNative added in v0.8.0

func (o *Options) ValidateNative() bool

ValidateNative returns true if the native (zero-dependency) validation strategy is selected.

type Runner added in v0.6.0

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

Runner holds per-invocation state for the code generator.

func NewRunner added in v0.6.0

func NewRunner() *Runner

NewRunner creates a new Runner.

func (*Runner) GenerateFile added in v0.6.0

func (r *Runner) GenerateFile(gen *protogen.Plugin, file *protogen.File, opts *Options) error

GenerateFile generates output files for a single proto file.

type ValidateConstraints added in v0.5.0

type ValidateConstraints struct {
	Required  bool
	MinLength *uint64
	MaxLength *uint64
	Pattern   string
	Email     bool
	UUID      bool
	URI       bool
	Gt        *string
	Gte       *string
	Lt        *string
	Lte       *string
	MinItems  *uint64
	MaxItems  *uint64

	// String constraints
	Len      *uint64 // exact string length
	Prefix   string  // string must start with
	Suffix   string  // string must end with
	Contains string  // string must contain
	Hostname bool    // string must be valid hostname
	IP       bool    // string must be valid IP

	// Numeric constraints
	Const *string  // field must equal this value
	In    []string // field must be one of these values
	NotIn []string // field must NOT be one of these values

	// Repeated constraints
	Unique bool // repeated items must be unique

	// Enum constraints
	DefinedOnly bool // enum value must be defined (not unknown)

	// Meta
	IgnoreEmpty bool // skip validation when field is zero-value
}

ValidateConstraints holds buf/validate rules extracted from proto field options.

func (*ValidateConstraints) HasConstraints added in v0.5.0

func (c *ValidateConstraints) HasConstraints() bool

func (*ValidateConstraints) ToPydanticArgs added in v0.5.0

func (c *ValidateConstraints) ToPydanticArgs() []string

Jump to

Keyboard shortcuts

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