Skip to content

Commit a8dd70a

Browse files
authored
Implement go.type.import meta for arbitrary import paths (#21)
* Implement go.type.import meta for arbitrary import paths * Dynamic import paths based on client/server/importTypesFrom opts * Fix stdlib/custom imports * Example: Add uuid.UUID type and regenerate
1 parent 4fb8b9d commit a8dd70a

13 files changed

+148
-55
lines changed

README.md

+36-16
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ As you can see, the `-target` supports default `golang`, any git URI, or a local
2222
### Set custom template variables
2323
Change any of the following values by passing `-option="Value"` CLI flag to `webrpc-gen`.
2424

25-
| webrpc-gen -option | Description | Default value | Added in |
26-
|----------------------|-----------------------------------------|----------------------------|----------|
27-
| `-pkg=<name>` | package name | `"proto"` | |
28-
| `-client` | generate client code | unset (`false`) | |
29-
| `-server` | generate server code | unset (`false`) | |
30-
| `-legacyErrors=true` | enable legacy errors (v0.10.0 or older) | unset (`false`) | v0.11.0 |
25+
| webrpc-gen -option | Description | Default value | Added in |
26+
|--------------------------|-------------------------------------------|----------------------------|----------|
27+
| `-pkg=<name>` | package name | `"proto"` | |
28+
| `-client` | generate client code | unset (`false`) | |
29+
| `-server` | generate server code | unset (`false`) | |
30+
| `-importTypesFrom=<pkg>` | do not generate types; import from a pkg | unset (`""`) | v0.12.0 |
31+
| `-legacyErrors=true` | enable legacy errors (v0.10.0 or older) | unset (`false`) | v0.11.0 |
3132

3233
Example:
3334
```
@@ -36,25 +37,44 @@ webrpc-gen -schema=./proto.json -target=golang -out openapi.gen.yaml -pkg=main -
3637

3738
## Set custom Go field meta tags in your RIDL file
3839

39-
| CLI option flag | Description |
40-
|---------------------------|------------------------------------------------------------------|
41-
| `+ go.field.name = ID` | Set custom field name |
42-
| `+ go.field.type = int64` | Set custom field type (must be able to JSON unmarshal the value) |
43-
| `+ go.tag.json = id` | Set `json:"id"` struct tag |
44-
| `+ go.tag.db = id` | Set `db:"id"` struct tag |
40+
| CLI option flag | Description |
41+
|----------------------------------------------|------------------------------------------------------------------|
42+
| `+ go.field.name = ID` | Set custom field name |
43+
| `+ go.field.type = uuid.UUID` | Set custom field type (must be able to JSON unmarshal the value) |
44+
| `+ go.type.import = github.com/google/uuid` | Set custom field type's import path |
45+
| `+ go.tag.json = id` | Set `json:"id"` struct tag |
46+
| `+ go.tag.db = id` | Set `db:"id"` struct tag |
4547

4648
Example:
4749
```ridl
48-
message User
49-
- id: uint64
50-
+ go.field.name = ID
50+
struct User
51+
- ID: int64
5152
+ go.tag.db = id
5253
+ go.tag.json = id
54+
- UUID: string
55+
+ go.field.type = uuid.UUID
56+
+ go.type.import = github.com/google/uuid
57+
+ go.tag.json = uuid
58+
+ go.tag.db = uuid
59+
- Age: int
60+
+ go.tag.db: age
61+
- Name: string
62+
+ go.tag.db = name
63+
- PasswordHash: string
64+
+ go.tag.db = passwd_hash
5365
```
66+
5467
will result in
68+
5569
```go
70+
import "github.com/google/uuid"
71+
5672
type User struct {
57-
ID uint64 `json:"id" db:"id"`
73+
ID int64 `json:"id" db:"id"`
74+
UUID uuid.UUID `json:"uuid" db:"uuid"`
75+
Name string `db:"name"`
76+
Age int `db:"age"`
77+
PasswordHash string `json:"-" db:"passwd_hash"`
5878
}
5979
```
6080

_examples/golang-basics/example.gen.go

+8-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

_examples/golang-basics/example.ridl

+5-2
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@ enum Kind: uint32
1010

1111
struct User
1212
- id: uint64
13-
+ json = id
1413
+ go.field.name = ID
15-
#+ go.field.type = int64
1614
+ go.tag.db = id
1715

16+
- uuid: string
17+
+ go.tag.db = id
18+
+ go.field.type = uuid.UUID
19+
+ go.type.import = github.com/google/uuid
20+
1821
- username: string
1922
+ json = USERNAME
2023
+ go.tag.db = username

_examples/golang-basics/go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99

1010
require (
1111
github.com/davecgh/go-spew v1.1.1 // indirect
12+
github.com/google/uuid v1.3.0 // indirect
1213
github.com/pmezard/go-difflib v1.0.0 // indirect
1314
gopkg.in/yaml.v3 v3.0.1 // indirect
1415
)

_examples/golang-basics/go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
33
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
44
github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
55
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
6+
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
7+
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
68
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
79
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
810
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

_examples/golang-imports/api.gen.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client.go.tmpl

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{{define "client"}}
22
{{- $typeMap := .TypeMap -}}
3+
{{- $typePrefix := .TypePrefix -}}
34
{{- if .Services -}}
45
//
56
// Client
@@ -34,22 +35,22 @@ func New{{.Name | firstLetterToUpper }}Client(addr string, client HTTPClient) {{
3435
{{- $inputs := $method.Inputs -}}
3536
{{- $outputs := $method.Outputs }}
3637

37-
func (c *{{$serviceName}}) {{.Name}}(ctx context.Context{{range $_, $input := $inputs}}, {{$input.Name}} {{template "type" dict "Type" $input.Type "Optional" $input.Optional "TypeMap" $typeMap}}{{end}}) {{if len .Outputs}}({{end}}{{range $i, $output := .Outputs}}{{template "type" dict "Type" $output.Type "Optional" $output.Optional "TypeMap" $typeMap}}{{if lt $i (len $method.Outputs)}}, {{end}}{{end}}error{{if len .Outputs}}){{end}} {
38+
func (c *{{$serviceName}}) {{.Name}}(ctx context.Context{{range $_, $input := $inputs}}, {{$input.Name}} {{template "type" dict "Type" $input.Type "Optional" $input.Optional "TypeMap" $typeMap "TypePrefix" $typePrefix}}{{end}}) {{if len .Outputs}}({{end}}{{range $i, $output := .Outputs}}{{template "type" dict "Type" $output.Type "Optional" $output.Optional "TypeMap" $typeMap "TypePrefix" $typePrefix}}{{if lt $i (len $method.Outputs)}}, {{end}}{{end}}error{{if len .Outputs}}){{end}} {
3839
{{- $inputVar := "nil" -}}
3940
{{- $outputVar := "nil" -}}
4041
{{- if $inputs | len}}
4142
{{- $inputVar = "in"}}
4243
in := struct {
4344
{{- range $i, $input := $inputs}}
44-
Arg{{$i}} {{template "type" dict "Type" $input.Type "Optional" $input.Optional "TypeMap" $typeMap}} `json:"{{firstLetterToLower $input.Name}}"`
45+
Arg{{$i}} {{template "type" dict "Type" $input.Type "Optional" $input.Optional "TypeMap" $typeMap "TypePrefix" $typePrefix}} `json:"{{firstLetterToLower $input.Name}}"`
4546
{{- end}}
4647
}{ {{- range $i, $input := $inputs}}{{if gt $i 0}}, {{end}}{{$input.Name}}{{end}}}
4748
{{- end}}
4849
{{- if $outputs | len}}
4950
{{- $outputVar = "&out"}}
5051
out := struct {
5152
{{- range $i, $output := .Outputs}}
52-
Ret{{$i}} {{template "type" dict "Type" $output.Type "Optional" $output.Optional "TypeMap" $typeMap}} `json:"{{firstLetterToLower $output.Name}}"`
53+
Ret{{$i}} {{template "type" dict "Type" $output.Type "Optional" $output.Optional "TypeMap" $typeMap "TypePrefix" $typePrefix}} `json:"{{firstLetterToLower $output.Name}}"`
5354
{{- end}}
5455
}{}
5556
{{- end}}

imports.go.tmpl

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{{- define "imports" -}}
2+
{{- $types := .Types -}}
3+
{{- $opts := .Opts -}}
4+
5+
{{- /* Map of import paths. */ -}}
6+
{{- $stdlibImports := dict -}}
7+
{{- set $stdlibImports "context" "" -}}
8+
{{- set $stdlibImports "errors" "" -}}
9+
{{- set $stdlibImports "encoding/json" "" -}}
10+
{{- set $stdlibImports "fmt" "" -}}
11+
{{- set $stdlibImports "io/ioutil" "" -}}
12+
{{- set $stdlibImports "net/http" "" -}}
13+
14+
{{- if $opts.client}}
15+
{{- set $stdlibImports "bytes" "" -}}
16+
{{- set $stdlibImports "io" "" -}}
17+
{{- set $stdlibImports "net/url" "" -}}
18+
{{- end -}}
19+
{{- if $opts.server}}
20+
{{- set $stdlibImports "strings" "" -}}
21+
{{- end -}}
22+
23+
{{- /* Import "time" if there's at least one timestamp. */ -}}
24+
{{ if eq $opts.importTypesFrom "" }}
25+
{{- range $_, $type := $types -}}
26+
{{- range $_, $field := $type.Fields -}}
27+
{{- if $field.Type -}}
28+
{{- if eq $field.Type.Expr "timestamp" -}}
29+
{{- set $stdlibImports "time" "" -}}
30+
{{- end -}}
31+
{{- end -}}
32+
{{- end -}}
33+
{{- end -}}
34+
{{- end -}}
35+
36+
{{- /* Print stdlib imports. */ -}}
37+
{{- range $import, $rename := $stdlibImports }}
38+
{{if ne $rename ""}}{{$rename}} {{end}}"{{$import}}"
39+
{{- end -}}
40+
41+
{{ if ne $opts.importTypesFrom "" }}
42+
43+
"{{ $opts.importTypesFrom }}"
44+
{{- else }}
45+
{{- /* Print custom type imports. */ -}}
46+
{{ $imports := dict }}
47+
{{ range $_, $type := $types -}}
48+
{{- range $_, $field := $type.Fields -}}
49+
{{- range $meta := $field.Meta -}}
50+
{{- if exists $meta "go.type.import" -}}
51+
{{- set $imports (get $meta "go.type.import") "" -}}
52+
{{- end -}}
53+
{{- end -}}
54+
{{- end -}}
55+
{{- end }}
56+
{{- range $import, $rename := $imports }}
57+
{{if ne $rename ""}}{{$rename}} {{end}}"{{$import}}"
58+
{{- end -}}
59+
{{- end }}
60+
61+
{{- end -}}

main.go.tmpl

+14-16
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@
55
{{- set $opts "pkg" (default .Opts.pkg "proto") -}}
66
{{- set $opts "client" (ternary (in .Opts.client "" "true") true false) -}}
77
{{- set $opts "server" (ternary (in .Opts.server "" "true") true false) -}}
8+
{{- set $opts "importTypesFrom" (default .Opts.importTypesFrom "" ) -}}
89
{{- set $opts "legacyErrors" (ternary (in .Opts.legacyErrors "true") true false) -}}
910

11+
{{- $typePrefix := (last (split "/" $opts.importTypesFrom)) -}}
12+
{{- if ne $typePrefix "" -}}
13+
{{- $typePrefix = (printf "%s." $typePrefix) -}}
14+
{{- end -}}
15+
1016
{{- /* Print help on -help. */ -}}
1117
{{- if exists .Opts "help" -}}
1218
{{- template "help" $opts -}}
@@ -33,7 +39,7 @@
3339
{{- end -}}
3440

3541
{{- /* Map webrpc core types to Go. */ -}}
36-
{{- $typeMap := dict }}
42+
{{- $typeMap := dict -}}
3743
{{- set $typeMap "null" "struct{}" -}}
3844
{{- set $typeMap "any" "interface{}" -}}
3945
{{- set $typeMap "byte" "byte" -}}
@@ -61,17 +67,7 @@
6167
package {{get $opts "pkg"}}
6268

6369
import (
64-
"bytes"
65-
"context"
66-
"errors"
67-
"encoding/json"
68-
"fmt"
69-
"io"
70-
"io/ioutil"
71-
"net/http"
72-
"net/url"
73-
"strings"
74-
"time"
70+
{{- template "imports" dict "Types" .Types "Opts" $opts }}
7571
)
7672

7773
// WebRPC description and code-gen version
@@ -89,19 +85,21 @@ func WebRPCSchemaHash() string {
8985
return "{{.SchemaHash}}"
9086
}
9187

92-
{{ template "types" dict "Services" .Services "Types" .Types "TypeMap" $typeMap }}
88+
{{ if eq $opts.importTypesFrom "" -}}
89+
{{ template "types" dict "Services" .Services "Types" .Types "TypeMap" $typeMap "TypePrefix" $typePrefix}}
90+
{{- end }}
9391

9492
{{- if $opts.server}}
95-
{{ template "server" dict "Services" .Services "TypeMap" $typeMap }}
93+
{{ template "server" dict "Services" .Services "TypeMap" $typeMap "TypePrefix" $typePrefix }}
9694
{{ end -}}
9795

9896
{{- if $opts.client }}
99-
{{ template "client" dict "Services" .Services "TypeMap" $typeMap }}
97+
{{ template "client" dict "Services" .Services "TypeMap" $typeMap "TypePrefix" $typePrefix }}
10098
{{ end -}}
10199

102100
{{ template "helpers" . }}
103101

104-
{{- template "errors" dict "WebrpcErrors" .WebrpcErrors "SchemaErrors" .Errors "Opts" $opts }}
102+
{{- template "errors" dict "WebrpcErrors" .WebrpcErrors "SchemaErrors" .Errors "Opts" $opts "TypePrefix" $typePrefix}}
105103

106104
{{- if $opts.legacyErrors }}
107105
{{ template "legacyErrors" . }}

server.go.tmpl

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{{define "server"}}
22
{{- $typeMap := .TypeMap -}}
3+
{{- $typePrefix := .TypePrefix -}}
34
{{- if .Services }}
45
//
56
// Server
@@ -14,10 +15,10 @@ type WebRPCServer interface {
1415
{{ $serviceName := (printf "%sServer" (.Name | firstLetterToLower)) }}
1516

1617
type {{$serviceName}} struct {
17-
{{.Name}}
18+
{{$typePrefix}}{{.Name}}
1819
}
1920

20-
func New{{ .Name | firstLetterToUpper }}Server(svc {{.Name}}) WebRPCServer {
21+
func New{{ .Name | firstLetterToUpper }}Server(svc {{$typePrefix}}{{.Name}}) WebRPCServer {
2122
return &{{$serviceName}}{
2223
{{.Name}}: svc,
2324
}
@@ -71,7 +72,7 @@ func (s *{{$serviceName}}) serve{{ .Name | firstLetterToUpper }}JSON(ctx context
7172
{{- if .Inputs|len}}
7273
reqContent := struct {
7374
{{- range $i, $input := .Inputs}}
74-
Arg{{$i}} {{template "type" dict "Type" $input.Type "Optional" $input.Optional "TypeMap" $typeMap}} `json:"{{firstLetterToLower $input.Name}}"`
75+
Arg{{$i}} {{template "type" dict "Type" $input.Type "Optional" $input.Optional "TypeMap" $typeMap "TypePrefix" $typePrefix}} `json:"{{firstLetterToLower $input.Name}}"`
7576
{{- end}}
7677
}{}
7778

@@ -93,7 +94,7 @@ func (s *{{$serviceName}}) serve{{ .Name | firstLetterToUpper }}JSON(ctx context
9394

9495
// Call service method
9596
{{- range $i, $output := .Outputs}}
96-
var ret{{$i}} {{template "type" dict "Type" $output.Type "Optional" $output.Optional "TypeMap" $typeMap}}
97+
var ret{{$i}} {{template "type" dict "Type" $output.Type "Optional" $output.Optional "TypeMap" $typeMap "TypePrefix" $typePrefix}}
9798
{{- end}}
9899
func() {
99100
defer func() {
@@ -108,7 +109,7 @@ func (s *{{$serviceName}}) serve{{ .Name | firstLetterToUpper }}JSON(ctx context
108109
{{- if .Outputs | len}}
109110
respContent := struct {
110111
{{- range $i, $output := .Outputs}}
111-
Ret{{$i}} {{template "type" dict "Type" $output.Type "Optional" $output.Optional "TypeMap" $typeMap}} `json:"{{firstLetterToLower $output.Name}}"`
112+
Ret{{$i}} {{template "type" dict "Type" $output.Type "Optional" $output.Optional "TypeMap" $typeMap "TypePrefix" $typePrefix}} `json:"{{firstLetterToLower $output.Name}}"`
112113
{{- end}}
113114
}{ {{- range $i, $_ := .Outputs}}{{if gt $i 0}}, {{end}}ret{{$i}}{{end}}}
114115
{{- end}}

struct.go.tmpl

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
{{- $name := .Name -}}
44
{{- $fields := .Fields -}}
55
{{- $typeMap := .TypeMap -}}
6+
{{- $typePrefix := .TypePrefix -}}
67

78
type {{$name}} struct {
89
{{- range $_, $field := $fields -}}
@@ -29,7 +30,7 @@ type {{$name}} struct {
2930
{{- end -}}
3031
{{- end -}}
3132
{{- end }}
32-
{{$fieldName}} {{template "type" dict "Type" $field.Type "CustomType" $customType "Optional" $field.Optional "TypeMap" $typeMap}} `{{$jsonTag}}{{if len $structTags}} {{end}}{{join (sort $structTags) " "}}`
33+
{{$fieldName}} {{template "type" dict "Type" $field.Type "CustomType" $customType "Optional" $field.Optional "TypeMap" $typeMap "TypePrefix" $typePrefix}} `{{$jsonTag}}{{if len $structTags}} {{end}}{{join (sort $structTags) " "}}`
3334
{{- end}}
3435
}
3536
{{- end }}

0 commit comments

Comments
 (0)