protoc-gen-ets: Protobuf, but make it sendable
protoc-gen-ets turns .proto schemas into ArkTS classes that OpenHarmony can move across workers without hand-written glue.
- protoc-gen-ets makes concurrency a codegen problem, not an app-level patch, by emitting ArkTS that can travel across OpenHarmony workers with @Sendable semantics.
- The repository's real advantage is architectural, because it builds a formal AST in Rust instead of assembling strings and hoping the output stays valid.
- Its collector first, emit second pipeline is what lets it resolve cross-file types, defaults, and imports before the first line of code is written.
- This is a narrow fork with a clear job: it is the right tool when your protobuf world has to fit OpenHarmony's runtime rules, not when you just need generic TypeScript.
OpenHarmony does not reward vague codegen. If a Protobuf message is going to cross a worker boundary, it has to obey ArkTS's rules, and that is where protoc-gen-ets earns its keep.
protoc plugin for ArkTS, Compile .proto files to plain ArkTS
Why this fork exists
The README says it plainly: this project was Forked from protoc-gen-ts. That is the right place to start, because the interesting move is not inventing Protobuf support from scratch. It is narrowing a general TypeScript generator until it matches OpenHarmony's flatter file layout, stricter typing, and sendable concurrency model.
Forked from protoc-gen-ts
That narrowing matters because ArkTS is not just TypeScript with a new badge. In OpenHarmony, classes that move between tasks need @Sendable, bigint mapping can change by deployment choice, and namespace shape is not cosmetic. The generator bakes those constraints into the emitted code so teams do not patch them after the fact.
How the pipeline works
The implementation leans on Rust and the SWC ecosystem to treat code generation like compilation, not templating. src/collector.rs walks the descriptors first and registers every message and enum. src/context.rs keeps the import graph and type registry in sync, and src/emit.rs turns the finished module items into ArkTS with swc_ecma_codegen.
That sequence is what keeps the generator honest. Cross-file references are available before emission, duplicate imports can be merged, and default-value logic in src/common/field.rs can decide whether a field belongs in the binary output or should be skipped because Proto3 still treats it as default.
What lives where
src/common/field.rshandles Proto3 defaults, oneof checks, and binary inclusion rules.src/options.rsturns flags likebigint_as_longandnamespace_as_fileinto generation behavior.js/plugin/wraps the Rust binary for npm distribution.js/runtime/supplies the PbShell test harness.
protoc \
--plugin=protoc-gen-ets=./node_modules/.bin/protoc-gen-ets \
--ets_out=namespace_as_file=true,bigint_as_long=true:./gen \
--proto_path=./proto \
./proto/example.proto
What it buys, and what it costs
Compared with a generic TypeScript generator, protoc-gen-ets gives you less surface area to babysit and more runtime fit. Compared with handwritten ArkTS wrappers, it gives you repeatable output, consistent defaults, and a place to encode policy once. The tradeoff is obvious: this is a specialist tool. It is strongest where OpenHarmony constraints are non-negotiable, and less interesting anywhere else.
Supports ArkTS(ets) with @Sendable for concurrent
| Approach | Strength | Weak spot | Best fit |
|---|---|---|---|
| protoc-gen-ets | ArkTS output tuned for OpenHarmony | Specialized and opinionated | Apps that need sendable Protobuf classes |
| protoc-gen-ts | General TypeScript generation | No OpenHarmony-specific runtime semantics | Standard TypeScript targets |
| Handwritten ArkTS wrappers | Total control over code shape | Slow to maintain and easy to drift | Tiny schemas or prototypes |





