Skip to content

feat!: migrate proto codegen + RPC from ts-proto/nice-grpc to protobuf-es/connect-es#68

Merged
philz3906 merged 11 commits into
mainfrom
dev/philz3906/protobuf-es-migration
Jun 10, 2026
Merged

feat!: migrate proto codegen + RPC from ts-proto/nice-grpc to protobuf-es/connect-es#68
philz3906 merged 11 commits into
mainfrom
dev/philz3906/protobuf-es-migration

Conversation

@philz3906

Copy link
Copy Markdown
Contributor

What

Migrates the SDK's TypeScript proto stack from ts-proto + nice-grpc to protobuf-es (@bufbuild/protobuf) + connect-es (@connectrpc/connect). Direct cutover across @sentio/protos, @sentio/runtime, @sentio/sdk, and @sentio/action.

Depends on the es_proto codegen targets landed in sentio-core (#260, #262).

Highlights

  • Codegen: write_gen now pulls protobuf-es output (*_pb.ts) from sentio-core's es_proto targets. Well-known types come from @bufbuild/protobuf/wkt; google.type.Money + the grpc-gateway openapiv2 option dep are handled (the latter stripped from common_pb.ts since the SDK never reads those options).
  • Runtime gRPC server: nice-grpc → connect-es connectNodeAdapter over HTTP/2 (h2c) — same gRPC wire protocol, so Go/other gRPC peers are unaffected. ServerError/StatusConnectError/Code; the nice-grpc-error-details middleware is dropped (connect serializes details intrinsically). Streaming handlers keep the rxjs/ix withAbort(ctx.signal) shape.
  • Consumers (~110 files): Foo.fromPartial(x)create(FooSchema, x); oneof flat fields → { case, value } discriminated unions; Timestamp Date ↔ WKT via timestampDate/timestampFromDate; google.protobuf.StructJsonObject; enum *FromJSON/*ToJSONenumFromJson/enumToJson.
  • Codegen templates updated (eth) so pnpm gen reproduces the protobuf-es output byte-for-byte.
  • deps: drop nice-grpc* + long; add @connectrpc/connect (+ -node for the runtime) and @bufbuild/protobuf.

Verification

  • tsc --noEmit clean across protos / runtime / sdk / action.
  • Tests: runtime 18/18, sdk 170/170, action 2/2.
  • pnpm gen (all chains) reproduces checked-in generated files byte-for-byte.
  • pnpm lint clean; compile + runtime bundle (ESM+DTS) green.

🤖 Generated with Claude Code

philz3906 and others added 11 commits June 9, 2026 16:19
Repoint //sentio-sdk:write_gen to the es_proto codegen targets and
regenerate packages/protos/src + packages/runtime/src/gen as protobuf-es
(*_pb.ts). Well-known types (empty/struct/timestamp) are no longer
generated locally — consumers import them from @bufbuild/protobuf/wkt.
The grpc-gateway openapiv2 option dependency is stripped from common_pb.ts
(the SDK never reads those options; verified protobuf-es boots + binary
round-trips without it). Allow generated *_pb.ts in .ls-lint.yml.

WIP: consumer code, the @sentio/protos index, package deps, and the
nice-grpc -> connect-es runtime server are NOT yet migrated; the SDK does
not compile until the ts-proto-API + nice-grpc rewrite lands. Part of the
single protobuf-es cutover PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s deps [WIP cutover]

- @sentio/protos index.ts: re-export protobuf-es output (*_pb), pull WKTs
  (Empty/Timestamp/Struct/Value/ListValue + Schemas + timestamp helpers) from
  @bufbuild/protobuf/wkt, and the common types + their *Schema. Package builds
  green (tsc).
- @sentio/protos deps: drop long + nice-grpc*; keep @bufbuild/protobuf only.
- @sentio/runtime deps: drop long + all nice-grpc*; add @connectrpc/connect +
  @connectrpc/connect-node (connect-es v2, pairs with protobuf-es v2).

WIP: runtime server + sdk consumers not yet migrated. Part of the single
protobuf-es cutover PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…IP cutover]

Rewrite the @sentio/runtime gRPC server stack from ts-proto + nice-grpc to
protobuf-es + connect-es:
- processor-runner.ts: createServer/server.add(Definition) -> connectNodeAdapter
  + http2.createServer (h2c gRPC wire; Go launcher client unaffected). Drop
  nice-grpc-error-details middleware.
- service.ts / service-v3.ts / full-service.ts: implement ServiceImpl<typeof
  Processor|ProcessorV3>; CallContext -> HandlerContext; ServerError(Status.X) ->
  ConnectError(Code.X); oneof flat fields -> {case,value}; *.fromPartial/.create
  -> create(Schema,...); DeepPartial -> MessageInitShape.
- consumers (db-context/utils/plugin/global-config/action-server): create(),
  oneof, Timestamp, enum transforms; doSend widened to the V2|V3 init union.
- @sentio/protos index: export * from common_pb so nested types are nameable
  (portable .d.ts); disambiguate the EventLogConfig collision.

Runtime SOURCE typechecks clean (tsc --noEmit, 0 non-test errors). Runtime test
files + the SDK package consumers are not yet migrated. Part of the single
protobuf-es cutover PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… cutover]

Update the 4 runtime test files (service.test, service-v3.test, seq-mode.test,
test-processor.test) to the protobuf-es API: import from @sentio/protos (*_pb),
create(Schema,...) for message construction, {case,value} oneof access,
CallContext -> HandlerContext mock. The @sentio/runtime package now typechecks
clean (tsc --noEmit, 0 errors).

Note: assertion *values* (deepEqual fixtures) still need a `pnpm test` runtime
pass to confirm against the new message shapes. Part of the single protobuf-es
cutover PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tover]

Rewrite all @sentio/sdk chain consumers (eth/aptos/sui/iota/fuel/solana/cosmos),
core, store, testing harness, and utils from ts-proto + nice-grpc to protobuf-es
+ connect-es. @sentio/sdk now typechecks clean (tsc --noEmit, 0 errors).

Highlights:
- create(FooSchema, ...) for all message construction; {case,value} discriminated
  unions for oneofs (Data, RichValue, DBRequest/Response, LogFilter.addressOrType,
  CoinID.id, Partition.value, fuel receiptFilter, etc.).
- ServerError(Status.X) -> ConnectError(Code.X) across ~22 files.
- Timestamp Date<->WKT via timestampDate/timestampFromDate; google.protobuf.Struct
  as plain JsonObject (RichStruct/RichValue keep message semantics + toBinary/fromBinary).
- HandlerOptions<F,D>: Partial<F> -> Omit<Partial<F>,'$typeName'|'$unknown'> so it
  feeds create(); HandleInterval literals wrapped in create(HandleIntervalSchema,...).
- test harness getConfig accepts MessageInitShape (so test `{}` calls work).
- SDK index disambiguates BigDecimal (core's @sentio/bigdecimal wins over proto's).
- deps: drop nice-grpc*; add @connectrpc/connect + @bufbuild/protobuf.
- CLAUDE.md: document the protobuf-es + connect-es stack.

Note: test assertion *values* still need a `pnpm test` runtime pass. Part of the
single protobuf-es cutover PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
action.test.ts: ProcessConfigResponse.fromPartial({}) -> create(ProcessConfigResponseSchema, {}).
action-plugin.ts uses ProcessConfigResponse as a type only (unchanged). Add
@bufbuild/protobuf dep. @sentio/action typechecks clean.

All four proto-consuming packages (protos, runtime, sdk, action) now typecheck
clean against protobuf-es + connect-es. Part of the single protobuf-es cutover PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The eth binding codegen emits EthCallContext construction in the generated
*BoundContractView.encodeCall methods. Update the template to emit
`create(EthCallContextSchema, {...})` instead of a bare object literal, and add
`EthCallContextSchema` + `create` (@bufbuild/protobuf) to the generated import
block. Verified: `pnpm gen:eth` now reproduces the checked-in generated files
byte-for-byte (clean git diff).

Only the eth codegen constructs proto messages; aptos/sui/iota/solana/fuel/store
codegen emit proto types as annotations only (no template change needed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make the test suites pass at runtime against the protobuf-es message shapes:
- service-v3.test: assert DBRequest fields individually (op.case/value) instead
  of deepEqual against the old flat {get} shape (branded $typeName).
- entity.test: dateValue round-trips through a WKT Timestamp (new Date object) ->
  compare by value (deepEqual) not reference.
- erc20-template handlerFactory: the loader populates templateInstances during
  start, but protobuf-es copies the StartRequest array eagerly; run the loader
  first (empty start) then instantiate via updateTemplates with the populated array.
- iota-facet: transaction.timestampMs is a string; new Date(string) is Invalid
  (NaN) and timestampFromDate throws -> new Date(Number(timestampMs)).

All tests green: runtime 18/18, sdk 170/170, action 2/2.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…utover]

- @sentio/protos index: stop re-exporting common_pb via `export *` (it leaked the
  proto `BigDecimal`, colliding with @sentio/bigdecimal's BigDecimal that the SDK
  re-exports — import-x/export error). Re-export only the common types consumers
  use + the oneof-referenced types needed for portable .d.ts; proto BigDecimal is
  exported solely as `BigDecimalRichValue`.
- @sentio/sdk index: drop the now-unneeded explicit BigDecimal re-export.
- convert.test: `expect(...).true` (chai getter, no-unused-expressions) -> `.eq(true)`.
- drop leftover unused imports (db-context, test-processor-server).

All packages typecheck clean; pnpm lint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
upload.ts imported UserInfo from the now-renamed ts-proto common.js (deep path
into @sentio/protos lib). Point it at common_pb.js and make it a type-only import
(UserInfo is used only as a cast). Fixes the CLI build in CI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The protobuf-es generated files are written verbatim by sentio-core's
scripts/sdk-sync.sh; ignore them in prettier so they are never reformatted
(and CI/lint-staged never flags formatting on machine-generated output).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@philz3906 philz3906 merged commit 6641e32 into main Jun 10, 2026
1 check passed
@philz3906 philz3906 deleted the dev/philz3906/protobuf-es-migration branch June 10, 2026 02:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant