From 4265ea98aa9abefd33d8aef6b2b994d9fb8a3a79 Mon Sep 17 00:00:00 2001 From: Marco Bardelli Date: Tue, 19 Jul 2022 08:56:34 +0200 Subject: [PATCH] added import_style parameter to generate import statements for browser that supports es6 --- src/index.ts | 7 ++++--- src/parameters.ts | 5 +++++ src/service/grpcweb.ts | 34 +++++++++++++++++++++++-------- src/util.ts | 22 ++++++++++++++++---- test/helpers/fakeGrpcTransport.ts | 2 +- 5 files changed, 53 insertions(+), 17 deletions(-) diff --git a/src/index.ts b/src/index.ts index da20bc75..108a2725 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,7 +5,7 @@ import {CodeGeneratorRequest, CodeGeneratorResponse} from "google-protobuf/googl import {FileDescriptorProto} from "google-protobuf/google/protobuf/descriptor_pb"; import {generateGrpcWebService} from "./service/grpcweb"; import {generateGrpcNodeService} from "./service/grpcnode"; -import {ServiceParameter} from "./parameters"; +import {ServiceParameter, ImportStyleParameter} from "./parameters"; /** * This is the ProtoC compiler plugin. @@ -28,10 +28,11 @@ withAllStdIn((inputBuff: Buffer) => { const fileNameToDescriptor: {[key: string]: FileDescriptorProto} = {}; const parameter = codeGenRequest.getParameter(); - const {service, mode} = getParameterEnums(parameter || ""); + const {service, mode, importStyle} = getParameterEnums(parameter || ""); const generateGrpcWebServices = service === ServiceParameter.GrpcWeb; const generateGrpcNodeServices = service === ServiceParameter.GrpcNode; + const useImportStyleES6 = importStyle === ImportStyleParameter.ES6; codeGenRequest.getProtoFileList().forEach(protoFileDescriptor => { const fileDescriptorName = protoFileDescriptor.getName() || throwError("Missing file descriptor name"); @@ -47,7 +48,7 @@ withAllStdIn((inputBuff: Buffer) => { codeGenResponse.addFile(thisFile); if (generateGrpcWebServices) { - generateGrpcWebService(outputFileName, fileNameToDescriptor[fileName], exportMap) + generateGrpcWebService(outputFileName, fileNameToDescriptor[fileName], exportMap, useImportStyleES6) .forEach(file => codeGenResponse.addFile(file)); } else if (generateGrpcNodeServices) { const file = generateGrpcNodeService(outputFileName, fileNameToDescriptor[fileName], exportMap, mode); diff --git a/src/parameters.ts b/src/parameters.ts index c5d8e7d4..44a323f4 100644 --- a/src/parameters.ts +++ b/src/parameters.ts @@ -8,3 +8,8 @@ export enum ModeParameter { None, GrpcJs } + +export enum ImportStyleParameter { + None, + ES6 +} diff --git a/src/service/grpcweb.ts b/src/service/grpcweb.ts index 1a9d8d54..4914be2e 100644 --- a/src/service/grpcweb.ts +++ b/src/service/grpcweb.ts @@ -5,10 +5,10 @@ import {FileDescriptorProto} from "google-protobuf/google/protobuf/descriptor_pb import {CodeGeneratorResponse} from "google-protobuf/google/protobuf/compiler/plugin_pb"; import {createFile, RPCMethodDescriptor, RPCDescriptor, GrpcServiceDescriptor} from "./common"; -export function generateGrpcWebService(filename: string, descriptor: FileDescriptorProto, exportMap: ExportMap): CodeGeneratorResponse.File[] { +export function generateGrpcWebService(filename: string, descriptor: FileDescriptorProto, exportMap: ExportMap, useImportStyleES6: boolean): CodeGeneratorResponse.File[] { return [ createFile(generateTypeScriptDefinition(descriptor, exportMap), `${filename}_service.d.ts`), - createFile(generateJavaScript(descriptor, exportMap), `${filename}_service.js`), + createFile(generateJavaScript(descriptor, exportMap, useImportStyleES6), `${filename}_service.js`), ]; } @@ -100,7 +100,7 @@ function generateTypeScriptDefinition(fileDescriptor: FileDescriptorProto, expor return printer.getOutput(); } -function generateJavaScript(fileDescriptor: FileDescriptorProto, exportMap: ExportMap): string { +function generateJavaScript(fileDescriptor: FileDescriptorProto, exportMap: ExportMap, useImportStyleES6: boolean): string { const serviceDescriptor = new GrpcServiceDescriptor(fileDescriptor, exportMap); const printer = new Printer(0); @@ -116,9 +116,17 @@ function generateJavaScript(fileDescriptor: FileDescriptorProto, exportMap: Expo // Import Statements serviceDescriptor.imports .forEach(importDescriptor => { - printer.printLn(`var ${importDescriptor.namespace} = require("${importDescriptor.path}");`); + if (useImportStyleES6) { + printer.printLn(`import * as ${importDescriptor.namespace} from "${importDescriptor.path}";`); + } else { + printer.printLn(`var ${importDescriptor.namespace} = require("${importDescriptor.path}");`); + } }); - printer.printLn(`var grpc = require("@improbable-eng/grpc-web").grpc;`); + if (useImportStyleES6) { + printer.printLn(`import {grpc} from "@improbable-eng/grpc-web";`); + } else { + printer.printLn(`var grpc = require("@improbable-eng/grpc-web").grpc;`); + } printer.printEmptyLn(); // Services. @@ -143,11 +151,15 @@ function generateJavaScript(fileDescriptor: FileDescriptorProto, exportMap: Expo printer.printLn(`};`); printer.printEmptyLn(); }); - printer.printLn(`exports.${service.name} = ${service.name};`); + if (useImportStyleES6) { + printer.printLn(`export {${service.name}};`); + } else { + printer.printLn(`exports.${service.name} = ${service.name};`); + } printer.printEmptyLn(); // Add a client stub that talks with the @improbable-eng/grpc-web library - printServiceStub(printer, service); + printServiceStub(printer, service, useImportStyleES6); printer.printEmptyLn(); }); @@ -155,7 +167,7 @@ function generateJavaScript(fileDescriptor: FileDescriptorProto, exportMap: Expo return printer.getOutput(); } -function printServiceStub(methodPrinter: Printer, service: RPCDescriptor) { +function printServiceStub(methodPrinter: Printer, service: RPCDescriptor, useImportStyleES6: boolean) { const printer = new CodePrinter(0, methodPrinter); printer @@ -177,7 +189,11 @@ function printServiceStub(methodPrinter: Printer, service: RPCDescriptor) { } printer.printEmptyLn(); }); - printer.printLn(`exports.${service.name}Client = ${service.name}Client;`); + if (useImportStyleES6) { + printer.printLn(`export {${service.name}Client};`); + } else { + printer.printLn(`exports.${service.name}Client = ${service.name}Client;`); + } } function printUnaryStubMethod(printer: CodePrinter, method: RPCMethodDescriptor) { diff --git a/src/util.ts b/src/util.ts index 847ee998..beb65abd 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,7 +1,7 @@ import {parse} from "querystring"; import {FileDescriptorProto} from "google-protobuf/google/protobuf/descriptor_pb"; import {ExportEnumEntry, ExportMessageEntry} from "./ExportMap"; -import {ServiceParameter, ModeParameter} from "./parameters"; +import {ServiceParameter, ModeParameter, ImportStyleParameter} from "./parameters"; export function filePathToPseudoNamespace(filePath: string): string { return filePath.replace(".proto", "").replace(/\//g, "_").replace(/\./g, "_").replace(/\-/g, "_") + "_pb"; @@ -182,13 +182,27 @@ export function getModeParameter(mode?: string): ModeParameter { } } +export function getImportStyleParameter(importStyle?: string): ImportStyleParameter { + switch (importStyle) { + case "es6": + return ImportStyleParameter.ES6; + case undefined: + return ImportStyleParameter.None; + default: + throw new Error(`Unrecognised import_style parameter: ${importStyle}`); + } +} + + export function getParameterEnums(parameter: string): { service: ServiceParameter, - mode: ModeParameter + mode: ModeParameter, + importStyle: ImportStyleParameter, } { - const {service, mode} = parse(parameter, ","); + const {service, mode, import_style} = parse(parameter, ","); return { service: getServiceParameter(service), - mode: getModeParameter(mode) + mode: getModeParameter(mode), + importStyle: getImportStyleParameter(import_style) }; } diff --git a/test/helpers/fakeGrpcTransport.ts b/test/helpers/fakeGrpcTransport.ts index 43d6f3f8..b821045a 100644 --- a/test/helpers/fakeGrpcTransport.ts +++ b/test/helpers/fakeGrpcTransport.ts @@ -23,7 +23,7 @@ function frameTrailers(trailers: grpc.Metadata): Uint8Array { trailers.forEach((key: string, values: string[]) => { asString += `${key}: ${values.join(", ")}\r\n`; }); - const bytes = new Buffer(asString); + const bytes = Buffer.from(asString); const frame = new ArrayBuffer(bytes.byteLength + 5); const dataview = new DataView(frame, 0, 5); dataview.setUint32(1, bytes.length, false /* big endian */);