Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(proto-loader-gen-types): add options for specifying file extensions #2912

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 42 additions & 33 deletions packages/proto-loader/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,44 +61,53 @@ The `proto-loader-gen-types` script distributed with this package can be used to
proto-loader-gen-types.js [options] filenames...

Options:
--help Show help [boolean]
--version Show version number [boolean]
--keepCase Preserve the case of field names
--help Show help [boolean]
--version Show version number [boolean]
--keepCase Preserve the case of field names
[boolean] [default: false]
--longs The type that should be used to output 64 bit integer
values. Can be String, Number[string] [default: "Long"]
--enums The type that should be used to output enum fields. Can
be String [string] [default: "number"]
--bytes The type that should be used to output bytes fields.
Can be String, Array [string] [default: "Buffer"]
--defaults Output default values for omitted fields
--longs The type that should be used to output 64 bit
integer values. Can be String, Number
[string] [default: "Long"]
--enums The type that should be used to output enum fields.
Can be String [string] [default: "number"]
--bytes The type that should be used to output bytes
fields. Can be String, Array
[string] [default: "Buffer"]
--defaults Output default values for omitted fields
[boolean] [default: false]
--arrays Output default values for omitted repeated fields even
if --defaults is not set [boolean] [default: false]
--objects Output default values for omitted message fields even
if --defaults is not set [boolean] [default: false]
--oneofs Output virtual oneof fields set to the present field's
name [boolean] [default: false]
--json Represent Infinity and NaN as strings in float fields.
Also decode google.protobuf.Any automatically
--arrays Output default values for omitted repeated fields
even if --defaults is not set
[boolean] [default: false]
--includeComments Generate doc comments from comments in the original
files [boolean] [default: false]
-I, --includeDirs Directories to search for included files [array]
-O, --outDir Directory in which to output files [string] [required]
--grpcLib The gRPC implementation library that these types will
be used with. If not provided, some types will not be
generated [string]
--inputTemplate Template for mapping input or "permissive" type names
[string] [default: "%s"]
--outputTemplate Template for mapping output or "restricted" type names
[string] [default: "%s__Output"]
--inputBranded Output property for branded type for "permissive"
types with fullName of the Message as its value
--objects Output default values for omitted message fields
even if --defaults is not set
[boolean] [default: false]
--outputBranded Output property for branded type for "restricted"
types with fullName of the Message as its value
--oneofs Output virtual oneof fields set to the present
field's name [boolean] [default: false]
--json Represent Infinity and NaN as strings in float
fields. Also decode google.protobuf.Any
automatically [boolean] [default: false]
--includeComments Generate doc comments from comments in the original
files [boolean] [default: false]
-I, --includeDirs Directories to search for included files [array]
-O, --outDir Directory in which to output files
[string] [required]
--grpcLib The gRPC implementation library that these types
will be used with. If not provided, some types will
not be generated [string]
--inputTemplate Template for mapping input or "permissive" type
names [string] [default: "%s"]
--outputTemplate Template for mapping output or "restricted" type
names [string] [default: "%s__Output"]
--inputBranded Output property for branded type for "permissive"
types with fullName of the Message as its value
[boolean] [default: false]
--outputBranded Output property for branded type for "restricted"
types with fullName of the Message as its value
[boolean] [default: false]
--targetFileExtension File extension for generated files. Defaults to .ts
[string] [default: ".ts"]
--importFileExtension File extension for import specifiers in generated
code. Defaults to none (omitted) [string]
```

### Example Usage
Expand Down
24 changes: 15 additions & 9 deletions packages/proto-loader/bin/proto-loader-gen-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ type GeneratorOptions = Protobuf.IParseOptions & Protobuf.IConversionOptions & {
outputTemplate: string;
inputBranded: boolean;
outputBranded: boolean;
targetFileExtension?: string;
importFileExtension?: string;
}

class TextFormatter {
Expand Down Expand Up @@ -105,8 +107,8 @@ function getImportPath(to: Protobuf.Type | Protobuf.Enum | Protobuf.Service): st
return stripLeadingPeriod(to.fullName).replace(/\./g, '/');
}

function getPath(to: Protobuf.Type | Protobuf.Enum | Protobuf.Service) {
return stripLeadingPeriod(to.fullName).replace(/\./g, '/') + '.ts';
function getPath(to: Protobuf.Type | Protobuf.Enum | Protobuf.Service, options: GeneratorOptions) {
return stripLeadingPeriod(to.fullName).replace(/\./g, '/') + options.targetFileExtension;
}

function getPathToRoot(from: Protobuf.NamespaceBase) {
Expand Down Expand Up @@ -153,7 +155,7 @@ function getImportLine(dependency: Protobuf.Type | Protobuf.Enum | Protobuf.Serv
throw new Error('Invalid object passed to getImportLine');
}
}
return `import type { ${importedTypes} } from '${filePath}';`
return `import type { ${importedTypes} } from '${filePath}${options.importFileExtension}';`
}

function getChildMessagesAndEnums(namespace: Protobuf.NamespaceBase): (Protobuf.Type | Protobuf.Enum)[] {
Expand Down Expand Up @@ -787,21 +789,21 @@ function generateFilesForNamespace(namespace: Protobuf.NamespaceBase, options: G
if (nested instanceof Protobuf.Type) {
generateMessageInterfaces(fileFormatter, nested, options);
if (options.verbose) {
console.log(`Writing ${options.outDir}/${getPath(nested)} from file ${nested.filename}`);
console.log(`Writing ${options.outDir}/${getPath(nested, options)} from file ${nested.filename}`);
}
filePromises.push(writeFile(`${options.outDir}/${getPath(nested)}`, fileFormatter.getFullText()));
filePromises.push(writeFile(`${options.outDir}/${getPath(nested, options)}`, fileFormatter.getFullText()));
} else if (nested instanceof Protobuf.Enum) {
generateEnumInterface(fileFormatter, nested, options);
if (options.verbose) {
console.log(`Writing ${options.outDir}/${getPath(nested)} from file ${nested.filename}`);
console.log(`Writing ${options.outDir}/${getPath(nested, options)} from file ${nested.filename}`);
}
filePromises.push(writeFile(`${options.outDir}/${getPath(nested)}`, fileFormatter.getFullText()));
filePromises.push(writeFile(`${options.outDir}/${getPath(nested, options)}`, fileFormatter.getFullText()));
} else if (nested instanceof Protobuf.Service) {
generateServiceInterfaces(fileFormatter, nested, options);
if (options.verbose) {
console.log(`Writing ${options.outDir}/${getPath(nested)} from file ${nested.filename}`);
console.log(`Writing ${options.outDir}/${getPath(nested, options)} from file ${nested.filename}`);
}
filePromises.push(writeFile(`${options.outDir}/${getPath(nested)}`, fileFormatter.getFullText()));
filePromises.push(writeFile(`${options.outDir}/${getPath(nested, options)}`, fileFormatter.getFullText()));
} else if (isNamespaceBase(nested)) {
filePromises.push(...generateFilesForNamespace(nested, options));
}
Expand Down Expand Up @@ -877,6 +879,8 @@ async function runScript() {
.option('outputTemplate', { string: true, default: `${templateStr}__Output` })
.option('inputBranded', boolDefaultFalseOption)
.option('outputBranded', boolDefaultFalseOption)
.option('targetFileExtension', { string: true, default: '.ts' })
.option('importFileExtension', { string: true, default: '' })
.coerce('longs', value => {
switch (value) {
case 'String': return String;
Expand Down Expand Up @@ -916,6 +920,8 @@ async function runScript() {
outputTemplate: 'Template for mapping output or "restricted" type names',
inputBranded: 'Output property for branded type for "permissive" types with fullName of the Message as its value',
outputBranded: 'Output property for branded type for "restricted" types with fullName of the Message as its value',
targetFileExtension: 'File extension for generated files. Defaults to .ts',
importFileExtension: 'File extension for import specifiers in generated code. Defaults to none (omitted)'
}).demandOption(['outDir'])
.demand(1)
.usage('$0 [options] filenames...')
Expand Down