mirror of
https://github.com/roleypoly/roleypoly.git
synced 2025-06-16 09:39:09 +00:00
chore(ts-protoc-gen): prettier
This commit is contained in:
parent
291ec9576f
commit
783915f057
16 changed files with 1660 additions and 1202 deletions
|
@ -1,26 +1,26 @@
|
||||||
import {Printer} from "./Printer";
|
import { Printer } from './Printer';
|
||||||
import {generateIndent} from "./util";
|
import { generateIndent } from './util';
|
||||||
|
|
||||||
export class CodePrinter {
|
export class CodePrinter {
|
||||||
private indentation: string;
|
private indentation: string;
|
||||||
constructor(private depth: number, private printer: Printer) {
|
constructor(private depth: number, private printer: Printer) {
|
||||||
this.indentation = generateIndent(1);
|
this.indentation = generateIndent(1);
|
||||||
}
|
}
|
||||||
indent() {
|
indent() {
|
||||||
this.depth++;
|
this.depth++;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
dedent() {
|
dedent() {
|
||||||
this.depth--;
|
this.depth--;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
printLn(line: string) {
|
printLn(line: string) {
|
||||||
this.printer.printLn(new Array(this.depth + 1).join(this.indentation) + line);
|
this.printer.printLn(new Array(this.depth + 1).join(this.indentation) + line);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
printEmptyLn() {
|
printEmptyLn() {
|
||||||
this.printer.printEmptyLn();
|
this.printer.printEmptyLn();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,84 +1,101 @@
|
||||||
import {
|
import {
|
||||||
FileDescriptorProto,
|
FileDescriptorProto,
|
||||||
DescriptorProto,
|
DescriptorProto,
|
||||||
MessageOptions,
|
MessageOptions,
|
||||||
EnumOptions,
|
EnumOptions,
|
||||||
FieldDescriptorProto
|
FieldDescriptorProto,
|
||||||
} from "google-protobuf/google/protobuf/descriptor_pb";
|
} from 'google-protobuf/google/protobuf/descriptor_pb';
|
||||||
|
|
||||||
import Type = FieldDescriptorProto.Type;
|
import Type = FieldDescriptorProto.Type;
|
||||||
|
|
||||||
export type ExportMessageEntry = {
|
export type ExportMessageEntry = {
|
||||||
pkg: string,
|
pkg: string;
|
||||||
fileName: string,
|
fileName: string;
|
||||||
messageOptions: MessageOptions,
|
messageOptions: MessageOptions;
|
||||||
mapFieldOptions?: {
|
mapFieldOptions?: {
|
||||||
key: [Type, string],
|
key: [Type, string];
|
||||||
value: [Type, string],
|
value: [Type, string];
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ExportEnumEntry = {
|
export type ExportEnumEntry = {
|
||||||
pkg: string,
|
pkg: string;
|
||||||
fileName: string,
|
fileName: string;
|
||||||
enumOptions: EnumOptions,
|
enumOptions: EnumOptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class ExportMap {
|
export class ExportMap {
|
||||||
messageMap: {[key: string]: ExportMessageEntry} = {};
|
messageMap: { [key: string]: ExportMessageEntry } = {};
|
||||||
enumMap: {[key: string]: ExportEnumEntry} = {};
|
enumMap: { [key: string]: ExportEnumEntry } = {};
|
||||||
|
|
||||||
exportNested(scope: string, fileDescriptor: FileDescriptorProto, message: DescriptorProto) {
|
exportNested(
|
||||||
const messageEntry: ExportMessageEntry = {
|
scope: string,
|
||||||
pkg: fileDescriptor.getPackage(),
|
fileDescriptor: FileDescriptorProto,
|
||||||
fileName: fileDescriptor.getName(),
|
message: DescriptorProto
|
||||||
messageOptions: message.getOptions(),
|
) {
|
||||||
mapFieldOptions: message.getOptions() && message.getOptions().getMapEntry() ? {
|
const messageEntry: ExportMessageEntry = {
|
||||||
key: [message.getFieldList()[0].getType(), message.getFieldList()[0].getTypeName().slice(1)],
|
pkg: fileDescriptor.getPackage(),
|
||||||
value: [message.getFieldList()[1].getType(), message.getFieldList()[1].getTypeName().slice(1)],
|
fileName: fileDescriptor.getName(),
|
||||||
} : undefined,
|
messageOptions: message.getOptions(),
|
||||||
};
|
mapFieldOptions:
|
||||||
|
message.getOptions() && message.getOptions().getMapEntry()
|
||||||
|
? {
|
||||||
|
key: [
|
||||||
|
message.getFieldList()[0].getType(),
|
||||||
|
message.getFieldList()[0].getTypeName().slice(1),
|
||||||
|
],
|
||||||
|
value: [
|
||||||
|
message.getFieldList()[1].getType(),
|
||||||
|
message.getFieldList()[1].getTypeName().slice(1),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
const packagePrefix = scope ? scope + "." : "";
|
const packagePrefix = scope ? scope + '.' : '';
|
||||||
|
|
||||||
const entryName = `${packagePrefix}${message.getName()}`;
|
const entryName = `${packagePrefix}${message.getName()}`;
|
||||||
this.messageMap[entryName] = messageEntry;
|
this.messageMap[entryName] = messageEntry;
|
||||||
|
|
||||||
message.getNestedTypeList().forEach(nested => {
|
message.getNestedTypeList().forEach((nested) => {
|
||||||
this.exportNested(`${packagePrefix}${message.getName()}`, fileDescriptor, nested);
|
this.exportNested(
|
||||||
});
|
`${packagePrefix}${message.getName()}`,
|
||||||
|
fileDescriptor,
|
||||||
|
nested
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
message.getEnumTypeList().forEach(enumType => {
|
message.getEnumTypeList().forEach((enumType) => {
|
||||||
const identifier = `${packagePrefix}${message.getName()}.${enumType.getName()}`;
|
const identifier = `${packagePrefix}${message.getName()}.${enumType.getName()}`;
|
||||||
this.enumMap[identifier] = {
|
this.enumMap[identifier] = {
|
||||||
pkg: fileDescriptor.getPackage(),
|
pkg: fileDescriptor.getPackage(),
|
||||||
fileName: fileDescriptor.getName(),
|
fileName: fileDescriptor.getName(),
|
||||||
enumOptions: enumType.getOptions(),
|
enumOptions: enumType.getOptions(),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addFileDescriptor(fileDescriptor: FileDescriptorProto) {
|
addFileDescriptor(fileDescriptor: FileDescriptorProto) {
|
||||||
const scope = fileDescriptor.getPackage();
|
const scope = fileDescriptor.getPackage();
|
||||||
fileDescriptor.getMessageTypeList().forEach(messageType => {
|
fileDescriptor.getMessageTypeList().forEach((messageType) => {
|
||||||
this.exportNested(scope, fileDescriptor, messageType);
|
this.exportNested(scope, fileDescriptor, messageType);
|
||||||
});
|
});
|
||||||
|
|
||||||
fileDescriptor.getEnumTypeList().forEach(enumType => {
|
fileDescriptor.getEnumTypeList().forEach((enumType) => {
|
||||||
const packagePrefix = scope ? scope + "." : "";
|
const packagePrefix = scope ? scope + '.' : '';
|
||||||
this.enumMap[packagePrefix + enumType.getName()] = {
|
this.enumMap[packagePrefix + enumType.getName()] = {
|
||||||
pkg: fileDescriptor.getPackage(),
|
pkg: fileDescriptor.getPackage(),
|
||||||
fileName: fileDescriptor.getName(),
|
fileName: fileDescriptor.getName(),
|
||||||
enumOptions: enumType.getOptions(),
|
enumOptions: enumType.getOptions(),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getMessage(str: string): ExportMessageEntry | undefined {
|
getMessage(str: string): ExportMessageEntry | undefined {
|
||||||
return this.messageMap[str];
|
return this.messageMap[str];
|
||||||
}
|
}
|
||||||
|
|
||||||
getEnum(str: string): ExportEnumEntry | undefined {
|
getEnum(str: string): ExportEnumEntry | undefined {
|
||||||
return this.enumMap[str];
|
return this.enumMap[str];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
import {generateIndent} from "./util";
|
import { generateIndent } from './util';
|
||||||
|
|
||||||
export class Printer {
|
export class Printer {
|
||||||
indentStr: string;
|
indentStr: string;
|
||||||
output: string = "";
|
output: string = '';
|
||||||
|
|
||||||
constructor(indentLevel: number) {
|
constructor(indentLevel: number) {
|
||||||
this.indentStr = generateIndent(indentLevel);
|
this.indentStr = generateIndent(indentLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
printLn(str: string) {
|
printLn(str: string) {
|
||||||
this.output += this.indentStr + str + "\n";
|
this.output += this.indentStr + str + '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
print(str: string) {
|
print(str: string) {
|
||||||
this.output += str;
|
this.output += str;
|
||||||
}
|
}
|
||||||
|
|
||||||
printEmptyLn() {
|
printEmptyLn() {
|
||||||
this.output += "\n";
|
this.output += '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
printIndentedLn(str: string) {
|
printIndentedLn(str: string) {
|
||||||
this.output += this.indentStr + " " + str + "\n";
|
this.output += this.indentStr + ' ' + str + '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutput(): string {
|
getOutput(): string {
|
||||||
return this.output;
|
return this.output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
export const WellKnownTypesMap: {[key: string]: string} = {
|
export const WellKnownTypesMap: { [key: string]: string } = {
|
||||||
"google/protobuf/compiler/plugin.proto": "google-protobuf/google/protobuf/compiler/plugin_pb",
|
'google/protobuf/compiler/plugin.proto':
|
||||||
"google/protobuf/any.proto": "google-protobuf/google/protobuf/any_pb",
|
'google-protobuf/google/protobuf/compiler/plugin_pb',
|
||||||
"google/protobuf/api.proto": "google-protobuf/google/protobuf/api_pb",
|
'google/protobuf/any.proto': 'google-protobuf/google/protobuf/any_pb',
|
||||||
"google/protobuf/descriptor.proto": "google-protobuf/google/protobuf/descriptor_pb",
|
'google/protobuf/api.proto': 'google-protobuf/google/protobuf/api_pb',
|
||||||
"google/protobuf/duration.proto": "google-protobuf/google/protobuf/duration_pb",
|
'google/protobuf/descriptor.proto': 'google-protobuf/google/protobuf/descriptor_pb',
|
||||||
"google/protobuf/empty.proto": "google-protobuf/google/protobuf/empty_pb",
|
'google/protobuf/duration.proto': 'google-protobuf/google/protobuf/duration_pb',
|
||||||
"google/protobuf/field_mask.proto": "google-protobuf/google/protobuf/field_mask_pb",
|
'google/protobuf/empty.proto': 'google-protobuf/google/protobuf/empty_pb',
|
||||||
"google/protobuf/source_context.proto": "google-protobuf/google/protobuf/source_context_pb",
|
'google/protobuf/field_mask.proto': 'google-protobuf/google/protobuf/field_mask_pb',
|
||||||
"google/protobuf/struct.proto": "google-protobuf/google/protobuf/struct_pb",
|
'google/protobuf/source_context.proto':
|
||||||
"google/protobuf/timestamp.proto": "google-protobuf/google/protobuf/timestamp_pb",
|
'google-protobuf/google/protobuf/source_context_pb',
|
||||||
"google/protobuf/type.proto": "google-protobuf/google/protobuf/type_pb",
|
'google/protobuf/struct.proto': 'google-protobuf/google/protobuf/struct_pb',
|
||||||
"google/protobuf/wrappers.proto": "google-protobuf/google/protobuf/wrappers_pb"
|
'google/protobuf/timestamp.proto': 'google-protobuf/google/protobuf/timestamp_pb',
|
||||||
|
'google/protobuf/type.proto': 'google-protobuf/google/protobuf/type_pb',
|
||||||
|
'google/protobuf/wrappers.proto': 'google-protobuf/google/protobuf/wrappers_pb',
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
import {printFileDescriptorTSD} from "./ts/fileDescriptorTSD";
|
import { printFileDescriptorTSD } from './ts/fileDescriptorTSD';
|
||||||
import {ExportMap} from "./ExportMap";
|
import { ExportMap } from './ExportMap';
|
||||||
import {replaceProtoSuffix, withAllStdIn, getParameterEnums} from "./util";
|
import { replaceProtoSuffix, withAllStdIn, getParameterEnums } from './util';
|
||||||
import {CodeGeneratorRequest, CodeGeneratorResponse} from "google-protobuf/google/protobuf/compiler/plugin_pb";
|
import {
|
||||||
import {FileDescriptorProto} from "google-protobuf/google/protobuf/descriptor_pb";
|
CodeGeneratorRequest,
|
||||||
import {generateGrpcWebService} from "./service/grpcweb";
|
CodeGeneratorResponse,
|
||||||
import {generateGrpcNodeService} from "./service/grpcnode";
|
} from 'google-protobuf/google/protobuf/compiler/plugin_pb';
|
||||||
import {ServiceParameter} from "./parameters";
|
import { FileDescriptorProto } from 'google-protobuf/google/protobuf/descriptor_pb';
|
||||||
|
import { generateGrpcWebService } from './service/grpcweb';
|
||||||
|
import { generateGrpcNodeService } from './service/grpcnode';
|
||||||
|
import { ServiceParameter } from './parameters';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the ProtoC compiler plugin.
|
* This is the ProtoC compiler plugin.
|
||||||
|
@ -17,45 +20,55 @@ import {ServiceParameter} from "./parameters";
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
withAllStdIn((inputBuff: Buffer) => {
|
withAllStdIn((inputBuff: Buffer) => {
|
||||||
try {
|
try {
|
||||||
const typedInputBuff = new Uint8Array(inputBuff.length);
|
const typedInputBuff = new Uint8Array(inputBuff.length);
|
||||||
typedInputBuff.set(inputBuff);
|
typedInputBuff.set(inputBuff);
|
||||||
|
|
||||||
const codeGenRequest = CodeGeneratorRequest.deserializeBinary(typedInputBuff);
|
const codeGenRequest = CodeGeneratorRequest.deserializeBinary(typedInputBuff);
|
||||||
const codeGenResponse = new CodeGeneratorResponse();
|
const codeGenResponse = new CodeGeneratorResponse();
|
||||||
const exportMap = new ExportMap();
|
const exportMap = new ExportMap();
|
||||||
const fileNameToDescriptor: {[key: string]: FileDescriptorProto} = {};
|
const fileNameToDescriptor: { [key: string]: FileDescriptorProto } = {};
|
||||||
|
|
||||||
const parameter = codeGenRequest.getParameter();
|
const parameter = codeGenRequest.getParameter();
|
||||||
const {service, mode} = getParameterEnums(parameter);
|
const { service, mode } = getParameterEnums(parameter);
|
||||||
|
|
||||||
const generateGrpcWebServices = service === ServiceParameter.GrpcWeb;
|
const generateGrpcWebServices = service === ServiceParameter.GrpcWeb;
|
||||||
const generateGrpcNodeServices = service === ServiceParameter.GrpcNode;
|
const generateGrpcNodeServices = service === ServiceParameter.GrpcNode;
|
||||||
|
|
||||||
codeGenRequest.getProtoFileList().forEach(protoFileDescriptor => {
|
codeGenRequest.getProtoFileList().forEach((protoFileDescriptor) => {
|
||||||
fileNameToDescriptor[protoFileDescriptor.getName()] = protoFileDescriptor;
|
fileNameToDescriptor[protoFileDescriptor.getName()] = protoFileDescriptor;
|
||||||
exportMap.addFileDescriptor(protoFileDescriptor);
|
exportMap.addFileDescriptor(protoFileDescriptor);
|
||||||
});
|
});
|
||||||
|
|
||||||
codeGenRequest.getFileToGenerateList().forEach(fileName => {
|
codeGenRequest.getFileToGenerateList().forEach((fileName) => {
|
||||||
const outputFileName = replaceProtoSuffix(fileName);
|
const outputFileName = replaceProtoSuffix(fileName);
|
||||||
const thisFile = new CodeGeneratorResponse.File();
|
const thisFile = new CodeGeneratorResponse.File();
|
||||||
thisFile.setName(outputFileName + ".d.ts");
|
thisFile.setName(outputFileName + '.d.ts');
|
||||||
thisFile.setContent(printFileDescriptorTSD(fileNameToDescriptor[fileName], exportMap));
|
thisFile.setContent(
|
||||||
codeGenResponse.addFile(thisFile);
|
printFileDescriptorTSD(fileNameToDescriptor[fileName], exportMap)
|
||||||
|
);
|
||||||
|
codeGenResponse.addFile(thisFile);
|
||||||
|
|
||||||
if (generateGrpcWebServices) {
|
if (generateGrpcWebServices) {
|
||||||
generateGrpcWebService(outputFileName, fileNameToDescriptor[fileName], exportMap)
|
generateGrpcWebService(
|
||||||
.forEach(file => codeGenResponse.addFile(file));
|
outputFileName,
|
||||||
} else if (generateGrpcNodeServices) {
|
fileNameToDescriptor[fileName],
|
||||||
const file = generateGrpcNodeService(outputFileName, fileNameToDescriptor[fileName], exportMap, mode);
|
exportMap
|
||||||
codeGenResponse.addFile(file);
|
).forEach((file) => codeGenResponse.addFile(file));
|
||||||
}
|
} else if (generateGrpcNodeServices) {
|
||||||
});
|
const file = generateGrpcNodeService(
|
||||||
|
outputFileName,
|
||||||
|
fileNameToDescriptor[fileName],
|
||||||
|
exportMap,
|
||||||
|
mode
|
||||||
|
);
|
||||||
|
codeGenResponse.addFile(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
process.stdout.write(Buffer.from(codeGenResponse.serializeBinary()));
|
process.stdout.write(Buffer.from(codeGenResponse.serializeBinary()));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("protoc-gen-ts error: " + err.stack + "\n");
|
console.error('protoc-gen-ts error: ' + err.stack + '\n');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
export enum ServiceParameter {
|
export enum ServiceParameter {
|
||||||
None,
|
None,
|
||||||
GrpcWeb,
|
GrpcWeb,
|
||||||
GrpcNode
|
GrpcNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ModeParameter {
|
export enum ModeParameter {
|
||||||
None,
|
None,
|
||||||
GrpcJs
|
GrpcJs,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,142 +1,183 @@
|
||||||
import {CodeGeneratorResponse} from "google-protobuf/google/protobuf/compiler/plugin_pb";
|
import { CodeGeneratorResponse } from 'google-protobuf/google/protobuf/compiler/plugin_pb';
|
||||||
import {FileDescriptorProto, MethodDescriptorProto, ServiceDescriptorProto} from "google-protobuf/google/protobuf/descriptor_pb";
|
import {
|
||||||
import {ExportMap} from "../ExportMap";
|
FileDescriptorProto,
|
||||||
import {WellKnownTypesMap} from "../WellKnown";
|
MethodDescriptorProto,
|
||||||
import {getFieldType, MESSAGE_TYPE} from "../ts/FieldTypes";
|
ServiceDescriptorProto,
|
||||||
import {filePathToPseudoNamespace, replaceProtoSuffix, getPathToRoot, normaliseFieldObjectName} from "../util";
|
} from 'google-protobuf/google/protobuf/descriptor_pb';
|
||||||
|
import { ExportMap } from '../ExportMap';
|
||||||
|
import { WellKnownTypesMap } from '../WellKnown';
|
||||||
|
import { getFieldType, MESSAGE_TYPE } from '../ts/FieldTypes';
|
||||||
|
import {
|
||||||
|
filePathToPseudoNamespace,
|
||||||
|
replaceProtoSuffix,
|
||||||
|
getPathToRoot,
|
||||||
|
normaliseFieldObjectName,
|
||||||
|
} from '../util';
|
||||||
|
|
||||||
export function createFile(output: string, filename: string): CodeGeneratorResponse.File {
|
export function createFile(output: string, filename: string): CodeGeneratorResponse.File {
|
||||||
const file = new CodeGeneratorResponse.File();
|
const file = new CodeGeneratorResponse.File();
|
||||||
file.setName(filename);
|
file.setName(filename);
|
||||||
file.setContent(output);
|
file.setContent(output);
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
type CallingTypes = {
|
type CallingTypes = {
|
||||||
requestType: string
|
requestType: string;
|
||||||
responseType: string
|
responseType: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
function getCallingTypes(method: MethodDescriptorProto, exportMap: ExportMap): CallingTypes {
|
function getCallingTypes(
|
||||||
return {
|
method: MethodDescriptorProto,
|
||||||
requestType: getFieldType(MESSAGE_TYPE, method.getInputType().slice(1), "", exportMap),
|
exportMap: ExportMap
|
||||||
responseType: getFieldType(MESSAGE_TYPE, method.getOutputType().slice(1), "", exportMap),
|
): CallingTypes {
|
||||||
};
|
return {
|
||||||
|
requestType: getFieldType(
|
||||||
|
MESSAGE_TYPE,
|
||||||
|
method.getInputType().slice(1),
|
||||||
|
'',
|
||||||
|
exportMap
|
||||||
|
),
|
||||||
|
responseType: getFieldType(
|
||||||
|
MESSAGE_TYPE,
|
||||||
|
method.getOutputType().slice(1),
|
||||||
|
'',
|
||||||
|
exportMap
|
||||||
|
),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function isUsed(fileDescriptor: FileDescriptorProto, pseudoNamespace: string, exportMap: ExportMap) {
|
function isUsed(
|
||||||
return fileDescriptor.getServiceList().some(service => {
|
fileDescriptor: FileDescriptorProto,
|
||||||
return service.getMethodList().some(method => {
|
pseudoNamespace: string,
|
||||||
const callingTypes = getCallingTypes(method, exportMap);
|
exportMap: ExportMap
|
||||||
const namespacePackage = pseudoNamespace + ".";
|
) {
|
||||||
return (
|
return fileDescriptor.getServiceList().some((service) => {
|
||||||
callingTypes.requestType.indexOf(namespacePackage) === 0 ||
|
return service.getMethodList().some((method) => {
|
||||||
callingTypes.responseType.indexOf(namespacePackage) === 0
|
const callingTypes = getCallingTypes(method, exportMap);
|
||||||
);
|
const namespacePackage = pseudoNamespace + '.';
|
||||||
|
return (
|
||||||
|
callingTypes.requestType.indexOf(namespacePackage) === 0 ||
|
||||||
|
callingTypes.responseType.indexOf(namespacePackage) === 0
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ImportDescriptor = {
|
export type ImportDescriptor = {
|
||||||
readonly namespace: string
|
readonly namespace: string;
|
||||||
readonly path: string
|
readonly path: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RPCMethodDescriptor = {
|
export type RPCMethodDescriptor = {
|
||||||
readonly nameAsPascalCase: string,
|
readonly nameAsPascalCase: string;
|
||||||
readonly nameAsCamelCase: string,
|
readonly nameAsCamelCase: string;
|
||||||
readonly functionName: string,
|
readonly functionName: string;
|
||||||
readonly serviceName: string,
|
readonly serviceName: string;
|
||||||
readonly requestStream: boolean
|
readonly requestStream: boolean;
|
||||||
readonly responseStream: boolean
|
readonly responseStream: boolean;
|
||||||
readonly requestType: string
|
readonly requestType: string;
|
||||||
readonly responseType: string
|
readonly responseType: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class RPCDescriptor {
|
export class RPCDescriptor {
|
||||||
private readonly grpcService: GrpcServiceDescriptor;
|
private readonly grpcService: GrpcServiceDescriptor;
|
||||||
private readonly protoService: ServiceDescriptorProto;
|
private readonly protoService: ServiceDescriptorProto;
|
||||||
private readonly exportMap: ExportMap;
|
private readonly exportMap: ExportMap;
|
||||||
|
|
||||||
constructor(grpcService: GrpcServiceDescriptor, protoService: ServiceDescriptorProto, exportMap: ExportMap) {
|
constructor(
|
||||||
this.grpcService = grpcService;
|
grpcService: GrpcServiceDescriptor,
|
||||||
this.protoService = protoService;
|
protoService: ServiceDescriptorProto,
|
||||||
this.exportMap = exportMap;
|
exportMap: ExportMap
|
||||||
}
|
) {
|
||||||
get name(): string {
|
this.grpcService = grpcService;
|
||||||
return this.protoService.getName();
|
this.protoService = protoService;
|
||||||
}
|
this.exportMap = exportMap;
|
||||||
|
}
|
||||||
|
get name(): string {
|
||||||
|
return this.protoService.getName();
|
||||||
|
}
|
||||||
|
|
||||||
get qualifiedName(): string {
|
get qualifiedName(): string {
|
||||||
return (this.grpcService.packageName ? `${this.grpcService.packageName}.` : "") + this.name;
|
return (
|
||||||
}
|
(this.grpcService.packageName ? `${this.grpcService.packageName}.` : '') +
|
||||||
|
this.name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
get methods(): RPCMethodDescriptor[] {
|
get methods(): RPCMethodDescriptor[] {
|
||||||
return this.protoService.getMethodList()
|
return this.protoService.getMethodList().map((method) => {
|
||||||
.map(method => {
|
const callingTypes = getCallingTypes(method, this.exportMap);
|
||||||
const callingTypes = getCallingTypes(method, this.exportMap);
|
const nameAsCamelCase =
|
||||||
const nameAsCamelCase = method.getName()[0].toLowerCase() + method.getName().substr(1);
|
method.getName()[0].toLowerCase() + method.getName().substr(1);
|
||||||
return {
|
return {
|
||||||
nameAsPascalCase: method.getName(),
|
nameAsPascalCase: method.getName(),
|
||||||
nameAsCamelCase,
|
nameAsCamelCase,
|
||||||
functionName: normaliseFieldObjectName(nameAsCamelCase),
|
functionName: normaliseFieldObjectName(nameAsCamelCase),
|
||||||
serviceName: this.name,
|
serviceName: this.name,
|
||||||
requestStream: method.getClientStreaming(),
|
requestStream: method.getClientStreaming(),
|
||||||
responseStream: method.getServerStreaming(),
|
responseStream: method.getServerStreaming(),
|
||||||
requestType: callingTypes.requestType,
|
requestType: callingTypes.requestType,
|
||||||
responseType: callingTypes.responseType,
|
responseType: callingTypes.responseType,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GrpcServiceDescriptor {
|
export class GrpcServiceDescriptor {
|
||||||
private readonly fileDescriptor: FileDescriptorProto;
|
private readonly fileDescriptor: FileDescriptorProto;
|
||||||
private readonly exportMap: ExportMap;
|
private readonly exportMap: ExportMap;
|
||||||
private readonly pathToRoot: string;
|
private readonly pathToRoot: string;
|
||||||
|
|
||||||
constructor(fileDescriptor: FileDescriptorProto, exportMap: ExportMap) {
|
constructor(fileDescriptor: FileDescriptorProto, exportMap: ExportMap) {
|
||||||
this.fileDescriptor = fileDescriptor;
|
this.fileDescriptor = fileDescriptor;
|
||||||
this.exportMap = exportMap;
|
this.exportMap = exportMap;
|
||||||
this.pathToRoot = getPathToRoot(fileDescriptor.getName());
|
this.pathToRoot = getPathToRoot(fileDescriptor.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
get filename(): string {
|
get filename(): string {
|
||||||
return this.fileDescriptor.getName();
|
return this.fileDescriptor.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
get packageName(): string {
|
get packageName(): string {
|
||||||
return this.fileDescriptor.getPackage();
|
return this.fileDescriptor.getPackage();
|
||||||
}
|
}
|
||||||
|
|
||||||
get imports(): ImportDescriptor[] {
|
get imports(): ImportDescriptor[] {
|
||||||
const dependencies = this.fileDescriptor.getDependencyList()
|
const dependencies = this.fileDescriptor
|
||||||
.filter(dependency => isUsed(this.fileDescriptor, filePathToPseudoNamespace(dependency), this.exportMap))
|
.getDependencyList()
|
||||||
.map(dependency => {
|
.filter((dependency) =>
|
||||||
const namespace = filePathToPseudoNamespace(dependency);
|
isUsed(
|
||||||
if (dependency in WellKnownTypesMap) {
|
this.fileDescriptor,
|
||||||
return {
|
filePathToPseudoNamespace(dependency),
|
||||||
namespace,
|
this.exportMap
|
||||||
path: WellKnownTypesMap[dependency],
|
)
|
||||||
};
|
)
|
||||||
} else {
|
.map((dependency) => {
|
||||||
return {
|
const namespace = filePathToPseudoNamespace(dependency);
|
||||||
namespace,
|
if (dependency in WellKnownTypesMap) {
|
||||||
path: `${this.pathToRoot}${replaceProtoSuffix(replaceProtoSuffix(dependency))}`
|
return {
|
||||||
};
|
namespace,
|
||||||
}
|
path: WellKnownTypesMap[dependency],
|
||||||
});
|
};
|
||||||
const hostProto = {
|
} else {
|
||||||
namespace: filePathToPseudoNamespace(this.filename),
|
return {
|
||||||
path: `${this.pathToRoot}${replaceProtoSuffix(this.filename)}`,
|
namespace,
|
||||||
};
|
path: `${this.pathToRoot}${replaceProtoSuffix(
|
||||||
return [ hostProto ].concat(dependencies);
|
replaceProtoSuffix(dependency)
|
||||||
}
|
)}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const hostProto = {
|
||||||
|
namespace: filePathToPseudoNamespace(this.filename),
|
||||||
|
path: `${this.pathToRoot}${replaceProtoSuffix(this.filename)}`,
|
||||||
|
};
|
||||||
|
return [hostProto].concat(dependencies);
|
||||||
|
}
|
||||||
|
|
||||||
get services(): RPCDescriptor[] {
|
get services(): RPCDescriptor[] {
|
||||||
return this.fileDescriptor.getServiceList()
|
return this.fileDescriptor.getServiceList().map((service) => {
|
||||||
.map(service => {
|
return new RPCDescriptor(this, service, this.exportMap);
|
||||||
return new RPCDescriptor(this, service, this.exportMap);
|
});
|
||||||
});
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,127 +1,162 @@
|
||||||
import {ExportMap} from "../ExportMap";
|
import { ExportMap } from '../ExportMap';
|
||||||
import {Printer} from "../Printer";
|
import { Printer } from '../Printer';
|
||||||
import {FileDescriptorProto} from "google-protobuf/google/protobuf/descriptor_pb";
|
import { FileDescriptorProto } from 'google-protobuf/google/protobuf/descriptor_pb';
|
||||||
import {CodeGeneratorResponse} from "google-protobuf/google/protobuf/compiler/plugin_pb";
|
import { CodeGeneratorResponse } from 'google-protobuf/google/protobuf/compiler/plugin_pb';
|
||||||
import {createFile, RPCDescriptor, GrpcServiceDescriptor, RPCMethodDescriptor} from "./common";
|
import {
|
||||||
import { ModeParameter } from "../parameters";
|
createFile,
|
||||||
|
RPCDescriptor,
|
||||||
|
GrpcServiceDescriptor,
|
||||||
|
RPCMethodDescriptor,
|
||||||
|
} from './common';
|
||||||
|
import { ModeParameter } from '../parameters';
|
||||||
|
|
||||||
export function generateGrpcNodeService(filename: string, descriptor: FileDescriptorProto, exportMap: ExportMap, modeParameter: ModeParameter): CodeGeneratorResponse.File {
|
export function generateGrpcNodeService(
|
||||||
const definitionFilename = filename.replace(/_pb$/, "_grpc_pb.d.ts");
|
filename: string,
|
||||||
return createFile(generateTypeScriptDefinition(descriptor, exportMap, modeParameter), definitionFilename);
|
descriptor: FileDescriptorProto,
|
||||||
|
exportMap: ExportMap,
|
||||||
|
modeParameter: ModeParameter
|
||||||
|
): CodeGeneratorResponse.File {
|
||||||
|
const definitionFilename = filename.replace(/_pb$/, '_grpc_pb.d.ts');
|
||||||
|
return createFile(
|
||||||
|
generateTypeScriptDefinition(descriptor, exportMap, modeParameter),
|
||||||
|
definitionFilename
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateTypeScriptDefinition(fileDescriptor: FileDescriptorProto, exportMap: ExportMap, modeParameter: ModeParameter): string {
|
function generateTypeScriptDefinition(
|
||||||
const serviceDescriptor = new GrpcServiceDescriptor(fileDescriptor, exportMap);
|
fileDescriptor: FileDescriptorProto,
|
||||||
const printer = new Printer(0);
|
exportMap: ExportMap,
|
||||||
|
modeParameter: ModeParameter
|
||||||
|
): string {
|
||||||
|
const serviceDescriptor = new GrpcServiceDescriptor(fileDescriptor, exportMap);
|
||||||
|
const printer = new Printer(0);
|
||||||
|
|
||||||
const hasServices = serviceDescriptor.services.length > 0;
|
const hasServices = serviceDescriptor.services.length > 0;
|
||||||
|
|
||||||
// Header.
|
// Header.
|
||||||
if (hasServices) {
|
if (hasServices) {
|
||||||
printer.printLn("// GENERATED CODE -- DO NOT EDIT!");
|
printer.printLn('// GENERATED CODE -- DO NOT EDIT!');
|
||||||
|
printer.printEmptyLn();
|
||||||
|
} else {
|
||||||
|
printer.printLn('// GENERATED CODE -- NO SERVICES IN PROTO');
|
||||||
|
return printer.getOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
printer.printLn(`// package: ${serviceDescriptor.packageName}`);
|
||||||
|
printer.printLn(`// file: ${serviceDescriptor.filename}`);
|
||||||
printer.printEmptyLn();
|
printer.printEmptyLn();
|
||||||
} else {
|
|
||||||
printer.printLn("// GENERATED CODE -- NO SERVICES IN PROTO");
|
// Import statements.
|
||||||
|
serviceDescriptor.imports.forEach((importDescriptor) => {
|
||||||
|
printer.printLn(
|
||||||
|
`import * as ${importDescriptor.namespace} from "${importDescriptor.path}";`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
const importPackage =
|
||||||
|
modeParameter === ModeParameter.GrpcJs ? '@grpc/grpc-js' : 'grpc';
|
||||||
|
printer.printLn(`import * as grpc from "${importPackage}";`);
|
||||||
|
|
||||||
|
// Services.
|
||||||
|
serviceDescriptor.services.forEach((service) => {
|
||||||
|
printer.printEmptyLn();
|
||||||
|
printService(printer, service);
|
||||||
|
printer.printEmptyLn();
|
||||||
|
printClient(printer, service);
|
||||||
|
});
|
||||||
|
|
||||||
return printer.getOutput();
|
return printer.getOutput();
|
||||||
}
|
|
||||||
|
|
||||||
printer.printLn(`// package: ${serviceDescriptor.packageName}`);
|
|
||||||
printer.printLn(`// file: ${serviceDescriptor.filename}`);
|
|
||||||
printer.printEmptyLn();
|
|
||||||
|
|
||||||
// Import statements.
|
|
||||||
serviceDescriptor.imports
|
|
||||||
.forEach(importDescriptor => {
|
|
||||||
printer.printLn(`import * as ${importDescriptor.namespace} from "${importDescriptor.path}";`);
|
|
||||||
});
|
|
||||||
const importPackage = modeParameter === ModeParameter.GrpcJs ? "@grpc/grpc-js" : "grpc";
|
|
||||||
printer.printLn(`import * as grpc from "${importPackage}";`);
|
|
||||||
|
|
||||||
// Services.
|
|
||||||
serviceDescriptor.services
|
|
||||||
.forEach(service => {
|
|
||||||
printer.printEmptyLn();
|
|
||||||
printService(printer, service);
|
|
||||||
printer.printEmptyLn();
|
|
||||||
printClient(printer, service);
|
|
||||||
});
|
|
||||||
|
|
||||||
return printer.getOutput();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function printService(printer: Printer, service: RPCDescriptor) {
|
function printService(printer: Printer, service: RPCDescriptor) {
|
||||||
const serviceName = `${service.name}Service`;
|
const serviceName = `${service.name}Service`;
|
||||||
printer.printLn(`interface I${serviceName} extends grpc.ServiceDefinition<grpc.UntypedServiceImplementation> {`);
|
printer.printLn(
|
||||||
service.methods
|
`interface I${serviceName} extends grpc.ServiceDefinition<grpc.UntypedServiceImplementation> {`
|
||||||
.forEach(method => {
|
);
|
||||||
const methodType = `grpc.MethodDefinition<${method.requestType}, ${method.responseType}>`;
|
service.methods.forEach((method) => {
|
||||||
printer.printIndentedLn(`${method.nameAsCamelCase}: ${methodType};`);
|
const methodType = `grpc.MethodDefinition<${method.requestType}, ${method.responseType}>`;
|
||||||
|
printer.printIndentedLn(`${method.nameAsCamelCase}: ${methodType};`);
|
||||||
});
|
});
|
||||||
printer.printLn("}");
|
printer.printLn('}');
|
||||||
printer.printEmptyLn();
|
printer.printEmptyLn();
|
||||||
printer.printLn(`export const ${serviceName}: I${serviceName};`);
|
printer.printLn(`export const ${serviceName}: I${serviceName};`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function printClient(printer: Printer, service: RPCDescriptor) {
|
function printClient(printer: Printer, service: RPCDescriptor) {
|
||||||
printer.printLn(`export class ${service.name}Client extends grpc.Client {`);
|
printer.printLn(`export class ${service.name}Client extends grpc.Client {`);
|
||||||
printer.printIndentedLn("constructor(address: string, credentials: grpc.ChannelCredentials, options?: object);");
|
printer.printIndentedLn(
|
||||||
service.methods
|
'constructor(address: string, credentials: grpc.ChannelCredentials, options?: object);'
|
||||||
.forEach(method => {
|
);
|
||||||
if (!method.requestStream && !method.responseStream) {
|
service.methods.forEach((method) => {
|
||||||
printUnaryRequestMethod(printer, method);
|
if (!method.requestStream && !method.responseStream) {
|
||||||
} else if (!method.requestStream) {
|
printUnaryRequestMethod(printer, method);
|
||||||
printServerStreamRequestMethod(printer, method);
|
} else if (!method.requestStream) {
|
||||||
} else if (!method.responseStream) {
|
printServerStreamRequestMethod(printer, method);
|
||||||
printClientStreamRequestMethod(printer, method);
|
} else if (!method.responseStream) {
|
||||||
} else {
|
printClientStreamRequestMethod(printer, method);
|
||||||
printBidiStreamRequest(printer, method);
|
} else {
|
||||||
}
|
printBidiStreamRequest(printer, method);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
printer.printLn("}");
|
printer.printLn('}');
|
||||||
}
|
}
|
||||||
|
|
||||||
const metadata = "metadata: grpc.Metadata | null";
|
const metadata = 'metadata: grpc.Metadata | null';
|
||||||
const options = "options: grpc.CallOptions | null";
|
const options = 'options: grpc.CallOptions | null';
|
||||||
const metadataOrOptions = "metadataOrOptions: grpc.Metadata | grpc.CallOptions | null";
|
const metadataOrOptions = 'metadataOrOptions: grpc.Metadata | grpc.CallOptions | null';
|
||||||
|
|
||||||
const optionalMetadata = "metadata?: grpc.Metadata | null";
|
const optionalMetadata = 'metadata?: grpc.Metadata | null';
|
||||||
const optionalOptions = "options?: grpc.CallOptions | null";
|
const optionalOptions = 'options?: grpc.CallOptions | null';
|
||||||
const optionalMetadataOrOptions = "metadataOrOptions?: grpc.Metadata | grpc.CallOptions | null";
|
const optionalMetadataOrOptions =
|
||||||
|
'metadataOrOptions?: grpc.Metadata | grpc.CallOptions | null';
|
||||||
|
|
||||||
function printUnaryRequestMethod(printer: Printer, method: RPCMethodDescriptor) {
|
function printUnaryRequestMethod(printer: Printer, method: RPCMethodDescriptor) {
|
||||||
const name = method.nameAsCamelCase;
|
const name = method.nameAsCamelCase;
|
||||||
const argument = `argument: ${method.requestType}`;
|
const argument = `argument: ${method.requestType}`;
|
||||||
const callback = `callback: grpc.requestCallback<${method.responseType}>`;
|
const callback = `callback: grpc.requestCallback<${method.responseType}>`;
|
||||||
const returnType = "grpc.ClientUnaryCall";
|
const returnType = 'grpc.ClientUnaryCall';
|
||||||
|
|
||||||
printer.printIndentedLn(`${name}(${argument}, ${callback}): ${returnType};`);
|
printer.printIndentedLn(`${name}(${argument}, ${callback}): ${returnType};`);
|
||||||
printer.printIndentedLn(`${name}(${argument}, ${metadataOrOptions}, ${callback}): ${returnType};`);
|
printer.printIndentedLn(
|
||||||
printer.printIndentedLn(`${name}(${argument}, ${metadata}, ${options}, ${callback}): ${returnType};`);
|
`${name}(${argument}, ${metadataOrOptions}, ${callback}): ${returnType};`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`${name}(${argument}, ${metadata}, ${options}, ${callback}): ${returnType};`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function printServerStreamRequestMethod(printer: Printer, method: RPCMethodDescriptor) {
|
function printServerStreamRequestMethod(printer: Printer, method: RPCMethodDescriptor) {
|
||||||
const name = method.nameAsCamelCase;
|
const name = method.nameAsCamelCase;
|
||||||
const argument = `argument: ${method.requestType}`;
|
const argument = `argument: ${method.requestType}`;
|
||||||
const returnType = `grpc.ClientReadableStream<${method.responseType}>`;
|
const returnType = `grpc.ClientReadableStream<${method.responseType}>`;
|
||||||
|
|
||||||
printer.printIndentedLn(`${name}(${argument}, ${optionalMetadataOrOptions}): ${returnType};`);
|
printer.printIndentedLn(
|
||||||
printer.printIndentedLn(`${name}(${argument}, ${optionalMetadata}, ${optionalOptions}): ${returnType};`);
|
`${name}(${argument}, ${optionalMetadataOrOptions}): ${returnType};`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`${name}(${argument}, ${optionalMetadata}, ${optionalOptions}): ${returnType};`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function printClientStreamRequestMethod(printer: Printer, method: RPCMethodDescriptor) {
|
function printClientStreamRequestMethod(printer: Printer, method: RPCMethodDescriptor) {
|
||||||
const name = method.nameAsCamelCase;
|
const name = method.nameAsCamelCase;
|
||||||
const callback = `callback: grpc.requestCallback<${method.responseType}>`;
|
const callback = `callback: grpc.requestCallback<${method.responseType}>`;
|
||||||
const returnType = `grpc.ClientWritableStream<${method.requestType}>`;
|
const returnType = `grpc.ClientWritableStream<${method.requestType}>`;
|
||||||
|
|
||||||
printer.printIndentedLn(`${name}(${callback}): grpc.ClientWritableStream<${method.requestType}>;`);
|
printer.printIndentedLn(
|
||||||
printer.printIndentedLn(`${name}(${metadataOrOptions}, ${callback}): ${returnType};`);
|
`${name}(${callback}): grpc.ClientWritableStream<${method.requestType}>;`
|
||||||
printer.printIndentedLn(`${name}(${metadata}, ${options}, ${callback}): ${returnType};`);
|
);
|
||||||
|
printer.printIndentedLn(`${name}(${metadataOrOptions}, ${callback}): ${returnType};`);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`${name}(${metadata}, ${options}, ${callback}): ${returnType};`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function printBidiStreamRequest(printer: Printer, method: RPCMethodDescriptor) {
|
function printBidiStreamRequest(printer: Printer, method: RPCMethodDescriptor) {
|
||||||
const name = method.nameAsCamelCase;
|
const name = method.nameAsCamelCase;
|
||||||
const returnType = `grpc.ClientDuplexStream<${method.requestType}, ${method.responseType}>`;
|
const returnType = `grpc.ClientDuplexStream<${method.requestType}, ${method.responseType}>`;
|
||||||
|
|
||||||
printer.printIndentedLn(`${name}(${optionalMetadataOrOptions}): ${returnType};`);
|
printer.printIndentedLn(`${name}(${optionalMetadataOrOptions}): ${returnType};`);
|
||||||
printer.printIndentedLn(`${name}(${optionalMetadata}, ${optionalOptions}): ${returnType};`);
|
printer.printIndentedLn(
|
||||||
|
`${name}(${optionalMetadata}, ${optionalOptions}): ${returnType};`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,397 +1,570 @@
|
||||||
import {ExportMap} from "../ExportMap";
|
import { ExportMap } from '../ExportMap';
|
||||||
import {Printer} from "../Printer";
|
import { Printer } from '../Printer';
|
||||||
import {CodePrinter} from "../CodePrinter";
|
import { CodePrinter } from '../CodePrinter';
|
||||||
import {FileDescriptorProto} from "google-protobuf/google/protobuf/descriptor_pb";
|
import { FileDescriptorProto } from 'google-protobuf/google/protobuf/descriptor_pb';
|
||||||
import {CodeGeneratorResponse} from "google-protobuf/google/protobuf/compiler/plugin_pb";
|
import { CodeGeneratorResponse } from 'google-protobuf/google/protobuf/compiler/plugin_pb';
|
||||||
import {createFile, RPCMethodDescriptor, RPCDescriptor, GrpcServiceDescriptor} from "./common";
|
import {
|
||||||
|
createFile,
|
||||||
|
RPCMethodDescriptor,
|
||||||
|
RPCDescriptor,
|
||||||
|
GrpcServiceDescriptor,
|
||||||
|
} from './common';
|
||||||
|
|
||||||
export function generateGrpcWebService(filename: string, descriptor: FileDescriptorProto, exportMap: ExportMap): CodeGeneratorResponse.File[] {
|
export function generateGrpcWebService(
|
||||||
return [
|
filename: string,
|
||||||
createFile(generateTypeScriptDefinition(descriptor, exportMap), `${filename}_service.d.ts`),
|
descriptor: FileDescriptorProto,
|
||||||
createFile(generateJavaScript(descriptor, exportMap), `${filename}_service.js`),
|
exportMap: ExportMap
|
||||||
];
|
): CodeGeneratorResponse.File[] {
|
||||||
|
return [
|
||||||
|
createFile(
|
||||||
|
generateTypeScriptDefinition(descriptor, exportMap),
|
||||||
|
`${filename}_service.d.ts`
|
||||||
|
),
|
||||||
|
createFile(generateJavaScript(descriptor, exportMap), `${filename}_service.js`),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateTypeScriptDefinition(fileDescriptor: FileDescriptorProto, exportMap: ExportMap): string {
|
function generateTypeScriptDefinition(
|
||||||
const serviceDescriptor = new GrpcServiceDescriptor(fileDescriptor, exportMap);
|
fileDescriptor: FileDescriptorProto,
|
||||||
const printer = new Printer(0);
|
exportMap: ExportMap
|
||||||
|
): string {
|
||||||
|
const serviceDescriptor = new GrpcServiceDescriptor(fileDescriptor, exportMap);
|
||||||
|
const printer = new Printer(0);
|
||||||
|
|
||||||
// Header.
|
// Header.
|
||||||
printer.printLn(`// package: ${serviceDescriptor.packageName}`);
|
printer.printLn(`// package: ${serviceDescriptor.packageName}`);
|
||||||
printer.printLn(`// file: ${serviceDescriptor.filename}`);
|
printer.printLn(`// file: ${serviceDescriptor.filename}`);
|
||||||
printer.printEmptyLn();
|
printer.printEmptyLn();
|
||||||
|
|
||||||
if (serviceDescriptor.services.length === 0) {
|
if (serviceDescriptor.services.length === 0) {
|
||||||
return printer.getOutput();
|
return printer.getOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import statements.
|
// Import statements.
|
||||||
serviceDescriptor.imports
|
serviceDescriptor.imports.forEach((importDescriptor) => {
|
||||||
.forEach(importDescriptor => {
|
printer.printLn(
|
||||||
printer.printLn(`import * as ${importDescriptor.namespace} from "${importDescriptor.path}";`);
|
`import * as ${importDescriptor.namespace} from "${importDescriptor.path}";`
|
||||||
|
);
|
||||||
});
|
});
|
||||||
printer.printLn(`import {grpc} from "@improbable-eng/grpc-web";`);
|
printer.printLn(`import {grpc} from "@improbable-eng/grpc-web";`);
|
||||||
printer.printEmptyLn();
|
printer.printEmptyLn();
|
||||||
|
|
||||||
// Services.
|
// Services.
|
||||||
serviceDescriptor.services
|
serviceDescriptor.services.forEach((service) => {
|
||||||
.forEach(service => {
|
// Method Type Definitions
|
||||||
|
service.methods.forEach((method) => {
|
||||||
// Method Type Definitions
|
printer.printLn(`type ${method.serviceName}${method.nameAsPascalCase} = {`);
|
||||||
service.methods.forEach(method => {
|
printer.printIndentedLn(`readonly methodName: string;`);
|
||||||
printer.printLn(`type ${method.serviceName}${method.nameAsPascalCase} = {`);
|
printer.printIndentedLn(`readonly service: typeof ${method.serviceName};`);
|
||||||
printer.printIndentedLn(`readonly methodName: string;`);
|
printer.printIndentedLn(`readonly requestStream: ${method.requestStream};`);
|
||||||
printer.printIndentedLn(`readonly service: typeof ${method.serviceName};`);
|
printer.printIndentedLn(`readonly responseStream: ${method.responseStream};`);
|
||||||
printer.printIndentedLn(`readonly requestStream: ${method.requestStream};`);
|
printer.printIndentedLn(
|
||||||
printer.printIndentedLn(`readonly responseStream: ${method.responseStream};`);
|
`readonly requestType: typeof ${method.requestType};`
|
||||||
printer.printIndentedLn(`readonly requestType: typeof ${method.requestType};`);
|
);
|
||||||
printer.printIndentedLn(`readonly responseType: typeof ${method.responseType};`);
|
printer.printIndentedLn(
|
||||||
printer.printLn(`};`);
|
`readonly responseType: typeof ${method.responseType};`
|
||||||
printer.printEmptyLn();
|
);
|
||||||
});
|
printer.printLn(`};`);
|
||||||
|
printer.printEmptyLn();
|
||||||
printer.printLn(`export class ${service.name} {`);
|
|
||||||
printer.printIndentedLn(`static readonly serviceName: string;`);
|
|
||||||
service.methods.forEach(method => {
|
|
||||||
printer.printIndentedLn(`static readonly ${method.nameAsPascalCase}: ${method.serviceName}${method.nameAsPascalCase};`);
|
|
||||||
});
|
|
||||||
printer.printLn(`}`);
|
|
||||||
printer.printEmptyLn();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
printer.printLn(`export type ServiceError = { message: string, code: number; metadata: grpc.Metadata }`);
|
|
||||||
printer.printLn(`export type Status = { details: string, code: number; metadata: grpc.Metadata }`);
|
|
||||||
printer.printEmptyLn();
|
|
||||||
printer.printLn("interface UnaryResponse {");
|
|
||||||
printer.printIndentedLn("cancel(): void;");
|
|
||||||
printer.printLn("}");
|
|
||||||
printer.printLn(`interface ResponseStream<T> {`);
|
|
||||||
printer.printIndentedLn(`cancel(): void;`);
|
|
||||||
printer.printIndentedLn(`on(type: 'data', handler: (message: T) => void): ResponseStream<T>;`);
|
|
||||||
printer.printIndentedLn(`on(type: 'end', handler: (status?: Status) => void): ResponseStream<T>;`);
|
|
||||||
printer.printIndentedLn(`on(type: 'status', handler: (status: Status) => void): ResponseStream<T>;`);
|
|
||||||
printer.printLn(`}`);
|
|
||||||
printer.printLn(`interface RequestStream<T> {`);
|
|
||||||
printer.printIndentedLn(`write(message: T): RequestStream<T>;`);
|
|
||||||
printer.printIndentedLn(`end(): void;`);
|
|
||||||
printer.printIndentedLn(`cancel(): void;`);
|
|
||||||
printer.printIndentedLn(`on(type: 'end', handler: (status?: Status) => void): RequestStream<T>;`);
|
|
||||||
printer.printIndentedLn(`on(type: 'status', handler: (status: Status) => void): RequestStream<T>;`);
|
|
||||||
printer.printLn(`}`);
|
|
||||||
printer.printLn(`interface BidirectionalStream<ReqT, ResT> {`);
|
|
||||||
printer.printIndentedLn(`write(message: ReqT): BidirectionalStream<ReqT, ResT>;`);
|
|
||||||
printer.printIndentedLn(`end(): void;`);
|
|
||||||
printer.printIndentedLn(`cancel(): void;`);
|
|
||||||
printer.printIndentedLn(`on(type: 'data', handler: (message: ResT) => void): BidirectionalStream<ReqT, ResT>;`);
|
|
||||||
printer.printIndentedLn(`on(type: 'end', handler: (status?: Status) => void): BidirectionalStream<ReqT, ResT>;`);
|
|
||||||
printer.printIndentedLn(`on(type: 'status', handler: (status: Status) => void): BidirectionalStream<ReqT, ResT>;`);
|
|
||||||
printer.printLn(`}`);
|
|
||||||
printer.printEmptyLn();
|
|
||||||
|
|
||||||
// Add a client stub that talks with the @improbable-eng/grpc-web library
|
|
||||||
serviceDescriptor.services
|
|
||||||
.forEach(service => {
|
|
||||||
printServiceStubTypes(printer, service);
|
|
||||||
printer.printEmptyLn();
|
|
||||||
});
|
|
||||||
|
|
||||||
return printer.getOutput();
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateJavaScript(fileDescriptor: FileDescriptorProto, exportMap: ExportMap): string {
|
|
||||||
const serviceDescriptor = new GrpcServiceDescriptor(fileDescriptor, exportMap);
|
|
||||||
const printer = new Printer(0);
|
|
||||||
|
|
||||||
// Header.
|
|
||||||
printer.printLn(`// package: ${serviceDescriptor.packageName}`);
|
|
||||||
printer.printLn(`// file: ${serviceDescriptor.filename}`);
|
|
||||||
printer.printEmptyLn();
|
|
||||||
|
|
||||||
if (serviceDescriptor.services.length === 0) {
|
|
||||||
return printer.getOutput();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Import Statements
|
|
||||||
serviceDescriptor.imports
|
|
||||||
.forEach(importDescriptor => {
|
|
||||||
printer.printLn(`var ${importDescriptor.namespace} = require("${importDescriptor.path}");`);
|
|
||||||
});
|
|
||||||
printer.printLn(`var grpc = require("@improbable-eng/grpc-web").grpc;`);
|
|
||||||
printer.printEmptyLn();
|
|
||||||
|
|
||||||
// Services.
|
|
||||||
serviceDescriptor.services
|
|
||||||
.forEach(service => {
|
|
||||||
printer.printLn(`var ${service.name} = (function () {`);
|
|
||||||
printer.printIndentedLn(`function ${service.name}() {}`);
|
|
||||||
printer.printIndentedLn(`${service.name}.serviceName = "${service.qualifiedName}";`);
|
|
||||||
printer.printIndentedLn(`return ${service.name};`);
|
|
||||||
printer.printLn(`}());`);
|
|
||||||
printer.printEmptyLn();
|
|
||||||
|
|
||||||
service.methods
|
|
||||||
.forEach(method => {
|
|
||||||
printer.printLn(`${method.serviceName}.${method.nameAsPascalCase} = {`);
|
|
||||||
printer.printIndentedLn(`methodName: "${method.nameAsPascalCase}",`);
|
|
||||||
printer.printIndentedLn(`service: ${method.serviceName},`);
|
|
||||||
printer.printIndentedLn(`requestStream: ${method.requestStream},`);
|
|
||||||
printer.printIndentedLn(`responseStream: ${method.responseStream},`);
|
|
||||||
printer.printIndentedLn(`requestType: ${method.requestType},`);
|
|
||||||
printer.printIndentedLn(`responseType: ${method.responseType}`);
|
|
||||||
printer.printLn(`};`);
|
|
||||||
printer.printEmptyLn();
|
|
||||||
});
|
});
|
||||||
printer.printLn(`exports.${service.name} = ${service.name};`);
|
|
||||||
printer.printEmptyLn();
|
|
||||||
|
|
||||||
// Add a client stub that talks with the @improbable-eng/grpc-web library
|
printer.printLn(`export class ${service.name} {`);
|
||||||
printServiceStub(printer, service);
|
printer.printIndentedLn(`static readonly serviceName: string;`);
|
||||||
|
service.methods.forEach((method) => {
|
||||||
printer.printEmptyLn();
|
printer.printIndentedLn(
|
||||||
|
`static readonly ${method.nameAsPascalCase}: ${method.serviceName}${method.nameAsPascalCase};`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
printer.printLn(`}`);
|
||||||
|
printer.printEmptyLn();
|
||||||
});
|
});
|
||||||
|
|
||||||
return printer.getOutput();
|
printer.printLn(
|
||||||
|
`export type ServiceError = { message: string, code: number; metadata: grpc.Metadata }`
|
||||||
|
);
|
||||||
|
printer.printLn(
|
||||||
|
`export type Status = { details: string, code: number; metadata: grpc.Metadata }`
|
||||||
|
);
|
||||||
|
printer.printEmptyLn();
|
||||||
|
printer.printLn('interface UnaryResponse {');
|
||||||
|
printer.printIndentedLn('cancel(): void;');
|
||||||
|
printer.printLn('}');
|
||||||
|
printer.printLn(`interface ResponseStream<T> {`);
|
||||||
|
printer.printIndentedLn(`cancel(): void;`);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`on(type: 'data', handler: (message: T) => void): ResponseStream<T>;`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`on(type: 'end', handler: (status?: Status) => void): ResponseStream<T>;`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`on(type: 'status', handler: (status: Status) => void): ResponseStream<T>;`
|
||||||
|
);
|
||||||
|
printer.printLn(`}`);
|
||||||
|
printer.printLn(`interface RequestStream<T> {`);
|
||||||
|
printer.printIndentedLn(`write(message: T): RequestStream<T>;`);
|
||||||
|
printer.printIndentedLn(`end(): void;`);
|
||||||
|
printer.printIndentedLn(`cancel(): void;`);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`on(type: 'end', handler: (status?: Status) => void): RequestStream<T>;`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`on(type: 'status', handler: (status: Status) => void): RequestStream<T>;`
|
||||||
|
);
|
||||||
|
printer.printLn(`}`);
|
||||||
|
printer.printLn(`interface BidirectionalStream<ReqT, ResT> {`);
|
||||||
|
printer.printIndentedLn(`write(message: ReqT): BidirectionalStream<ReqT, ResT>;`);
|
||||||
|
printer.printIndentedLn(`end(): void;`);
|
||||||
|
printer.printIndentedLn(`cancel(): void;`);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`on(type: 'data', handler: (message: ResT) => void): BidirectionalStream<ReqT, ResT>;`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`on(type: 'end', handler: (status?: Status) => void): BidirectionalStream<ReqT, ResT>;`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`on(type: 'status', handler: (status: Status) => void): BidirectionalStream<ReqT, ResT>;`
|
||||||
|
);
|
||||||
|
printer.printLn(`}`);
|
||||||
|
printer.printEmptyLn();
|
||||||
|
|
||||||
|
// Add a client stub that talks with the @improbable-eng/grpc-web library
|
||||||
|
serviceDescriptor.services.forEach((service) => {
|
||||||
|
printServiceStubTypes(printer, service);
|
||||||
|
printer.printEmptyLn();
|
||||||
|
});
|
||||||
|
|
||||||
|
return printer.getOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateJavaScript(
|
||||||
|
fileDescriptor: FileDescriptorProto,
|
||||||
|
exportMap: ExportMap
|
||||||
|
): string {
|
||||||
|
const serviceDescriptor = new GrpcServiceDescriptor(fileDescriptor, exportMap);
|
||||||
|
const printer = new Printer(0);
|
||||||
|
|
||||||
|
// Header.
|
||||||
|
printer.printLn(`// package: ${serviceDescriptor.packageName}`);
|
||||||
|
printer.printLn(`// file: ${serviceDescriptor.filename}`);
|
||||||
|
printer.printEmptyLn();
|
||||||
|
|
||||||
|
if (serviceDescriptor.services.length === 0) {
|
||||||
|
return printer.getOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import Statements
|
||||||
|
serviceDescriptor.imports.forEach((importDescriptor) => {
|
||||||
|
printer.printLn(
|
||||||
|
`var ${importDescriptor.namespace} = require("${importDescriptor.path}");`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
printer.printLn(`var grpc = require("@improbable-eng/grpc-web").grpc;`);
|
||||||
|
printer.printEmptyLn();
|
||||||
|
|
||||||
|
// Services.
|
||||||
|
serviceDescriptor.services.forEach((service) => {
|
||||||
|
printer.printLn(`var ${service.name} = (function () {`);
|
||||||
|
printer.printIndentedLn(`function ${service.name}() {}`);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`${service.name}.serviceName = "${service.qualifiedName}";`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(`return ${service.name};`);
|
||||||
|
printer.printLn(`}());`);
|
||||||
|
printer.printEmptyLn();
|
||||||
|
|
||||||
|
service.methods.forEach((method) => {
|
||||||
|
printer.printLn(`${method.serviceName}.${method.nameAsPascalCase} = {`);
|
||||||
|
printer.printIndentedLn(`methodName: "${method.nameAsPascalCase}",`);
|
||||||
|
printer.printIndentedLn(`service: ${method.serviceName},`);
|
||||||
|
printer.printIndentedLn(`requestStream: ${method.requestStream},`);
|
||||||
|
printer.printIndentedLn(`responseStream: ${method.responseStream},`);
|
||||||
|
printer.printIndentedLn(`requestType: ${method.requestType},`);
|
||||||
|
printer.printIndentedLn(`responseType: ${method.responseType}`);
|
||||||
|
printer.printLn(`};`);
|
||||||
|
printer.printEmptyLn();
|
||||||
|
});
|
||||||
|
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);
|
||||||
|
|
||||||
|
printer.printEmptyLn();
|
||||||
|
});
|
||||||
|
|
||||||
|
return printer.getOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
function printServiceStub(methodPrinter: Printer, service: RPCDescriptor) {
|
function printServiceStub(methodPrinter: Printer, service: RPCDescriptor) {
|
||||||
const printer = new CodePrinter(0, methodPrinter);
|
const printer = new CodePrinter(0, methodPrinter);
|
||||||
|
|
||||||
printer
|
printer
|
||||||
.printLn(`function ${service.name}Client(serviceHost, options) {`)
|
.printLn(`function ${service.name}Client(serviceHost, options) {`)
|
||||||
.indent().printLn(`this.serviceHost = serviceHost;`)
|
.indent()
|
||||||
.printLn(`this.options = options || {};`)
|
.printLn(`this.serviceHost = serviceHost;`)
|
||||||
.dedent().printLn(`}`)
|
.printLn(`this.options = options || {};`)
|
||||||
.printEmptyLn();
|
.dedent()
|
||||||
|
.printLn(`}`)
|
||||||
|
.printEmptyLn();
|
||||||
|
|
||||||
service.methods.forEach((method: RPCMethodDescriptor) => {
|
service.methods.forEach((method: RPCMethodDescriptor) => {
|
||||||
if (method.requestStream && method.responseStream) {
|
if (method.requestStream && method.responseStream) {
|
||||||
printBidirectionalStubMethod(printer, method);
|
printBidirectionalStubMethod(printer, method);
|
||||||
} else if (method.requestStream) {
|
} else if (method.requestStream) {
|
||||||
printClientStreamStubMethod(printer, method);
|
printClientStreamStubMethod(printer, method);
|
||||||
} else if (method.responseStream) {
|
} else if (method.responseStream) {
|
||||||
printServerStreamStubMethod(printer, method);
|
printServerStreamStubMethod(printer, method);
|
||||||
} else {
|
} else {
|
||||||
printUnaryStubMethod(printer, method);
|
printUnaryStubMethod(printer, method);
|
||||||
}
|
}
|
||||||
printer.printEmptyLn();
|
printer.printEmptyLn();
|
||||||
});
|
});
|
||||||
printer.printLn(`exports.${service.name}Client = ${service.name}Client;`);
|
printer.printLn(`exports.${service.name}Client = ${service.name}Client;`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function printUnaryStubMethod(printer: CodePrinter, method: RPCMethodDescriptor) {
|
function printUnaryStubMethod(printer: CodePrinter, method: RPCMethodDescriptor) {
|
||||||
printer
|
printer
|
||||||
.printLn(`${method.serviceName}Client.prototype.${method.nameAsCamelCase} = function ${method.functionName}(requestMessage, metadata, callback) {`)
|
.printLn(
|
||||||
.indent().printLn(`if (arguments.length === 2) {`)
|
`${method.serviceName}Client.prototype.${method.nameAsCamelCase} = function ${method.functionName}(requestMessage, metadata, callback) {`
|
||||||
.indent().printLn(`callback = arguments[1];`)
|
)
|
||||||
.dedent().printLn("}")
|
.indent()
|
||||||
.printLn(`var client = grpc.unary(${method.serviceName}.${method.nameAsPascalCase}, {`)
|
.printLn(`if (arguments.length === 2) {`)
|
||||||
.indent().printLn(`request: requestMessage,`)
|
.indent()
|
||||||
.printLn(`host: this.serviceHost,`)
|
.printLn(`callback = arguments[1];`)
|
||||||
.printLn(`metadata: metadata,`)
|
.dedent()
|
||||||
.printLn(`transport: this.options.transport,`)
|
.printLn('}')
|
||||||
.printLn(`debug: this.options.debug,`)
|
.printLn(
|
||||||
.printLn(`onEnd: function (response) {`)
|
`var client = grpc.unary(${method.serviceName}.${method.nameAsPascalCase}, {`
|
||||||
.indent().printLn(`if (callback) {`)
|
)
|
||||||
.indent().printLn(`if (response.status !== grpc.Code.OK) {`)
|
.indent()
|
||||||
.indent().printLn(`var err = new Error(response.statusMessage);`)
|
.printLn(`request: requestMessage,`)
|
||||||
.printLn(`err.code = response.status;`)
|
.printLn(`host: this.serviceHost,`)
|
||||||
.printLn(`err.metadata = response.trailers;`)
|
.printLn(`metadata: metadata,`)
|
||||||
.printLn(`callback(err, null);`)
|
.printLn(`transport: this.options.transport,`)
|
||||||
.dedent().printLn(`} else {`)
|
.printLn(`debug: this.options.debug,`)
|
||||||
.indent().printLn(`callback(null, response.message);`)
|
.printLn(`onEnd: function (response) {`)
|
||||||
.dedent().printLn(`}`)
|
.indent()
|
||||||
.dedent().printLn(`}`)
|
.printLn(`if (callback) {`)
|
||||||
.dedent().printLn(`}`)
|
.indent()
|
||||||
.dedent().printLn(`});`)
|
.printLn(`if (response.status !== grpc.Code.OK) {`)
|
||||||
.printLn(`return {`)
|
.indent()
|
||||||
.indent().printLn(`cancel: function () {`)
|
.printLn(`var err = new Error(response.statusMessage);`)
|
||||||
.indent().printLn(`callback = null;`)
|
.printLn(`err.code = response.status;`)
|
||||||
.printLn(`client.close();`)
|
.printLn(`err.metadata = response.trailers;`)
|
||||||
.dedent().printLn(`}`)
|
.printLn(`callback(err, null);`)
|
||||||
.dedent().printLn(`};`)
|
.dedent()
|
||||||
.dedent().printLn(`};`);
|
.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(`};`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function printServerStreamStubMethod(printer: CodePrinter, method: RPCMethodDescriptor) {
|
function printServerStreamStubMethod(printer: CodePrinter, method: RPCMethodDescriptor) {
|
||||||
printer
|
printer
|
||||||
.printLn(`${method.serviceName}Client.prototype.${method.nameAsCamelCase} = function ${method.functionName}(requestMessage, metadata) {`)
|
.printLn(
|
||||||
.indent().printLn(`var listeners = {`)
|
`${method.serviceName}Client.prototype.${method.nameAsCamelCase} = function ${method.functionName}(requestMessage, metadata) {`
|
||||||
.indent().printLn(`data: [],`)
|
)
|
||||||
.printLn(`end: [],`)
|
.indent()
|
||||||
.printLn(`status: []`)
|
.printLn(`var listeners = {`)
|
||||||
.dedent().printLn(`};`)
|
.indent()
|
||||||
.printLn(`var client = grpc.invoke(${method.serviceName}.${method.nameAsPascalCase}, {`)
|
.printLn(`data: [],`)
|
||||||
.indent().printLn(`request: requestMessage,`)
|
.printLn(`end: [],`)
|
||||||
.printLn(`host: this.serviceHost,`)
|
.printLn(`status: []`)
|
||||||
.printLn(`metadata: metadata,`)
|
.dedent()
|
||||||
.printLn(`transport: this.options.transport,`)
|
.printLn(`};`)
|
||||||
.printLn(`debug: this.options.debug,`)
|
.printLn(
|
||||||
.printLn(`onMessage: function (responseMessage) {`)
|
`var client = grpc.invoke(${method.serviceName}.${method.nameAsPascalCase}, {`
|
||||||
.indent().printLn(`listeners.data.forEach(function (handler) {`)
|
)
|
||||||
.indent().printLn(`handler(responseMessage);`)
|
.indent()
|
||||||
.dedent().printLn(`});`)
|
.printLn(`request: requestMessage,`)
|
||||||
.dedent().printLn(`},`)
|
.printLn(`host: this.serviceHost,`)
|
||||||
.printLn(`onEnd: function (status, statusMessage, trailers) {`)
|
.printLn(`metadata: metadata,`)
|
||||||
.indent().printLn(`listeners.status.forEach(function (handler) {`)
|
.printLn(`transport: this.options.transport,`)
|
||||||
.indent().printLn(`handler({ code: status, details: statusMessage, metadata: trailers });`)
|
.printLn(`debug: this.options.debug,`)
|
||||||
.dedent().printLn(`});`)
|
.printLn(`onMessage: function (responseMessage) {`)
|
||||||
.printLn(`listeners.end.forEach(function (handler) {`)
|
.indent()
|
||||||
.indent().printLn(`handler({ code: status, details: statusMessage, metadata: trailers });`)
|
.printLn(`listeners.data.forEach(function (handler) {`)
|
||||||
.dedent().printLn(`});`)
|
.indent()
|
||||||
.printLn(`listeners = null;`)
|
.printLn(`handler(responseMessage);`)
|
||||||
.dedent().printLn(`}`)
|
.dedent()
|
||||||
.dedent().printLn(`});`)
|
.printLn(`});`)
|
||||||
.printLn(`return {`)
|
.dedent()
|
||||||
.indent().printLn(`on: function (type, handler) {`)
|
.printLn(`},`)
|
||||||
.indent().printLn(`listeners[type].push(handler);`)
|
.printLn(`onEnd: function (status, statusMessage, trailers) {`)
|
||||||
.printLn(`return this;`)
|
.indent()
|
||||||
.dedent().printLn(`},`)
|
.printLn(`listeners.status.forEach(function (handler) {`)
|
||||||
.printLn(`cancel: function () {`)
|
.indent()
|
||||||
.indent().printLn(`listeners = null;`)
|
.printLn(`handler({ code: status, details: statusMessage, metadata: trailers });`)
|
||||||
.printLn(`client.close();`)
|
.dedent()
|
||||||
.dedent().printLn(`}`)
|
.printLn(`});`)
|
||||||
.dedent().printLn(`};`)
|
.printLn(`listeners.end.forEach(function (handler) {`)
|
||||||
.dedent().printLn(`};`);
|
.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(`}`)
|
||||||
|
.dedent()
|
||||||
|
.printLn(`};`)
|
||||||
|
.dedent()
|
||||||
|
.printLn(`};`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function printClientStreamStubMethod(printer: CodePrinter, method: RPCMethodDescriptor) {
|
function printClientStreamStubMethod(printer: CodePrinter, method: RPCMethodDescriptor) {
|
||||||
printer
|
printer
|
||||||
.printLn(`${method.serviceName}Client.prototype.${method.nameAsCamelCase} = function ${method.functionName}(metadata) {`)
|
.printLn(
|
||||||
.indent().printLn(`var listeners = {`)
|
`${method.serviceName}Client.prototype.${method.nameAsCamelCase} = function ${method.functionName}(metadata) {`
|
||||||
.indent().printLn(`end: [],`)
|
)
|
||||||
.printLn(`status: []`)
|
.indent()
|
||||||
.dedent().printLn(`};`)
|
.printLn(`var listeners = {`)
|
||||||
.printLn(`var client = grpc.client(${method.serviceName}.${method.nameAsPascalCase}, {`)
|
.indent()
|
||||||
.indent().printLn(`host: this.serviceHost,`)
|
.printLn(`end: [],`)
|
||||||
.printLn(`metadata: metadata,`)
|
.printLn(`status: []`)
|
||||||
.printLn(`transport: this.options.transport`)
|
.dedent()
|
||||||
.dedent().printLn(`});`)
|
.printLn(`};`)
|
||||||
.printLn(`client.onEnd(function (status, statusMessage, trailers) {`)
|
.printLn(
|
||||||
.indent().printLn(`listeners.status.forEach(function (handler) {`)
|
`var client = grpc.client(${method.serviceName}.${method.nameAsPascalCase}, {`
|
||||||
.indent().printLn(`handler({ code: status, details: statusMessage, metadata: trailers });`)
|
)
|
||||||
.dedent().printLn(`});`)
|
.indent()
|
||||||
.printLn(`listeners.end.forEach(function (handler) {`)
|
.printLn(`host: this.serviceHost,`)
|
||||||
.indent().printLn(`handler({ code: status, details: statusMessage, metadata: trailers });`)
|
.printLn(`metadata: metadata,`)
|
||||||
.dedent().printLn(`});`)
|
.printLn(`transport: this.options.transport`)
|
||||||
.printLn(`listeners = null;`)
|
.dedent()
|
||||||
.dedent().printLn(`});`)
|
.printLn(`});`)
|
||||||
.printLn(`return {`)
|
.printLn(`client.onEnd(function (status, statusMessage, trailers) {`)
|
||||||
.indent().printLn(`on: function (type, handler) {`)
|
.indent()
|
||||||
.indent().printLn(`listeners[type].push(handler);`)
|
.printLn(`listeners.status.forEach(function (handler) {`)
|
||||||
.printLn(`return this;`)
|
.indent()
|
||||||
.dedent().printLn(`},`)
|
.printLn(`handler({ code: status, details: statusMessage, metadata: trailers });`)
|
||||||
.printLn(`write: function (requestMessage) {`)
|
.dedent()
|
||||||
.indent().printLn(`if (!client.started) {`)
|
.printLn(`});`)
|
||||||
.indent().printLn(`client.start(metadata);`)
|
.printLn(`listeners.end.forEach(function (handler) {`)
|
||||||
.dedent().printLn(`}`)
|
.indent()
|
||||||
.printLn(`client.send(requestMessage);`)
|
.printLn(`handler({ code: status, details: statusMessage, metadata: trailers });`)
|
||||||
.printLn(`return this;`)
|
.dedent()
|
||||||
.dedent().printLn(`},`)
|
.printLn(`});`)
|
||||||
.printLn(`end: function () {`)
|
.printLn(`listeners = null;`)
|
||||||
.indent().printLn(`client.finishSend();`)
|
.dedent()
|
||||||
.dedent().printLn(`},`)
|
.printLn(`});`)
|
||||||
.printLn(`cancel: function () {`)
|
.printLn(`return {`)
|
||||||
.indent().printLn(`listeners = null;`)
|
.indent()
|
||||||
.printLn(`client.close();`)
|
.printLn(`on: function (type, handler) {`)
|
||||||
.dedent().printLn(`}`)
|
.indent()
|
||||||
.dedent().printLn(`};`)
|
.printLn(`listeners[type].push(handler);`)
|
||||||
.dedent().printLn(`};`);
|
.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(`};`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function printBidirectionalStubMethod(printer: CodePrinter, method: RPCMethodDescriptor) {
|
function printBidirectionalStubMethod(printer: CodePrinter, method: RPCMethodDescriptor) {
|
||||||
printer
|
printer
|
||||||
.printLn(`${method.serviceName}Client.prototype.${method.nameAsCamelCase} = function ${method.functionName}(metadata) {`)
|
.printLn(
|
||||||
.indent().printLn(`var listeners = {`)
|
`${method.serviceName}Client.prototype.${method.nameAsCamelCase} = function ${method.functionName}(metadata) {`
|
||||||
.indent().printLn(`data: [],`)
|
)
|
||||||
.printLn(`end: [],`)
|
.indent()
|
||||||
.printLn(`status: []`)
|
.printLn(`var listeners = {`)
|
||||||
.dedent().printLn(`};`)
|
.indent()
|
||||||
.printLn(`var client = grpc.client(${method.serviceName}.${method.nameAsPascalCase}, {`)
|
.printLn(`data: [],`)
|
||||||
.indent().printLn(`host: this.serviceHost,`)
|
.printLn(`end: [],`)
|
||||||
.printLn(`metadata: metadata,`)
|
.printLn(`status: []`)
|
||||||
.printLn(`transport: this.options.transport`)
|
.dedent()
|
||||||
.dedent().printLn(`});`)
|
.printLn(`};`)
|
||||||
.printLn(`client.onEnd(function (status, statusMessage, trailers) {`)
|
.printLn(
|
||||||
.indent().printLn(`listeners.status.forEach(function (handler) {`)
|
`var client = grpc.client(${method.serviceName}.${method.nameAsPascalCase}, {`
|
||||||
.indent().printLn(`handler({ code: status, details: statusMessage, metadata: trailers });`)
|
)
|
||||||
.dedent().printLn(`});`)
|
.indent()
|
||||||
.printLn(`listeners.end.forEach(function (handler) {`)
|
.printLn(`host: this.serviceHost,`)
|
||||||
.indent().printLn(`handler({ code: status, details: statusMessage, metadata: trailers });`)
|
.printLn(`metadata: metadata,`)
|
||||||
.dedent().printLn(`});`)
|
.printLn(`transport: this.options.transport`)
|
||||||
.printLn(`listeners = null;`)
|
.dedent()
|
||||||
.dedent().printLn(`});`)
|
.printLn(`});`)
|
||||||
.printLn(`client.onMessage(function (message) {`)
|
.printLn(`client.onEnd(function (status, statusMessage, trailers) {`)
|
||||||
.indent().printLn(`listeners.data.forEach(function (handler) {`)
|
.indent()
|
||||||
.indent().printLn(`handler(message);`)
|
.printLn(`listeners.status.forEach(function (handler) {`)
|
||||||
.dedent().printLn(`})`)
|
.indent()
|
||||||
.dedent().printLn(`});`)
|
.printLn(`handler({ code: status, details: statusMessage, metadata: trailers });`)
|
||||||
.printLn(`client.start(metadata);`)
|
.dedent()
|
||||||
.printLn(`return {`)
|
.printLn(`});`)
|
||||||
.indent().printLn(`on: function (type, handler) {`)
|
.printLn(`listeners.end.forEach(function (handler) {`)
|
||||||
.indent().printLn(`listeners[type].push(handler);`)
|
.indent()
|
||||||
.printLn(`return this;`)
|
.printLn(`handler({ code: status, details: statusMessage, metadata: trailers });`)
|
||||||
.dedent().printLn(`},`)
|
.dedent()
|
||||||
.printLn(`write: function (requestMessage) {`)
|
.printLn(`});`)
|
||||||
.indent().printLn(`client.send(requestMessage);`)
|
.printLn(`listeners = null;`)
|
||||||
.printLn(`return this;`)
|
.dedent()
|
||||||
.dedent().printLn(`},`)
|
.printLn(`});`)
|
||||||
.printLn(`end: function () {`)
|
.printLn(`client.onMessage(function (message) {`)
|
||||||
.indent().printLn(`client.finishSend();`)
|
.indent()
|
||||||
.dedent().printLn(`},`)
|
.printLn(`listeners.data.forEach(function (handler) {`)
|
||||||
.printLn(`cancel: function () {`)
|
.indent()
|
||||||
.indent().printLn(`listeners = null;`)
|
.printLn(`handler(message);`)
|
||||||
.printLn(`client.close();`)
|
.dedent()
|
||||||
.dedent().printLn(`}`)
|
.printLn(`})`)
|
||||||
.dedent().printLn(`};`)
|
.dedent()
|
||||||
.dedent().printLn(`};`);
|
.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(`};`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function printServiceStubTypes(methodPrinter: Printer, service: RPCDescriptor) {
|
function printServiceStubTypes(methodPrinter: Printer, service: RPCDescriptor) {
|
||||||
const printer = new CodePrinter(0, methodPrinter);
|
const printer = new CodePrinter(0, methodPrinter);
|
||||||
|
|
||||||
printer
|
printer
|
||||||
.printLn(`export class ${service.name}Client {`)
|
.printLn(`export class ${service.name}Client {`)
|
||||||
.indent().printLn(`readonly serviceHost: string;`)
|
.indent()
|
||||||
|
.printLn(`readonly serviceHost: string;`)
|
||||||
.printEmptyLn()
|
.printEmptyLn()
|
||||||
.printLn(`constructor(serviceHost: string, options?: grpc.RpcOptions);`);
|
.printLn(`constructor(serviceHost: string, options?: grpc.RpcOptions);`);
|
||||||
|
|
||||||
service.methods.forEach((method: RPCMethodDescriptor) => {
|
service.methods.forEach((method: RPCMethodDescriptor) => {
|
||||||
if (method.requestStream && method.responseStream) {
|
if (method.requestStream && method.responseStream) {
|
||||||
printBidirectionalStubMethodTypes(printer, method);
|
printBidirectionalStubMethodTypes(printer, method);
|
||||||
} else if (method.requestStream) {
|
} else if (method.requestStream) {
|
||||||
printClientStreamStubMethodTypes(printer, method);
|
printClientStreamStubMethodTypes(printer, method);
|
||||||
} else if (method.responseStream) {
|
} else if (method.responseStream) {
|
||||||
printServerStreamStubMethodTypes(printer, method);
|
printServerStreamStubMethodTypes(printer, method);
|
||||||
} else {
|
} else {
|
||||||
printUnaryStubMethodTypes(printer, method);
|
printUnaryStubMethodTypes(printer, method);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
printer.dedent().printLn("}");
|
printer.dedent().printLn('}');
|
||||||
}
|
}
|
||||||
|
|
||||||
function printUnaryStubMethodTypes(printer: CodePrinter, method: RPCMethodDescriptor) {
|
function printUnaryStubMethodTypes(printer: CodePrinter, method: RPCMethodDescriptor) {
|
||||||
printer
|
printer
|
||||||
.printLn(`${method.nameAsCamelCase}(`)
|
.printLn(`${method.nameAsCamelCase}(`)
|
||||||
.indent().printLn(`requestMessage: ${method.requestType},`)
|
.indent()
|
||||||
.printLn(`metadata: grpc.Metadata,`)
|
.printLn(`requestMessage: ${method.requestType},`)
|
||||||
.printLn(`callback: (error: ServiceError|null, responseMessage: ${method.responseType}|null) => void`)
|
.printLn(`metadata: grpc.Metadata,`)
|
||||||
.dedent().printLn(`): UnaryResponse;`)
|
.printLn(
|
||||||
.printLn(`${method.nameAsCamelCase}(`)
|
`callback: (error: ServiceError|null, responseMessage: ${method.responseType}|null) => void`
|
||||||
.indent().printLn(`requestMessage: ${method.requestType},`)
|
)
|
||||||
.printLn(`callback: (error: ServiceError|null, responseMessage: ${method.responseType}|null) => void`)
|
.dedent()
|
||||||
.dedent().printLn(`): UnaryResponse;`);
|
.printLn(`): UnaryResponse;`)
|
||||||
|
.printLn(`${method.nameAsCamelCase}(`)
|
||||||
|
.indent()
|
||||||
|
.printLn(`requestMessage: ${method.requestType},`)
|
||||||
|
.printLn(
|
||||||
|
`callback: (error: ServiceError|null, responseMessage: ${method.responseType}|null) => void`
|
||||||
|
)
|
||||||
|
.dedent()
|
||||||
|
.printLn(`): UnaryResponse;`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function printServerStreamStubMethodTypes(printer: CodePrinter, method: RPCMethodDescriptor) {
|
function printServerStreamStubMethodTypes(
|
||||||
printer.printLn(`${method.nameAsCamelCase}(requestMessage: ${method.requestType}, metadata?: grpc.Metadata): ResponseStream<${method.responseType}>;`);
|
printer: CodePrinter,
|
||||||
|
method: RPCMethodDescriptor
|
||||||
|
) {
|
||||||
|
printer.printLn(
|
||||||
|
`${method.nameAsCamelCase}(requestMessage: ${method.requestType}, metadata?: grpc.Metadata): ResponseStream<${method.responseType}>;`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function printClientStreamStubMethodTypes(printer: CodePrinter, method: RPCMethodDescriptor) {
|
function printClientStreamStubMethodTypes(
|
||||||
printer.printLn(`${method.nameAsCamelCase}(metadata?: grpc.Metadata): RequestStream<${method.requestType}>;`);
|
printer: CodePrinter,
|
||||||
|
method: RPCMethodDescriptor
|
||||||
|
) {
|
||||||
|
printer.printLn(
|
||||||
|
`${method.nameAsCamelCase}(metadata?: grpc.Metadata): RequestStream<${method.requestType}>;`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function printBidirectionalStubMethodTypes(printer: CodePrinter, method: RPCMethodDescriptor) {
|
function printBidirectionalStubMethodTypes(
|
||||||
printer.printLn(`${method.nameAsCamelCase}(metadata?: grpc.Metadata): BidirectionalStream<${method.requestType}, ${method.responseType}>;`);
|
printer: CodePrinter,
|
||||||
|
method: RPCMethodDescriptor
|
||||||
|
) {
|
||||||
|
printer.printLn(
|
||||||
|
`${method.nameAsCamelCase}(metadata?: grpc.Metadata): BidirectionalStream<${method.requestType}, ${method.responseType}>;`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,59 +1,64 @@
|
||||||
import {filePathToPseudoNamespace, withinNamespaceFromExportEntry} from "../util";
|
import { filePathToPseudoNamespace, withinNamespaceFromExportEntry } from '../util';
|
||||||
import {ExportMap} from "../ExportMap";
|
import { ExportMap } from '../ExportMap';
|
||||||
import {FieldDescriptorProto} from "google-protobuf/google/protobuf/descriptor_pb";
|
import { FieldDescriptorProto } from 'google-protobuf/google/protobuf/descriptor_pb';
|
||||||
|
|
||||||
export const MESSAGE_TYPE = 11;
|
export const MESSAGE_TYPE = 11;
|
||||||
export const BYTES_TYPE = 12;
|
export const BYTES_TYPE = 12;
|
||||||
export const ENUM_TYPE = 14;
|
export const ENUM_TYPE = 14;
|
||||||
|
|
||||||
const TypeNumToTypeString: {[key: number]: string} = {};
|
const TypeNumToTypeString: { [key: number]: string } = {};
|
||||||
TypeNumToTypeString[1] = "number"; // TYPE_DOUBLE
|
TypeNumToTypeString[1] = 'number'; // TYPE_DOUBLE
|
||||||
TypeNumToTypeString[2] = "number"; // TYPE_FLOAT
|
TypeNumToTypeString[2] = 'number'; // TYPE_FLOAT
|
||||||
TypeNumToTypeString[3] = "number"; // TYPE_INT64
|
TypeNumToTypeString[3] = 'number'; // TYPE_INT64
|
||||||
TypeNumToTypeString[4] = "number"; // TYPE_UINT64
|
TypeNumToTypeString[4] = 'number'; // TYPE_UINT64
|
||||||
TypeNumToTypeString[5] = "number"; // TYPE_INT32
|
TypeNumToTypeString[5] = 'number'; // TYPE_INT32
|
||||||
TypeNumToTypeString[6] = "number"; // TYPE_FIXED64
|
TypeNumToTypeString[6] = 'number'; // TYPE_FIXED64
|
||||||
TypeNumToTypeString[7] = "number"; // TYPE_FIXED32
|
TypeNumToTypeString[7] = 'number'; // TYPE_FIXED32
|
||||||
TypeNumToTypeString[8] = "boolean"; // TYPE_BOOL
|
TypeNumToTypeString[8] = 'boolean'; // TYPE_BOOL
|
||||||
TypeNumToTypeString[9] = "string"; // TYPE_STRING
|
TypeNumToTypeString[9] = 'string'; // TYPE_STRING
|
||||||
TypeNumToTypeString[10] = "Object"; // TYPE_GROUP
|
TypeNumToTypeString[10] = 'Object'; // TYPE_GROUP
|
||||||
TypeNumToTypeString[MESSAGE_TYPE] = "Object"; // TYPE_MESSAGE - Length-delimited aggregate.
|
TypeNumToTypeString[MESSAGE_TYPE] = 'Object'; // TYPE_MESSAGE - Length-delimited aggregate.
|
||||||
TypeNumToTypeString[BYTES_TYPE] = "Uint8Array"; // TYPE_BYTES
|
TypeNumToTypeString[BYTES_TYPE] = 'Uint8Array'; // TYPE_BYTES
|
||||||
TypeNumToTypeString[13] = "number"; // TYPE_UINT32
|
TypeNumToTypeString[13] = 'number'; // TYPE_UINT32
|
||||||
TypeNumToTypeString[ENUM_TYPE] = "number"; // TYPE_ENUM
|
TypeNumToTypeString[ENUM_TYPE] = 'number'; // TYPE_ENUM
|
||||||
TypeNumToTypeString[15] = "number"; // TYPE_SFIXED32
|
TypeNumToTypeString[15] = 'number'; // TYPE_SFIXED32
|
||||||
TypeNumToTypeString[16] = "number"; // TYPE_SFIXED64
|
TypeNumToTypeString[16] = 'number'; // TYPE_SFIXED64
|
||||||
TypeNumToTypeString[17] = "number"; // TYPE_SINT32 - Uses ZigZag encoding.
|
TypeNumToTypeString[17] = 'number'; // TYPE_SINT32 - Uses ZigZag encoding.
|
||||||
TypeNumToTypeString[18] = "number"; // TYPE_SINT64 - Uses ZigZag encoding.
|
TypeNumToTypeString[18] = 'number'; // TYPE_SINT64 - Uses ZigZag encoding.
|
||||||
|
|
||||||
export function getTypeName(fieldTypeNum: number): string {
|
export function getTypeName(fieldTypeNum: number): string {
|
||||||
return TypeNumToTypeString[fieldTypeNum];
|
return TypeNumToTypeString[fieldTypeNum];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getFieldType(type: FieldDescriptorProto.Type, typeName: string, currentFileName: string, exportMap: ExportMap): string {
|
export function getFieldType(
|
||||||
if (type === MESSAGE_TYPE) {
|
type: FieldDescriptorProto.Type,
|
||||||
const fromExport = exportMap.getMessage(typeName);
|
typeName: string,
|
||||||
if (!fromExport) {
|
currentFileName: string,
|
||||||
throw new Error("Could not getFieldType for message: " + typeName);
|
exportMap: ExportMap
|
||||||
}
|
): string {
|
||||||
const withinNamespace = withinNamespaceFromExportEntry(typeName, fromExport);
|
if (type === MESSAGE_TYPE) {
|
||||||
if (fromExport.fileName === currentFileName) {
|
const fromExport = exportMap.getMessage(typeName);
|
||||||
return withinNamespace;
|
if (!fromExport) {
|
||||||
|
throw new Error('Could not getFieldType for message: ' + typeName);
|
||||||
|
}
|
||||||
|
const withinNamespace = withinNamespaceFromExportEntry(typeName, fromExport);
|
||||||
|
if (fromExport.fileName === currentFileName) {
|
||||||
|
return withinNamespace;
|
||||||
|
} else {
|
||||||
|
return filePathToPseudoNamespace(fromExport.fileName) + '.' + withinNamespace;
|
||||||
|
}
|
||||||
|
} else if (type === ENUM_TYPE) {
|
||||||
|
const fromExport = exportMap.getEnum(typeName);
|
||||||
|
if (!fromExport) {
|
||||||
|
throw new Error('Could not getFieldType for enum: ' + typeName);
|
||||||
|
}
|
||||||
|
const withinNamespace = withinNamespaceFromExportEntry(typeName, fromExport);
|
||||||
|
if (fromExport.fileName === currentFileName) {
|
||||||
|
return `${withinNamespace}Map`;
|
||||||
|
} else {
|
||||||
|
return filePathToPseudoNamespace(fromExport.fileName) + '.' + withinNamespace;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return filePathToPseudoNamespace(fromExport.fileName) + "." + withinNamespace;
|
return TypeNumToTypeString[type];
|
||||||
}
|
}
|
||||||
} else if (type === ENUM_TYPE) {
|
|
||||||
const fromExport = exportMap.getEnum(typeName);
|
|
||||||
if (!fromExport) {
|
|
||||||
throw new Error("Could not getFieldType for enum: " + typeName);
|
|
||||||
}
|
|
||||||
const withinNamespace = withinNamespaceFromExportEntry(typeName, fromExport);
|
|
||||||
if (fromExport.fileName === currentFileName) {
|
|
||||||
return `${withinNamespace}Map`;
|
|
||||||
} else {
|
|
||||||
return filePathToPseudoNamespace(fromExport.fileName) + "." + withinNamespace;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return TypeNumToTypeString[type];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
import {EnumDescriptorProto} from "google-protobuf/google/protobuf/descriptor_pb";
|
import { EnumDescriptorProto } from 'google-protobuf/google/protobuf/descriptor_pb';
|
||||||
import {Printer} from "../Printer";
|
import { Printer } from '../Printer';
|
||||||
|
|
||||||
export function printEnum(enumDescriptor: EnumDescriptorProto, indentLevel: number) {
|
export function printEnum(enumDescriptor: EnumDescriptorProto, indentLevel: number) {
|
||||||
const printer = new Printer(indentLevel);
|
const printer = new Printer(indentLevel);
|
||||||
const enumInterfaceName = `${enumDescriptor.getName()}Map`;
|
const enumInterfaceName = `${enumDescriptor.getName()}Map`;
|
||||||
printer.printEmptyLn();
|
printer.printEmptyLn();
|
||||||
printer.printLn(`export interface ${enumInterfaceName} {`);
|
printer.printLn(`export interface ${enumInterfaceName} {`);
|
||||||
enumDescriptor.getValueList().forEach(value => {
|
enumDescriptor.getValueList().forEach((value) => {
|
||||||
printer.printIndentedLn(`${value.getName().toUpperCase()}: ${value.getNumber()};`);
|
printer.printIndentedLn(
|
||||||
});
|
`${value.getName().toUpperCase()}: ${value.getNumber()};`
|
||||||
printer.printLn(`}`);
|
);
|
||||||
printer.printEmptyLn();
|
});
|
||||||
printer.printLn(`export const ${enumDescriptor.getName()}: ${enumInterfaceName};`);
|
printer.printLn(`}`);
|
||||||
return printer.getOutput();
|
printer.printEmptyLn();
|
||||||
|
printer.printLn(`export const ${enumDescriptor.getName()}: ${enumInterfaceName};`);
|
||||||
|
return printer.getOutput();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,26 @@
|
||||||
import {Printer} from "../Printer";
|
import { Printer } from '../Printer';
|
||||||
import {ExportMap} from "../ExportMap";
|
import { ExportMap } from '../ExportMap';
|
||||||
import {FieldDescriptorProto} from "google-protobuf/google/protobuf/descriptor_pb";
|
import { FieldDescriptorProto } from 'google-protobuf/google/protobuf/descriptor_pb';
|
||||||
import {snakeToCamel} from "../util";
|
import { snakeToCamel } from '../util';
|
||||||
import {getFieldType} from "./FieldTypes";
|
import { getFieldType } from './FieldTypes';
|
||||||
|
|
||||||
export function printExtension(fileName: string, exportMap: ExportMap, extension: FieldDescriptorProto, indentLevel: number): string {
|
export function printExtension(
|
||||||
const printer = new Printer(indentLevel + 1);
|
fileName: string,
|
||||||
printer.printEmptyLn();
|
exportMap: ExportMap,
|
||||||
const extensionName = snakeToCamel(extension.getName());
|
extension: FieldDescriptorProto,
|
||||||
const fieldType = getFieldType(extension.getType(), extension.getTypeName().slice(1), fileName, exportMap);
|
indentLevel: number
|
||||||
printer.printLn(`export const ${extensionName}: jspb.ExtensionFieldInfo<${fieldType}>;`);
|
): string {
|
||||||
return printer.output;
|
const printer = new Printer(indentLevel + 1);
|
||||||
|
printer.printEmptyLn();
|
||||||
|
const extensionName = snakeToCamel(extension.getName());
|
||||||
|
const fieldType = getFieldType(
|
||||||
|
extension.getType(),
|
||||||
|
extension.getTypeName().slice(1),
|
||||||
|
fileName,
|
||||||
|
exportMap
|
||||||
|
);
|
||||||
|
printer.printLn(
|
||||||
|
`export const ${extensionName}: jspb.ExtensionFieldInfo<${fieldType}>;`
|
||||||
|
);
|
||||||
|
return printer.output;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,49 +1,56 @@
|
||||||
import {filePathToPseudoNamespace, replaceProtoSuffix, getPathToRoot} from "../util";
|
import { filePathToPseudoNamespace, replaceProtoSuffix, getPathToRoot } from '../util';
|
||||||
import {ExportMap} from "../ExportMap";
|
import { ExportMap } from '../ExportMap';
|
||||||
import {Printer} from "../Printer";
|
import { Printer } from '../Printer';
|
||||||
import {FileDescriptorProto} from "google-protobuf/google/protobuf/descriptor_pb";
|
import { FileDescriptorProto } from 'google-protobuf/google/protobuf/descriptor_pb';
|
||||||
import {WellKnownTypesMap} from "../WellKnown";
|
import { WellKnownTypesMap } from '../WellKnown';
|
||||||
import {printMessage} from "./message";
|
import { printMessage } from './message';
|
||||||
import {printEnum} from "./enum";
|
import { printEnum } from './enum';
|
||||||
import {printExtension} from "./extensions";
|
import { printExtension } from './extensions';
|
||||||
|
|
||||||
export function printFileDescriptorTSD(fileDescriptor: FileDescriptorProto, exportMap: ExportMap) {
|
export function printFileDescriptorTSD(
|
||||||
const fileName = fileDescriptor.getName();
|
fileDescriptor: FileDescriptorProto,
|
||||||
const packageName = fileDescriptor.getPackage();
|
exportMap: ExportMap
|
||||||
|
) {
|
||||||
|
const fileName = fileDescriptor.getName();
|
||||||
|
const packageName = fileDescriptor.getPackage();
|
||||||
|
|
||||||
const printer = new Printer(0);
|
const printer = new Printer(0);
|
||||||
|
|
||||||
printer.printLn(`// package: ${packageName}`);
|
printer.printLn(`// package: ${packageName}`);
|
||||||
printer.printLn(`// file: ${fileDescriptor.getName()}`);
|
printer.printLn(`// file: ${fileDescriptor.getName()}`);
|
||||||
|
|
||||||
const upToRoot = getPathToRoot(fileName);
|
const upToRoot = getPathToRoot(fileName);
|
||||||
|
|
||||||
printer.printEmptyLn();
|
printer.printEmptyLn();
|
||||||
printer.printLn(`import * as jspb from "google-protobuf";`);
|
printer.printLn(`import * as jspb from "google-protobuf";`);
|
||||||
|
|
||||||
fileDescriptor.getDependencyList().forEach((dependency: string) => {
|
fileDescriptor.getDependencyList().forEach((dependency: string) => {
|
||||||
const pseudoNamespace = filePathToPseudoNamespace(dependency);
|
const pseudoNamespace = filePathToPseudoNamespace(dependency);
|
||||||
if (dependency in WellKnownTypesMap) {
|
if (dependency in WellKnownTypesMap) {
|
||||||
printer.printLn(`import * as ${pseudoNamespace} from "${WellKnownTypesMap[dependency]}";`);
|
printer.printLn(
|
||||||
} else {
|
`import * as ${pseudoNamespace} from "${WellKnownTypesMap[dependency]}";`
|
||||||
const filePath = replaceProtoSuffix(dependency);
|
);
|
||||||
printer.printLn(`import * as ${pseudoNamespace} from "${upToRoot}${filePath}";`);
|
} else {
|
||||||
}
|
const filePath = replaceProtoSuffix(dependency);
|
||||||
});
|
printer.printLn(
|
||||||
|
`import * as ${pseudoNamespace} from "${upToRoot}${filePath}";`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
fileDescriptor.getMessageTypeList().forEach(enumType => {
|
fileDescriptor.getMessageTypeList().forEach((enumType) => {
|
||||||
printer.print(printMessage(fileName, exportMap, enumType, 0, fileDescriptor));
|
printer.print(printMessage(fileName, exportMap, enumType, 0, fileDescriptor));
|
||||||
});
|
});
|
||||||
|
|
||||||
fileDescriptor.getExtensionList().forEach(extension => {
|
fileDescriptor.getExtensionList().forEach((extension) => {
|
||||||
printer.print(printExtension(fileName, exportMap, extension, 0));
|
printer.print(printExtension(fileName, exportMap, extension, 0));
|
||||||
});
|
});
|
||||||
|
|
||||||
fileDescriptor.getEnumTypeList().forEach(enumType => {
|
fileDescriptor.getEnumTypeList().forEach((enumType) => {
|
||||||
printer.print(printEnum(enumType, 0));
|
printer.print(printEnum(enumType, 0));
|
||||||
});
|
});
|
||||||
|
|
||||||
printer.printEmptyLn();
|
printer.printEmptyLn();
|
||||||
|
|
||||||
return printer.getOutput();
|
return printer.getOutput();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,235 +1,361 @@
|
||||||
import {
|
import {
|
||||||
filePathToPseudoNamespace, snakeToCamel, uppercaseFirst, oneOfName, isProto2,
|
filePathToPseudoNamespace,
|
||||||
withinNamespaceFromExportEntry, normaliseFieldObjectName, stripPrefix
|
snakeToCamel,
|
||||||
} from "../util";
|
uppercaseFirst,
|
||||||
import {ExportMap} from "../ExportMap";
|
oneOfName,
|
||||||
|
isProto2,
|
||||||
|
withinNamespaceFromExportEntry,
|
||||||
|
normaliseFieldObjectName,
|
||||||
|
stripPrefix,
|
||||||
|
} from '../util';
|
||||||
|
import { ExportMap } from '../ExportMap';
|
||||||
import {
|
import {
|
||||||
FieldDescriptorProto, FileDescriptorProto, DescriptorProto,
|
FieldDescriptorProto,
|
||||||
FieldOptions
|
FileDescriptorProto,
|
||||||
} from "google-protobuf/google/protobuf/descriptor_pb";
|
DescriptorProto,
|
||||||
import {MESSAGE_TYPE, BYTES_TYPE, ENUM_TYPE, getFieldType, getTypeName} from "./FieldTypes";
|
FieldOptions,
|
||||||
import {Printer} from "../Printer";
|
} from 'google-protobuf/google/protobuf/descriptor_pb';
|
||||||
import {printEnum} from "./enum";
|
import {
|
||||||
import {printOneOfDecl} from "./oneof";
|
MESSAGE_TYPE,
|
||||||
import {printExtension} from "./extensions";
|
BYTES_TYPE,
|
||||||
|
ENUM_TYPE,
|
||||||
|
getFieldType,
|
||||||
|
getTypeName,
|
||||||
|
} from './FieldTypes';
|
||||||
|
import { Printer } from '../Printer';
|
||||||
|
import { printEnum } from './enum';
|
||||||
|
import { printOneOfDecl } from './oneof';
|
||||||
|
import { printExtension } from './extensions';
|
||||||
import JSType = FieldOptions.JSType;
|
import JSType = FieldOptions.JSType;
|
||||||
|
|
||||||
function hasFieldPresence(field: FieldDescriptorProto, fileDescriptor: FileDescriptorProto): boolean {
|
function hasFieldPresence(
|
||||||
if (field.getLabel() === FieldDescriptorProto.Label.LABEL_REPEATED) {
|
field: FieldDescriptorProto,
|
||||||
return false;
|
fileDescriptor: FileDescriptorProto
|
||||||
}
|
): boolean {
|
||||||
|
if (field.getLabel() === FieldDescriptorProto.Label.LABEL_REPEATED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (field.hasOneofIndex()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (field.getType() === MESSAGE_TYPE) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isProto2(fileDescriptor)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function printMessage(fileName: string, exportMap: ExportMap, messageDescriptor: DescriptorProto, indentLevel: number, fileDescriptor: FileDescriptorProto) {
|
|
||||||
const messageName = messageDescriptor.getName();
|
|
||||||
const messageOptions = messageDescriptor.getOptions();
|
|
||||||
if (messageOptions !== undefined && messageOptions.getMapEntry()) {
|
|
||||||
// this message type is the entry tuple for a map - don't output it
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
const objectTypeName = `AsObject`;
|
|
||||||
const toObjectType = new Printer(indentLevel + 1);
|
|
||||||
toObjectType.printLn(`export type ${objectTypeName} = {`);
|
|
||||||
|
|
||||||
const printer = new Printer(indentLevel);
|
|
||||||
printer.printEmptyLn();
|
|
||||||
printer.printLn(`export class ${messageName} extends jspb.Message {`);
|
|
||||||
|
|
||||||
const oneOfGroups: Array<Array<FieldDescriptorProto>> = [];
|
|
||||||
|
|
||||||
messageDescriptor.getFieldList().forEach(field => {
|
|
||||||
if (field.hasOneofIndex()) {
|
if (field.hasOneofIndex()) {
|
||||||
const oneOfIndex = field.getOneofIndex();
|
return true;
|
||||||
let existing = oneOfGroups[oneOfIndex];
|
|
||||||
if (existing === undefined) {
|
|
||||||
existing = [];
|
|
||||||
oneOfGroups[oneOfIndex] = existing;
|
|
||||||
}
|
|
||||||
existing.push(field);
|
|
||||||
}
|
|
||||||
const snakeCaseName = stripPrefix(field.getName().toLowerCase(), "_");
|
|
||||||
const camelCaseName = snakeToCamel(snakeCaseName);
|
|
||||||
const withUppercase = uppercaseFirst(camelCaseName);
|
|
||||||
const type = field.getType();
|
|
||||||
|
|
||||||
let exportType;
|
|
||||||
const fullTypeName = field.getTypeName().slice(1);
|
|
||||||
if (type === MESSAGE_TYPE) {
|
|
||||||
const fieldMessageType = exportMap.getMessage(fullTypeName);
|
|
||||||
if (fieldMessageType === undefined) {
|
|
||||||
throw new Error("No message export for: " + fullTypeName);
|
|
||||||
}
|
|
||||||
if (fieldMessageType.messageOptions !== undefined && fieldMessageType.messageOptions.getMapEntry()) {
|
|
||||||
// This field is a map
|
|
||||||
const keyTuple = fieldMessageType.mapFieldOptions!.key;
|
|
||||||
const keyType = keyTuple[0];
|
|
||||||
const keyTypeName = getFieldType(keyType, keyTuple[1], fileName, exportMap);
|
|
||||||
const valueTuple = fieldMessageType.mapFieldOptions!.value;
|
|
||||||
const valueType = valueTuple[0];
|
|
||||||
let valueTypeName = getFieldType(valueType, valueTuple[1], fileName, exportMap);
|
|
||||||
if (valueType === BYTES_TYPE) {
|
|
||||||
valueTypeName = "Uint8Array | string";
|
|
||||||
}
|
|
||||||
if (valueType === ENUM_TYPE) {
|
|
||||||
valueTypeName = `${valueTypeName}[keyof ${valueTypeName}]`;
|
|
||||||
}
|
|
||||||
printer.printIndentedLn(`get${withUppercase}Map(): jspb.Map<${keyTypeName}, ${valueTypeName}>;`);
|
|
||||||
printer.printIndentedLn(`clear${withUppercase}Map(): void;`);
|
|
||||||
toObjectType.printIndentedLn(`${camelCaseName}Map: Array<[${keyTypeName}${keyType === MESSAGE_TYPE ? ".AsObject" : ""}, ${valueTypeName}${valueType === MESSAGE_TYPE ? ".AsObject" : ""}]>,`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const withinNamespace = withinNamespaceFromExportEntry(fullTypeName, fieldMessageType);
|
|
||||||
if (fieldMessageType.fileName === fileName) {
|
|
||||||
exportType = withinNamespace;
|
|
||||||
} else {
|
|
||||||
exportType = filePathToPseudoNamespace(fieldMessageType.fileName) + "." + withinNamespace;
|
|
||||||
}
|
|
||||||
} else if (type === ENUM_TYPE) {
|
|
||||||
const fieldEnumType = exportMap.getEnum(fullTypeName);
|
|
||||||
if (fieldEnumType === undefined) {
|
|
||||||
throw new Error("No enum export for: " + fullTypeName);
|
|
||||||
}
|
|
||||||
const withinNamespace = withinNamespaceFromExportEntry(fullTypeName, fieldEnumType);
|
|
||||||
if (fieldEnumType.fileName === fileName) {
|
|
||||||
exportType = withinNamespace;
|
|
||||||
} else {
|
|
||||||
exportType = filePathToPseudoNamespace(fieldEnumType.fileName) + "." + withinNamespace;
|
|
||||||
}
|
|
||||||
exportType = `${exportType}Map[keyof ${exportType}Map]`;
|
|
||||||
} else {
|
|
||||||
if (field.getOptions() && field.getOptions().hasJstype()) {
|
|
||||||
switch (field.getOptions().getJstype()) {
|
|
||||||
case JSType.JS_NUMBER:
|
|
||||||
exportType = "number";
|
|
||||||
break;
|
|
||||||
case JSType.JS_STRING:
|
|
||||||
exportType = "string";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
exportType = getTypeName(type);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
exportType = getTypeName(type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let hasClearMethod = false;
|
if (field.getType() === MESSAGE_TYPE) {
|
||||||
function printClearIfNotPresent() {
|
return true;
|
||||||
if (!hasClearMethod) {
|
|
||||||
hasClearMethod = true;
|
|
||||||
printer.printIndentedLn(`clear${withUppercase}${field.getLabel() === FieldDescriptorProto.Label.LABEL_REPEATED ? "List" : ""}(): void;`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasFieldPresence(field, fileDescriptor)) {
|
if (isProto2(fileDescriptor)) {
|
||||||
printer.printIndentedLn(`has${withUppercase}(): boolean;`);
|
return true;
|
||||||
printClearIfNotPresent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function printRepeatedAddMethod(valueType: string) {
|
return false;
|
||||||
const optionalValue = field.getType() === MESSAGE_TYPE;
|
}
|
||||||
printer.printIndentedLn(`add${withUppercase}(value${optionalValue ? "?" : ""}: ${valueType}, index?: number): ${valueType};`);
|
|
||||||
}
|
export function printMessage(
|
||||||
|
fileName: string,
|
||||||
if (field.getLabel() === FieldDescriptorProto.Label.LABEL_REPEATED) {// is repeated
|
exportMap: ExportMap,
|
||||||
printClearIfNotPresent();
|
messageDescriptor: DescriptorProto,
|
||||||
if (type === BYTES_TYPE) {
|
indentLevel: number,
|
||||||
toObjectType.printIndentedLn(`${camelCaseName}List: Array<Uint8Array | string>,`);
|
fileDescriptor: FileDescriptorProto
|
||||||
printer.printIndentedLn(`get${withUppercase}List(): Array<Uint8Array | string>;`);
|
) {
|
||||||
printer.printIndentedLn(`get${withUppercase}List_asU8(): Array<Uint8Array>;`);
|
const messageName = messageDescriptor.getName();
|
||||||
printer.printIndentedLn(`get${withUppercase}List_asB64(): Array<string>;`);
|
const messageOptions = messageDescriptor.getOptions();
|
||||||
printer.printIndentedLn(`set${withUppercase}List(value: Array<Uint8Array | string>): void;`);
|
if (messageOptions !== undefined && messageOptions.getMapEntry()) {
|
||||||
printRepeatedAddMethod("Uint8Array | string");
|
// this message type is the entry tuple for a map - don't output it
|
||||||
} else {
|
return '';
|
||||||
toObjectType.printIndentedLn(`${camelCaseName}List: Array<${exportType}${type === MESSAGE_TYPE ? ".AsObject" : ""}>,`);
|
}
|
||||||
printer.printIndentedLn(`get${withUppercase}List(): Array<${exportType}>;`);
|
|
||||||
printer.printIndentedLn(`set${withUppercase}List(value: Array<${exportType}>): void;`);
|
const objectTypeName = `AsObject`;
|
||||||
printRepeatedAddMethod(exportType);
|
const toObjectType = new Printer(indentLevel + 1);
|
||||||
}
|
toObjectType.printLn(`export type ${objectTypeName} = {`);
|
||||||
} else {
|
|
||||||
if (type === BYTES_TYPE) {
|
const printer = new Printer(indentLevel);
|
||||||
toObjectType.printIndentedLn(`${camelCaseName}: Uint8Array | string,`);
|
printer.printEmptyLn();
|
||||||
printer.printIndentedLn(`get${withUppercase}(): Uint8Array | string;`);
|
printer.printLn(`export class ${messageName} extends jspb.Message {`);
|
||||||
printer.printIndentedLn(`get${withUppercase}_asU8(): Uint8Array;`);
|
|
||||||
printer.printIndentedLn(`get${withUppercase}_asB64(): string;`);
|
const oneOfGroups: Array<Array<FieldDescriptorProto>> = [];
|
||||||
printer.printIndentedLn(`set${withUppercase}(value: Uint8Array | string): void;`);
|
|
||||||
} else {
|
messageDescriptor.getFieldList().forEach((field) => {
|
||||||
let fieldObjectType = exportType;
|
if (field.hasOneofIndex()) {
|
||||||
let canBeUndefined = false;
|
const oneOfIndex = field.getOneofIndex();
|
||||||
if (type === MESSAGE_TYPE) {
|
let existing = oneOfGroups[oneOfIndex];
|
||||||
fieldObjectType += ".AsObject";
|
if (existing === undefined) {
|
||||||
if (!isProto2(fileDescriptor) || (field.getLabel() === FieldDescriptorProto.Label.LABEL_OPTIONAL)) {
|
existing = [];
|
||||||
canBeUndefined = true;
|
oneOfGroups[oneOfIndex] = existing;
|
||||||
}
|
}
|
||||||
} else {
|
existing.push(field);
|
||||||
if (isProto2(fileDescriptor)) {
|
}
|
||||||
canBeUndefined = true;
|
const snakeCaseName = stripPrefix(field.getName().toLowerCase(), '_');
|
||||||
}
|
const camelCaseName = snakeToCamel(snakeCaseName);
|
||||||
}
|
const withUppercase = uppercaseFirst(camelCaseName);
|
||||||
const fieldObjectName = normaliseFieldObjectName(camelCaseName);
|
const type = field.getType();
|
||||||
toObjectType.printIndentedLn(`${fieldObjectName}${canBeUndefined ? "?" : ""}: ${fieldObjectType},`);
|
|
||||||
printer.printIndentedLn(`get${withUppercase}(): ${exportType}${canBeUndefined ? " | undefined" : ""};`);
|
let exportType;
|
||||||
printer.printIndentedLn(`set${withUppercase}(value${type === MESSAGE_TYPE ? "?" : ""}: ${exportType}): void;`);
|
const fullTypeName = field.getTypeName().slice(1);
|
||||||
}
|
if (type === MESSAGE_TYPE) {
|
||||||
}
|
const fieldMessageType = exportMap.getMessage(fullTypeName);
|
||||||
printer.printEmptyLn();
|
if (fieldMessageType === undefined) {
|
||||||
});
|
throw new Error('No message export for: ' + fullTypeName);
|
||||||
|
}
|
||||||
toObjectType.printLn(`}`);
|
if (
|
||||||
|
fieldMessageType.messageOptions !== undefined &&
|
||||||
messageDescriptor.getOneofDeclList().forEach(oneOfDecl => {
|
fieldMessageType.messageOptions.getMapEntry()
|
||||||
printer.printIndentedLn(`get${oneOfName(oneOfDecl.getName())}Case(): ${messageName}.${oneOfName(oneOfDecl.getName())}Case;`);
|
) {
|
||||||
});
|
// This field is a map
|
||||||
|
const keyTuple = fieldMessageType.mapFieldOptions!.key;
|
||||||
printer.printIndentedLn(`serializeBinary(): Uint8Array;`);
|
const keyType = keyTuple[0];
|
||||||
printer.printIndentedLn(`toObject(includeInstance?: boolean): ${messageName}.${objectTypeName};`);
|
const keyTypeName = getFieldType(
|
||||||
printer.printIndentedLn(`static toObject(includeInstance: boolean, msg: ${messageName}): ${messageName}.${objectTypeName};`);
|
keyType,
|
||||||
printer.printIndentedLn(`static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};`);
|
keyTuple[1],
|
||||||
printer.printIndentedLn(`static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};`);
|
fileName,
|
||||||
printer.printIndentedLn(`static serializeBinaryToWriter(message: ${messageName}, writer: jspb.BinaryWriter): void;`);
|
exportMap
|
||||||
printer.printIndentedLn(`static deserializeBinary(bytes: Uint8Array): ${messageName};`);
|
);
|
||||||
printer.printIndentedLn(`static deserializeBinaryFromReader(message: ${messageName}, reader: jspb.BinaryReader): ${messageName};`);
|
const valueTuple = fieldMessageType.mapFieldOptions!.value;
|
||||||
|
const valueType = valueTuple[0];
|
||||||
printer.printLn(`}`);
|
let valueTypeName = getFieldType(
|
||||||
printer.printEmptyLn();
|
valueType,
|
||||||
|
valueTuple[1],
|
||||||
printer.printLn(`export namespace ${messageName} {`);
|
fileName,
|
||||||
|
exportMap
|
||||||
printer.print(toObjectType.getOutput());
|
);
|
||||||
|
if (valueType === BYTES_TYPE) {
|
||||||
messageDescriptor.getNestedTypeList().forEach(nested => {
|
valueTypeName = 'Uint8Array | string';
|
||||||
const msgOutput = printMessage(fileName, exportMap, nested, indentLevel + 1, fileDescriptor);
|
}
|
||||||
if (msgOutput !== "") {
|
if (valueType === ENUM_TYPE) {
|
||||||
// If the message class is a Map entry then it isn't output, so don't print the namespace block
|
valueTypeName = `${valueTypeName}[keyof ${valueTypeName}]`;
|
||||||
printer.print(msgOutput);
|
}
|
||||||
}
|
printer.printIndentedLn(
|
||||||
});
|
`get${withUppercase}Map(): jspb.Map<${keyTypeName}, ${valueTypeName}>;`
|
||||||
messageDescriptor.getEnumTypeList().forEach(enumType => {
|
);
|
||||||
printer.print(`${printEnum(enumType, indentLevel + 1)}`);
|
printer.printIndentedLn(`clear${withUppercase}Map(): void;`);
|
||||||
});
|
toObjectType.printIndentedLn(
|
||||||
messageDescriptor.getOneofDeclList().forEach((oneOfDecl, index) => {
|
`${camelCaseName}Map: Array<[${keyTypeName}${
|
||||||
printer.print(`${printOneOfDecl(oneOfDecl, oneOfGroups[index] || [], indentLevel + 1)}`);
|
keyType === MESSAGE_TYPE ? '.AsObject' : ''
|
||||||
});
|
}, ${valueTypeName}${
|
||||||
messageDescriptor.getExtensionList().forEach(extension => {
|
valueType === MESSAGE_TYPE ? '.AsObject' : ''
|
||||||
printer.print(printExtension(fileName, exportMap, extension, indentLevel + 1));
|
}]>,`
|
||||||
});
|
);
|
||||||
|
return;
|
||||||
printer.printLn(`}`);
|
}
|
||||||
|
const withinNamespace = withinNamespaceFromExportEntry(
|
||||||
return printer.getOutput();
|
fullTypeName,
|
||||||
|
fieldMessageType
|
||||||
|
);
|
||||||
|
if (fieldMessageType.fileName === fileName) {
|
||||||
|
exportType = withinNamespace;
|
||||||
|
} else {
|
||||||
|
exportType =
|
||||||
|
filePathToPseudoNamespace(fieldMessageType.fileName) +
|
||||||
|
'.' +
|
||||||
|
withinNamespace;
|
||||||
|
}
|
||||||
|
} else if (type === ENUM_TYPE) {
|
||||||
|
const fieldEnumType = exportMap.getEnum(fullTypeName);
|
||||||
|
if (fieldEnumType === undefined) {
|
||||||
|
throw new Error('No enum export for: ' + fullTypeName);
|
||||||
|
}
|
||||||
|
const withinNamespace = withinNamespaceFromExportEntry(
|
||||||
|
fullTypeName,
|
||||||
|
fieldEnumType
|
||||||
|
);
|
||||||
|
if (fieldEnumType.fileName === fileName) {
|
||||||
|
exportType = withinNamespace;
|
||||||
|
} else {
|
||||||
|
exportType =
|
||||||
|
filePathToPseudoNamespace(fieldEnumType.fileName) +
|
||||||
|
'.' +
|
||||||
|
withinNamespace;
|
||||||
|
}
|
||||||
|
exportType = `${exportType}Map[keyof ${exportType}Map]`;
|
||||||
|
} else {
|
||||||
|
if (field.getOptions() && field.getOptions().hasJstype()) {
|
||||||
|
switch (field.getOptions().getJstype()) {
|
||||||
|
case JSType.JS_NUMBER:
|
||||||
|
exportType = 'number';
|
||||||
|
break;
|
||||||
|
case JSType.JS_STRING:
|
||||||
|
exportType = 'string';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
exportType = getTypeName(type);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
exportType = getTypeName(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let hasClearMethod = false;
|
||||||
|
function printClearIfNotPresent() {
|
||||||
|
if (!hasClearMethod) {
|
||||||
|
hasClearMethod = true;
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`clear${withUppercase}${
|
||||||
|
field.getLabel() === FieldDescriptorProto.Label.LABEL_REPEATED
|
||||||
|
? 'List'
|
||||||
|
: ''
|
||||||
|
}(): void;`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasFieldPresence(field, fileDescriptor)) {
|
||||||
|
printer.printIndentedLn(`has${withUppercase}(): boolean;`);
|
||||||
|
printClearIfNotPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function printRepeatedAddMethod(valueType: string) {
|
||||||
|
const optionalValue = field.getType() === MESSAGE_TYPE;
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`add${withUppercase}(value${
|
||||||
|
optionalValue ? '?' : ''
|
||||||
|
}: ${valueType}, index?: number): ${valueType};`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field.getLabel() === FieldDescriptorProto.Label.LABEL_REPEATED) {
|
||||||
|
// is repeated
|
||||||
|
printClearIfNotPresent();
|
||||||
|
if (type === BYTES_TYPE) {
|
||||||
|
toObjectType.printIndentedLn(
|
||||||
|
`${camelCaseName}List: Array<Uint8Array | string>,`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`get${withUppercase}List(): Array<Uint8Array | string>;`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`get${withUppercase}List_asU8(): Array<Uint8Array>;`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`get${withUppercase}List_asB64(): Array<string>;`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`set${withUppercase}List(value: Array<Uint8Array | string>): void;`
|
||||||
|
);
|
||||||
|
printRepeatedAddMethod('Uint8Array | string');
|
||||||
|
} else {
|
||||||
|
toObjectType.printIndentedLn(
|
||||||
|
`${camelCaseName}List: Array<${exportType}${
|
||||||
|
type === MESSAGE_TYPE ? '.AsObject' : ''
|
||||||
|
}>,`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`get${withUppercase}List(): Array<${exportType}>;`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`set${withUppercase}List(value: Array<${exportType}>): void;`
|
||||||
|
);
|
||||||
|
printRepeatedAddMethod(exportType);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (type === BYTES_TYPE) {
|
||||||
|
toObjectType.printIndentedLn(`${camelCaseName}: Uint8Array | string,`);
|
||||||
|
printer.printIndentedLn(`get${withUppercase}(): Uint8Array | string;`);
|
||||||
|
printer.printIndentedLn(`get${withUppercase}_asU8(): Uint8Array;`);
|
||||||
|
printer.printIndentedLn(`get${withUppercase}_asB64(): string;`);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`set${withUppercase}(value: Uint8Array | string): void;`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let fieldObjectType = exportType;
|
||||||
|
let canBeUndefined = false;
|
||||||
|
if (type === MESSAGE_TYPE) {
|
||||||
|
fieldObjectType += '.AsObject';
|
||||||
|
if (
|
||||||
|
!isProto2(fileDescriptor) ||
|
||||||
|
field.getLabel() === FieldDescriptorProto.Label.LABEL_OPTIONAL
|
||||||
|
) {
|
||||||
|
canBeUndefined = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isProto2(fileDescriptor)) {
|
||||||
|
canBeUndefined = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const fieldObjectName = normaliseFieldObjectName(camelCaseName);
|
||||||
|
toObjectType.printIndentedLn(
|
||||||
|
`${fieldObjectName}${canBeUndefined ? '?' : ''}: ${fieldObjectType},`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`get${withUppercase}(): ${exportType}${
|
||||||
|
canBeUndefined ? ' | undefined' : ''
|
||||||
|
};`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`set${withUppercase}(value${
|
||||||
|
type === MESSAGE_TYPE ? '?' : ''
|
||||||
|
}: ${exportType}): void;`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printer.printEmptyLn();
|
||||||
|
});
|
||||||
|
|
||||||
|
toObjectType.printLn(`}`);
|
||||||
|
|
||||||
|
messageDescriptor.getOneofDeclList().forEach((oneOfDecl) => {
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`get${oneOfName(oneOfDecl.getName())}Case(): ${messageName}.${oneOfName(
|
||||||
|
oneOfDecl.getName()
|
||||||
|
)}Case;`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
printer.printIndentedLn(`serializeBinary(): Uint8Array;`);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`toObject(includeInstance?: boolean): ${messageName}.${objectTypeName};`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`static toObject(includeInstance: boolean, msg: ${messageName}): ${messageName}.${objectTypeName};`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`static serializeBinaryToWriter(message: ${messageName}, writer: jspb.BinaryWriter): void;`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`static deserializeBinary(bytes: Uint8Array): ${messageName};`
|
||||||
|
);
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`static deserializeBinaryFromReader(message: ${messageName}, reader: jspb.BinaryReader): ${messageName};`
|
||||||
|
);
|
||||||
|
|
||||||
|
printer.printLn(`}`);
|
||||||
|
printer.printEmptyLn();
|
||||||
|
|
||||||
|
printer.printLn(`export namespace ${messageName} {`);
|
||||||
|
|
||||||
|
printer.print(toObjectType.getOutput());
|
||||||
|
|
||||||
|
messageDescriptor.getNestedTypeList().forEach((nested) => {
|
||||||
|
const msgOutput = printMessage(
|
||||||
|
fileName,
|
||||||
|
exportMap,
|
||||||
|
nested,
|
||||||
|
indentLevel + 1,
|
||||||
|
fileDescriptor
|
||||||
|
);
|
||||||
|
if (msgOutput !== '') {
|
||||||
|
// If the message class is a Map entry then it isn't output, so don't print the namespace block
|
||||||
|
printer.print(msgOutput);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
messageDescriptor.getEnumTypeList().forEach((enumType) => {
|
||||||
|
printer.print(`${printEnum(enumType, indentLevel + 1)}`);
|
||||||
|
});
|
||||||
|
messageDescriptor.getOneofDeclList().forEach((oneOfDecl, index) => {
|
||||||
|
printer.print(
|
||||||
|
`${printOneOfDecl(oneOfDecl, oneOfGroups[index] || [], indentLevel + 1)}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
messageDescriptor.getExtensionList().forEach((extension) => {
|
||||||
|
printer.print(printExtension(fileName, exportMap, extension, indentLevel + 1));
|
||||||
|
});
|
||||||
|
|
||||||
|
printer.printLn(`}`);
|
||||||
|
|
||||||
|
return printer.getOutput();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,25 @@
|
||||||
import {Printer} from "../Printer";
|
import { Printer } from '../Printer';
|
||||||
import {OneofDescriptorProto, FieldDescriptorProto} from "google-protobuf/google/protobuf/descriptor_pb";
|
import {
|
||||||
import {oneOfName} from "../util";
|
OneofDescriptorProto,
|
||||||
|
FieldDescriptorProto,
|
||||||
|
} from 'google-protobuf/google/protobuf/descriptor_pb';
|
||||||
|
import { oneOfName } from '../util';
|
||||||
|
|
||||||
export function printOneOfDecl(oneOfDecl: OneofDescriptorProto, oneOfFields: Array<FieldDescriptorProto>, indentLevel: number) {
|
export function printOneOfDecl(
|
||||||
const printer = new Printer(indentLevel);
|
oneOfDecl: OneofDescriptorProto,
|
||||||
printer.printEmptyLn();
|
oneOfFields: Array<FieldDescriptorProto>,
|
||||||
printer.printLn(`export enum ${oneOfName(oneOfDecl.getName())}Case {`);
|
indentLevel: number
|
||||||
printer.printIndentedLn(`${oneOfDecl.getName().toUpperCase()}_NOT_SET = 0,`);
|
) {
|
||||||
oneOfFields.forEach(field => {
|
const printer = new Printer(indentLevel);
|
||||||
printer.printIndentedLn(`${field.getName().toUpperCase()} = ${field.getNumber()},`);
|
printer.printEmptyLn();
|
||||||
});
|
printer.printLn(`export enum ${oneOfName(oneOfDecl.getName())}Case {`);
|
||||||
printer.printLn("}");
|
printer.printIndentedLn(`${oneOfDecl.getName().toUpperCase()}_NOT_SET = 0,`);
|
||||||
|
oneOfFields.forEach((field) => {
|
||||||
|
printer.printIndentedLn(
|
||||||
|
`${field.getName().toUpperCase()} = ${field.getNumber()},`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
printer.printLn('}');
|
||||||
|
|
||||||
return printer.output;
|
return printer.output;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,184 +1,200 @@
|
||||||
import {parse} from "querystring";
|
import { parse } from 'querystring';
|
||||||
import {FileDescriptorProto} from "google-protobuf/google/protobuf/descriptor_pb";
|
import { FileDescriptorProto } from 'google-protobuf/google/protobuf/descriptor_pb';
|
||||||
import {ExportEnumEntry, ExportMessageEntry} from "./ExportMap";
|
import { ExportEnumEntry, ExportMessageEntry } from './ExportMap';
|
||||||
import {ServiceParameter, ModeParameter} from "./parameters";
|
import { ServiceParameter, ModeParameter } from './parameters';
|
||||||
export function filePathToPseudoNamespace(filePath: string): string {
|
export function filePathToPseudoNamespace(filePath: string): string {
|
||||||
return filePath.replace(".proto", "").replace(/\//g, "_").replace(/\./g, "_").replace(/\-/g, "_") + "_pb";
|
return (
|
||||||
|
filePath
|
||||||
|
.replace('.proto', '')
|
||||||
|
.replace(/\//g, '_')
|
||||||
|
.replace(/\./g, '_')
|
||||||
|
.replace(/\-/g, '_') + '_pb'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function stripPrefix(str: string, prefix: string) {
|
export function stripPrefix(str: string, prefix: string) {
|
||||||
if (str.substr(0, prefix.length) === prefix) {
|
if (str.substr(0, prefix.length) === prefix) {
|
||||||
return str.substr(prefix.length);
|
return str.substr(prefix.length);
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function snakeToCamel(str: string): string {
|
export function snakeToCamel(str: string): string {
|
||||||
return str.replace(/(\_\w)/g, function(m) {
|
return str.replace(/(\_\w)/g, function (m) {
|
||||||
return m[1].toUpperCase();
|
return m[1].toUpperCase();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function uppercaseFirst(str: string): string {
|
export function uppercaseFirst(str: string): string {
|
||||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const PROTO2_SYNTAX = "proto2";
|
const PROTO2_SYNTAX = 'proto2';
|
||||||
export function isProto2(fileDescriptor: FileDescriptorProto): boolean {
|
export function isProto2(fileDescriptor: FileDescriptorProto): boolean {
|
||||||
// Empty syntax defaults to proto2
|
// Empty syntax defaults to proto2
|
||||||
return (fileDescriptor.getSyntax() === "" || fileDescriptor.getSyntax() === PROTO2_SYNTAX);
|
return (
|
||||||
|
fileDescriptor.getSyntax() === '' || fileDescriptor.getSyntax() === PROTO2_SYNTAX
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function oneOfName(name: string) {
|
export function oneOfName(name: string) {
|
||||||
return uppercaseFirst(snakeToCamel(name.toLowerCase()));
|
return uppercaseFirst(snakeToCamel(name.toLowerCase()));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateIndent(indentLevel: number): string {
|
export function generateIndent(indentLevel: number): string {
|
||||||
let indent = "";
|
let indent = '';
|
||||||
for (let i = 0; i < indentLevel; i++) {
|
for (let i = 0; i < indentLevel; i++) {
|
||||||
indent += " ";
|
indent += ' ';
|
||||||
}
|
}
|
||||||
return indent;
|
return indent;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPathToRoot(fileName: string) {
|
export function getPathToRoot(fileName: string) {
|
||||||
const depth = fileName.split("/").length;
|
const depth = fileName.split('/').length;
|
||||||
return depth === 1 ? "./" : new Array(depth).join("../");
|
return depth === 1 ? './' : new Array(depth).join('../');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function withinNamespaceFromExportEntry(name: string, exportEntry: ExportMessageEntry | ExportEnumEntry) {
|
export function withinNamespaceFromExportEntry(
|
||||||
return exportEntry.pkg ? name.substring(exportEntry.pkg.length + 1) : name;
|
name: string,
|
||||||
|
exportEntry: ExportMessageEntry | ExportEnumEntry
|
||||||
|
) {
|
||||||
|
return exportEntry.pkg ? name.substring(exportEntry.pkg.length + 1) : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function replaceProtoSuffix(protoFilePath: string): string {
|
export function replaceProtoSuffix(protoFilePath: string): string {
|
||||||
const suffix = ".proto";
|
const suffix = '.proto';
|
||||||
const hasProtoSuffix = protoFilePath.slice(protoFilePath.length - suffix.length) === suffix;
|
const hasProtoSuffix =
|
||||||
return hasProtoSuffix
|
protoFilePath.slice(protoFilePath.length - suffix.length) === suffix;
|
||||||
? protoFilePath.slice(0, -suffix.length) + "_pb"
|
return hasProtoSuffix
|
||||||
: protoFilePath;
|
? protoFilePath.slice(0, -suffix.length) + '_pb'
|
||||||
|
: protoFilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function withAllStdIn(callback: (buffer: Buffer) => void): void {
|
export function withAllStdIn(callback: (buffer: Buffer) => void): void {
|
||||||
const ret: Buffer[] = [];
|
const ret: Buffer[] = [];
|
||||||
let len = 0;
|
let len = 0;
|
||||||
|
|
||||||
const stdin = process.stdin;
|
const stdin = process.stdin;
|
||||||
stdin.on("readable", function () {
|
stdin.on('readable', function () {
|
||||||
let chunk;
|
let chunk;
|
||||||
|
|
||||||
while ((chunk = stdin.read())) {
|
while ((chunk = stdin.read())) {
|
||||||
if (!(chunk instanceof Buffer)) throw new Error("Did not receive buffer");
|
if (!(chunk instanceof Buffer)) throw new Error('Did not receive buffer');
|
||||||
ret.push(chunk);
|
ret.push(chunk);
|
||||||
len += chunk.length;
|
len += chunk.length;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
stdin.on("end", function () {
|
stdin.on('end', function () {
|
||||||
callback(Buffer.concat(ret, len));
|
callback(Buffer.concat(ret, len));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// normaliseFieldObjectName modifies the field name that appears in the `asObject` representation
|
// normaliseFieldObjectName modifies the field name that appears in the `asObject` representation
|
||||||
// to match the logic found in `protobuf/compiler/js/js_generator.cc`. See: https://goo.gl/tX1dPQ
|
// to match the logic found in `protobuf/compiler/js/js_generator.cc`. See: https://goo.gl/tX1dPQ
|
||||||
export function normaliseFieldObjectName(name: string): string {
|
export function normaliseFieldObjectName(name: string): string {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case "abstract":
|
case 'abstract':
|
||||||
case "boolean":
|
case 'boolean':
|
||||||
case "break":
|
case 'break':
|
||||||
case "byte":
|
case 'byte':
|
||||||
case "case":
|
case 'case':
|
||||||
case "catch":
|
case 'catch':
|
||||||
case "char":
|
case 'char':
|
||||||
case "class":
|
case 'class':
|
||||||
case "const":
|
case 'const':
|
||||||
case "continue":
|
case 'continue':
|
||||||
case "debugger":
|
case 'debugger':
|
||||||
case "default":
|
case 'default':
|
||||||
case "delete":
|
case 'delete':
|
||||||
case "do":
|
case 'do':
|
||||||
case "double":
|
case 'double':
|
||||||
case "else":
|
case 'else':
|
||||||
case "enum":
|
case 'enum':
|
||||||
case "export":
|
case 'export':
|
||||||
case "extends":
|
case 'extends':
|
||||||
case "false":
|
case 'false':
|
||||||
case "final":
|
case 'final':
|
||||||
case "finally":
|
case 'finally':
|
||||||
case "float":
|
case 'float':
|
||||||
case "for":
|
case 'for':
|
||||||
case "function":
|
case 'function':
|
||||||
case "goto":
|
case 'goto':
|
||||||
case "if":
|
case 'if':
|
||||||
case "implements":
|
case 'implements':
|
||||||
case "import":
|
case 'import':
|
||||||
case "in":
|
case 'in':
|
||||||
case "instanceof":
|
case 'instanceof':
|
||||||
case "int":
|
case 'int':
|
||||||
case "interface":
|
case 'interface':
|
||||||
case "long":
|
case 'long':
|
||||||
case "native":
|
case 'native':
|
||||||
case "new":
|
case 'new':
|
||||||
case "null":
|
case 'null':
|
||||||
case "package":
|
case 'package':
|
||||||
case "private":
|
case 'private':
|
||||||
case "protected":
|
case 'protected':
|
||||||
case "public":
|
case 'public':
|
||||||
case "return":
|
case 'return':
|
||||||
case "short":
|
case 'short':
|
||||||
case "static":
|
case 'static':
|
||||||
case "super":
|
case 'super':
|
||||||
case "switch":
|
case 'switch':
|
||||||
case "synchronized":
|
case 'synchronized':
|
||||||
case "this":
|
case 'this':
|
||||||
case "throw":
|
case 'throw':
|
||||||
case "throws":
|
case 'throws':
|
||||||
case "transient":
|
case 'transient':
|
||||||
case "try":
|
case 'try':
|
||||||
case "typeof":
|
case 'typeof':
|
||||||
case "var":
|
case 'var':
|
||||||
case "void":
|
case 'void':
|
||||||
case "volatile":
|
case 'volatile':
|
||||||
case "while":
|
case 'while':
|
||||||
case "with":
|
case 'with':
|
||||||
return `pb_${name}`;
|
return `pb_${name}`;
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getServiceParameter(service?: string): ServiceParameter {
|
export function getServiceParameter(service?: string): ServiceParameter {
|
||||||
switch (service) {
|
switch (service) {
|
||||||
case "true":
|
case 'true':
|
||||||
console.warn("protoc-gen-ts warning: The service=true parameter has been deprecated. Use service=grpc-web instead.");
|
console.warn(
|
||||||
return ServiceParameter.GrpcWeb;
|
'protoc-gen-ts warning: The service=true parameter has been deprecated. Use service=grpc-web instead.'
|
||||||
case "grpc-web":
|
);
|
||||||
return ServiceParameter.GrpcWeb;
|
return ServiceParameter.GrpcWeb;
|
||||||
case "grpc-node":
|
case 'grpc-web':
|
||||||
return ServiceParameter.GrpcNode;
|
return ServiceParameter.GrpcWeb;
|
||||||
case undefined:
|
case 'grpc-node':
|
||||||
return ServiceParameter.None;
|
return ServiceParameter.GrpcNode;
|
||||||
default:
|
case undefined:
|
||||||
throw new Error(`Unrecognised service parameter: ${service}`);
|
return ServiceParameter.None;
|
||||||
}
|
default:
|
||||||
|
throw new Error(`Unrecognised service parameter: ${service}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getModeParameter(mode?: string): ModeParameter {
|
export function getModeParameter(mode?: string): ModeParameter {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case "grpc-js":
|
case 'grpc-js':
|
||||||
return ModeParameter.GrpcJs;
|
return ModeParameter.GrpcJs;
|
||||||
case undefined:
|
case undefined:
|
||||||
return ModeParameter.None;
|
return ModeParameter.None;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unrecognised mode parameter: ${mode}`);
|
throw new Error(`Unrecognised mode parameter: ${mode}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getParameterEnums(parameter: string): {
|
export function getParameterEnums(
|
||||||
service: ServiceParameter,
|
parameter: string
|
||||||
mode: ModeParameter
|
): {
|
||||||
|
service: ServiceParameter;
|
||||||
|
mode: ModeParameter;
|
||||||
} {
|
} {
|
||||||
const {service, mode} = parse(parameter, ",");
|
const { service, mode } = parse(parameter, ',');
|
||||||
return {
|
return {
|
||||||
service: getServiceParameter(service),
|
service: getServiceParameter(service),
|
||||||
mode: getModeParameter(mode)
|
mode: getModeParameter(mode),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue