Skip to content

Commit 3fb0b15

Browse files
committed
enable js code generation for build & server
out dir can be configured via `build.proto.js.out`.
1 parent 93bf722 commit 3fb0b15

File tree

9 files changed

+279
-145
lines changed

9 files changed

+279
-145
lines changed

starport/chainconf/config.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,14 @@ var (
3636
"third_party/proto",
3737
"proto_vendor",
3838
},
39+
JS: ProtoJS{
40+
Out: "vue/generated",
41+
},
3942
},
4043
},
44+
Frontend: Frontend{
45+
Path: "vue",
46+
},
4147
Faucet: Faucet{
4248
Port: 4500,
4349
},
@@ -51,6 +57,7 @@ type Config struct {
5157
Validator Validator `yaml:"validator"`
5258
Faucet Faucet `yaml:"faucet"`
5359
Build Build `yaml:"build"`
60+
Frontend Frontend `yaml:"frontend"`
5461
Init Init `yaml:"init"`
5562
Genesis map[string]interface{} `yaml:"genesis"`
5663
Servers Servers `yaml:"servers"`
@@ -97,6 +104,21 @@ type Proto struct {
97104
// ThirdPartyPath is the relative path of where the third party proto files are
98105
// located that used by the app.
99106
ThirdPartyPaths []string `yaml:"third_party_paths"`
107+
108+
// JS holds JavaScript code generation configs.
109+
JS ProtoJS `yaml:"js"`
110+
}
111+
112+
// ProtoJS holds JavaScript code generation configs.
113+
type ProtoJS struct {
114+
// Out sets the destination path for generated JS code.
115+
Out string
116+
}
117+
118+
// Frontend holds front-end options.
119+
type Frontend struct {
120+
// Path is the relative source code path of app's frontend.
121+
Path string
100122
}
101123

102124
// Faucet configuration.

starport/pkg/cosmosprotoc/cosmosprotoc.go

Lines changed: 0 additions & 124 deletions
This file was deleted.
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
package cosmosprotoc
2+
3+
import (
4+
"context"
5+
"io/ioutil"
6+
"os"
7+
"path/filepath"
8+
9+
"github.com/otiai10/copy"
10+
"github.com/pkg/errors"
11+
"github.com/tendermint/starport/starport/pkg/cmdrunner"
12+
"github.com/tendermint/starport/starport/pkg/cmdrunner/step"
13+
"github.com/tendermint/starport/starport/pkg/gomodule"
14+
"github.com/tendermint/starport/starport/pkg/protobufjs"
15+
"github.com/tendermint/starport/starport/pkg/protoc"
16+
"github.com/tendermint/starport/starport/pkg/protopath"
17+
"golang.org/x/mod/modfile"
18+
)
19+
20+
var (
21+
protocOuts = []string{
22+
"--gocosmos_out=plugins=interfacetype+grpc,Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types:.",
23+
"--grpc-gateway_out=logtostderr=true:.",
24+
}
25+
26+
sdkImport = "github.com/cosmos/cosmos-sdk"
27+
sdkProto = "proto"
28+
sdkProtoThirdParty = "third_party/proto"
29+
30+
jsGeneratedProtoPath = "proto"
31+
)
32+
33+
type generateOptions struct {
34+
goEnabled bool
35+
gomodPath string
36+
jsEnabled bool
37+
jsOutPath string
38+
}
39+
40+
// Target adds a new code generation target to Generate.
41+
type Target func(*generateOptions)
42+
43+
// WithJSGeneration adds JS code generation.
44+
func WithJSGeneration(outPath string) Target {
45+
return func(o *generateOptions) {
46+
o.jsEnabled = true
47+
o.jsOutPath = outPath
48+
}
49+
}
50+
51+
// WithGoGeneration adds Go code generation.
52+
func WithGoGeneration(gomodPath string) Target {
53+
return func(o *generateOptions) {
54+
o.goEnabled = true
55+
o.gomodPath = gomodPath
56+
}
57+
}
58+
59+
// generator generates code for sdk and sdk apps.
60+
type generator struct {
61+
ctx context.Context
62+
projectPath string
63+
protoPath string
64+
includePaths []string
65+
o *generateOptions
66+
modfile *modfile.File
67+
}
68+
69+
// Generate generates code from proto app's proto files.
70+
// make sure that all paths are absolute.
71+
func Generate(
72+
ctx context.Context,
73+
projectPath,
74+
protoPath string,
75+
includePaths []string,
76+
target Target,
77+
otherTargets ...Target,
78+
) error {
79+
g := &generator{
80+
ctx: ctx,
81+
projectPath: projectPath,
82+
protoPath: protoPath,
83+
includePaths: includePaths,
84+
o: &generateOptions{},
85+
}
86+
87+
for _, target := range append(otherTargets, target) {
88+
target(g.o)
89+
}
90+
91+
if err := g.setup(); err != nil {
92+
return err
93+
}
94+
95+
if g.o.jsEnabled {
96+
if err := g.generateJS(); err != nil {
97+
return err
98+
}
99+
}
100+
101+
if g.o.goEnabled {
102+
if err := g.generateGo(); err != nil {
103+
return err
104+
}
105+
}
106+
107+
return nil
108+
}
109+
110+
func (g *generator) setup() (err error) {
111+
// Cosmos SDK hosts proto files of own x/ modules and some third party ones needed by itself and
112+
// blockchain apps. Generate should be aware of these and make them available to the blockchain
113+
// app that wants to generate code for its own proto.
114+
//
115+
// blockchain apps may use different versions of the SDK. following code first makes sure that
116+
// app's dependencies are download by 'go mod' and cached under the local filesystem.
117+
// and then, it determines which version of the SDK is used by the app and what is the absolute path
118+
// of its source code.
119+
if err := cmdrunner.
120+
New(cmdrunner.DefaultWorkdir(g.projectPath)).
121+
Run(g.ctx, step.New(step.Exec("go", "mod", "download"))); err != nil {
122+
return err
123+
}
124+
125+
// parse the go.mod of the app.
126+
g.modfile, err = gomodule.ParseAt(g.projectPath)
127+
128+
return
129+
}
130+
131+
func (g *generator) generateGo() error {
132+
includePaths, err := g.resolveInclude(protopath.NewModule(sdkImport, sdkProto, sdkProtoThirdParty))
133+
if err != nil {
134+
return err
135+
}
136+
137+
// created a temporary dir to locate generated code under which later only some of them will be moved to the
138+
// app's source code. this also prevents having leftover files in the app's source code or its parent dir -when
139+
// command executed directly there- in case of an interrupt.
140+
tmp, err := ioutil.TempDir("", "")
141+
if err != nil {
142+
return err
143+
}
144+
defer os.RemoveAll(tmp)
145+
146+
if err := protoc.Generate(g.ctx, tmp, g.protoPath, append(g.includePaths, includePaths...), protocOuts); err != nil {
147+
return err
148+
}
149+
150+
// move generated code for the app under the relative locations in its source code.
151+
generatedPath := filepath.Join(tmp, g.o.gomodPath)
152+
err = copy.Copy(generatedPath, g.projectPath)
153+
return errors.Wrap(err, "cannot copy path")
154+
}
155+
156+
func (g *generator) generateJS() error {
157+
includePaths, err := g.resolveInclude(protopath.NewModule(sdkImport, sdkProto))
158+
if err != nil {
159+
return err
160+
}
161+
162+
outPath := filepath.Join(g.o.jsOutPath, jsGeneratedProtoPath)
163+
return protobufjs.Generate(g.ctx, outPath, "types", g.protoPath, append(g.includePaths, includePaths...))
164+
}
165+
166+
func (g *generator) resolveInclude(modules ...protopath.Module) (paths []string, err error) {
167+
return protopath.ResolveDependencyPaths(g.modfile.Require, modules...)
168+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package cosmosprotoc
2+
3+
import (
4+
"bytes"
5+
"context"
6+
7+
"github.com/pkg/errors"
8+
"github.com/tendermint/starport/starport/pkg/cmdrunner"
9+
"github.com/tendermint/starport/starport/pkg/cmdrunner/step"
10+
"github.com/tendermint/starport/starport/pkg/xexec"
11+
)
12+
13+
// ErrProtocNotInstalled is returned when protoc isn't installed on the system.
14+
var ErrProtocNotInstalled = errors.New("protoc is not installed")
15+
16+
// InstallDependencies installs protoc dependencies needed by Cosmos ecosystem.
17+
func InstallDependencies(ctx context.Context, appPath string) error {
18+
if !xexec.IsCommandAvailable("protoc") {
19+
return ErrProtocNotInstalled
20+
}
21+
22+
errb := &bytes.Buffer{}
23+
err := cmdrunner.
24+
New(
25+
cmdrunner.DefaultStderr(errb),
26+
cmdrunner.DefaultWorkdir(appPath),
27+
).
28+
Run(ctx,
29+
// installs the gocosmos plugin with the version specified under the
30+
// go.mod of the app.
31+
step.New(
32+
step.Exec(
33+
"go",
34+
"get",
35+
"github.com/regen-network/cosmos-proto/protoc-gen-gocosmos@v0.3.1",
36+
),
37+
),
38+
// install grpc-gateway.
39+
step.New(
40+
step.Exec(
41+
"go",
42+
"get",
43+
"github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway@v1.16.0",
44+
"github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger@v1.16.0",
45+
"github.com/golang/protobuf/protoc-gen-go@v1.4.3",
46+
),
47+
),
48+
)
49+
return errors.Wrap(err, errb.String())
50+
}

0 commit comments

Comments
 (0)