-
Notifications
You must be signed in to change notification settings - Fork 6
Suggestion: cleaner definition types #27
Comments
finished a more complete example of the latter (interface is the single source of truth, clients and handlers are based off of them). It includes both a handler and a client. It has to use the handlers to create the clients though, which is still a tad awkward |
heres a slightly stranger option that would reduce the boilerplate but would require the use of a |
@andykais thanks for your detailed typescript playground examples! I can however, clearly see that it is possible to define only a handler once, and have the service types be inferred. However, I believe the original reason the handlers and service definitions are separate is: We use the RPC client only on the React Web UI, whereas the Server side handlers implement the handlers using server side specific packages (like a DB driver). Both sides import the service definition, but neither side imports each other. Now, it's possible with good tree shaking, or stubbing out webpack builds, or a typescript -> webpack build, to have the Web UI import the service definition types only without implementation. However, this could present more challenges than it's worth, and is not trivial to do depending on how you've set up the build. Therefore, the simple solution is to have the service definition to have decoupling of the interfaces. In a microservices multi-repo based approach, the definitions could even live in their own repository, with the RPC client not even able to reach the handler code at all. Let me know if your use case falls outside this. |
Ah fair enough, I had not considered the annoyances of tree shaking. The third example (using a |
@andykais I am interested in your RPC implementation. May you put it in a gist? |
@lingz How can I gain understanding of the lib usage and implementation? I mean, should I look into grpc-web documentation? What actually your lib add or customises beyond grpc-web? First thing I need to know is how to customise headers and send cookies. Where can I read about how this grpc+json implementation and how it's way of operation differs from regular POST?
Thank you! |
How do you do dynamic validation? |
Regular POST can be sent currently over http2, while grpc-web cannot, right? |
Why no need for proxy? |
@lishine I actually have a full working implementation of what I described, but unfortunately I am waiting for it to be cleared with my company before I opens source it. What I can share right now, is that this is fairly easy to roll yourself w/ proxies. As for dynamic validation, if you want to stick with pure typescript types, theres a fantastic library for creating runtime validators from typescript types here https://www.npmjs.com/package/typescript-is. Finally, I will just leave some general advice about RPCs. They work fantastic for client/server implementations where the surface api is relatively small, and where the client and server are both written by you. It keeps your code DRY. Adding dynamic validation really implies that the api is open to the public and you want to be ready for any input under the sun. This is where RPCs start to get unwieldy. GraphQL & REST apis are more suited as client facing apis since they have well known verbage and allow more flexible usage. In those cases, its actually beneficial to not share an implementation on the client and server. |
@andykais thanks for your help |
I dont want to hijack this thread too much since we're getting off topic but I will try to answer concisely:
the solution I built uses proxies (it has compile time safety, but no runtime safety)
there are definitely large apps built with grpc, if you wish to go this route that is certainly an option, but I can argue that the implementation will be more complex than a simple typescript rpc, specifically because it has to support so many different usage patterns
It is like you said, a rpc implementation using only typescript can rely on compile time checks for safety, but if you do not know if your clients will all use typescript, then you will want some kind of runtime safety, hence grpc, graphql, rest, etc |
Hi! Super excited about this library, gRPC was too unapproachable no its own but this library has a much smaller footprint which is awesome. One thing that stuck out though was your service definitions. They look a tad awkward. Messing around, I figured out how to convert handlers into definitions using typescript object traversal. I was wondering if this could be useful in some capacity.
Personally I like the idea of defining my protocols once instead of a type and then a handler. However, if you think defnitions should be the source of truth (like gRPC) then you could define a type only in typescript and pass that around instead of this definitions object that also holds the definition types
The text was updated successfully, but these errors were encountered: