Skip to content

Releases: pinealctx/gcode

Add HTTP pre-validation hooks and restore flat Go output layout

07 May 12:01

Choose a tag to compare

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 WithPreValidateHook and WithInterceptors handler options.
  • Added generated XxxHandlerWithOptions functions for service RPC HTTP handlers.
  • Added runtime recovery for pre-validation hook panics, converting them into panicx.ErrPanic-compatible errors.

Changed

  • httpruntime.NewHandler remains 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 -out directory.
  • 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_package into 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.NewHandler callers 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

15 Apr 05:30
a1b5a8a

Choose a tag to compare

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 correctlycommon.proto and other shared files are no longer dropped from generated create/update protos when cross-file enum or message types are used.
  • items constraints fully supportedsint32, sint64, sfixed32, sfixed64, fixed32, fixed64 scalar types and repeated enum fields now generate correct validation annotations. Previously these were silently skipped.
  • JSON and validate annotations preserved in derived messagesjson tags and validate_message annotations are now correctly carried through to generated create/update protos.
  • .meta.proto imports remapped correctly — External imports in schema files are now remapped to their .entity.proto counterparts instead of being dropped.
  • ApplyTo now handles message-type fields — Previously, message-type fields were incorrectly classified as condition fields and skipped during ApplyTo and ToMap. This is now fixed via explicit condition_fields in UpdateSourceOptions.
  • items.not_in nil-slice case — Added test coverage for nil-slice pass case, symmetric with items.in.

Documentation

  • Added in/not_in examples to the items constraints section in annotations docs (EN + ZH).
  • Removed the "repeated enum defined_only not enforced" known limitation — this was fixed in this release.

Internal

  • Removed ~100 lines of typeSourceIndex + collectExternalImports machinery in favor of letting protocompile resolve imports directly.
  • Added item.meta.proto cross-file compat test scenario with full golden file coverage.

Full Changelog: v0.4.0...v0.5.0

v0.4.0: .meta.proto schema pipeline

14 Apr 09:07
f7ce8ee

Choose a tag to compare

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:

  1. Write person.meta.proto with option (gcode.schema) = {};
  2. Run gcode gen-proto -in proto/ — generates all three proto files
  3. 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 struct
  • condition_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 every gen-proto run.

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-ptrptr 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"

12 Apr 16:35
aaf8fc3

Choose a tag to compare

  • 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

11 Apr 12:42
44e9b30

Choose a tag to compare

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)

11 Apr 06:36
38eb9ec

Choose a tag to compare

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:
- 1000BadRequest (JSON parse errors)
- 1001ValidationErr (field constraint failures)
- 5000DefaultErr (internal errors, message never exposed to client)

Test Coverage Improvements

┌────────────────────┬──────────┐
│      PackageCoverage │
├────────────────────┼──────────┤
│ internal/naming100%     │
├────────────────────┼──────────┤
│ internal/tsrender100%     │
├────────────────────┼──────────┤
│ httpruntime100%     │
├────────────────────┼──────────┤
│ runtime95.2%    │
├────────────────────┼──────────┤
│ internal/transform94.0%    │
├────────────────────┼──────────┤
│ validateruntime90.9%    │
├────────────────────┼──────────┤
│ internal/app86.7%    │
├────────────────────┼──────────┤
│ internal/render86.3%    │
├────────────────────┼──────────┤
│ internal/source86.8%    │
├────────────────────┼──────────┤
│ internal/config80.0%    │
├────────────────────┼──────────┤
│ internal/parser79.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

┌─────────────────────────────────────────────────────────────────┬──────────┐
│                           LimitationSeverity │
├─────────────────────────────────────────────────────────────────┼──────────┤
│ Streaming RPC not supportedMedium   │
├─────────────────────────────────────────────────────────────────┼──────────┤
│ map<K,V> not supportedMedium   │
├─────────────────────────────────────────────────────────────────┼──────────┤
│ oneof not supportedMedium   │
├─────────────────────────────────────────────────────────────────┼──────────┤
│ Well-known types not supportedMedium   │
├─────────────────────────────────────────────────────────────────┼──────────┤
│ Proto2 not supportedLow      │
├─────────────────────────────────────────────────────────────────┼──────────┤
│ Cross-package enum imports not auto-generated in derived protosLow      │
├─────────────────────────────────────────────────────────────────┼──────────┤
│ HTTP path params not bound by generated handlersLow      │
├─────────────────────────────────────────────────────────────────┼──────────┤
│ repeated enum defined_only silently skippedLow      │
└─────────────────────────────────────────────────────────────────┴──────────┘

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.Interceptorexisting calls without interceptors are unaffected.

Full Changelog: https://github.com/pinealctx/gcode/compare/v0.2.0...v0.3.0

Feat: add TypeScript code generation (gen-ts)

02 Apr 10:05
8e82012

Choose a tag to compare

Summary

  • Add gcode gen-ts subcommand that generates TypeScript type definitions from proto files
  • Generates .pb.ts files with interfaces, enums, enum name mappings, and validation metadata
  • Cross-file type references resolved via TypeRegistry with ES module imports (.js extension)
  • Runtime verification via tsc --noEmit + tsx test runner, integrated into Go tests
  • Documentation updated (EN/ZH): getting-started, architecture, design-decisions, README

Initial release of gcode

31 Mar 14:11

Choose a tag to compare

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