update versioned types#151
Merged
Merged
Conversation
Generate versioned message envelopes with a function-like `versioned_type!` proc macro that accepts an N-variant list, assigns positional SCALE codec indices, and implements `Versioned` (Latest/LATEST/version). Single-version envelopes also get trivial `IntoLatest`/`FromLatest`; multi-version envelopes leave those bespoke conversions to hand-written impls. The three traits in `truapi::versioned` define a total upgrade/downgrade contract for a server to normalize requests to the latest version, handle them in latest-only terms, and map results back to the caller's version. Generated TypeScript output is byte-identical; codegen skips the helper traits.
461abc8 to
b8ad4a1
Compare
…ndices - compute the contiguity check in usize so a >255-variant enum reports a clean error instead of overflowing the u8 counter - accept an optional visibility on each declared enum (pub/pub(crate)/none) instead of requiring pub - document that versioned_type! expands to crate::versioned::* paths and is meant for use inside the truapi crate - add a multi-version regression test pinning positional codec indices (V1->0, V2->1), version(), and LATEST - call versioned_type! via its fully-qualified path in the versioned modules - refresh the local-e2e troubleshooting note that referenced the removed IntoVersion/Version API
b8ad4a1 to
bb5b018
Compare
2 tasks
filvecchiato
approved these changes
Jun 1, 2026
Collaborator
filvecchiato
left a comment
There was a problem hiding this comment.
Clean design. Total conversions by construction (IntoLatest/FromLatest are infallible) is the right property — version mismatches are decided at design time, not runtime.
The proc macro is well-structured: contiguity validation, proper error spans, single-variant auto-impl vs multi-variant manual. Test coverage looks good.
Will conflict with #145 on versioned/mod.rs (both remove the old Version/IntoVersion), but resolution is straightforward.
filvecchiato
approved these changes
Jun 1, 2026
Collaborator
filvecchiato
left a comment
There was a problem hiding this comment.
Overall looks good
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Versioned message envelopes
Versioned request/response/error types in
truapi::versionedare SCALE enumswhose variants (
V1,V2, …) are successive versions of one logical message,newest last. They are generated by the
versioned_type!function-like procmacro:
The macro assigns positional SCALE codec indices, enforces contiguous
V1..=Vn, and implementsVersioned(theLatestpayload type, theLATESTversion number, and
version()). Single-version envelopes additionally gettrivial
IntoLatest/FromLatest; multi-version envelopes implement those byhand, since the conversion between versions is bespoke. Adding a version is one
line on the envelope plus the hand-written conversion for the direction that
changed.
Conversion contract
Three traits express how a server moves between wire versions and its internal
"latest" representation. Both directions are total by construction, so the
mapping for an old client is decided at design time rather than failing at
runtime:
Intended server usage
The traits are shaped so the whole version dance collapses into one generic
dispatch step. Handlers are written once against
*::Latestand never observeolder versions. (The adapter itself is not part of this PR; it lands with the
server work.)
Codegen
Codegen treats only
truapi::api::*traits as protocol surface and skips theversionedhelper traits, so the generated TypeScript client and wire tablesare byte-identical. The emitted
types.tscarries no standaloneVersiontype, since the protocol exposes no such type.