diff --git a/examples/generated/proto/examplecom/simple_service_pb_service.d.ts b/examples/generated/proto/examplecom/simple_service_pb_service.d.ts index 351e7360..02f17987 100644 --- a/examples/generated/proto/examplecom/simple_service_pb_service.d.ts +++ b/examples/generated/proto/examplecom/simple_service_pb_service.d.ts @@ -80,13 +80,13 @@ interface RequestStream { on(type: 'end', handler: () => void): RequestStream; on(type: 'status', handler: (status: Status) => void): RequestStream; } -interface BidirectionalStream { - write(message: T): BidirectionalStream; +interface BidirectionalStream { + write(message: Req): BidirectionalStream; end(): void; cancel(): void; - on(type: 'data', handler: (message: T) => void): BidirectionalStream; - on(type: 'end', handler: () => void): BidirectionalStream; - on(type: 'status', handler: (status: Status) => void): BidirectionalStream; + on(type: 'data', handler: (message: Res) => void): BidirectionalStream; + on(type: 'end', handler: () => void): BidirectionalStream; + on(type: 'status', handler: (status: Status) => void): BidirectionalStream; } export class SimpleServiceClient { @@ -104,7 +104,7 @@ export class SimpleServiceClient { ): UnaryResponse; doServerStream(requestMessage: proto_examplecom_simple_service_pb.StreamRequest, metadata?: grpc.Metadata): ResponseStream; doClientStream(metadata?: grpc.Metadata): RequestStream; - doBidiStream(metadata?: grpc.Metadata): BidirectionalStream; + doBidiStream(metadata?: grpc.Metadata): BidirectionalStream; delete( requestMessage: proto_examplecom_simple_service_pb.UnaryRequest, metadata: grpc.Metadata, diff --git a/examples/generated/proto/orphan_pb_service.d.ts b/examples/generated/proto/orphan_pb_service.d.ts index ab177ea5..ee2a88eb 100644 --- a/examples/generated/proto/orphan_pb_service.d.ts +++ b/examples/generated/proto/orphan_pb_service.d.ts @@ -48,13 +48,13 @@ interface RequestStream { on(type: 'end', handler: () => void): RequestStream; on(type: 'status', handler: (status: Status) => void): RequestStream; } -interface BidirectionalStream { - write(message: T): BidirectionalStream; +interface BidirectionalStream { + write(message: Req): BidirectionalStream; end(): void; cancel(): void; - on(type: 'data', handler: (message: T) => void): BidirectionalStream; - on(type: 'end', handler: () => void): BidirectionalStream; - on(type: 'status', handler: (status: Status) => void): BidirectionalStream; + on(type: 'data', handler: (message: Res) => void): BidirectionalStream; + on(type: 'end', handler: () => void): BidirectionalStream; + on(type: 'status', handler: (status: Status) => void): BidirectionalStream; } export class OrphanServiceClient { diff --git a/src/service/grpcweb.ts b/src/service/grpcweb.ts index 6c4f9d1f..f4dba71a 100644 --- a/src/service/grpcweb.ts +++ b/src/service/grpcweb.ts @@ -1,14 +1,14 @@ -import {filePathToPseudoNamespace, normaliseFieldObjectName, replaceProtoSuffix, getPathToRoot} from "../util"; -import {ExportMap} from "../ExportMap"; -import {Printer} from "../Printer"; -import {CodePrinter} from "../CodePrinter"; +import { filePathToPseudoNamespace, normaliseFieldObjectName, replaceProtoSuffix, getPathToRoot } from "../util"; +import { ExportMap } from "../ExportMap"; +import { Printer } from "../Printer"; +import { CodePrinter } from "../CodePrinter"; import { FileDescriptorProto, MethodDescriptorProto, ServiceDescriptorProto } from "google-protobuf/google/protobuf/descriptor_pb"; -import {WellKnownTypesMap} from "../WellKnown"; -import {getFieldType, MESSAGE_TYPE} from "../ts/FieldTypes"; -import {CodeGeneratorResponse} from "google-protobuf/google/protobuf/compiler/plugin_pb"; +import { WellKnownTypesMap } from "../WellKnown"; +import { getFieldType, MESSAGE_TYPE } from "../ts/FieldTypes"; +import { CodeGeneratorResponse } from "google-protobuf/google/protobuf/compiler/plugin_pb"; export function generateGrpcWebService(filename: string, descriptor: FileDescriptorProto, exportMap: ExportMap): CodeGeneratorResponse.File[] { return [ @@ -142,7 +142,7 @@ class GrpcWebServiceDescriptor { namespace: filePathToPseudoNamespace(this.filename), path: `${this.pathToRoot}${replaceProtoSuffix(this.filename)}`, }; - return [ hostProto ].concat(dependencies); + return [hostProto].concat(dependencies); } get services(): RPCDescriptor[] { @@ -222,13 +222,13 @@ function generateTypescriptDefinition(fileDescriptor: FileDescriptorProto, expor printer.printIndentedLn(`on(type: 'end', handler: () => void): RequestStream;`); printer.printIndentedLn(`on(type: 'status', handler: (status: Status) => void): RequestStream;`); printer.printLn(`}`); - printer.printLn(`interface BidirectionalStream {`); - printer.printIndentedLn(`write(message: T): BidirectionalStream;`); + printer.printLn(`interface BidirectionalStream {`); + printer.printIndentedLn(`write(message: Req): BidirectionalStream;`); printer.printIndentedLn(`end(): void;`); printer.printIndentedLn(`cancel(): void;`); - printer.printIndentedLn(`on(type: 'data', handler: (message: T) => void): BidirectionalStream;`); - printer.printIndentedLn(`on(type: 'end', handler: () => void): BidirectionalStream;`); - printer.printIndentedLn(`on(type: 'status', handler: (status: Status) => void): BidirectionalStream;`); + printer.printIndentedLn(`on(type: 'data', handler: (message: Res) => void): BidirectionalStream;`); + printer.printIndentedLn(`on(type: 'end', handler: () => void): BidirectionalStream;`); + printer.printIndentedLn(`on(type: 'status', handler: (status: Status) => void): BidirectionalStream;`); printer.printLn(`}`); printer.printEmptyLn(); @@ -301,10 +301,10 @@ function printServiceStub(methodPrinter: Printer, service: RPCDescriptor) { const printer = new CodePrinter(0, methodPrinter); printer - .printLn(`function ${service.name}Client(serviceHost, options) {`) + .printLn(`function ${service.name}Client(serviceHost, options) {`) .indent().printLn(`this.serviceHost = serviceHost;`) - .printLn(`this.options = options || {};`) - .dedent().printLn(`}`) + .printLn(`this.options = options || {};`) + .dedent().printLn(`}`) .printEmptyLn(); service.methods.forEach((method: RPCMethodDescriptor) => { @@ -324,180 +324,180 @@ function printServiceStub(methodPrinter: Printer, service: RPCDescriptor) { function printUnaryStubMethod(printer: CodePrinter, method: RPCMethodDescriptor) { printer - .printLn(`${method.serviceName}Client.prototype.${method.nameAsCamelCase} = function ${method.functionName}(requestMessage, metadata, callback) {`) - .indent().printLn(`if (arguments.length === 2) {`) - .indent().printLn(`callback = arguments[1];`) - .dedent().printLn("}") - .printLn(`var client = grpc.unary(${method.serviceName}.${method.nameAsPascalCase}, {`) - .indent().printLn(`request: requestMessage,`) - .printLn(`host: this.serviceHost,`) - .printLn(`metadata: metadata,`) - .printLn(`transport: this.options.transport,`) - .printLn(`debug: this.options.debug,`) - .printLn(`onEnd: function (response) {`) - .indent().printLn(`if (callback) {`) - .indent().printLn(`if (response.status !== grpc.Code.OK) {`) - .indent().printLn(`var err = new Error(response.statusMessage);`) - .printLn(`err.code = response.status;`) - .printLn(`err.metadata = response.trailers;`) - .printLn(`callback(err, null);`) - .dedent().printLn(`} else {`) - .indent().printLn(`callback(null, response.message);`) - .dedent().printLn(`}`) - .dedent().printLn(`}`) - .dedent().printLn(`}`) - .dedent().printLn(`});`) - .printLn(`return {`) - .indent().printLn(`cancel: function () {`) - .indent().printLn(`callback = null;`) - .printLn(`client.close();`) - .dedent().printLn(`}`) + .printLn(`${method.serviceName}Client.prototype.${method.nameAsCamelCase} = function ${method.functionName}(requestMessage, metadata, callback) {`) + .indent().printLn(`if (arguments.length === 2) {`) + .indent().printLn(`callback = arguments[1];`) + .dedent().printLn("}") + .printLn(`var client = grpc.unary(${method.serviceName}.${method.nameAsPascalCase}, {`) + .indent().printLn(`request: requestMessage,`) + .printLn(`host: this.serviceHost,`) + .printLn(`metadata: metadata,`) + .printLn(`transport: this.options.transport,`) + .printLn(`debug: this.options.debug,`) + .printLn(`onEnd: function (response) {`) + .indent().printLn(`if (callback) {`) + .indent().printLn(`if (response.status !== grpc.Code.OK) {`) + .indent().printLn(`var err = new Error(response.statusMessage);`) + .printLn(`err.code = response.status;`) + .printLn(`err.metadata = response.trailers;`) + .printLn(`callback(err, null);`) + .dedent().printLn(`} else {`) + .indent().printLn(`callback(null, response.message);`) + .dedent().printLn(`}`) + .dedent().printLn(`}`) + .dedent().printLn(`}`) + .dedent().printLn(`});`) + .printLn(`return {`) + .indent().printLn(`cancel: function () {`) + .indent().printLn(`callback = null;`) + .printLn(`client.close();`) + .dedent().printLn(`}`) .dedent().printLn(`};`) - .dedent().printLn(`};`); + .dedent().printLn(`};`); } function printServerStreamStubMethod(printer: CodePrinter, method: RPCMethodDescriptor) { printer - .printLn(`${method.serviceName}Client.prototype.${method.nameAsCamelCase} = function ${method.functionName}(requestMessage, metadata) {`) + .printLn(`${method.serviceName}Client.prototype.${method.nameAsCamelCase} = function ${method.functionName}(requestMessage, metadata) {`) .indent().printLn(`var listeners = {`) - .indent().printLn(`data: [],`) - .printLn(`end: [],`) - .printLn(`status: []`) + .indent().printLn(`data: [],`) + .printLn(`end: [],`) + .printLn(`status: []`) .dedent().printLn(`};`) - .printLn(`var client = grpc.invoke(${method.serviceName}.${method.nameAsPascalCase}, {`) - .indent().printLn(`request: requestMessage,`) - .printLn(`host: this.serviceHost,`) - .printLn(`metadata: metadata,`) - .printLn(`transport: this.options.transport,`) - .printLn(`debug: this.options.debug,`) - .printLn(`onMessage: function (responseMessage) {`) - .indent().printLn(`listeners.data.forEach(function (handler) {`) - .indent().printLn(`handler(responseMessage);`) - .dedent().printLn(`});`) - .dedent().printLn(`},`) - .printLn(`onEnd: function (status, statusMessage, trailers) {`) - .indent().printLn(`listeners.end.forEach(function (handler) {`) - .indent().printLn(`handler();`) - .dedent().printLn(`});`) - .printLn(`listeners.status.forEach(function (handler) {`) - .indent().printLn(`handler({ code: status, details: statusMessage, metadata: trailers });`) - .dedent().printLn(`});`) - .printLn(`listeners = null;`) - .dedent().printLn(`}`) + .printLn(`var client = grpc.invoke(${method.serviceName}.${method.nameAsPascalCase}, {`) + .indent().printLn(`request: requestMessage,`) + .printLn(`host: this.serviceHost,`) + .printLn(`metadata: metadata,`) + .printLn(`transport: this.options.transport,`) + .printLn(`debug: this.options.debug,`) + .printLn(`onMessage: function (responseMessage) {`) + .indent().printLn(`listeners.data.forEach(function (handler) {`) + .indent().printLn(`handler(responseMessage);`) + .dedent().printLn(`});`) + .dedent().printLn(`},`) + .printLn(`onEnd: function (status, statusMessage, trailers) {`) + .indent().printLn(`listeners.end.forEach(function (handler) {`) + .indent().printLn(`handler();`) + .dedent().printLn(`});`) + .printLn(`listeners.status.forEach(function (handler) {`) + .indent().printLn(`handler({ code: status, details: statusMessage, metadata: trailers });`) + .dedent().printLn(`});`) + .printLn(`listeners = null;`) + .dedent().printLn(`}`) .dedent().printLn(`});`) - .printLn(`return {`) - .indent().printLn(`on: function (type, handler) {`) - .indent().printLn(`listeners[type].push(handler);`) - .printLn(`return this;`) - .dedent().printLn(`},`) - .printLn(`cancel: function () {`) - .indent().printLn(`listeners = null;`) - .printLn(`client.close();`) - .dedent().printLn(`}`) + .printLn(`return {`) + .indent().printLn(`on: function (type, handler) {`) + .indent().printLn(`listeners[type].push(handler);`) + .printLn(`return this;`) + .dedent().printLn(`},`) + .printLn(`cancel: function () {`) + .indent().printLn(`listeners = null;`) + .printLn(`client.close();`) + .dedent().printLn(`}`) .dedent().printLn(`};`) - .dedent().printLn(`};`); + .dedent().printLn(`};`); } function printClientStreamStubMethod(printer: CodePrinter, method: RPCMethodDescriptor) { printer - .printLn(`${method.serviceName}Client.prototype.${method.nameAsCamelCase} = function ${method.functionName}(metadata) {`) + .printLn(`${method.serviceName}Client.prototype.${method.nameAsCamelCase} = function ${method.functionName}(metadata) {`) .indent().printLn(`var listeners = {`) - .indent().printLn(`end: [],`) - .printLn(`status: []`) + .indent().printLn(`end: [],`) + .printLn(`status: []`) .dedent().printLn(`};`) - .printLn(`var client = grpc.client(${method.serviceName}.${method.nameAsPascalCase}, {`) - .indent().printLn(`host: this.serviceHost,`) - .printLn(`metadata: metadata,`) - .printLn(`transport: this.options.transport`) + .printLn(`var client = grpc.client(${method.serviceName}.${method.nameAsPascalCase}, {`) + .indent().printLn(`host: this.serviceHost,`) + .printLn(`metadata: metadata,`) + .printLn(`transport: this.options.transport`) .dedent().printLn(`});`) - .printLn(`client.onEnd(function (status, statusMessage, trailers) {`) - .indent().printLn(`listeners.end.forEach(function (handler) {`) - .indent().printLn(`handler();`) - .dedent().printLn(`});`) - .printLn(`listeners.status.forEach(function (handler) {`) - .indent().printLn(`handler({ code: status, details: statusMessage, metadata: trailers });`) - .dedent().printLn(`});`) - .printLn(`listeners = null;`) + .printLn(`client.onEnd(function (status, statusMessage, trailers) {`) + .indent().printLn(`listeners.end.forEach(function (handler) {`) + .indent().printLn(`handler();`) .dedent().printLn(`});`) - .printLn(`return {`) - .indent().printLn(`on: function (type, handler) {`) - .indent().printLn(`listeners[type].push(handler);`) - .printLn(`return this;`) - .dedent().printLn(`},`) - .printLn(`write: function (requestMessage) {`) - .indent().printLn(`if (!client.started) {`) - .indent().printLn(`client.start(metadata);`) - .dedent().printLn(`}`) - .printLn(`client.send(requestMessage);`) - .printLn(`return this;`) - .dedent().printLn(`},`) - .printLn(`end: function () {`) - .indent().printLn(`client.finishSend();`) - .dedent().printLn(`},`) - .printLn(`cancel: function () {`) - .indent().printLn(`listeners = null;`) - .printLn(`client.close();`) - .dedent().printLn(`}`) + .printLn(`listeners.status.forEach(function (handler) {`) + .indent().printLn(`handler({ code: status, details: statusMessage, metadata: trailers });`) + .dedent().printLn(`});`) + .printLn(`listeners = null;`) + .dedent().printLn(`});`) + .printLn(`return {`) + .indent().printLn(`on: function (type, handler) {`) + .indent().printLn(`listeners[type].push(handler);`) + .printLn(`return this;`) + .dedent().printLn(`},`) + .printLn(`write: function (requestMessage) {`) + .indent().printLn(`if (!client.started) {`) + .indent().printLn(`client.start(metadata);`) + .dedent().printLn(`}`) + .printLn(`client.send(requestMessage);`) + .printLn(`return this;`) + .dedent().printLn(`},`) + .printLn(`end: function () {`) + .indent().printLn(`client.finishSend();`) + .dedent().printLn(`},`) + .printLn(`cancel: function () {`) + .indent().printLn(`listeners = null;`) + .printLn(`client.close();`) + .dedent().printLn(`}`) .dedent().printLn(`};`) - .dedent().printLn(`};`); + .dedent().printLn(`};`); } function printBidirectionalStubMethod(printer: CodePrinter, method: RPCMethodDescriptor) { printer - .printLn(`${method.serviceName}Client.prototype.${method.nameAsCamelCase} = function ${method.functionName}(metadata) {`) + .printLn(`${method.serviceName}Client.prototype.${method.nameAsCamelCase} = function ${method.functionName}(metadata) {`) .indent().printLn(`var listeners = {`) - .indent().printLn(`data: [],`) - .printLn(`end: [],`) - .printLn(`status: []`) + .indent().printLn(`data: [],`) + .printLn(`end: [],`) + .printLn(`status: []`) .dedent().printLn(`};`) - .printLn(`var client = grpc.client(${method.serviceName}.${method.nameAsPascalCase}, {`) - .indent().printLn(`host: this.serviceHost,`) - .printLn(`metadata: metadata,`) - .printLn(`transport: this.options.transport`) + .printLn(`var client = grpc.client(${method.serviceName}.${method.nameAsPascalCase}, {`) + .indent().printLn(`host: this.serviceHost,`) + .printLn(`metadata: metadata,`) + .printLn(`transport: this.options.transport`) + .dedent().printLn(`});`) + .printLn(`client.onEnd(function (status, statusMessage, trailers) {`) + .indent().printLn(`listeners.end.forEach(function (handler) {`) + .indent().printLn(`handler();`) + .dedent().printLn(`});`) + .printLn(`listeners.status.forEach(function (handler) {`) + .indent().printLn(`handler({ code: status, details: statusMessage, metadata: trailers });`) .dedent().printLn(`});`) - .printLn(`client.onEnd(function (status, statusMessage, trailers) {`) - .indent().printLn(`listeners.end.forEach(function (handler) {`) - .indent().printLn(`handler();`) - .dedent().printLn(`});`) - .printLn(`listeners.status.forEach(function (handler) {`) - .indent().printLn(`handler({ code: status, details: statusMessage, metadata: trailers });`) - .dedent().printLn(`});`) - .printLn(`listeners = null;`) + .printLn(`listeners = null;`) .dedent().printLn(`});`) - .printLn(`client.onMessage(function (message) {`) - .indent().printLn(`listeners.data.forEach(function (handler) {`) - .indent().printLn(`handler(message);`) - .dedent().printLn(`})`) + .printLn(`client.onMessage(function (message) {`) + .indent().printLn(`listeners.data.forEach(function (handler) {`) + .indent().printLn(`handler(message);`) + .dedent().printLn(`})`) .dedent().printLn(`});`) - .printLn(`client.start(metadata);`) - .printLn(`return {`) - .indent().printLn(`on: function (type, handler) {`) - .indent().printLn(`listeners[type].push(handler);`) - .printLn(`return this;`) - .dedent().printLn(`},`) - .printLn(`write: function (requestMessage) {`) - .indent().printLn(`client.send(requestMessage);`) - .printLn(`return this;`) - .dedent().printLn(`},`) - .printLn(`end: function () {`) - .indent().printLn(`client.finishSend();`) - .dedent().printLn(`},`) - .printLn(`cancel: function () {`) - .indent().printLn(`listeners = null;`) - .printLn(`client.close();`) - .dedent().printLn(`}`) + .printLn(`client.start(metadata);`) + .printLn(`return {`) + .indent().printLn(`on: function (type, handler) {`) + .indent().printLn(`listeners[type].push(handler);`) + .printLn(`return this;`) + .dedent().printLn(`},`) + .printLn(`write: function (requestMessage) {`) + .indent().printLn(`client.send(requestMessage);`) + .printLn(`return this;`) + .dedent().printLn(`},`) + .printLn(`end: function () {`) + .indent().printLn(`client.finishSend();`) + .dedent().printLn(`},`) + .printLn(`cancel: function () {`) + .indent().printLn(`listeners = null;`) + .printLn(`client.close();`) + .dedent().printLn(`}`) .dedent().printLn(`};`) - .dedent().printLn(`};`); + .dedent().printLn(`};`); } function printServiceStubTypes(methodPrinter: Printer, service: RPCDescriptor) { const printer = new CodePrinter(0, methodPrinter); printer - .printLn(`export class ${service.name}Client {`) + .printLn(`export class ${service.name}Client {`) .indent().printLn(`readonly serviceHost: string;`) - .printEmptyLn() - .printLn(`constructor(serviceHost: string, options?: ServiceClientOptions);`); + .printEmptyLn() + .printLn(`constructor(serviceHost: string, options?: ServiceClientOptions);`); service.methods.forEach((method: RPCMethodDescriptor) => { if (method.requestStream && method.responseStream) { @@ -515,14 +515,14 @@ function printServiceStubTypes(methodPrinter: Printer, service: RPCDescriptor) { function printUnaryStubMethodTypes(printer: CodePrinter, method: RPCMethodDescriptor) { printer - .printLn(`${method.nameAsCamelCase}(`) - .indent().printLn(`requestMessage: ${method.requestType},`) - .printLn(`metadata: grpc.Metadata,`) - .printLn(`callback: (error: ServiceError|null, responseMessage: ${method.responseType}|null) => void`) + .printLn(`${method.nameAsCamelCase}(`) + .indent().printLn(`requestMessage: ${method.requestType},`) + .printLn(`metadata: grpc.Metadata,`) + .printLn(`callback: (error: ServiceError|null, responseMessage: ${method.responseType}|null) => void`) .dedent().printLn(`): UnaryResponse;`) - .printLn(`${method.nameAsCamelCase}(`) - .indent().printLn(`requestMessage: ${method.requestType},`) - .printLn(`callback: (error: ServiceError|null, responseMessage: ${method.responseType}|null) => void`) + .printLn(`${method.nameAsCamelCase}(`) + .indent().printLn(`requestMessage: ${method.requestType},`) + .printLn(`callback: (error: ServiceError|null, responseMessage: ${method.responseType}|null) => void`) .dedent().printLn(`): UnaryResponse;`); } @@ -535,5 +535,5 @@ function printClientStreamStubMethodTypes(printer: CodePrinter, method: RPCMetho } function printBidirectionalStubMethodTypes(printer: CodePrinter, method: RPCMethodDescriptor) { - printer.printLn(`${method.nameAsCamelCase}(metadata?: grpc.Metadata): BidirectionalStream<${method.responseType}>;`); + printer.printLn(`${method.nameAsCamelCase}(metadata?: grpc.Metadata): BidirectionalStream<${method.requestType}, ${method.responseType}>;`); } diff --git a/test/integration/service/grpcweb.ts b/test/integration/service/grpcweb.ts index f803aa87..bb863a94 100644 --- a/test/integration/service/grpcweb.ts +++ b/test/integration/service/grpcweb.ts @@ -453,7 +453,8 @@ describe("service/grpc-web", () => { }); describe("bidirectional streaming", () => { - const [ payload ] = makePayloads("some value"); + const payload = new StreamRequest(); + payload.setSomeString("some value"); it("should route the request to the expected endpoint", (done) => { let targetUrl = ""; @@ -496,7 +497,7 @@ describe("service/grpc-web", () => { it("should invoke onEnd before onStatus if the server ends the stream", (done) => { let onEndInvoked = false; - makeClient(new StubTransportBuilder().withMessages([ payload ])) + makeClient(new StubTransportBuilder().withMessages([payload])) .doBidiStream() .on("end", () => { onEndInvoked = true; }) .on("status", () => { @@ -535,7 +536,10 @@ describe("service/grpc-web", () => { }); it("should allow the caller to supply multiple messages", (done) => { - const [ reqMsgOne, reqMsgTwo ] = makePayloads("one", "two"); + const reqMsgOne = new StreamRequest(); + reqMsgOne.setSomeString("one"); + const reqMsgTwo = new StreamRequest(); + reqMsgTwo.setSomeString("two"); const sentMessageBytes: ArrayBufferView[] = []; makeClient(new StubTransportBuilder().withMessageListener(v => { sentMessageBytes.push(v); }))