Comments (9)
To make it really generic, we could also:
- Change the signature of the request function to take
interface Rpc {
- request(service: string, method: string, data: Uint8Array): Promise<Uint8Array>;
+ request<Req extends Codec, Res extends Codec>(service: string, method: string, req: Req): Promise<Res>;
}
where Codec
is just:
// This is the interface that's already implemented by all types in ts-proto,
// i only gave it a name
interface Codec<T> {
encode(message: T, writer: Writer = Writer.create()): Writer;
decode(input: Uint8Array | Reader, length?: number): T;
fromJSON(object: any): T;
fromPartial(object: DeepPartial<T>): T;
toJSON(message: T): unknown;
}
- Then, it would be the user's responsability, when implementing the Rpc interface, to decide which wire format to use:
const implWithUint8Array: Rpc = {
request<Req, Res>(service: string, method: string, req: Req): Promise<Res> {
const data = Req.encode(req).finish();
// Do whatever you used to do before, e.g. gRPC
const wireResponse = ...;
return Res.decode(new Reader(wireResponse))
}
}
const implWithJSON: Rpc = {
request<Req, Res>(service: string, method: string, req: Req): Promise<Res> {
const data = Req.toJSON(req);
// Do whatever you used to do before, e.g. gRPC with JSON
const wireResponse = ...;
return Res.fromJSON(wireResponse);
}
}
Advantages:
- no need for an additional protoc option
- allow users to use Uint8Array, JSON for wire transfer... or do other more fancy stuff.
from ts-proto.
I think ideally it would be possible to pass a protoc option to specify which wire formats to generate. This would be nice because JSON-only clients then wouldn't need to import the JS protobuf package.
from ts-proto.
@alecthomas yeah, that is a good point. We'd only needed protobuf/twirp for our rpc/services, so was all we've implemented so far...
The service impl code is fairly straightforward:
https://github.com/stephenh/ts-proto/blob/master/src/main.ts#L725
And I think really it'd just be generateRegularRpc
function that could be the first place to add some conditional "if output type" type logic:
https://github.com/stephenh/ts-proto/blob/master/src/main.ts#L695
Would you be interesting in tacking a crack at this?
I might be able to hack on this at some point, but all the better if you'd like to, and then could verify the impl / usage / etc. within your project / ecosystem.
from ts-proto.
I started to take a look at what would be involved here.
Unfortunately, protobuf.js does not support encoding/decoding to/from canonical proto3 JSON: protobufjs/protobuf.js#1304
It looks like it's partially implemented, but lacking support for important well-known-types like Timestamp
and Duration
.
And google's JS protobuf library has no support at all: protocolbuffers/protobuf-javascript#95
Do you see any way forward?
from ts-proto.
It looks like there are some open PRs that would help, e.g. protobufjs/protobuf.js#1258
Maybe the way forward is to implement this using protobufjs, without support for those well-known types, and then either fork protobuf.js, patch it at runtime, or wait for it to be fixed upstream.
from ts-proto.
Hey @isherman apologies for the really late reply here. It'd be awesome if you could poke around at this.
Per the protobuf.js PRs, I think that shouldn't be a problem, because ts-proto implements its own direct support for the proto3 JSON protocol.
I.e. here is where we generate Message.fromJSON
methods and handle timestamps:
https://github.com/stephenh/ts-proto/blob/master/src/main.ts#L759
We don't handle encoding/encoding Durations yet.
So, in theory, a JSON client would just be some glue that takes the service
interfaces and makes a <Service>JsonClient
that uses ts-proto's existing fromJSON
/toJSON
methods to serde the messages.
from ts-proto.
@amaurymartiny Agree. In my case, I also need the Res codec too.
interface Rpc {
- request(service: string, method: string, data: Uint8Array): Promise<Uint8Array>;
+ request<Req extends Codec, Res extends Codec>(
+ service: string,
+ method: string,
+ data: Uint8Array,
+ req: Req,
+ res: Res
+ ): Promise<Uint8Array>;
}
from ts-proto.
Thanks for picking this up @disjukr, @amaurymartiny, @stephenh.
I lost momentum on #106 when the motivation for JSON serialization became less clear in my application. Will close that now.
Your approach looks more general, an improvement for sure. One tradeoff is it's a breaking change.
But I'm no longer a stakeholder here, so I defer to the maintainer!
from ts-proto.
any moving forward for this issue?
from ts-proto.
Related Issues (20)
- Array message type generates invalid code on account of name collision. HOT 8
- Use bigint literals instead of BigInt constructor. HOT 5
- Compiling generated code causes a heap overflow with tsc HOT 1
- toJSON methods don't respect useDate=false HOT 7
- protoc-gen-ts: program not found or is not executable HOT 1
- Cannot find name 'I'. - when passing opts: --ts_proto_opt="outputServices=generic-definitions,outputServices=default" HOT 4
- Add support for bigint in maps
- Enhancement: `json_name` defined in a proto file should be able to be extracted. HOT 1
- Configurability of the unrecognized enum type HOT 3
- Compilation error when combining `useOptionals=all` with `forceLong=long` HOT 1
- Support Values as service return values HOT 2
- Generate google.api.http-based clients HOT 5
- Is there an example of how to use the grpc-web implementation? HOT 1
- Type error in field_mask.ts when outputServices=grpc-js and useOptionals=all HOT 3
- Support for FieldOptions.JSType HOT 2
- Add support for generating only NestJS clients HOT 2
- Issue with message struct serialization/deserialization in method return type HOT 1
- useDate=false doesn't match protobuf JSON spec HOT 11
- Enum field decoding skipping 0 value HOT 1
- env=browser treated same as env=both. Causes globalThis.Buffer typescript error HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ts-proto.