1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | var Printer_1 = require("../Printer");
|
4 | var CodePrinter_1 = require("../CodePrinter");
|
5 | var common_1 = require("./common");
|
6 | function generateGrpcWebService(filename, descriptor, exportMap) {
|
7 | return [
|
8 | common_1.createFile(generateTypeScriptDefinition(descriptor, exportMap), filename + "_service.d.ts"),
|
9 | common_1.createFile(generateJavaScript(descriptor, exportMap), filename + "_service.js"),
|
10 | ];
|
11 | }
|
12 | exports.generateGrpcWebService = generateGrpcWebService;
|
13 | function generateTypeScriptDefinition(fileDescriptor, exportMap) {
|
14 | var serviceDescriptor = new common_1.GrpcServiceDescriptor(fileDescriptor, exportMap);
|
15 | var printer = new Printer_1.Printer(0);
|
16 | printer.printLn("// package: " + serviceDescriptor.packageName);
|
17 | printer.printLn("// file: " + serviceDescriptor.filename);
|
18 | printer.printEmptyLn();
|
19 | if (serviceDescriptor.services.length === 0) {
|
20 | return printer.getOutput();
|
21 | }
|
22 | serviceDescriptor.imports
|
23 | .forEach(function (importDescriptor) {
|
24 | printer.printLn("import * as " + importDescriptor.namespace + " from \"" + importDescriptor.path + "\";");
|
25 | });
|
26 | printer.printLn("import {grpc} from \"@improbable-eng/grpc-web\";");
|
27 | printer.printEmptyLn();
|
28 | serviceDescriptor.services
|
29 | .forEach(function (service) {
|
30 | service.methods.forEach(function (method) {
|
31 | printer.printLn("type " + method.serviceName + method.nameAsPascalCase + " = {");
|
32 | printer.printIndentedLn("readonly methodName: string;");
|
33 | printer.printIndentedLn("readonly service: typeof " + method.serviceName + ";");
|
34 | printer.printIndentedLn("readonly requestStream: " + method.requestStream + ";");
|
35 | printer.printIndentedLn("readonly responseStream: " + method.responseStream + ";");
|
36 | printer.printIndentedLn("readonly requestType: typeof " + method.requestType + ";");
|
37 | printer.printIndentedLn("readonly responseType: typeof " + method.responseType + ";");
|
38 | printer.printLn("};");
|
39 | printer.printEmptyLn();
|
40 | });
|
41 | printer.printLn("export class " + service.name + " {");
|
42 | printer.printIndentedLn("static readonly serviceName: string;");
|
43 | service.methods.forEach(function (method) {
|
44 | printer.printIndentedLn("static readonly " + method.nameAsPascalCase + ": " + method.serviceName + method.nameAsPascalCase + ";");
|
45 | });
|
46 | printer.printLn("}");
|
47 | printer.printEmptyLn();
|
48 | });
|
49 | printer.printLn("export type ServiceError = { message: string, code: number; metadata: grpc.Metadata }");
|
50 | printer.printLn("export type Status = { details: string, code: number; metadata: grpc.Metadata }");
|
51 | printer.printEmptyLn();
|
52 | printer.printLn("interface UnaryResponse {");
|
53 | printer.printIndentedLn("cancel(): void;");
|
54 | printer.printLn("}");
|
55 | printer.printLn("interface ResponseStream<T> {");
|
56 | printer.printIndentedLn("cancel(): void;");
|
57 | printer.printIndentedLn("on(type: 'data', handler: (message: T) => void): ResponseStream<T>;");
|
58 | printer.printIndentedLn("on(type: 'end', handler: (status?: Status) => void): ResponseStream<T>;");
|
59 | printer.printIndentedLn("on(type: 'status', handler: (status: Status) => void): ResponseStream<T>;");
|
60 | printer.printLn("}");
|
61 | printer.printLn("interface RequestStream<T> {");
|
62 | printer.printIndentedLn("write(message: T): RequestStream<T>;");
|
63 | printer.printIndentedLn("end(): void;");
|
64 | printer.printIndentedLn("cancel(): void;");
|
65 | printer.printIndentedLn("on(type: 'end', handler: (status?: Status) => void): RequestStream<T>;");
|
66 | printer.printIndentedLn("on(type: 'status', handler: (status: Status) => void): RequestStream<T>;");
|
67 | printer.printLn("}");
|
68 | printer.printLn("interface BidirectionalStream<ReqT, ResT> {");
|
69 | printer.printIndentedLn("write(message: ReqT): BidirectionalStream<ReqT, ResT>;");
|
70 | printer.printIndentedLn("end(): void;");
|
71 | printer.printIndentedLn("cancel(): void;");
|
72 | printer.printIndentedLn("on(type: 'data', handler: (message: ResT) => void): BidirectionalStream<ReqT, ResT>;");
|
73 | printer.printIndentedLn("on(type: 'end', handler: (status?: Status) => void): BidirectionalStream<ReqT, ResT>;");
|
74 | printer.printIndentedLn("on(type: 'status', handler: (status: Status) => void): BidirectionalStream<ReqT, ResT>;");
|
75 | printer.printLn("}");
|
76 | printer.printEmptyLn();
|
77 | serviceDescriptor.services
|
78 | .forEach(function (service) {
|
79 | printServiceStubTypes(printer, service);
|
80 | printer.printEmptyLn();
|
81 | });
|
82 | return printer.getOutput();
|
83 | }
|
84 | function generateJavaScript(fileDescriptor, exportMap) {
|
85 | var serviceDescriptor = new common_1.GrpcServiceDescriptor(fileDescriptor, exportMap);
|
86 | var printer = new Printer_1.Printer(0);
|
87 | printer.printLn("// package: " + serviceDescriptor.packageName);
|
88 | printer.printLn("// file: " + serviceDescriptor.filename);
|
89 | printer.printEmptyLn();
|
90 | if (serviceDescriptor.services.length === 0) {
|
91 | return printer.getOutput();
|
92 | }
|
93 | serviceDescriptor.imports
|
94 | .forEach(function (importDescriptor) {
|
95 | printer.printLn("var " + importDescriptor.namespace + " = require(\"" + importDescriptor.path + "\");");
|
96 | });
|
97 | printer.printLn("var grpc = require(\"@improbable-eng/grpc-web\").grpc;");
|
98 | printer.printEmptyLn();
|
99 | serviceDescriptor.services
|
100 | .forEach(function (service) {
|
101 | printer.printLn("var " + service.name + " = (function () {");
|
102 | printer.printIndentedLn("function " + service.name + "() {}");
|
103 | printer.printIndentedLn(service.name + ".serviceName = \"" + service.qualifiedName + "\";");
|
104 | printer.printIndentedLn("return " + service.name + ";");
|
105 | printer.printLn("}());");
|
106 | printer.printEmptyLn();
|
107 | service.methods
|
108 | .forEach(function (method) {
|
109 | printer.printLn(method.serviceName + "." + method.nameAsPascalCase + " = {");
|
110 | printer.printIndentedLn("methodName: \"" + method.nameAsPascalCase + "\",");
|
111 | printer.printIndentedLn("service: " + method.serviceName + ",");
|
112 | printer.printIndentedLn("requestStream: " + method.requestStream + ",");
|
113 | printer.printIndentedLn("responseStream: " + method.responseStream + ",");
|
114 | printer.printIndentedLn("requestType: " + method.requestType + ",");
|
115 | printer.printIndentedLn("responseType: " + method.responseType);
|
116 | printer.printLn("};");
|
117 | printer.printEmptyLn();
|
118 | });
|
119 | printer.printLn("exports." + service.name + " = " + service.name + ";");
|
120 | printer.printEmptyLn();
|
121 | printServiceStub(printer, service);
|
122 | printer.printEmptyLn();
|
123 | });
|
124 | return printer.getOutput();
|
125 | }
|
126 | function printServiceStub(methodPrinter, service) {
|
127 | var printer = new CodePrinter_1.CodePrinter(0, methodPrinter);
|
128 | printer
|
129 | .printLn("function " + service.name + "Client(serviceHost, options) {")
|
130 | .indent().printLn("this.serviceHost = serviceHost;")
|
131 | .printLn("this.options = options || {};")
|
132 | .dedent().printLn("}")
|
133 | .printEmptyLn();
|
134 | service.methods.forEach(function (method) {
|
135 | if (method.requestStream && method.responseStream) {
|
136 | printBidirectionalStubMethod(printer, method);
|
137 | }
|
138 | else if (method.requestStream) {
|
139 | printClientStreamStubMethod(printer, method);
|
140 | }
|
141 | else if (method.responseStream) {
|
142 | printServerStreamStubMethod(printer, method);
|
143 | }
|
144 | else {
|
145 | printUnaryStubMethod(printer, method);
|
146 | }
|
147 | printer.printEmptyLn();
|
148 | });
|
149 | printer.printLn("exports." + service.name + "Client = " + service.name + "Client;");
|
150 | }
|
151 | function printUnaryStubMethod(printer, method) {
|
152 | printer
|
153 | .printLn(method.serviceName + "Client.prototype." + method.nameAsCamelCase + " = function " + method.functionName + "(requestMessage, metadata, callback) {")
|
154 | .indent().printLn("if (arguments.length === 2) {")
|
155 | .indent().printLn("callback = arguments[1];")
|
156 | .dedent().printLn("}")
|
157 | .printLn("var client = grpc.unary(" + method.serviceName + "." + method.nameAsPascalCase + ", {")
|
158 | .indent().printLn("request: requestMessage,")
|
159 | .printLn("host: this.serviceHost,")
|
160 | .printLn("metadata: metadata,")
|
161 | .printLn("transport: this.options.transport,")
|
162 | .printLn("debug: this.options.debug,")
|
163 | .printLn("onEnd: function (response) {")
|
164 | .indent().printLn("if (callback) {")
|
165 | .indent().printLn("if (response.status !== grpc.Code.OK) {")
|
166 | .indent().printLn("var err = new Error(response.statusMessage);")
|
167 | .printLn("err.code = response.status;")
|
168 | .printLn("err.metadata = response.trailers;")
|
169 | .printLn("callback(err, null);")
|
170 | .dedent().printLn("} else {")
|
171 | .indent().printLn("callback(null, response.message);")
|
172 | .dedent().printLn("}")
|
173 | .dedent().printLn("}")
|
174 | .dedent().printLn("}")
|
175 | .dedent().printLn("});")
|
176 | .printLn("return {")
|
177 | .indent().printLn("cancel: function () {")
|
178 | .indent().printLn("callback = null;")
|
179 | .printLn("client.close();")
|
180 | .dedent().printLn("}")
|
181 | .dedent().printLn("};")
|
182 | .dedent().printLn("};");
|
183 | }
|
184 | function printServerStreamStubMethod(printer, method) {
|
185 | printer
|
186 | .printLn(method.serviceName + "Client.prototype." + method.nameAsCamelCase + " = function " + method.functionName + "(requestMessage, metadata) {")
|
187 | .indent().printLn("var listeners = {")
|
188 | .indent().printLn("data: [],")
|
189 | .printLn("end: [],")
|
190 | .printLn("status: []")
|
191 | .dedent().printLn("};")
|
192 | .printLn("var client = grpc.invoke(" + method.serviceName + "." + method.nameAsPascalCase + ", {")
|
193 | .indent().printLn("request: requestMessage,")
|
194 | .printLn("host: this.serviceHost,")
|
195 | .printLn("metadata: metadata,")
|
196 | .printLn("transport: this.options.transport,")
|
197 | .printLn("debug: this.options.debug,")
|
198 | .printLn("onMessage: function (responseMessage) {")
|
199 | .indent().printLn("listeners.data.forEach(function (handler) {")
|
200 | .indent().printLn("handler(responseMessage);")
|
201 | .dedent().printLn("});")
|
202 | .dedent().printLn("},")
|
203 | .printLn("onEnd: function (status, statusMessage, trailers) {")
|
204 | .indent().printLn("listeners.status.forEach(function (handler) {")
|
205 | .indent().printLn("handler({ code: status, details: statusMessage, metadata: trailers });")
|
206 | .dedent().printLn("});")
|
207 | .printLn("listeners.end.forEach(function (handler) {")
|
208 | .indent().printLn("handler({ code: status, details: statusMessage, metadata: trailers });")
|
209 | .dedent().printLn("});")
|
210 | .printLn("listeners = null;")
|
211 | .dedent().printLn("}")
|
212 | .dedent().printLn("});")
|
213 | .printLn("return {")
|
214 | .indent().printLn("on: function (type, handler) {")
|
215 | .indent().printLn("listeners[type].push(handler);")
|
216 | .printLn("return this;")
|
217 | .dedent().printLn("},")
|
218 | .printLn("cancel: function () {")
|
219 | .indent().printLn("listeners = null;")
|
220 | .printLn("client.close();")
|
221 | .dedent().printLn("}")
|
222 | .dedent().printLn("};")
|
223 | .dedent().printLn("};");
|
224 | }
|
225 | function printClientStreamStubMethod(printer, method) {
|
226 | printer
|
227 | .printLn(method.serviceName + "Client.prototype." + method.nameAsCamelCase + " = function " + method.functionName + "(metadata) {")
|
228 | .indent().printLn("var listeners = {")
|
229 | .indent().printLn("end: [],")
|
230 | .printLn("status: []")
|
231 | .dedent().printLn("};")
|
232 | .printLn("var client = grpc.client(" + method.serviceName + "." + method.nameAsPascalCase + ", {")
|
233 | .indent().printLn("host: this.serviceHost,")
|
234 | .printLn("metadata: metadata,")
|
235 | .printLn("transport: this.options.transport")
|
236 | .dedent().printLn("});")
|
237 | .printLn("client.onEnd(function (status, statusMessage, trailers) {")
|
238 | .indent().printLn("listeners.status.forEach(function (handler) {")
|
239 | .indent().printLn("handler({ code: status, details: statusMessage, metadata: trailers });")
|
240 | .dedent().printLn("});")
|
241 | .printLn("listeners.end.forEach(function (handler) {")
|
242 | .indent().printLn("handler({ code: status, details: statusMessage, metadata: trailers });")
|
243 | .dedent().printLn("});")
|
244 | .printLn("listeners = null;")
|
245 | .dedent().printLn("});")
|
246 | .printLn("return {")
|
247 | .indent().printLn("on: function (type, handler) {")
|
248 | .indent().printLn("listeners[type].push(handler);")
|
249 | .printLn("return this;")
|
250 | .dedent().printLn("},")
|
251 | .printLn("write: function (requestMessage) {")
|
252 | .indent().printLn("if (!client.started) {")
|
253 | .indent().printLn("client.start(metadata);")
|
254 | .dedent().printLn("}")
|
255 | .printLn("client.send(requestMessage);")
|
256 | .printLn("return this;")
|
257 | .dedent().printLn("},")
|
258 | .printLn("end: function () {")
|
259 | .indent().printLn("client.finishSend();")
|
260 | .dedent().printLn("},")
|
261 | .printLn("cancel: function () {")
|
262 | .indent().printLn("listeners = null;")
|
263 | .printLn("client.close();")
|
264 | .dedent().printLn("}")
|
265 | .dedent().printLn("};")
|
266 | .dedent().printLn("};");
|
267 | }
|
268 | function printBidirectionalStubMethod(printer, method) {
|
269 | printer
|
270 | .printLn(method.serviceName + "Client.prototype." + method.nameAsCamelCase + " = function " + method.functionName + "(metadata) {")
|
271 | .indent().printLn("var listeners = {")
|
272 | .indent().printLn("data: [],")
|
273 | .printLn("end: [],")
|
274 | .printLn("status: []")
|
275 | .dedent().printLn("};")
|
276 | .printLn("var client = grpc.client(" + method.serviceName + "." + method.nameAsPascalCase + ", {")
|
277 | .indent().printLn("host: this.serviceHost,")
|
278 | .printLn("metadata: metadata,")
|
279 | .printLn("transport: this.options.transport")
|
280 | .dedent().printLn("});")
|
281 | .printLn("client.onEnd(function (status, statusMessage, trailers) {")
|
282 | .indent().printLn("listeners.status.forEach(function (handler) {")
|
283 | .indent().printLn("handler({ code: status, details: statusMessage, metadata: trailers });")
|
284 | .dedent().printLn("});")
|
285 | .printLn("listeners.end.forEach(function (handler) {")
|
286 | .indent().printLn("handler({ code: status, details: statusMessage, metadata: trailers });")
|
287 | .dedent().printLn("});")
|
288 | .printLn("listeners = null;")
|
289 | .dedent().printLn("});")
|
290 | .printLn("client.onMessage(function (message) {")
|
291 | .indent().printLn("listeners.data.forEach(function (handler) {")
|
292 | .indent().printLn("handler(message);")
|
293 | .dedent().printLn("})")
|
294 | .dedent().printLn("});")
|
295 | .printLn("client.start(metadata);")
|
296 | .printLn("return {")
|
297 | .indent().printLn("on: function (type, handler) {")
|
298 | .indent().printLn("listeners[type].push(handler);")
|
299 | .printLn("return this;")
|
300 | .dedent().printLn("},")
|
301 | .printLn("write: function (requestMessage) {")
|
302 | .indent().printLn("client.send(requestMessage);")
|
303 | .printLn("return this;")
|
304 | .dedent().printLn("},")
|
305 | .printLn("end: function () {")
|
306 | .indent().printLn("client.finishSend();")
|
307 | .dedent().printLn("},")
|
308 | .printLn("cancel: function () {")
|
309 | .indent().printLn("listeners = null;")
|
310 | .printLn("client.close();")
|
311 | .dedent().printLn("}")
|
312 | .dedent().printLn("};")
|
313 | .dedent().printLn("};");
|
314 | }
|
315 | function printServiceStubTypes(methodPrinter, service) {
|
316 | var printer = new CodePrinter_1.CodePrinter(0, methodPrinter);
|
317 | printer
|
318 | .printLn("export class " + service.name + "Client {")
|
319 | .indent().printLn("readonly serviceHost: string;")
|
320 | .printEmptyLn()
|
321 | .printLn("constructor(serviceHost: string, options?: grpc.RpcOptions);");
|
322 | service.methods.forEach(function (method) {
|
323 | if (method.requestStream && method.responseStream) {
|
324 | printBidirectionalStubMethodTypes(printer, method);
|
325 | }
|
326 | else if (method.requestStream) {
|
327 | printClientStreamStubMethodTypes(printer, method);
|
328 | }
|
329 | else if (method.responseStream) {
|
330 | printServerStreamStubMethodTypes(printer, method);
|
331 | }
|
332 | else {
|
333 | printUnaryStubMethodTypes(printer, method);
|
334 | }
|
335 | });
|
336 | printer.dedent().printLn("}");
|
337 | }
|
338 | function printUnaryStubMethodTypes(printer, method) {
|
339 | printer
|
340 | .printLn(method.nameAsCamelCase + "(")
|
341 | .indent().printLn("requestMessage: " + method.requestType + ",")
|
342 | .printLn("metadata: grpc.Metadata,")
|
343 | .printLn("callback: (error: ServiceError|null, responseMessage: " + method.responseType + "|null) => void")
|
344 | .dedent().printLn("): UnaryResponse;")
|
345 | .printLn(method.nameAsCamelCase + "(")
|
346 | .indent().printLn("requestMessage: " + method.requestType + ",")
|
347 | .printLn("callback: (error: ServiceError|null, responseMessage: " + method.responseType + "|null) => void")
|
348 | .dedent().printLn("): UnaryResponse;");
|
349 | }
|
350 | function printServerStreamStubMethodTypes(printer, method) {
|
351 | printer.printLn(method.nameAsCamelCase + "(requestMessage: " + method.requestType + ", metadata?: grpc.Metadata): ResponseStream<" + method.responseType + ">;");
|
352 | }
|
353 | function printClientStreamStubMethodTypes(printer, method) {
|
354 | printer.printLn(method.nameAsCamelCase + "(metadata?: grpc.Metadata): RequestStream<" + method.requestType + ">;");
|
355 | }
|
356 | function printBidirectionalStubMethodTypes(printer, method) {
|
357 | printer.printLn(method.nameAsCamelCase + "(metadata?: grpc.Metadata): BidirectionalStream<" + method.requestType + ", " + method.responseType + ">;");
|
358 | }
|
359 |
|
\ | No newline at end of file |