-
Notifications
You must be signed in to change notification settings - Fork 350
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
I've been writing a Protobuf plugin for TypeScript #250
Comments
Hey! Thanks for reaching out! Yep, would be great to have you collaborate on ts-proto. A lot of what you want makes sense, and especially All of your asks/suggestions makes sense, and I agree splitting them out into per-issue/per-PR proposals makes sense. Just glancing, I think the only thing that sticks out is that I originally had I'm in a rush, but will do a 1st-pass-thoughts on each of ^ later today/tonight. |
Initial thoughts:
As a summary, I'm not -1 on anything you want to contribute, so feel free to start some PRs. :-) |
Yep that's fine for 99% cases, though I can imagine cases when we need to preserve micro and nanoseconds. Unfortunately, I don't know of any JS lib that allows to work with date/time with sub-millisecond precision. Anyways, this is minor for now.
Ideally, I'd like to have the same codegen that would work with both
Yep I feel you, though currently to build a new framework, you have to first do the codegen stuff. With generic service definitions, you can start right away. You can also make a breaking change to the framework's server/client signatures without changing the code generator. That said, I agree that having the complete server/client types generated is good for users, because they can see the signatures of all methods in generated code; while with mapped types, they need an IDE to see final types. So my proposal is to have an option to output generic definitions, and then (sometime in the future) another option to also output server/client types for |
Ah sure.
Cool, I'd down to try it and see how it goes. Would be great to make it easier to onboard new frameworks, as you said, without bespoke codegen for each. |
PR for type registry and Decided to go with |
PR for generic service definitions: #316 |
@aikoven I was just going through issues today; do you think this one can be closed out? |
Yeah, let's close it, thanks for discussion! |
I was in the middle of writing by own Protobuf plugin for TypeScript, when I discovered
ts-proto
, and I find it so awesome, that I'm considering abandoning my project, and instead start contributing to this one.I'm not sure why I didn't discover it earlier, and I'm surprised how many similar design decisions we have, including:
.proto
files, instead of outputting a single file, or mimicking protobuf package structure.I'd like to discuss the differences between our approaches. Some of them are minor, but some are blockers for us to adopt
ts-proto
, which I'm looking forward to contribute:Nested messages produce nested types, e.g.:
This allows to reference nested type as
Parent.Child
, and its functions asParent.Child.serialize(...)
.Enums produce string unions:
TypeScript string enums are also fine, however, with function
fromNumber
, we could automatically convert unknown numbers to0
, according to Protobuf rules. Still, with TypeScript enums, we can do it manually usingOneof fields appear at top level:
This allows to keep the original structure of fields, and also avoid large changes to the code, when existing field is moved into a
oneof
. It still works as discriminated union:This approach has a downside: it's not easy to assign a different oneof case of existing object, while keeping TypeScript happy. We'd have to treat objects as immutable, and use object spread to alter oneof case:
So in the end, I think that your approach to oneofs is more developer-friendly.
Getting fully-qualified type names given a message object at runtime. This is needed for implementing helpers for
google.protobuf.Any
type (see below). We've solved it by adding@type
field to generated types:Resolving messages given fully-qualified type name at runtime. This is also needed for implementing helpers for
google.protobuf.Any
type (see below). This could be solved using a runtime type registry library, e.g.:and later using it like:
There's an option to codegen type registry as well, instead of having it as a separate library, and put it into the root of
out
dir. This would allow to support different shapes of registered objects, since the shape depends on plugin options.Helpers for
google.protobuf.Any
. This is critical for us. We need a way to have pack and unpack helpers.google.protobuf.Timestamp
produce the same code as any other message, but with extra helperstoDate
/fromDate
:Having implicit conversion to/from
Date
is fine for most cases, but breaks for cases where sub-millisecond precision is required.Generic service definitions. I wrote a library for gRPC (nice-grpc), and it currently consumes service definitions generated for
grpc-js
. I'm currently writing another library for gRPC-Web, which requires service definitions in a different format. My idea was to generate only generic definitions, without generating code for server/client stubs. These stubs can then be generated at type level and at runtime. I'd also like to have service options accessible at runtime, e.g.idempotency_level
could be used for automatic retries.This can later be transformed at type level to server/client type like:
I'd like to hear your thoughts on this. The most critical parts for us are
google.protobuf.Any
helpers and service definitions. If that sounds right to you, I can create separate proposal issues and later work on PRs once we settle with solutions.Btw, your
ts-poet
library is neat! Nice work.The text was updated successfully, but these errors were encountered: