Conversation
- generate `d.ts` file from MVC routes - introduce `@Trpc`, `@Trpc.Query` and `@Trpc.Mutation` - implement `GET` on APT - ref #3863
- ref #3863
- it uses a cool parser which allow to provide custom implemantation of it (Jackson/Avajeb) - remove hardcode dependency to Jackson - implement Java/Kotlin code generation - implement success, void/empty and error reponses - add protocol integration test - ref #3863
- more code cleanup
This major refactor unifies the tRPC route generation with the standard MVC routing flow, eliminating code duplication and properly integrating tRPC endpoints with Jooby's native reactive pipeline. Key changes: * Unify Code Generation: Merged `generateTrpcMethod` into `generateHandlerCall` in `MvcRoute.java` to use a single, robust parameter extraction and method invocation flow. * Reactive Pipeline Support: Fixed an architectural issue where reactive types (CompletableFuture, Mono, Uni, etc.) were incorrectly wrapped in a synchronous TrpcResponse. The APT now generates `Publisher<TrpcResponse<T>>`, injecting the proper `.map(TrpcResponse::of)` operator natively based on the library. * Hybrid Route Support: `MvcRouter.java` now correctly splits dual-purpose methods. If a method is annotated with both a standard HTTP method (e.g., `@GET`) and `@Trpc`, the processor generates two separate mappings and handlers (one traditional MVC, one strict tRPC). * tRPC Precedence & Validation: Enforced strict rules for tRPC annotations. `@Trpc.Query`/`@Trpc.Mutation` take precedence. A bare `@Trpc` annotation now requires an accompanying `@GET` or `@POST` annotation, otherwise it fails the build with a descriptive error. * Kotlin Codegen Fixes: Fixed Return type mismatches for generic parameterized types (adding `as Type` casts), fixed missing non-null assertions (`!!`), and ensured `Void`/`Unit` methods correctly emit `TrpcResponse.empty()`. * Cleanup: Removed dead `trpcPath` resolution methods from `MvcContext` and `HttpPath`, as well as the obsolete `TrpcMethod` record.
This update removes the mandatory JSON array tuple wrapper for single-parameter tRPC procedures. Single arguments now map 1:1, creating a much more natural API for TypeScript clients while preserving the required tuple array for multi-argument methods. Key changes: * TrpcGenerator: Updated TypeScript generation to output raw types for single arguments (e.g., `input: Movie`) instead of wrapping them in tuples. Removed the `buildClassesDir` property to rely strictly on the `ClassLoader`, and aligned annotation precedence to match the APT rules. * APT / MvcRoute: The route generator now evaluates `isTuple` at compile-time (`parameters.size() > 1`) and passes this boolean directly into the `TrpcParser`, eliminating runtime ambiguity and hacky token detection. * JSON Readers: Updated `JacksonTrpcReader` and `AvajeTrpcReader` to accept the `isTuple` flag. The readers now cleanly branch between iterating over an array or reading a raw value directly from the root. * Testing: Overhauled `TrpcProtocolTest` to validate the new seamless protocol, covering raw objects, single-argument collections, multi-argument tuples, reactive payloads, and URL encoding compliance.
This update hardens the TypeScript generation pipeline to prevent internal JVM and reactive wrapper types from leaking into the client definitions, and expands tRPC mutation support to cover all standard state-changing HTTP verbs. Key changes: * TrpcGenerator: Fixed a bug where `CompletableFuture`, `Mono`, `Single`, and other async wrappers were being emitted in the `trpc.d.ts` output. Implemented a deep recursive unwrapping mechanism to extract the true underlying DTOs from complex generic, wildcard, and array signatures. * TrpcGenerator: Added a Jackson "firewall" to the typescript-generator settings, explicitly mapping all known async wrappers to `any` to prevent indirect discovery via reflection. * TrpcGenerator: Dynamically extracts generic type parameters (e.g., `Future<V>`) via reflection to satisfy typescript-generator's strict custom mapping validation, while safely ignoring wrappers not present on the compilation classpath. * TrpcGenerator: Made the `AppRouter` output 100% deterministic to prevent test flakiness. Procedures are now grouped by namespace, visually separated into `// queries` and `// mutations`, and sorted alphabetically. * MvcRoute (APT) & TrpcGenerator: Expanded mutation detection. Methods annotated with base `@Trpc` alongside `@PUT`, `@PATCH`, or `@DELETE` are now correctly categorized as mutations in the TypeScript router and mapped to HTTP POST proxy routes by the Jooby annotation processor.
This commit introduces the build tool plugins required to execute the tRPC TypeScript generator automatically during the build lifecycle, and fixes a bug regarding how framework-specific parameters are handled in the tRPC network payload. Key changes: * MvcRoute (APT) & TrpcGenerator: Explicitly filter out `io.jooby.Context` and `kotlin.coroutines.Continuation` when evaluating tRPC parameters. This prevents the backend from incorrectly expecting a JSON array (tuple) when a method mixes a single payload argument with framework injections, and ensures the TypeScript signatures remain clean. * Maven Plugin: Added `TrpcMojo` bound to the `process-classes` phase. Exposes full configuration for the generator, including `jsonLibrary` (Jackson2, JSON-B, Gson), `customTypeMappings`, and `outputDir` (defaulting to `target/classes`). * Gradle Plugin: Added `TrpcTask` and registered the `io.jooby.trpc` plugin in the `jooby-gradle-plugin` build script, ensuring feature parity with the Maven implementation.
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.
Overview
This PR introduces native, out-of-the-box support for the tRPC (trpc.io) protocol in Jooby.
Historically restricted to the Node.js/TypeScript ecosystem, this feature allows developers to write standard Java/Kotlin controllers and consume them directly in the browser using the official
@trpc/client—complete with 100% type safety, autocomplete, and zero manual client generation.Key Features & Implementation
@Trpc,@Trpc.Query, and@Trpc.Mutationannotations.GETand mutations to HTTPPOSTat the routing layer.@POST,@PUT,@DELETEresolve as tRPC mutations).io.jooby.Contextand KotlinContinuation.TrpcGenerator):typescript-generatorto emit a strictly typedAppRouterand associated data models (DTOs).CompletableFuture,Mono,Single,Uni, etc.) so internal JVM wrapper types never leak into the TypeScript definitions.trpc.d.tsfile grouped by namespaces.TrpcMojotied to theprocess-classesphase.TrpcTaskto thejooby-gradle-plugin.Example
1. The Java Controller
Write standard Jooby controllers using the new
@Trpcannotations.The Generated TypeScript (trpc.d.ts)
The build plugin automatically extracts the DTOs and generates the exact AppRouter shape expected by the frontend @trpc/client.