Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Next major overview #887

Closed
25 of 60 tasks
KATT opened this issue Sep 5, 2021 · 8 comments
Closed
25 of 60 tasks

[RFC] Next major overview #887

KATT opened this issue Sep 5, 2021 · 8 comments
Assignees
Labels
💸 Get paid! I'll send you money through your GitHub sponsors for addressing this next-major/definite Definite things for next major 🙏 review please needs community sign-off

Comments

@KATT
Copy link
Member

KATT commented Sep 5, 2021

So. We're making a new major.

Goals

  • More ergonomic API for creating procedures and building out your backend
  • CMD+Click from your frontend and jump straight into the backend procedure. This will work with react-query as well!
  • Better scaling than the current structure - the TypeScript server starts choking a bit when you get close to 100 procedures in your backend
  • Fully backward compatible for the 99% use-case with a migration path which you can do incrementally.

Todos

Important for contributors: All of the work here is related to the next branch.

Tracked in https://github.com/orgs/trpc/projects/1

  • New Router API
    • Tracked in trpc/v10-playground - the current winning proposal is [RFC] Chainable resolvers  v10-playground#33
    • Error formatting in new API - formatError()-equivalent.
    • meta-equivalent
    • Maybe we need a createRootRouter() that additionally accepts { transformer: X, formatError: Y}
    • Implement new API in tRPC
    • Make old routers compatible (.legacy() at the end to transform them to the new version)
  • New client API with backward compatibility
    • Maybe old can be client.query('postById', input, options) whilst new stuff can be client.queries.postById({ input, ...options})
  • New react-query API with backward compat
  • Make actual issues for all of these
  • Add all old projects in a folder (copy/paste examples/* to examples/.test so we can track breaking changes easily and make sure we remain backward compatible for a long time
  • Rewrite TRPCClient to be functional instead of a class but reuse the same interface
  • Write a migration guide
    • New router API
    • New links
  • Move transformers back to runtime to make it backward compatible
  • Explore: Add stripInternal-flag
  • Simplify HTTP-responses
  • New links architecture (New link architecture #1366)
  • Refactor observables implementation to have unknown errors or make it guaranteed to be TRPCClientError of some sort.
  • Make transformers dynamically opt-in similar to how a batch request is indicated by ?batch=1 maybe a transformed request could be ?transform=1 or transform=TRANSFORMER_NAME?
  • Write a blog post about new major and API.
  • "Marketing"? Hype video, new website, etc
  • Decide on structure for react-query integration
  • Add old website on www/-docs as v9.trpc.io
    • Link it in Docusaurus
    • Make sure we have deployment for a "v9"-branch

Stretch

Old notes

Definite

  • Remove official support for node 12.x
    • Remove E2E-test for 12.x
    • Change tsconfig build target
  • Add official support for node 16.x
  • Add stripInternal-flag
  • Remove all @deprecated stuff
  • New links architecture (New link architecture #1366)
  • Move official support for react-query 3 to 4
  • Simplify HTTP-responses
    • From { id:null, result: {type: 'data', data: x } } -> { result: { data: x } }
    • maybe remove id: null from HTTP responses?
  • Migration guides for all changed parts
    • New Links

Maybe ❓

Feedback please!

Transformers

  • Turn transformers into a link on the client (New link architecture #1366)
  • Revert above and put transformers back to runtime 😬
  • Turn transformers into a middleware on the server
  • Make transformers dynamically opt-in similar to how a batch request is indicated by ?batch=1 maybe a transformed request could be ?transform=1 or transform=TRANSFORMER_NAME?

Misc

  • Rename @trpc/react/ssg -> @trpc/react/ssr & createSSGHelpers -> createServerSideHelpers (or something, as it is often used in getServerSideProps() as well as getStaticProps())

Open questions

  • Should we continue to follow OpenRPC?
  • Any changes that could make tRPC easier to support stuff like Svelte/Vue?
  • Any changes that could make tRPC stricter support stuff like AWS Lambdas? (Already is doable to do Lambdas but through an Express->Lambda converter) Add lambda gateway handler #882
  • Ideas?
@KATT KATT added ⏭ major bump needed Requires a major version bump and removed ⏭ major bump needed Requires a major version bump labels Sep 5, 2021
@KATT KATT modified the milestones: v9, v10 Sep 5, 2021
@KATT KATT changed the title remove support for node 12.x Next major notes Sep 8, 2021
@KATT KATT changed the title Next major notes Notes for next major bump Sep 9, 2021
@KATT KATT self-assigned this Sep 26, 2021
@KATT KATT added the ⏭ major bump needed Requires a major version bump label Sep 26, 2021
@KATT

This comment has been minimized.

@mmkal

This comment has been minimized.

@KATT KATT added the 🙏 review please needs community sign-off label Oct 6, 2021
@mmkal

This comment has been minimized.

@KATT KATT pinned this issue Jan 11, 2022
@KATT KATT changed the title Notes for next major bump [RFC] Next major bump Jan 12, 2022
@KATT KATT added the 💸 Get paid! I'll send you money through your GitHub sponsors for addressing this label Mar 6, 2022
@KATT KATT unpinned this issue Mar 6, 2022
@jlalmes
Copy link
Contributor

jlalmes commented Mar 17, 2022

Regarding Simplify HTTP-responses:

  • This would means moving away from the JSON-RPC spec, are we ok with this?
  • Would this also mean removing id: 1 from the HTTP-request?
  • I see you've listed https://jsonapi.org/format/ as a maybe? I've been using the Slack Web API (https://api.slack.com/web#slack-web-api__basics) recently which has a very similar RPC-type structure. Could be worth taking a look and drawing inspiration.

@jlalmes
Copy link
Contributor

jlalmes commented Mar 17, 2022

continued...

@skimhugo

This comment was marked as off-topic.

@KATT KATT pinned this issue Apr 7, 2022
@KATT KATT changed the title [RFC] Next major bump [RFC] Next major overview Apr 10, 2022
@KATT KATT removed this from the v10 milestone Apr 11, 2022
@KATT KATT moved this to In Progress in Roadmap and priorities Apr 11, 2022
@KATT KATT added next-major/definite Definite things for next major and removed ⏭ major bump needed Requires a major version bump labels Apr 12, 2022
@rakeshpai
Copy link

rakeshpai commented Aug 1, 2022

Hey. Just came across this upcoming update. I wasn't aware that this update was in the works, and had started work on a similar project. https://github.com/rakeshpai/birdsong It isn't production-ready yet. It is heavily inspired by tRPC, but these are the differences from tRPC 9:

  • Using actual tokens instead of strings to name methods (tRPC 10 takes care of this.)
  • Cmd+click to jump to definition between client and server. (Again, 10 takes care of this.)
  • Handling all the built-in JS types, eg. Dates, Maps, Sets, etc., and not just the primitives that JSON supports, without needing an external library. (tRPC requires an external library for this, but that might be ok for most people.)
  • Easily extending the supported types by writing simple serialiser / deserialiser functions for the new custom types - useful for custom types that don't have internal state, like for eg. Email. (I haven't exposed this currently even in my package, but the design has been done to allow for this.)
  • Being agnostic to the environment (node / deno / CF workers, etc) that the server is going to run in. This has been done by converting node's request and response objects to W3C Request and Response objects at the boundaries, and using the W3C objects everywhere in the code rather than the node built-ins.
  • Automatically detecting if a method's network call should be a GET or a POST rather than explicitly having to specify if the method is a query or a mutation - this has been done by seeing if the method name starts with some known prefixes like get or list. So, getUsers would be a GET request, and updateUser would be a POST just because of how they're named. I'm on the fence about whether this is a good idea. It does simplify the API somewhat, but introduces a little bit of magic and/or forces a convention.
  • Keeping the client-side bundle vanishingly small - it's currently under 5kb before minification and gzip, and IIRC it's under 3kb after minification and gzip. (Aren't proxies magical!) This does forgo many runtime checks, but that should be ok since the TS types are very strict.
  • A functional composition based API, rather than a chaining+router API, for writing the server code. You could put this down to personal preference - a chaining API might be what most people prefer anyway.
  • Simplified imports - there's just one package to be npm installed, and the server and client code are both part of the same package. Client-side bundling + tree-shaking eliminates server code, so there's no leakage of server code into the client bundle.
  • Built-in but opt-in pretty logging on the client-side similar to redux-logger to help with debugging.

I had even more ambitious plans with my package, but some of those have fallen by the wayside for now:

  • Having the same API for communication between the browser main thread and web workers to enable functionality similar to Comlink. The API has been designed to minimise HTTP-specifics to enable this in the future, but I haven't done anything to actually build this out. The end result is that in large client-heavy projects, there's only one RPC API that teams need to learn, regardless of which thread/network boundary they're crossing.
  • Ditto for communication between the main thread and service workers. This is particularly interesting since the semantics are still of making HTTP calls from the main thread, except you run the 'server' inside a service worker. This could potentially open up the doors to building new kinds of apps that run primarily in the service worker, but are painful to do today because of how the sw APIs are. Again, I haven't really explored this yet.

I'm very happy to know that the first two points above, which are the biggest ergonomic differences from tRPC 9, are now going to be handled in 10. With that in mind, I'm happy to abandon my project. However, I thought I'd leave the rest of the list here to see if there's interest in targeting them with upcoming updates to tRPC.

You can see usage examples of my package in the tests. Apologies for not documenting this better.

Edit: Terminology (/s/module/package)

@sachinraja
Copy link
Member

sachinraja commented Aug 1, 2022

Hey @rakeshpai! Birdsong looks great! Here's a response to your points:

Handling all the built-in JS types

I don't see this changing for us. superjson handles all of this as you noted and allows you to have custom types with serializer/deserializer functions.

Being agnostic to the environment (node / deno / CF workers, etc) that the server is going to run in

tRPC v10 can run anywhere and is agnostic to the environment. We cannot use the Fetch API Request and Response yet because they aren't available in Node so we just use a common format for request/response shapes. Also tRPC v10 has a Fetch adapter to convert these shapes to Request/Response objects.

Automatically detecting if a method's network call should be a GET or a POST rather than explicitly having to specify if the method is a query or a mutation - this has been done by seeing if the method name starts with some known prefixes like get or list

We can consider this, but I don't think it's a great idea. I'm not a fan of implicit behavior on this level. In a way, having to specify keywords in front of the procedure names is still explicit. As a side note this was also brought up in #2270 (reply in thread).

Keeping the client-side bundle vanishingly small

We'd love to have your help here! This is something on our radar to look at before release. That being said, the client is kept fairly minimal.

Simplified imports - there's just one package to be npm installed

Yeah, this is also something we discussed. It's not a huge problem right now (compared to the other things we're working on), but we're open to ideas here.

Built-in but opt-in pretty logging on the client-side

Awesome! tRPC has this too with the loggerLink.

Having the same API for communication between the browser main thread and web workers to enable functionality similar to Comlink. The API has been designed to minimise HTTP-specifics to enable this in the future, but I haven't done anything to actually build this out.

You can likely achieve this with a custom link on the client. tRPC has also also been designed to minimize HTTP-specifics. For example, see the WebSocket link and trpc-chrome.


It seems like you've thought about this a lot and we'd love to have you involved in the decision-making for v10. We'd also love to have you as a contributor to tRPC! If you're interested, please join the Discord and we can talk more.

@KATT KATT closed this as completed Sep 22, 2022
Repository owner moved this from 🚧 In Progress to ✅ Done in Roadmap and priorities Sep 22, 2022
@trpc trpc locked and limited conversation to collaborators Sep 22, 2022
@sachinraja sachinraja unpinned this issue Sep 24, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
💸 Get paid! I'll send you money through your GitHub sponsors for addressing this next-major/definite Definite things for next major 🙏 review please needs community sign-off
Projects
Archived in project
Development

No branches or pull requests

6 participants