Releases: pinealctx/gcode
Add HTTP pre-validation hooks and restore flat Go output layout
Release Notes
Added
- Added option-based HTTP handler construction with
httpruntime.NewHandlerWithOptions. - Added pre-validation request hooks that run after JSON binding and before
Validate(). - Added
WithPreValidateHookandWithInterceptorshandler options. - Added generated
XxxHandlerWithOptionsfunctions for service RPC HTTP handlers. - Added runtime recovery for pre-validation hook panics, converting them into
panicx.ErrPanic-compatible errors.
Changed
httpruntime.NewHandlerremains backward compatible and now delegates internally through the option-based handler path.- Go generation now uses a flat output directory model again. All generated Go files are written into the single
-outdirectory. - Same-basename proto files are rejected in one Go generation run with
ErrOutputFilenameCollision, even if they are in different source subdirectories. - Documentation now explicitly describes the flat Go output directory constraint.
Fixed
- Fixed a Go generation layout regression where preserving source proto subdirectories could split one logical
go_packageinto multiple Go package directories and produce uncompilable cross-file references. - Added a regression test that compiles generated Go output for subdirectory proto files with cross-file message references.
- Improved validation compatibility test coverage for cross-file enums, ignored fields, optional nil fields, and boundary values.
Compatibility Notes
- Existing generated
XxxHandler(svc, interceptors...)functions are unchanged. - Existing
httpruntime.NewHandlercallers are unchanged. - Pre-validation hooks are opt-in through
XxxHandlerWithOptions. - Projects with proto files that share the same basename in one Go generation run must rename those proto files or generate them separately into different output directories.
v0.5.0 — gen-proto pipeline correctness fixes
Title:
v0.5.0 — gen-proto pipeline correctness fixes
Body:
What's Changed
This release fixes multiple correctness bugs in the gen-proto pipeline that caused silent data loss or invalid generated code.
Bug Fixes
- Cross-file imports now propagate correctly —
common.protoand other shared files are no longer dropped from generatedcreate/updateprotos when cross-file enum or message types are used. itemsconstraints fully supported —sint32,sint64,sfixed32,sfixed64,fixed32,fixed64scalar types and repeated enum fields now generate correct validation annotations. Previously these were silently skipped.- JSON and validate annotations preserved in derived messages —
jsontags andvalidate_messageannotations are now correctly carried through to generatedcreate/updateprotos. .meta.protoimports remapped correctly — External imports in schema files are now remapped to their.entity.protocounterparts instead of being dropped.ApplyTonow handles message-type fields — Previously, message-type fields were incorrectly classified as condition fields and skipped duringApplyToandToMap. This is now fixed via explicitcondition_fieldsinUpdateSourceOptions.items.not_innil-slice case — Added test coverage for nil-slice pass case, symmetric withitems.in.
Documentation
- Added
in/not_inexamples to theitemsconstraints section in annotations docs (EN + ZH). - Removed the "repeated enum
defined_onlynot enforced" known limitation — this was fixed in this release.
Internal
- Removed ~100 lines of
typeSourceIndex+collectExternalImportsmachinery in favor of lettingprotocompileresolve imports directly. - Added
item.meta.protocross-file compat test scenario with full golden file coverage.
Full Changelog: v0.4.0...v0.5.0
v0.4.0: .meta.proto schema pipeline
v0.4.0
New workflow: schema-driven proto generation
The primary change in this release is a new way to define entity/create/update
message groups. Instead of writing three proto files by hand, you define a
single .meta.proto schema file and let gen-proto generate the rest.
Before: write person.entity.proto, person.create.proto,
person.update.proto manually, keep them in sync by hand.
Now:
- Write
person.meta.protowithoption (gcode.schema) = {}; - Run
gcode gen-proto -in proto/— generates all three proto files - Run
gcode -in proto/ -out dao/— generates Go code as before
The generated entity proto has GORM annotations but no validate rules —
Entity.Validate() always returns nil. The generated create/update protos
have validate rules copied directly from the schema. This makes validation
explicit: no implicit inheritance, no cross-file lookup.
Source message rule: do NOT use optional on source message fields.
Optionality is controlled by the derived message annotations:
required_fields→ non-pointer (required) in create structcondition_fields→ non-pointer (WHERE clause) in update struct- all other fields → pointer (optional) in both
Cross-file enum and message type references in derived protos are resolved
automatically — no manual import management needed.
Do not manually edit
*.entity.proto,*.create.proto, or
*.update.proto. They are overwritten on everygen-protorun.
New generated methods
DeepClone() on all message structs
Every generated struct now has DeepClone() returning a fully independent
copy with no shared memory. Handles all field kinds correctly:
original := entity.DeepClone()
updateMsg.ApplyTo(entity)
// compare original vs entity for diff or audit log
ToEntity() on create-derived messages
Converts a create struct to the source entity. Handles all four pointer
combination cases. Fields excluded by ignore_fields remain at zero value.
person := req.ToEntity() // returns *dao.Person
person.CreatedAt = time.Now().Unix()
db.Create(person)
ApplyTo() on update-derived messages
Merges non-nil fields into an existing entity, skipping condition fields.
Useful for in-memory or cache partial updates without a database round-trip.
original := entity.DeepClone()
req.ApplyTo(entity)
cache.Set(key, entity)
Bug fixes
- Fix required/optional/message-type field classification in create/update
validate generation
- Fix ToEntity() non-ptr→ptr branch: value was previously shared between
create struct and entity
- Fix cross-file import resolution in gen-proto
- Fix first-pass parse error chaining
Documentation
All user docs updated (EN + ZH). Key additions:
- getting-started: new capability overview table (what gcode generates,
scope and constraints), corrected source message proto example, field
pointer rules table, new DeepClone usage step
- annotations: source message design principles, ToEntity/ApplyTo usage
examples, DeepClone field handling reference
See docs/getting-started.md for the full walkthrough.
Upgrade notes
No breaking changes to existing gen-dao or gen-ts workflows. Proto files
without option (gcode.schema) = {}; are unaffected. The gen-proto command
is purely additive.Refactor: unify generated Go receiver name to "x"
- Unified "x" receiver name in generated Go methods — Simplified the code generator to always use x as the receiver name instead of deriving it from the type name. This matches the standard protobuf-go convention and avoids potential naming conflicts in
generated code.
Feat: add version command and migrate CLI to urfave/cli/v2
Summary
- Add gcode version subcommand that prints version, commit, and build time — resolved automatically via runtime/debug.ReadBuildInfo, so go install @latest produces meaningful output without ldflags
- Migrate CLI from manual switch-based routing to urfave/cli/v2, adding auto-help on no arguments
- Refactor config package to use sentinel ErrUnknownFlag for flag parse errors
- Add exclusive-bound (gt/lt) and pattern validation tests with golden file snapshots
- Update documentation (EN/ZH): getting-started, architecture
What's Changed
- feat(cli): add version command and migrate to urfave/cli/v2 — cmd/gcode/main.go, internal/version/version.go, internal/app/app.go
- refactor(config): use sentinel ErrUnknownFlag for flag parse errors — internal/config/errors.go, internal/config/config.go, internal/config/tsconfig.go
- test(compat): add exclusive-bound and pattern validation tests — testdata/compat/all_types_validate_test.go, golden files updated
- docs: add version command and internal/version package to documentation — docs/getting-started.md, docs/architecture.md (EN/ZH)
Full Changelog: v0.2.0...v0.3.1
Release Notes (v0.3.0)
What's New in v0.3.0
HTTP Handler Interceptor Chain
Generated HTTP handlers now accept optional handlerx.Interceptor args, enabling logging, metrics, tracing, or any cross-cutting concern per route. Built-in panic recovery is always applied as the outermost layer.
// Before (v0.2.0) — still works
r.POST("/persons", dao.CreatePersonHandler(svc))
// Now — with interceptor
r.DELETE("/persons/:id", dao.DeletePersonHandler(svc,
LoggingInterceptor[DeletePersonRequest, DeletePersonResponse](logger),
))
Error Handling Overhaul
All internal error matching migrated from strings.Contains to errorx.Sentinel domain errors. Each package (app, config, render, source, parser, transform) now has its own error domain with typed sentinels.
Security Fixes
- JSDoc */ properly escaped in TypeScript comment generation
- Nesting depth limits enforced in code generation
- Proto string injection vectors closed
- String literals in generated validate code use %q formatting
BizCode Redefined
HTTP response codes redefined as 4-digit constants with reserved ranges:
- 1000 — BadRequest (JSON parse errors)
- 1001 — ValidationErr (field constraint failures)
- 5000 — DefaultErr (internal errors, message never exposed to client)
Test Coverage Improvements
┌────────────────────┬──────────┐
│ Package │ Coverage │
├────────────────────┼──────────┤
│ internal/naming │ 100% │
├────────────────────┼──────────┤
│ internal/tsrender │ 100% │
├────────────────────┼──────────┤
│ httpruntime │ 100% │
├────────────────────┼──────────┤
│ runtime │ 95.2% │
├────────────────────┼──────────┤
│ internal/transform │ 94.0% │
├────────────────────┼──────────┤
│ validateruntime │ 90.9% │
├────────────────────┼──────────┤
│ internal/app │ 86.7% │
├────────────────────┼──────────┤
│ internal/render │ 86.3% │
├────────────────────┼──────────┤
│ internal/source │ 86.8% │
├────────────────────┼──────────┤
│ internal/config │ 80.0% │
├────────────────────┼──────────┤
│ internal/parser │ 79.9% │
└────────────────────┴──────────┘
New test suites: all_types proto coverage matrix, fuzz testing, HTTP handler e2e, truncated input, unknown field handling, wire type error paths, TreeNode edge cases.
Known Limitations
┌─────────────────────────────────────────────────────────────────┬──────────┐
│ Limitation │ Severity │
├─────────────────────────────────────────────────────────────────┼──────────┤
│ Streaming RPC not supported │ Medium │
├─────────────────────────────────────────────────────────────────┼──────────┤
│ map<K,V> not supported │ Medium │
├─────────────────────────────────────────────────────────────────┼──────────┤
│ oneof not supported │ Medium │
├─────────────────────────────────────────────────────────────────┼──────────┤
│ Well-known types not supported │ Medium │
├─────────────────────────────────────────────────────────────────┼──────────┤
│ Proto2 not supported │ Low │
├─────────────────────────────────────────────────────────────────┼──────────┤
│ Cross-package enum imports not auto-generated in derived protos │ Low │
├─────────────────────────────────────────────────────────────────┼──────────┤
│ HTTP path params not bound by generated handlers │ Low │
├─────────────────────────────────────────────────────────────────┼──────────┤
│ repeated enum defined_only silently skipped │ Low │
└─────────────────────────────────────────────────────────────────┴──────────┘
Upgrade Notes
- Breaking: BizCode constants changed from 1/2/99 to 1000/1001/5000. If you match on specific code values in client code, update accordingly.
- Generated HTTP handler signatures now accept optional ...handlerx.Interceptor — existing calls without interceptors are unaffected.
Full Changelog: https://github.com/pinealctx/gcode/compare/v0.2.0...v0.3.0Feat: add TypeScript code generation (gen-ts)
Summary
- Add
gcode gen-tssubcommand that generates TypeScript type definitions from proto files - Generates
.pb.tsfiles with interfaces, enums, enum name mappings, and validation metadata - Cross-file type references resolved via
TypeRegistrywith ES module imports (.jsextension) - Runtime verification via
tsc --noEmit+tsxtest runner, integrated into Go tests - Documentation updated (EN/ZH): getting-started, architecture, design-decisions, README
Initial release of gcode
Proto-to-Go code generator targeting DAO/business layer code
Key features:
- Pure Go proto parser via protocompile, no protoc dependency
- Generated structs with json/gorm tags, MarshalBinary/UnmarshalBinary
- Validate() methods via buf/validate annotation syntax
- Derived message generation (update_message / create_message)
- Service interface and gin HTTP handler factory generation
- Duplicate field detection via [2]uint64 bitmask (supports up to 128
non-repeated fields; exceeding the limit is a generation-time error) - Public runtime packages: runtime, validateruntime, httpruntime
- Full compatibility test suite against protoc-gen-go wire output
- Chinese/English documentation (architecture, annotations, design decisions)
Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com