Skip to content

Commit

Permalink
fix: code-generation for Services with Struct response types (#407)
Browse files Browse the repository at this point in the history
* Fix rpc services that use structs, move struct utils to Struct classes
  • Loading branch information
boukeversteegh committed Nov 27, 2021
1 parent 92f6995 commit f041fa1
Show file tree
Hide file tree
Showing 15 changed files with 892 additions and 298 deletions.
448 changes: 448 additions & 0 deletions integration/grpc-js/google/protobuf/struct.ts

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion integration/grpc-js/google/protobuf/timestamp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,16 @@ export const protobufPackage = 'google.protobuf';
* .setNanos((int) ((millis % 1000) * 1000000)).build();
*
*
* Example 5: Compute Timestamp from current time in Python.
* Example 5: Compute Timestamp from Java `Instant.now()`.
*
* Instant now = Instant.now();
*
* Timestamp timestamp =
* Timestamp.newBuilder().setSeconds(now.getEpochSecond())
* .setNanos(now.getNano()).build();
*
*
* Example 6: Compute Timestamp from current time in Python.
*
* timestamp = Timestamp()
* timestamp.GetCurrentTime()
Expand Down
Binary file modified integration/grpc-js/google/protobuf/wrappers.bin
Binary file not shown.
37 changes: 28 additions & 9 deletions integration/grpc-js/grpc-js-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,32 @@ describe('grpc-js-test', () => {
): void {
callback(null, call.request);
},
struct(
call: ServerUnaryCall<{ [key: string]: any } | undefined, { [key: string]: any }>,
callback: sendUnaryData<{ [key: string]: any } | undefined>){
callback(null, call.request);
},
value(
call: ServerUnaryCall<any | undefined, any | undefined>,
callback: sendUnaryData<any | undefined>) {
callback(null, call.request);
},
listValue(
call: ServerUnaryCall<Array<any> | undefined, Array<any> | undefined>,
callback: sendUnaryData<Array<any> | undefined>) {
callback(null, call.request);
},
serverStreaming(call) {
call.write({
timestamp: call.request.timestamp,
});
call.end();
},
serverStringValueStreaming(call) {
serverStreamingStringValue(call) {
call.write(call.request);
call.end();
},
serverStreamingStruct(call) {
call.write(call.request);
call.end();
},
Expand All @@ -88,7 +107,7 @@ describe('grpc-js-test', () => {
});
});
},
clientStringValueStreaming(call, callback) {
clientStreamingStringValue(call, callback) {
call.on('data', (request) => {
callback(null, request);
});
Expand All @@ -103,7 +122,7 @@ describe('grpc-js-test', () => {
call.end();
});
},
bidiStringValueStreaming(call) {
bidiStreamingStringValue(call) {
call.on('data', (request) => {
call.write(request);
});
Expand Down Expand Up @@ -188,8 +207,8 @@ describe('grpc-js-test', () => {
serverStreamingCall.on('data', (response) => {
expect(response.timestamp).toEqual(timestamp);
});
const serverStringValueStreamingCall = client.serverStringValueStreaming('foobar');
serverStringValueStreamingCall.on('data', (response) => {
const serverStreamingStringValueCall = client.serverStreamingStringValue('foobar');
serverStreamingStringValueCall.on('data', (response) => {
expect(response).toEqual('foobar');
});

Expand All @@ -199,11 +218,11 @@ describe('grpc-js-test', () => {
clientStreamingCall.write({ timestamp });
clientStreamingCall.end();

const clientStringValueStreamingCall = client.clientStringValueStreaming((err, res) => {
const clientStreamingStringValueCall = client.clientStreamingStringValue((err, res) => {
expect(res).toEqual('foobar');
});
clientStringValueStreamingCall.write('foobar');
clientStringValueStreamingCall.end();
clientStreamingStringValueCall.write('foobar');
clientStreamingStringValueCall.end();

const bidiStreamingCall = client.bidiStreaming();
bidiStreamingCall.write({ timestamp });
Expand All @@ -212,7 +231,7 @@ describe('grpc-js-test', () => {
bidiStreamingCall.end();
});

const bidiStringValueStreamingCall = client.bidiStringValueStreaming();
const bidiStringValueStreamingCall = client.bidiStreamingStringValue();
bidiStringValueStreamingCall.write('foobar');
bidiStringValueStreamingCall.on('data', (response) => {
expect(response).toEqual('foobar');
Expand Down
Binary file modified integration/grpc-js/simple.bin
Binary file not shown.
11 changes: 8 additions & 3 deletions integration/grpc-js/simple.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ syntax = "proto3";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
import "google/protobuf/struct.proto";

package simple;

Expand All @@ -25,18 +26,22 @@ service Test {
rpc UnaryDoubleValue(google.protobuf.DoubleValue) returns (google.protobuf.DoubleValue);
rpc UnaryBoolValue(google.protobuf.BoolValue) returns (google.protobuf.BoolValue);
rpc UnaryTimestamp(google.protobuf.Timestamp) returns (google.protobuf.Timestamp);
rpc Struct(google.protobuf.Struct) returns (google.protobuf.Struct);
rpc Value(google.protobuf.Value) returns (google.protobuf.Value);
rpc ListValue(google.protobuf.ListValue) returns (google.protobuf.ListValue);

// Server Streaming
rpc ServerStreaming (TestMessage) returns (stream TestMessage) {}
rpc ServerStringValueStreaming (google.protobuf.StringValue) returns (stream google.protobuf.StringValue) {}
rpc ServerStreamingStringValue (google.protobuf.StringValue) returns (stream google.protobuf.StringValue) {}
rpc ServerStreamingStruct(google.protobuf.Struct) returns (stream google.protobuf.Struct) {}

// Client Streaming
rpc ClientStreaming (stream TestMessage) returns (TestMessage) {}
rpc ClientStringValueStreaming (stream google.protobuf.StringValue) returns (google.protobuf.StringValue) {}
rpc ClientStreamingStringValue (stream google.protobuf.StringValue) returns (google.protobuf.StringValue) {}

// Bidi Streaming
rpc BidiStreaming (stream TestMessage) returns (stream TestMessage) {}
rpc BidiStringValueStreaming (stream google.protobuf.StringValue) returns (stream google.protobuf.StringValue) {}
rpc BidiStreamingStringValue (stream google.protobuf.StringValue) returns (stream google.protobuf.StringValue) {}
}

message TestMessage {
Expand Down
140 changes: 122 additions & 18 deletions integration/grpc-js/simple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
DoubleValue,
BoolValue,
} from './google/protobuf/wrappers';
import { Struct, ListValue, Value } from './google/protobuf/struct';

export const protobufPackage = 'simple';

Expand Down Expand Up @@ -200,6 +201,37 @@ export const TestService = {
responseSerialize: (value: Date) => Buffer.from(Timestamp.encode(toTimestamp(value)).finish()),
responseDeserialize: (value: Buffer) => Timestamp.decode(value),
},
struct: {
path: '/simple.Test/Struct',
requestStream: false,
responseStream: false,
requestSerialize: (value: { [key: string]: any } | undefined) =>
Buffer.from(Struct.encode(Struct.wrap(value)).finish()),
requestDeserialize: (value: Buffer) => Struct.unwrap(Struct.decode(value)),
responseSerialize: (value: { [key: string]: any } | undefined) =>
Buffer.from(Struct.encode(Struct.wrap(value)).finish()),
responseDeserialize: (value: Buffer) => Struct.unwrap(Struct.decode(value)),
},
value: {
path: '/simple.Test/Value',
requestStream: false,
responseStream: false,
requestSerialize: (value: any | undefined) => Buffer.from(Value.encode(value).finish()),
requestDeserialize: (value: Buffer) => Value.decode(value),
responseSerialize: (value: any | undefined) => Buffer.from(Value.encode(value).finish()),
responseDeserialize: (value: Buffer) => Value.decode(value),
},
listValue: {
path: '/simple.Test/ListValue',
requestStream: false,
responseStream: false,
requestSerialize: (value: Array<any> | undefined) =>
Buffer.from(ListValue.encode({ values: value ?? [] }).finish()),
requestDeserialize: (value: Buffer) => ListValue.unwrap(ListValue.decode(value)),
responseSerialize: (value: Array<any> | undefined) =>
Buffer.from(ListValue.encode({ values: value ?? [] }).finish()),
responseDeserialize: (value: Buffer) => ListValue.unwrap(ListValue.decode(value)),
},
/** Server Streaming */
serverStreaming: {
path: '/simple.Test/ServerStreaming',
Expand All @@ -210,15 +242,26 @@ export const TestService = {
responseSerialize: (value: TestMessage) => Buffer.from(TestMessage.encode(value).finish()),
responseDeserialize: (value: Buffer) => TestMessage.decode(value),
},
serverStringValueStreaming: {
path: '/simple.Test/ServerStringValueStreaming',
serverStreamingStringValue: {
path: '/simple.Test/ServerStreamingStringValue',
requestStream: false,
responseStream: true,
requestSerialize: (value: string | undefined) => Buffer.from(StringValue.encode({ value: value ?? '' }).finish()),
requestDeserialize: (value: Buffer) => StringValue.decode(value).value,
responseSerialize: (value: string | undefined) => Buffer.from(StringValue.encode({ value: value ?? '' }).finish()),
responseDeserialize: (value: Buffer) => StringValue.decode(value).value,
},
serverStreamingStruct: {
path: '/simple.Test/ServerStreamingStruct',
requestStream: false,
responseStream: true,
requestSerialize: (value: { [key: string]: any } | undefined) =>
Buffer.from(Struct.encode(Struct.wrap(value)).finish()),
requestDeserialize: (value: Buffer) => Struct.unwrap(Struct.decode(value)),
responseSerialize: (value: { [key: string]: any } | undefined) =>
Buffer.from(Struct.encode(Struct.wrap(value)).finish()),
responseDeserialize: (value: Buffer) => Struct.unwrap(Struct.decode(value)),
},
/** Client Streaming */
clientStreaming: {
path: '/simple.Test/ClientStreaming',
Expand All @@ -229,8 +272,8 @@ export const TestService = {
responseSerialize: (value: TestMessage) => Buffer.from(TestMessage.encode(value).finish()),
responseDeserialize: (value: Buffer) => TestMessage.decode(value),
},
clientStringValueStreaming: {
path: '/simple.Test/ClientStringValueStreaming',
clientStreamingStringValue: {
path: '/simple.Test/ClientStreamingStringValue',
requestStream: true,
responseStream: false,
requestSerialize: (value: string | undefined) => Buffer.from(StringValue.encode({ value: value ?? '' }).finish()),
Expand All @@ -248,8 +291,8 @@ export const TestService = {
responseSerialize: (value: TestMessage) => Buffer.from(TestMessage.encode(value).finish()),
responseDeserialize: (value: Buffer) => TestMessage.decode(value),
},
bidiStringValueStreaming: {
path: '/simple.Test/BidiStringValueStreaming',
bidiStreamingStringValue: {
path: '/simple.Test/BidiStreamingStringValue',
requestStream: true,
responseStream: true,
requestSerialize: (value: string | undefined) => Buffer.from(StringValue.encode({ value: value ?? '' }).finish()),
Expand All @@ -276,15 +319,22 @@ export interface TestServer extends UntypedServiceImplementation {
unaryDoubleValue: handleUnaryCall<number | undefined, number | undefined>;
unaryBoolValue: handleUnaryCall<boolean | undefined, boolean | undefined>;
unaryTimestamp: handleUnaryCall<Date, Date>;
struct: handleUnaryCall<{ [key: string]: any } | undefined, { [key: string]: any } | undefined>;
value: handleUnaryCall<any | undefined, any | undefined>;
listValue: handleUnaryCall<Array<any> | undefined, Array<any> | undefined>;
/** Server Streaming */
serverStreaming: handleServerStreamingCall<TestMessage, TestMessage>;
serverStringValueStreaming: handleServerStreamingCall<string | undefined, string | undefined>;
serverStreamingStringValue: handleServerStreamingCall<string | undefined, string | undefined>;
serverStreamingStruct: handleServerStreamingCall<
{ [key: string]: any } | undefined,
{ [key: string]: any } | undefined
>;
/** Client Streaming */
clientStreaming: handleClientStreamingCall<TestMessage, TestMessage>;
clientStringValueStreaming: handleClientStreamingCall<string | undefined, string | undefined>;
clientStreamingStringValue: handleClientStreamingCall<string | undefined, string | undefined>;
/** Bidi Streaming */
bidiStreaming: handleBidiStreamingCall<TestMessage, TestMessage>;
bidiStringValueStreaming: handleBidiStreamingCall<string | undefined, string | undefined>;
bidiStreamingStringValue: handleBidiStreamingCall<string | undefined, string | undefined>;
}

export interface TestClient extends Client {
Expand Down Expand Up @@ -452,22 +502,76 @@ export interface TestClient extends Client {
options: Partial<CallOptions>,
callback: (error: ServiceError | null, response: Date) => void
): ClientUnaryCall;
struct(
request: { [key: string]: any } | undefined,
callback: (error: ServiceError | null, response: { [key: string]: any } | undefined) => void
): ClientUnaryCall;
struct(
request: { [key: string]: any } | undefined,
metadata: Metadata,
callback: (error: ServiceError | null, response: { [key: string]: any } | undefined) => void
): ClientUnaryCall;
struct(
request: { [key: string]: any } | undefined,
metadata: Metadata,
options: Partial<CallOptions>,
callback: (error: ServiceError | null, response: { [key: string]: any } | undefined) => void
): ClientUnaryCall;
value(
request: any | undefined,
callback: (error: ServiceError | null, response: any | undefined) => void
): ClientUnaryCall;
value(
request: any | undefined,
metadata: Metadata,
callback: (error: ServiceError | null, response: any | undefined) => void
): ClientUnaryCall;
value(
request: any | undefined,
metadata: Metadata,
options: Partial<CallOptions>,
callback: (error: ServiceError | null, response: any | undefined) => void
): ClientUnaryCall;
listValue(
request: Array<any> | undefined,
callback: (error: ServiceError | null, response: Array<any> | undefined) => void
): ClientUnaryCall;
listValue(
request: Array<any> | undefined,
metadata: Metadata,
callback: (error: ServiceError | null, response: Array<any> | undefined) => void
): ClientUnaryCall;
listValue(
request: Array<any> | undefined,
metadata: Metadata,
options: Partial<CallOptions>,
callback: (error: ServiceError | null, response: Array<any> | undefined) => void
): ClientUnaryCall;
/** Server Streaming */
serverStreaming(request: TestMessage, options?: Partial<CallOptions>): ClientReadableStream<TestMessage>;
serverStreaming(
request: TestMessage,
metadata?: Metadata,
options?: Partial<CallOptions>
): ClientReadableStream<TestMessage>;
serverStringValueStreaming(
serverStreamingStringValue(
request: string | undefined,
options?: Partial<CallOptions>
): ClientReadableStream<string | undefined>;
serverStringValueStreaming(
serverStreamingStringValue(
request: string | undefined,
metadata?: Metadata,
options?: Partial<CallOptions>
): ClientReadableStream<string | undefined>;
serverStreamingStruct(
request: { [key: string]: any } | undefined,
options?: Partial<CallOptions>
): ClientReadableStream<{ [key: string]: any } | undefined>;
serverStreamingStruct(
request: { [key: string]: any } | undefined,
metadata?: Metadata,
options?: Partial<CallOptions>
): ClientReadableStream<{ [key: string]: any } | undefined>;
/** Client Streaming */
clientStreaming(
callback: (error: ServiceError | null, response: TestMessage) => void
Expand All @@ -485,18 +589,18 @@ export interface TestClient extends Client {
options: Partial<CallOptions>,
callback: (error: ServiceError | null, response: TestMessage) => void
): ClientWritableStream<TestMessage>;
clientStringValueStreaming(
clientStreamingStringValue(
callback: (error: ServiceError | null, response: string | undefined) => void
): ClientWritableStream<string | undefined>;
clientStringValueStreaming(
clientStreamingStringValue(
metadata: Metadata,
callback: (error: ServiceError | null, response: string | undefined) => void
): ClientWritableStream<string | undefined>;
clientStringValueStreaming(
clientStreamingStringValue(
options: Partial<CallOptions>,
callback: (error: ServiceError | null, response: string | undefined) => void
): ClientWritableStream<string | undefined>;
clientStringValueStreaming(
clientStreamingStringValue(
metadata: Metadata,
options: Partial<CallOptions>,
callback: (error: ServiceError | null, response: string | undefined) => void
Expand All @@ -505,9 +609,9 @@ export interface TestClient extends Client {
bidiStreaming(): ClientDuplexStream<TestMessage, TestMessage>;
bidiStreaming(options: Partial<CallOptions>): ClientDuplexStream<TestMessage, TestMessage>;
bidiStreaming(metadata: Metadata, options?: Partial<CallOptions>): ClientDuplexStream<TestMessage, TestMessage>;
bidiStringValueStreaming(): ClientDuplexStream<string | undefined, string | undefined>;
bidiStringValueStreaming(options: Partial<CallOptions>): ClientDuplexStream<string | undefined, string | undefined>;
bidiStringValueStreaming(
bidiStreamingStringValue(): ClientDuplexStream<string | undefined, string | undefined>;
bidiStreamingStringValue(options: Partial<CallOptions>): ClientDuplexStream<string | undefined, string | undefined>;
bidiStreamingStringValue(
metadata: Metadata,
options?: Partial<CallOptions>
): ClientDuplexStream<string | undefined, string | undefined>;
Expand Down

0 comments on commit f041fa1

Please sign in to comment.