feat: add support of go-modules for gotsrpc

This commit is contained in:
Stefan Martinov 2019-05-28 10:43:38 +02:00
parent b1b9a92ea1
commit a466ce70f7
18 changed files with 175 additions and 119 deletions

View File

@ -1,13 +1,13 @@
language: go
go:
- 1.11.2
- 1.12.5
cache:
directories:
- ./vendor
- $HOME/.cache/go-build
- $HOME/gopath/pkg/mod
script:
- make glide
- make test
- if [[ -n "${TRAVIS_TAG}" ]]; then
make release;

View File

@ -26,10 +26,6 @@ release: goreleaser
goreleaser:
@go get github.com/goreleaser/goreleaser && go install github.com/goreleaser/goreleaser
.PHONY: glide
glide:
@go get github.com/Masterminds/glide && glide install
.PHONY: test
test:
go test -v ./...

View File

@ -29,14 +29,14 @@ gotsrpc gotsrpc.yml
Will generate client and server side go and TypeScript code. Have fun!
## config examples
## Configuration Examples
### commonjs
### Standard Example
[demo/config.yml](demo/config-commonjs.yml)
```yaml
---
modulekind: commonjs
# if you want an async api vs classic callbacks - here you are
tsclientflavor: async
@ -61,7 +61,8 @@ mappings:
out: /tmp/test-files-demo-nested.ts
...
```
#### an async example
#### Async Example
How to use async clients in this case with axios:
@ -100,12 +101,12 @@ export async function test() {
```
### oldschool TypeScript
### Oldschool Typescript
[demo/config.yml](demo/config.yml)
```yaml
---
targets:
demo:
module: GoTSRPC.Demo
@ -130,3 +131,15 @@ mappings:
out: /tmp/test-files-demo-nested.ts
...
```
## GOModule Support
To support go modules add
```yaml
module:
name: github.com/foomo/gotsrpc
path: ../ # Relative Or Absolute Path where the package was checked out (root of the package)
```

View File

@ -52,6 +52,14 @@ func commonJSImports(conf *config.Config, c *code, tsFilename string) {
}
func getPathForTarget(gomod config.Namespace, goPath string, target *config.Target) (outputPath string) {
if gomod.Name != "" && strings.HasPrefix(target.Package, gomod.Name) {
return strings.Replace(goPath, gomod.Name, gomod.Path, 1)
} else {
return path.Join(goPath, "src", target.Package)
}
}
func Build(conf *config.Config, goPath string) {
if conf.ModuleKind == config.ModuleKindCommonJS {
@ -72,10 +80,12 @@ func Build(conf *config.Config, goPath string) {
longPackageName := target.Package
longPackageNameParts := strings.Split(longPackageName, "/")
goRPCProxiesFilename := path.Join(goPath, "src", longPackageName, "gorpc.go")
goRPCClientsFilename := path.Join(goPath, "src", longPackageName, "gorpcclient.go")
goTSRPCProxiesFilename := path.Join(goPath, "src", longPackageName, "gotsrpc.go")
goTSRPCClientsFilename := path.Join(goPath, "src", longPackageName, "gotsrpcclient.go")
outputPath := getPathForTarget(conf.Module, goPath, target)
goRPCProxiesFilename := path.Join(outputPath, "gorpc.go")
goRPCClientsFilename := path.Join(outputPath, "gorpcclient.go")
goTSRPCProxiesFilename := path.Join(outputPath, "gotsrpc.go")
goTSRPCClientsFilename := path.Join(outputPath, "gotsrpcclient.go")
remove := func(filename string) {
_, err := os.Stat(filename)
@ -103,10 +113,10 @@ func Build(conf *config.Config, goPath string) {
goPaths = append(goPaths, vendorDirectory)
}
services, structs, scalarTypes, constants, err := Read(goPaths, longPackageName, target.Services)
services, structs, scalarTypes, constants, err := Read(goPaths, conf.Module, longPackageName, target.Services)
if err != nil {
fmt.Fprintln(os.Stderr, " an error occured while trying to understand your code", err)
fmt.Fprintln(os.Stderr, "\t an error occured while trying to understand your code: ", err)
os.Exit(2)
}

View File

@ -3,9 +3,10 @@ package config
import (
"errors"
"fmt"
"io/ioutil"
"gopkg.in/yaml.v2"
"io/ioutil"
"path"
"path/filepath"
)
type PHPTarget struct {
@ -73,7 +74,13 @@ const (
TSClientFlavorAsync TSClientFlavor = "async"
)
type Namespace struct {
Name string
Path string
}
type Config struct {
Module Namespace
ModuleKind ModuleKind
TSClientFlavor TSClientFlavor
Targets map[string]*Target
@ -83,10 +90,21 @@ type Config struct {
func LoadConfigFile(file string) (conf *Config, err error) {
yamlBytes, readErr := ioutil.ReadFile(file)
if readErr != nil {
err = errors.New("could not read config file: " + readErr.Error())
return
return nil, errors.New("could not read config file: " + readErr.Error())
}
return loadConfig(yamlBytes)
conf, err = loadConfig(yamlBytes)
if err != nil {
return nil, err
}
if conf.Module.Path != "" && !path.IsAbs(conf.Module.Path) {
absPath, err := filepath.Abs(filepath.Join(filepath.Dir(file), conf.Module.Path))
if err != nil {
return nil, err
}
conf.Module.Path = absPath
}
return conf, nil
}
var ErrInvalidTSClientFlavor = errors.New(fmt.Sprintln("unknown ts client flavor: must be empty or ", TSClientFlavorAsync))
@ -115,5 +133,6 @@ func loadConfig(yamlBytes []byte) (conf *Config, err error) {
for goPackage, mapping := range conf.Mappings {
mapping.GoPackage = goPackage
}
return
}

View File

@ -1,6 +1,11 @@
package config
import "testing"
import (
"fmt"
"github.com/stretchr/testify/assert"
"strings"
"testing"
)
const sampleConf = `---
targets:
@ -89,3 +94,16 @@ func TestLoadConfigInvalidClientFlavor(t *testing.T) {
t.Fatal("that config must be invalid")
}
}
func TestLoadConfigFile_GomodAbsolute(t *testing.T) {
config, err := LoadConfigFile("testdata/gomod.absolute.yml")
assert.NoError(t, err)
assert.Equal(t, "/go/src/github.com/foomo/gotsrpc", config.Module.Path)
}
func TestLoadConfigFile_GomodRelative(t *testing.T) {
config, err := LoadConfigFile("testdata/gomod.relative.yml")
assert.NoError(t, err)
fmt.Println(config.Module.Path)
assert.True(t, strings.HasSuffix(config.Module.Path, "gotsrpc/config/demo"))
}

5
config/testdata/gomod.absolute.yml vendored Normal file
View File

@ -0,0 +1,5 @@
---
module:
name: github.com/foomo/gotsrpc
path: /go/src/github.com/foomo/gotsrpc

4
config/testdata/gomod.relative.yml vendored Normal file
View File

@ -0,0 +1,4 @@
---
module:
name: github.com/foomo/gotsrpc
path: ../demo

View File

@ -1,4 +1,8 @@
---
module:
name: github.com/foomo/gotsrpc
path: ../
modulekind: commonjs
tsclientflavor: async
targets:

View File

@ -1,4 +1,8 @@
---
module:
name: github.com/foomo/gotsrpc
path: ../
modulekind: commonjs
targets:
demo:

View File

@ -1,4 +1,8 @@
---
module:
name: github.com/foomo/gotsrpc
path: ../
targets:
demo:
module: GoTSRPC.Demo
@ -8,11 +12,11 @@ targets:
package: github.com/foomo/gotsrpc/demo
out: demo/output/client.ts
gorpc:
- Foo
- Demo
- Foo
- Demo
tsrpc:
- Foo
- Demo
- Foo
- Demo
mappings:
github.com/foomo/gotsrpc/demo:

59
glide.lock generated
View File

@ -1,59 +0,0 @@
hash: fa41763018fc177e5a35bdae1c36d2c2b51697c6931528836ed78f74a531f05d
updated: 2018-11-26T16:35:09.040671+01:00
imports:
- name: github.com/beorn7/perks
version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
subpackages:
- quantile
- name: github.com/golang/protobuf
version: 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9
subpackages:
- proto
- name: github.com/matttproud/golang_protobuf_extensions
version: c12348ce28de40eed0136aa2b644d0ee0650e56c
subpackages:
- pbutil
- name: github.com/pkg/errors
version: c605e284fe17294bda444b34710735b29d1a9d90
- name: github.com/prometheus/client_golang
version: c5b7fccd204277076155f10851dad72b76a49317
subpackages:
- prometheus
- name: github.com/prometheus/client_model
version: fa8ad6fec33561be4280a8f0514318c79d7f6cb6
subpackages:
- go
- name: github.com/prometheus/common
version: 0d5de9d6d8629cb8bee6d4674da4127cd8b615a3
subpackages:
- expfmt
- internal/bitbucket.org/ww/goautoneg
- model
- name: github.com/prometheus/procfs
version: abf152e5f3e97f2fafac028d2cc06c1feb87ffa5
- name: github.com/stretchr/testify
version: f35b8ab0b5a2cef36673838d662e249dd9c94686
subpackages:
- assert
- name: github.com/ugorji/go
version: b4c50a2b199d93b13dc15e78929cfb23bfdf21ab
subpackages:
- codec
- name: github.com/valyala/gorpc
version: 908281bef77441f2d0ec1792189b4032a1dace0c
- name: golang.org/x/tools
version: 6d70fb2e85323e81c89374331d3d2b93304faa36
subpackages:
- go/ast/astutil
- imports
- name: gopkg.in/yaml.v2
version: a5b47d31c556af34a302ce5d659e6fea44d90de0
testImports:
- name: github.com/davecgh/go-spew
version: 8991bc29aa16c548c550c7ff78260e27b9ab7c73
subpackages:
- spew
- name: github.com/pmezard/go-difflib
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
subpackages:
- difflib

View File

@ -1,18 +0,0 @@
package: github.com/foomo/gotsrpc
import:
- package: github.com/pkg/errors
- package: github.com/prometheus/client_golang
version: ~0.8.0
subpackages:
- prometheus
- package: github.com/valyala/gorpc
- package: gopkg.in/yaml.v2
- package: github.com/stretchr/testify
version: ^1.1.4
- package: golang.org/x/tools
subpackages:
- imports
- package: github.com/ugorji/go
version: ^1.1.1
subpackages:
- codec

21
go.mod Normal file
View File

@ -0,0 +1,21 @@
module github.com/foomo/gotsrpc
go 1.12
require (
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/protobuf v0.0.0-20171021043952-1643683e1b54
github.com/matttproud/golang_protobuf_extensions v1.0.1
github.com/pkg/errors v0.0.0-20170505043639-c605e284fe17
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v0.8.0
github.com/prometheus/client_model v0.0.0-20150212101744-fa8ad6fec335
github.com/prometheus/common v0.0.0-20161114134743-0d5de9d6d862
github.com/prometheus/procfs v0.0.0-20160411190841-abf152e5f3e9
github.com/stretchr/testify v1.2.2
github.com/ugorji/go v1.1.1
github.com/valyala/gorpc v0.0.0-20160519171614-908281bef774
golang.org/x/tools v0.0.0-20171116013056-6d70fb2e8532
gopkg.in/yaml.v2 v2.0.0-20160928153709-a5b47d31c556
)

23
go.sum Normal file
View File

@ -0,0 +1,23 @@
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang/protobuf v0.0.0-20171021043952-1643683e1b54/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/pkg/errors v0.0.0-20170505043639-c605e284fe17 h1:chPfVn+gpAM5CTpTyVU9j8J+xgRGwmoDlNDLjKnJiYo=
github.com/pkg/errors v0.0.0-20170505043639-c605e284fe17/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_model v0.0.0-20150212101744-fa8ad6fec335/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.0.0-20161114134743-0d5de9d6d862/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20160411190841-abf152e5f3e9/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/ugorji/go v1.1.1 h1:gmervu+jDMvXTbcHQ0pd2wee85nEoE0BsVyEuzkfK8w=
github.com/ugorji/go v1.1.1/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/valyala/gorpc v0.0.0-20160519171614-908281bef774 h1:SUHFQHAaySqF0YHCmmm0EIFooFZpDPpi5KTom7YJ07c=
github.com/valyala/gorpc v0.0.0-20160519171614-908281bef774/go.mod h1:8uNqM1i7pr0jO7gdvbNCgsSa8Ki2vMh7JCQxO9BlF90=
golang.org/x/tools v0.0.0-20171116013056-6d70fb2e8532 h1:xK4KvCVyo6hV0MhHUva46Vd7t2ISEQfxoNyJsGFdXLc=
golang.org/x/tools v0.0.0-20171116013056-6d70fb2e8532/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/yaml.v2 v2.0.0-20160928153709-a5b47d31c556 h1:hKXbLW5oaJoQgs8KrzTLdF4PoHi+0oQPgea9TNtvE3E=
gopkg.in/yaml.v2 v2.0.0-20160928153709-a5b47d31c556/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=

View File

@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/foomo/gotsrpc/config"
"github.com/pkg/errors"
"github.com/ugorji/go/codec"
"go/ast"
@ -96,7 +97,14 @@ func Reply(response []interface{}, stats *CallStats, r *http.Request, w http.Res
}
}
func parseDir(goPaths []string, packageName string) (map[string]*ast.Package, error) {
func parseDir(goPaths []string, gomod config.Namespace, packageName string) (map[string]*ast.Package, error) {
if gomod.Name != "" && strings.HasPrefix(packageName, gomod.Name) {
fset := token.NewFileSet()
dir := strings.Replace(packageName, gomod.Name, gomod.Path, 1)
return parser.ParseDir(fset, dir, nil, parser.AllErrors)
}
errorStrings := map[string]string{}
for _, goPath := range goPaths {
fset := token.NewFileSet()
@ -129,8 +137,8 @@ func (a byLen) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}
func parsePackage(goPaths []string, packageName string) (pkg *ast.Package, err error) {
pkgs, err := parseDir(goPaths, packageName)
func parsePackage(goPaths []string, gomod config.Namespace, packageName string) (pkg *ast.Package, err error) {
pkgs, err := parseDir(goPaths, gomod, packageName)
if err != nil {
return nil, errors.New("could not parse package " + packageName + ": " + err.Error())
}
@ -139,7 +147,7 @@ func parsePackage(goPaths []string, packageName string) (pkg *ast.Package, err e
return nil, errors.New("invalid package name given")
}
strippedPackageName := packageNameParts[len(packageNameParts)-1]
foundPackages := []string{}
var foundPackages []string
sortedGoPaths := make([]string, len(goPaths))
for iGoPath := range goPaths {
sortedGoPaths[iGoPath] = goPaths[iGoPath]

View File

@ -1,6 +1,7 @@
package gotsrpc
import (
"github.com/foomo/gotsrpc/config"
"os"
"testing"
@ -15,7 +16,7 @@ func getTestServiceList(t *testing.T) ServiceList {
packageName := "github.com/foomo/gotsrpc/demo"
pkg, parseErr := parsePackage([]string{os.Getenv("GOPATH")}, packageName)
pkg, parseErr := parsePackage([]string{os.Getenv("GOPATH")}, config.Namespace{}, packageName)
assert.NoError(t, parseErr)
services, err := readServicesInPackage(pkg, packageName, serviceMap)

View File

@ -3,6 +3,7 @@ package gotsrpc
import (
"errors"
"fmt"
"github.com/foomo/gotsrpc/config"
"go/ast"
"go/token"
"reflect"
@ -193,6 +194,7 @@ func loadConstants(pkg *ast.Package) map[string]*ast.BasicLit {
func Read(
goPaths []string,
gomod config.Namespace,
packageName string,
serviceMap map[string]string,
) (
@ -206,7 +208,7 @@ func Read(
err = errors.New("nothing to do service names are empty")
return
}
pkg, parseErr := parsePackage(goPaths, packageName)
pkg, parseErr := parsePackage(goPaths, gomod, packageName)
if parseErr != nil {
err = parseErr
return
@ -231,7 +233,7 @@ func Read(
structs = map[string]*Struct{}
scalars = map[string]*Scalar{}
collectErr := collectTypes(goPaths, missingTypes, structs, scalars)
collectErr := collectTypes(goPaths, gomod, missingTypes, structs, scalars)
if collectErr != nil {
err = errors.New("error while collecting structs: " + collectErr.Error())
}
@ -248,7 +250,7 @@ func Read(
_, ok := constants[structPackage]
if !ok {
// fmt.Println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", structPackage)
pkg, constPkgErr := parsePackage(goPaths, structPackage)
pkg, constPkgErr := parsePackage(goPaths, gomod, structPackage)
if constPkgErr != nil {
err = constPkgErr
return
@ -290,7 +292,7 @@ func fixFieldStructs(fields []*Field, structs map[string]*Struct, scalars map[st
}
}
func collectTypes(goPaths []string, missingTypes map[string]bool, structs map[string]*Struct, scalars map[string]*Scalar) error {
func collectTypes(goPaths []string, gomod config.Namespace, missingTypes map[string]bool, structs map[string]*Struct, scalars map[string]*Scalar) error {
scannedPackageStructs := map[string]map[string]*Struct{}
scannedPackageScalars := map[string]map[string]*Scalar{}
missingTypeNames := func() []string {
@ -323,7 +325,7 @@ func collectTypes(goPaths []string, missingTypes map[string]bool, structs map[st
packageStructs, structOK := scannedPackageStructs[packageName]
packageScalars, scalarOK := scannedPackageScalars[packageName]
if !structOK || !scalarOK {
parsedPackageStructs, parsedPackageScalars, err := getTypesInPackage(goPaths, packageName)
parsedPackageStructs, parsedPackageScalars, err := getTypesInPackage(goPaths, gomod, packageName)
if err != nil {
return err
}
@ -467,13 +469,14 @@ func (st *StructType) FullName() string {
func getTypesInPackage(
goPaths []string,
gomod config.Namespace,
packageName string,
) (
structs map[string]*Struct,
scalars map[string]*Scalar,
err error,
) {
pkg, err := parsePackage(goPaths, packageName)
pkg, err := parsePackage(goPaths, gomod, packageName)
if err != nil {
return nil, nil, err
}
@ -490,7 +493,7 @@ func getStructTypeForField(value *Value) *StructType {
switch true {
case value.StructType != nil:
strType = value.StructType
//case field.Value.ArrayType
//case field.Value.ArrayType
case value.Map != nil:
strType = getStructTypeForField(value.Map.Value)
case value.Array != nil:
@ -505,7 +508,7 @@ func getScalarForField(value *Value) *Scalar {
switch true {
case value.Scalar != nil:
scalarType = value.Scalar
//case field.Value.ArrayType
//case field.Value.ArrayType
case value.Map != nil:
scalarType = getScalarForField(value.Map.Value)
case value.Array != nil: