Skip to content

Commit ef864aa

Browse files
feat(cosmosgen,cosmosanalysis): generic query template (#4706)
* feat(cosmosgen,cosmosanalysis): generic quey template * up * updates * updates * updates * updates * Update changelog.md * updates * feat: ensure correct property types and casing in REST return types * add query fields + improve paginated * add tests * lint * remove uncessary goldens * add another type (not present in msg & queries) * add missing services, resolve typescript types, simplify template (but temporarily remove pagination) * updates * make queries tpl deterministic + support repeated * hardcode pagination * add todo for follow-up * use ordered map instead of map * chore: Showcase typing from ts-proto genereated types * re-gen tests --------- Co-authored-by: “Clockwork” <[email protected]>
1 parent 4f9e525 commit ef864aa

File tree

48 files changed

+12554
-346
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+12554
-346
lines changed

changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
- [#4717](https://github.com/ignite/cli/pull/4717) Bump Cosmos SDK to `v0.53.2`.
88
- [#4718](https://github.com/ignite/cli/pull/4718) Bump default Ignite Apps.
99

10+
### Fixes
11+
12+
- [#4691](https://github.com/ignite/cli/pull/4691), [#4706](https://github.com/ignite/cli/pull/4706) Fix ts-client query template and solely Go template for `ts-client` generation.
13+
1014
## [`v29.0.0`](https://github.com/ignite/cli/releases/tag/v29.0.0)
1115

1216
### Features

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ require (
2323
github.com/cosmos/gogoproto v1.7.0
2424
github.com/emicklei/proto v1.12.2
2525
github.com/emicklei/proto-contrib v0.15.0
26+
github.com/ettle/strcase v0.2.0
2627
github.com/getsentry/sentry-go v0.32.0
2728
github.com/go-delve/delve v1.24.0
2829
github.com/go-git/go-git/v5 v5.13.2
@@ -198,7 +199,6 @@ require (
198199
github.com/emicklei/dot v1.6.2 // indirect
199200
github.com/emirpasic/gods v1.18.1 // indirect
200201
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
201-
github.com/ettle/strcase v0.2.0 // indirect
202202
github.com/fatih/color v1.18.0 // indirect
203203
github.com/fatih/structs v1.1.0 // indirect
204204
github.com/fatih/structtag v1.2.0 // indirect

ignite/cmd/generate_typescript_client.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ changes when the blockchain is started with a flag:
3636
3737
ignite chain serve --generate-clients
3838
`,
39-
RunE: generateTSClientHandler,
40-
Hidden: true, // TODO(julienrbrt): remove this after https://github.com/ignite/cli/pull/4706.
39+
RunE: generateTSClientHandler,
4140
}
4241

4342
c.Flags().AddFlagSet(flagSetYes())

ignite/pkg/cosmosanalysis/module/module.go

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ type HTTPQuery struct {
5858
// Name of the RPC func.
5959
Name string `json:"name,omitempty"`
6060

61+
// ResponseType is the type of the response.
62+
ResponseType string `json:"response_type,omitempty"`
63+
6164
// FullName of the query with service name and rpc func name.
6265
FullName string `json:"full_name,omitempty"`
6366

@@ -66,6 +69,9 @@ type HTTPQuery struct {
6669

6770
// Paginated indicates that the query is using pagination.
6871
Paginated bool `json:"paginated,omitempty"`
72+
73+
// FilePath is the path of the .proto file where message is defined at.
74+
FilePath string `json:"file_path,omitempty"`
6975
}
7076

7177
// Type is a proto type that might be used by module.
@@ -84,9 +90,9 @@ type moduleDiscoverer struct {
8490
registeredModules []string
8591
}
8692

87-
// IsCosmosSDKModulePkg check if a Go import path is a Cosmos SDK package module.
88-
// These type of package have the "cosmossdk.io/x" prefix.
89-
func IsCosmosSDKModulePkg(path string) bool {
93+
// IsCosmosSDKPackage check if a Go import path is a Cosmos SDK package.
94+
// These type of package have the "cosmossdk.io/x" prefix or "github.com/cosmos/cosmos-sdk" prefix.
95+
func IsCosmosSDKPackage(path string) bool {
9096
return strings.Contains(path, "cosmossdk.io/x/") || strings.Contains(path, "github.com/cosmos/cosmos-sdk")
9197
}
9298

@@ -140,7 +146,7 @@ func Discover(ctx context.Context, chainRoot, sourcePath string, options ...Disc
140146
// SDK package because the module packages doesn't contain the proto files. These
141147
// files are only available from the Cosmos SDK package.
142148
var protoPath string
143-
if o.sdkDir != "" && IsCosmosSDKModulePkg(sourcePath) {
149+
if o.sdkDir != "" && IsCosmosSDKPackage(sourcePath) {
144150
protoPath = switchCosmosSDKPackagePath(sourcePath, o.sdkDir)
145151
} else {
146152
protoPath = filepath.Join(sourcePath, o.protoDir)
@@ -247,17 +253,6 @@ func (d *moduleDiscoverer) discover(pkg protoanalysis.Package) (Module, error) {
247253

248254
// fill types.
249255
for _, protomsg := range pkg.Messages {
250-
// Update pagination for RPC functions when a service response uses pagination
251-
if hasPagination(protomsg) {
252-
for _, s := range pkg.Services {
253-
for i, q := range s.RPCFuncs {
254-
if q.RequestType == protomsg.Name || q.ReturnsType == protomsg.Name {
255-
s.RPCFuncs[i].Paginated = true
256-
}
257-
}
258-
}
259-
}
260-
261256
if !isType(protomsg) {
262257
continue
263258
}
@@ -271,32 +266,44 @@ func (d *moduleDiscoverer) discover(pkg protoanalysis.Package) (Module, error) {
271266
// fill queries & messages.
272267
for _, s := range pkg.Services {
273268
for _, q := range s.RPCFuncs {
269+
pkgmsg, err := pkg.MessageByName(q.RequestType)
270+
if err != nil {
271+
// no msg found in the proto defs corresponds to discovered sdk message.
272+
// if it cannot be found, nothing to worry about, this means that it is used
273+
// only internally and not open for actual use.
274+
continue
275+
}
276+
274277
switch s.Name {
275278
case "Msg":
276-
pkgmsg, err := pkg.MessageByName(q.RequestType)
277-
if err != nil {
278-
// no msg found in the proto defs corresponds to discovered sdk message.
279-
// if it cannot be found, nothing to worry about, this means that it is used
280-
// only internally and not open for actual use.
281-
continue
282-
}
283279

284280
m.Msgs = append(m.Msgs, Msg{
285281
Name: q.RequestType,
286282
URI: fmt.Sprintf("%s.%s", pkg.Name, q.RequestType),
287283
FilePath: pkgmsg.Path,
288284
})
289-
case "Query":
285+
case "Query", "Service":
290286
// no http rules means this query is not exposed as a REST endpoint.
291287
if len(q.HTTPRules) == 0 {
292288
continue
293289
}
294290

291+
// check if the query is paginated.
292+
isPaginated := false
293+
for _, hr := range q.HTTPRules {
294+
if hr.IsPaginated() {
295+
isPaginated = true
296+
break
297+
}
298+
}
299+
295300
m.HTTPQueries = append(m.HTTPQueries, HTTPQuery{
296-
Name: q.Name,
297-
FullName: s.Name + q.Name,
298-
Rules: q.HTTPRules,
299-
Paginated: q.Paginated,
301+
Name: q.Name,
302+
FullName: s.Name + q.Name,
303+
Rules: q.HTTPRules,
304+
Paginated: isPaginated,
305+
FilePath: pkgmsg.Path,
306+
ResponseType: q.ReturnsType,
300307
})
301308
}
302309
}
@@ -399,19 +406,6 @@ func (d moduleDiscoverer) isPkgFromRegisteredModule(pkg protoanalysis.Package) (
399406
return false, nil
400407
}
401408

402-
func hasPagination(msg protoanalysis.Message) bool {
403-
for _, fieldType := range msg.Fields {
404-
// Message field type suffix check to match common pagination types:
405-
// cosmos.base.query.v1beta1.PageRequest
406-
// cosmos.base.query.v1beta1.PageResponse
407-
if strings.HasSuffix(fieldType, "PageRequest") || strings.HasSuffix(fieldType, "PageResponse") {
408-
return true
409-
}
410-
}
411-
412-
return false
413-
}
414-
415409
func switchCosmosSDKPackagePath(srcPath, sdkDir string) string {
416410
modName := xstrings.StringBetween(srcPath, "/x/", "@")
417411
if modName == "" {

ignite/pkg/cosmosanalysis/module/module_test.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,19 +114,23 @@ func newModule(relChainPath, goImportPath string) module.Module {
114114
ReturnsType: "QueryMyQueryResponse",
115115
HTTPRules: []protoanalysis.HTTPRule{
116116
{
117+
Endpoint: "/tendermint/mars/my_query/{mytypefield}",
117118
Params: []string{"mytypefield"},
118119
HasQuery: true,
119-
HasBody: false,
120+
QueryFields: map[string]string{
121+
"pagination": "cosmos.base.query.v1beta1.PageRequest",
122+
},
123+
HasBody: false,
120124
},
121125
},
122-
Paginated: true,
123126
},
124127
{
125128
Name: "Foo",
126129
RequestType: "QueryFooRequest",
127130
ReturnsType: "QueryFooResponse",
128131
HTTPRules: []protoanalysis.HTTPRule{
129132
{
133+
Endpoint: "/tendermint/mars/foo",
130134
HasQuery: false,
131135
HasBody: false,
132136
},
@@ -150,26 +154,35 @@ func newModule(relChainPath, goImportPath string) module.Module {
150154
},
151155
HTTPQueries: []module.HTTPQuery{
152156
{
153-
Name: "MyQuery",
154-
FullName: "QueryMyQuery",
157+
Name: "MyQuery",
158+
FullName: "QueryMyQuery",
159+
ResponseType: "QueryMyQueryResponse",
155160
Rules: []protoanalysis.HTTPRule{
156161
{
162+
Endpoint: "/tendermint/mars/my_query/{mytypefield}",
157163
Params: []string{"mytypefield"},
158164
HasQuery: true,
159-
HasBody: false,
165+
QueryFields: map[string]string{
166+
"pagination": "cosmos.base.query.v1beta1.PageRequest",
167+
},
168+
HasBody: false,
160169
},
161170
},
162171
Paginated: true,
172+
FilePath: filepath.Join(relChainPath, "proto/planet/mars/mars.proto"),
163173
},
164174
{
165-
Name: "Foo",
166-
FullName: "QueryFoo",
175+
Name: "Foo",
176+
FullName: "QueryFoo",
177+
ResponseType: "QueryFooResponse",
167178
Rules: []protoanalysis.HTTPRule{
168179
{
180+
Endpoint: "/tendermint/mars/foo",
169181
HasQuery: false,
170182
HasBody: false,
171183
},
172184
},
185+
FilePath: filepath.Join(relChainPath, "proto/planet/mars/mars.proto"),
173186
},
174187
},
175188
Types: []module.Type(nil),

ignite/pkg/cosmosanalysis/module/testdata/earth/proto/planet/mars/mars.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ service Query {
3232
}
3333

3434
rpc Foo(QueryFooRequest) returns (QueryFooResponse) {
35-
option (google.api.http).get = "/tendermint/mars/foo/";
35+
option (google.api.http).get = "/tendermint/mars/foo";
3636
}
3737
}
3838

ignite/pkg/cosmosanalysis/module/testdata/planet/app/app.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package app
22

33
import (
44
"github.com/cosmos/cosmos-sdk/baseapp"
5-
"github.com/cosmos/cosmos-sdk/types/module"
65
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
76
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
87
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
@@ -19,5 +18,3 @@ type Foo struct {
1918
GovKeeper govkeeper.Keeper
2019
MarsKeeper marskeeper.Keeper
2120
}
22-
23-
var ModuleBasics = module.NewBasicManager(mars.AppModuleBasic{})

ignite/pkg/cosmosanalysis/module/testdata/planet/proto/planet/mars/mars.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ service Query {
3232
}
3333

3434
rpc Foo(QueryFooRequest) returns (QueryFooResponse) {
35-
option (google.api.http).get = "/tendermint/mars/foo/";
35+
option (google.api.http).get = "/tendermint/mars/foo";
3636
}
3737
}
3838

ignite/pkg/cosmosgen/generate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ func (g *generator) resolveIncludes(ctx context.Context, path, protoDir string)
262262
// The "cosmossdk.io" module packages must use SDK's proto path which is
263263
// where all proto files for there type of Go package are.
264264
var protoPath string
265-
if module.IsCosmosSDKModulePkg(path) {
265+
if module.IsCosmosSDKPackage(path) {
266266
protoPath = filepath.Join(g.sdkDir, "proto")
267267
} else {
268268
// Check that the app/package proto directory exists

ignite/pkg/cosmosgen/generate_typescript.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ func (g *tsGenerator) generateModuleTemplate(
132132
// All "cosmossdk.io" module packages must use SDK's
133133
// proto path which is where the proto files are stored.
134134
protoPath := filepath.Join(appPath, g.g.protoDir) // use module app path
135-
if module.IsCosmosSDKModulePkg(appPath) {
135+
if module.IsCosmosSDKPackage(appPath) {
136136
protoPath = filepath.Join(g.g.sdkDir, "proto")
137137
}
138138

@@ -143,6 +143,7 @@ func (g *tsGenerator) generateModuleTemplate(
143143
typesOut,
144144
g.g.tsTemplate(),
145145
cosmosbuf.IncludeWKT(),
146+
// TODO: we should exclude folders that are irrelevant for the module.
146147
); err != nil {
147148
return err
148149
}
@@ -158,7 +159,7 @@ func (g *tsGenerator) generateModuleTemplate(
158159

159160
// Generate the rest API template (using axios)
160161
return templateTSClientRest.Write(out, protoPath, struct {
161-
Module module.Module
162+
module.Module
162163
}{
163164
Module: m,
164165
})

0 commit comments

Comments
 (0)