Skip to content

Commit

Permalink
fix: invalid TS module name for proto files with dash or dot chars
Browse files Browse the repository at this point in the history
Fixes grpc-ecosystem#42

The fix patches `data.GetModuleName` func to return a camel cased string to be used as a unique module name in TS artifacts. Here we replace manual conversion of a package name and base file name with `ToCamel` func of the `github.com/iancoleman/strcase` package. This helper package has already been included in go.mod.
`ToCamel` removes `.`, `-`, `_` or whitespace chars from the input string and uses those as a mark to capitalize the next letter.
  • Loading branch information
anatolym authored and dpup committed May 12, 2024
1 parent 6341565 commit 233a149
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 10 deletions.
16 changes: 7 additions & 9 deletions data/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"path/filepath"
"sort"
"strings"

"github.com/iancoleman/strcase"
)

// File store the information about rendering a file
Expand Down Expand Up @@ -95,20 +97,16 @@ type Dependency struct {
SourceFile string
}

// GetModuleName returns module name = package name + file name to be the unique identifier for source file in a ts file
// GetModuleName returns module name = package name + base file name to be the
// unique identifier for source file in a ts file. Package name and base file
// name are converted to camel case, special characters like dot, dash and
// underscore are removed.
func GetModuleName(packageName, fileName string) string {
baseName := filepath.Base(fileName)
ext := filepath.Ext(fileName)
name := baseName[0 : len(baseName)-len(ext)]
packageParts := strings.Split(packageName, ".")

if packageName != "" {
for i, p := range packageParts {
packageParts[i] = strings.ToUpper(p[:1]) + p[1:]
}
}

return strings.Join(packageParts, "") + strings.ToUpper(name[:1]) + name[1:]
return strcase.ToCamel(packageName) + strcase.ToCamel(name)
}

// GetTSFileName gets the typescript filename out of the proto file name
Expand Down
27 changes: 27 additions & 0 deletions data/file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package data

import "testing"

func TestGetModuleName(t *testing.T) {
tests := []struct {
name string
packageName string
fileName string
want string
}{
{"empty", "", "", ""},
{"simple", "mypackage", "service.proto", "MypackageService"},
{"with file path", "mypackage", "path/to/proto/file/service.proto", "MypackageService"},
{"with underscore", "my_package", "cool_service.proto", "MyPackageCoolService"},
{"with dash", "my-package", "cool-service.proto", "MyPackageCoolService"},
{"with dash and underscore", "my-package", "cool_service.proto", "MyPackageCoolService"},
{"with dots", "my.package", "cool.service.proto", "MyPackageCoolService"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := GetModuleName(tt.packageName, tt.fileName); got != tt.want {
t.Errorf("GetModuleName() = %v, want %v", got, tt.want)
}
})
}
}
2 changes: 1 addition & 1 deletion registry/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ func (r *Registry) collectExternalDependenciesFromData(filesData map[string]*dat

if _, ok := dependencies[identifier]; !ok {
// only fill in if this file has not been mentioned before.
// the way import in the genrated file works is like
// the way import in the generated file works is like
// import * as [ModuleIdentifier] from '[Source File]'
// so there only needs to be added once.
// Referencing types will be [ModuleIdentifier].[PackageIdentifier]
Expand Down

0 comments on commit 233a149

Please sign in to comment.