Add Dart + Protobuf converters; make all 8 converters lossless round-trip#16
Merged
Conversation
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced Apr 19, 2026
Closed
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.
Closes #2 (protobuf support).
TLDR
Adds Dart and Protobuf converters, rewrites C#/Go/Python/Rust to round-trip
HOME_PAGE_SAMPLEbyte-for-byte, and wires the new languages into the web converter page.Details
New converters
packages/typediagram/src/converters/dart.ts): sealed-class DUs (sealed class+final class ... extends),typedefaliases,Option<T>↔T?, first-class generics.packages/typediagram/src/converters/protobuf.ts):messagefor records,enumfor unit-only unions,oneof+ nestedmessagefor struct-variant unions,repeated/optional/map<K,V>field labels. Uses// @td-generics:,// @td-type:,// @td-alias:comment directives to encode typeDiagram concepts proto3 can't express natively (generics,Option<List<T>>, aliases).New shared helper
packages/typediagram/src/converters/brace-lang.ts:extractBalancedBlock,splitTopLevelCommas,formatGenericsDecl,extractTrailingNullable,parseGenericParamList. Used by C#, Dart, Protobuf.Converter rewrites for lossless round-trip
using Alias = Target;aliases, primary-constructor records preserving original field names. Replaces the priorJsonPropertyName-discriminated interface pattern.is<Union>()) encoding with union-qualified variant struct names, Go 1.18[T any]generics, field names kept verbatim. Legacy embedded-type ifaces still parse as a fallback.@dataclassclasses plus aName = VarA | "VarB"alias line; parser reads that line back and collapses the variant classes into union variants. Generics viaGeneric[T]/TypeVar. Top-levelEmail = strnow parses asalias.[^}]*enum regex with a brace-balanced body extractor; addedsplitRsFieldListthat respects angle/brace/paren depth soHashMap<String, String>survives as a single field.Option<T>emits asT | undefined; parser acceptsT | undefined,T | null,T | undefined | null,T | null | undefinedasOption<T>. Alias-vs-union detection excludes the option shape.Shared test helper
expectLosslessRoundTrip(converter)intest/converters/helpers.tsasserts TD → lang → TD is byte-for-byte identical toHOME_PAGE_SAMPLE(now exported frompackages/typediagram/src/sample.ts). Each per-language test file now calls it.Web converter page
SupportedLangwidened to includedartandprotobuf.converter.ts; new highlighter rule sets inconverter-highlight.ts.playground.tsandconverter.tsboth source the sample fromHOME_PAGE_SAMPLE— single source of truth across the app.Makefile
make cleannow also removes per-packagecoverage/dirs.make clean-starttarget: kills anything on the Vite dev port (default 5173), full clean, build, then dev.Budgets / config
packages/typediagram/scripts/bundle-size.mjs: budget raised 50 → 75 KB to accommodate two new converters (~8-10 KB each, unminified parser + emitter). Current bundle: 67.81 KB.coverage-thresholds.json: typediagrambranches90.76 → 90.89,functions98.5 → 98.58 (ratcheted up only).packages/cli/test/roundtrip.e2e.test.ts: updated expected C# output frompublic recordtopublic sealed recordto match the new DU emission.How Do The Automated Tests Prove It Works?
Round-trip (all 8 languages pass):
[CONV-FS-RT],[CONV-TS-RT],[CONV-RUST-RT],[CONV-CS-RT],[CONV-PY-RT],[CONV-GO-RT],[CONV-DART-RT],[CONV-PROTO-RT]— each callsexpectLosslessRoundTrip(converter)againstHOME_PAGE_SAMPLEand assertsprintSource(fromSource(toSource(parsed))) === HOME_PAGE_SAMPLEbyte-for-byte.Feature coverage for new converters:
[CONV-DART-FROM]/[CONV-DART-TO]/[CONV-DART-EDGE]/[CONV-DART-ERR](13 tests) — verifies Dart sealed-class DU parsing, generic sealed classes with extending variants,implementsas well asextendson variants,T?↔Option<T>field mapping, empty enums, malformed-field resilience.[CONV-PROTO-FROM]/[CONV-PROTO-TO]/[CONV-PROTO-EDGE]/[CONV-PROTO-ERR](12 tests) — verifiesoneof+ nested message parsing,UNSPECIFIEDsentinel handling,// @td-type/// @td-generics/// @td-aliasdirective handling,map<K, V>andOption<Map<K,V>>edge cases, malformed-line skipping.[CONV-BRACE-LANG](16 tests) — covers the shared helper: balanced-brace extraction for malformed and nested inputs, angle-aware comma splitting, generic-params parsing for plain /extends/ Go-styleT anyforms, nullable extraction, generics formatting.Regression-guarded behaviour changes:
[CONV-CS-BUG-10]reworded to assert the newabstract record+ nestedsealed recordemission (no moreJsonPropertyName("kind")/interface IContentItem).[CONV-CS-BUG-11]reworded to assert primary-constructor records preserving original field names (no more PascalCase +JsonPropertyNameproperty-bag).[CONV-CS-BUG-12]reworded to assert aliases emit asusing X = Y;(previously inlined).[CONV-GO-TO-COMPLEX]and[CONV-GO-RT]updated to assert lowercase field names and union-qualified variant struct names (e.g.ContentItemTextnotText).[WEB-CONVERTER] renders a tab for every supported language— loosened from hardcoded 6 to "expect Dart and Protobuf tabs alongside the original 6".Suite totals: 278 typediagram tests + 211 web tests + 59 CLI tests all pass locally under
make ci. Bundle size 67.81 KB (under 75 KB budget). Coverage meets the ratcheted thresholds (lines ≥ 95%, branches ≥ 90.89%, functions ≥ 98.58% for typediagram-core).