From ab3f5c1e473598058a969c9419ede446da6bc83c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jer=C3=B3nimo=20Albi?= Date: Mon, 4 Dec 2023 14:29:27 +0100 Subject: [PATCH] fix: restore runtime app API registered module discovery (#3785) * fix: restore runtime app API registered modules * ci: fix lint issue with unused argument * tests: fix broken unit tests * ci: fix linting issue * feat: add support for IBC modules discovery This is a temporary feature that should be removed once IBC modules are injected inteas of being wired using the definitions from the scafolded app file `app/ibc.go`. * fix: correct issue that cause modules not to be discovered The removed snippet was not able to handle some Go import paths which were removed, like the IBC ones, also causing that the TS client generation was incomplete because of the missing modules. * feat(pkg/xstrings): add `StringBetween` function * fix: discover "cosmossdk.io/x" based packages proto files The "cosmossdk.io/x" Go packages MUST search proto files in the Cosmos SDK Go package because these packages don't have the proto files included so they can't be discovered. * feat(pkg/gocmd): add Go mod download support * feat(pkg/cosmosanalysis): add find module support * refactor(pkg/cosmosanalysis): change Cosmos SDK package path discovery Discovery changed to use go mod download instead of using Go's module path which might not be present in some context. * refactor: add filter function to remove duplicated modules * chore: TS template updates * fix: correct TS imports for generated "cosmossdk.io" module packages * tests: add unit tests for the new `pkg/gomodule` functions * refactor: add options to `pkg/cosmosanalysis` Discover function * fix: Update package.json template --------- Co-authored-by: Danilo Pantani Co-authored-by: Clockwork --- ignite/pkg/cosmosanalysis/app/app.go | 364 ++++++++++++++---- ignite/pkg/cosmosanalysis/app/app_test.go | 142 ++----- .../app/testdata/modules/app_config/go.mod | 30 ++ .../app/testdata/modules/crescent/app.go | 11 - .../app/testdata/modules/crescent/go.mod | 29 ++ .../app/testdata/modules/gaia/app.go | 12 - .../app/testdata/modules/gaia/go.mod | 28 ++ .../app/testdata/modules/juno/go.mod | 33 ++ .../app/testdata/modules/single_app/go.mod | 32 ++ .../app/testdata/modules/spn/go.mod | 343 +++++++++++++++++ ignite/pkg/cosmosanalysis/module/module.go | 34 +- .../pkg/cosmosanalysis/module/module_test.go | 4 +- ignite/pkg/cosmosanalysis/module/options.go | 22 ++ ignite/pkg/cosmosgen/cosmosgen.go | 1 + ignite/pkg/cosmosgen/generate.go | 83 ++-- ignite/pkg/cosmosgen/generate_typescript.go | 9 +- .../cosmosgen/templates/module/index.ts.tpl | 4 +- .../cosmosgen/templates/module/module.ts.tpl | 4 +- .../cosmosgen/templates/root/client.ts.tpl | 6 +- .../pkg/cosmosgen/templates/root/index.ts.tpl | 2 +- .../cosmosgen/templates/root/modules.ts.tpl | 4 +- .../cosmosgen/templates/root/package.json.tpl | 3 +- ignite/pkg/gocmd/gocmd.go | 12 + ignite/pkg/gomodule/gomodule.go | 119 ++++-- ignite/pkg/gomodule/gomodule_test.go | 97 +++++ ignite/pkg/gomodule/testdata/module/go.mod | 8 + ignite/pkg/xstrings/xstrings.go | 22 ++ ignite/pkg/xstrings/xstrings_test.go | 8 + 28 files changed, 1166 insertions(+), 300 deletions(-) create mode 100644 ignite/pkg/cosmosanalysis/app/testdata/modules/app_config/go.mod create mode 100644 ignite/pkg/cosmosanalysis/app/testdata/modules/crescent/go.mod create mode 100644 ignite/pkg/cosmosanalysis/app/testdata/modules/gaia/go.mod create mode 100644 ignite/pkg/cosmosanalysis/app/testdata/modules/juno/go.mod create mode 100644 ignite/pkg/cosmosanalysis/app/testdata/modules/single_app/go.mod create mode 100644 ignite/pkg/cosmosanalysis/app/testdata/modules/spn/go.mod create mode 100644 ignite/pkg/cosmosanalysis/module/options.go create mode 100644 ignite/pkg/gomodule/gomodule_test.go create mode 100644 ignite/pkg/gomodule/testdata/module/go.mod diff --git a/ignite/pkg/cosmosanalysis/app/app.go b/ignite/pkg/cosmosanalysis/app/app.go index 41f284e4e2..85e54ab098 100644 --- a/ignite/pkg/cosmosanalysis/app/app.go +++ b/ignite/pkg/cosmosanalysis/app/app.go @@ -1,19 +1,25 @@ package app import ( + "context" + "errors" "fmt" "go/ast" "go/parser" "go/token" + "os" "path/filepath" "strings" + "github.com/ignite/cli/ignite/pkg/cosmosanalysis" + "github.com/ignite/cli/ignite/pkg/cosmosver" "github.com/ignite/cli/ignite/pkg/goanalysis" + "github.com/ignite/cli/ignite/pkg/gomodule" "github.com/ignite/cli/ignite/pkg/xast" - - "github.com/ignite/cli/ignite/pkg/cosmosanalysis" ) +const registerRoutesMethod = "RegisterAPIRoutes" + // CheckKeeper checks for the existence of the keeper with the provided name in the app structure. func CheckKeeper(path, keeperName string) error { // find app type @@ -84,58 +90,37 @@ func FindRegisteredModules(chainRoot string) ([]string, error) { return nil, err } - // Loop on package's files - var blankImports []string + // Search the app for the imported SDK modules var discovered []string for _, f := range appPkg.Files { - blankImports = append(blankImports, goanalysis.FindBlankImports(f)...) + discovered = append(discovered, goanalysis.FindBlankImports(f)...) fileImports := goanalysis.FormatImports(f) - d, err := FindKeepersModules(f, fileImports) + d, err := DiscoverModules(f, chainRoot, fileImports) if err != nil { return nil, err } discovered = append(discovered, d...) } - return mergeImports(blankImports, discovered), nil -} -// mergeImports merge all discovered imports into the blank imports found in the app files. -func mergeImports(blankImports, discovered []string) []string { - imports := make([]string, len(blankImports)) - copy(imports, blankImports) - for i, m := range discovered { - split := strings.Split(m, "/") - - j := len(split) - maxTrim := len(split) - 3 - LoopBack: - for j > maxTrim { - j-- - // x path means we are reaching the root of the module - if split[j] == "x" { - j = maxTrim - goto LoopBack - } - for _, imp := range blankImports { - // check if the import exist into the blank imports - if strings.Contains(imp, m) { - j = -1 - goto LoopBack - } - } - m = strings.TrimSuffix(m, "/"+split[j]) - } - if j == maxTrim { - imports = append(imports, discovered[i]) + // Discover IBC wired modules + // TODO: This can be removed once IBC modules use dependency injection + ibcPath := filepath.Join(chainRoot, "app", "ibc.go") + if _, err := os.Stat(ibcPath); err == nil { + m, err := discoverIBCModules(ibcPath) + if err != nil { + return nil, err } + + discovered = append(discovered, m...) } - return imports + + return removeDuplicateEntries(discovered), nil } -// FindKeepersModules find a map of import modules based on the keepers params on the App struct. -func FindKeepersModules(n ast.Node, fileImports map[string]string) ([]string, error) { +// DiscoverModules find a map of import modules based on the configured app. +func DiscoverModules(file *ast.File, chainRoot string, fileImports map[string]string) ([]string, error) { // find app type - appImpl := cosmosanalysis.FindImplementationInFile(n, cosmosanalysis.AppImplementation) + appImpl := cosmosanalysis.FindImplementationInFile(file, cosmosanalysis.AppImplementation) appTypeName := "App" switch { case len(appImpl) > 1: @@ -144,63 +129,245 @@ func FindKeepersModules(n ast.Node, fileImports map[string]string) ([]string, er appTypeName = appImpl[0] } - file, ok := n.(*ast.File) - if !ok { - return nil, nil + var discovered []string + for _, decl := range file.Decls { + switch x := decl.(type) { + case *ast.GenDecl: + discovered = append(discovered, discoverKeeperModules(x, appTypeName, fileImports)...) + case *ast.FuncDecl: + // The modules registered by Cosmos SDK `rumtime.App` are included + // when the app registers API modules though the `App` instance. + if isRuntimeAppCalled(x) { + m, err := discoverRuntimeAppModules(chainRoot) + if err != nil { + return nil, err + } + discovered = append(discovered, m...) + } + } } + return removeDuplicateEntries(discovered), nil +} - keeperParamsMap := make(map[string]struct{}) - for _, decl := range file.Decls { - genDecl, ok := decl.(*ast.GenDecl) +func removeDuplicateEntries(entries []string) (res []string) { + seen := make(map[string]struct{}) + for _, e := range entries { + if _, ok := seen[e]; ok { + continue + } + + seen[e] = struct{}{} + res = append(res, e) + } + return +} + +func discoverKeeperModules(d *ast.GenDecl, appTypeName string, imports map[string]string) []string { + var modules []string + for _, spec := range d.Specs { + typeSpec, ok := spec.(*ast.TypeSpec) if !ok { continue } - for _, spec := range genDecl.Specs { - typeSpec, ok := spec.(*ast.TypeSpec) - if !ok { + if typeSpec.Name.Name != appTypeName { + continue + } + structType, ok := typeSpec.Type.(*ast.StructType) + if !ok { + continue + } + for _, field := range structType.Fields.List { + f := field.Type + CheckSpec: + switch spec := f.(type) { + case *ast.StarExpr: + f, ok = spec.X.(*ast.SelectorExpr) + if !ok { + continue + } + goto CheckSpec + case *ast.SelectorExpr: + if !strings.HasSuffix(spec.Sel.Name, "Keeper") { + continue + } + ident, ok := spec.X.(*ast.Ident) + if !ok { + continue + } + fileImport, ok := imports[ident.Name] + if !ok { + continue + } + modules = append(modules, removeKeeperPkgPath(fileImport)) + } + } + } + return modules +} + +func discoverRuntimeAppModules(chainRoot string) ([]string, error) { + // Resolve the absolute path to the Cosmos SDK module + cosmosPath, err := resolveCosmosPackagePath(chainRoot) + if err != nil { + return nil, err + } + + var modules []string + + // When runtime package doesn't exists it means is an older Cosmos SDK version, + // so all the module API registrations are defined within user's app. + path := filepath.Join(cosmosPath, "runtime", "app.go") + if _, err := os.Stat(path); os.IsNotExist(err) { + return modules, nil + } + + f, _, err := xast.ParseFile(path) + if err != nil { + return nil, err + } + + imports := goanalysis.FormatImports(f) + err = xast.Inspect(f, func(n ast.Node) error { + if pkgs := findRegisterAPIRoutesRegistrations(n); pkgs != nil { + for _, p := range pkgs { + if m := imports[p]; m != "" { + modules = append(modules, m) + } + } + return xast.ErrStop + } + return nil + }) + + if err != nil { + return nil, err + } + return modules, nil +} + +func discoverIBCModules(ibcPath string) ([]string, error) { + f, _, err := xast.ParseFile(ibcPath) + if err != nil { + return nil, err + } + + var ( + names []string + imports = goanalysis.FormatImports(f) + ) + err = xast.Inspect(f, func(n ast.Node) error { + fn, _ := n.(*ast.FuncDecl) + if fn == nil { + return nil + } + + if fn.Name.Name != "AddIBCModuleManager" { + return nil + } + + for _, stmt := range fn.Body.List { + x, _ := stmt.(*ast.AssignStmt) + if x == nil { continue } - if typeSpec.Name.Name != appTypeName { + + if len(x.Rhs) == 0 { continue } - structType, ok := typeSpec.Type.(*ast.StructType) - if !ok { + + c, _ := x.Rhs[0].(*ast.CompositeLit) + if c == nil { continue } - for _, field := range structType.Fields.List { - f := field.Type - CheckSpec: - switch spec := f.(type) { - case *ast.StarExpr: - f, ok = spec.X.(*ast.SelectorExpr) - if !ok { - continue - } - goto CheckSpec - case *ast.SelectorExpr: - if !strings.HasSuffix(spec.Sel.Name, "Keeper") { - continue - } - ident, ok := spec.X.(*ast.Ident) - if !ok { - continue - } - fileImport, ok := fileImports[ident.Name] - if !ok { - continue - } - keeperParamsMap[removeKeeperPkgPath(fileImport)] = struct{}{} - } + + s, _ := c.Type.(*ast.SelectorExpr) + if s == nil || s.Sel.Name != "AppModule" { + continue } + + if m, _ := s.X.(*ast.Ident); m != nil { + names = append(names, m.Name) + } + } + + return xast.ErrStop + }) + if err != nil { + return nil, err + } + + var modules []string + for _, n := range names { + modules = append(modules, imports[n]) + } + return modules, nil +} + +func resolveCosmosPackagePath(chainRoot string) (string, error) { + modFile, err := gomodule.ParseAt(chainRoot) + if err != nil { + return "", err + } + + deps, err := gomodule.ResolveDependencies(modFile, false) + if err != nil { + return "", err + } + + var pkg string + for _, dep := range deps { + if dep.Path == cosmosver.CosmosModulePath { + pkg = dep.String() + break } } - keeperParams := make([]string, 0) - for param := range keeperParamsMap { - keeperParams = append(keeperParams, param) + if pkg == "" { + return "", errors.New("cosmos SDK package version not found") + } + + m, err := gomodule.FindModule(context.Background(), chainRoot, pkg) + if err != nil { + return "", err } + return m.Dir, nil +} - return keeperParams, nil +func findRegisterAPIRoutesRegistrations(n ast.Node) []string { + funcLitType, ok := n.(*ast.FuncDecl) + if !ok { + return nil + } + + if funcLitType.Name.Name != registerRoutesMethod { + return nil + } + + var packagesRegistered []string + for _, stmt := range funcLitType.Body.List { + exprStmt, ok := stmt.(*ast.ExprStmt) + if !ok { + continue + } + exprCall, ok := exprStmt.X.(*ast.CallExpr) + if !ok { + continue + } + exprFun, ok := exprCall.Fun.(*ast.SelectorExpr) + if !ok || exprFun.Sel.Name != "RegisterGRPCGatewayRoutes" { + continue + } + identType, ok := exprFun.X.(*ast.Ident) + if !ok { + continue + } + pkgName := identType.Name + if pkgName == "" { + continue + } + packagesRegistered = append(packagesRegistered, identType.Name) + } + return packagesRegistered } func removeKeeperPkgPath(pkg string) string { @@ -208,3 +375,40 @@ func removeKeeperPkgPath(pkg string) string { path = strings.TrimSuffix(path, "/controller") return strings.TrimSuffix(path, "/host") } + +func isRuntimeAppCalled(fn *ast.FuncDecl) bool { + if fn.Name.Name != registerRoutesMethod { + return false + } + + for _, stmt := range fn.Body.List { + exprStmt, ok := stmt.(*ast.ExprStmt) + if !ok { + continue + } + + exprCall, ok := exprStmt.X.(*ast.CallExpr) + if !ok { + continue + } + + exprFun, ok := exprCall.Fun.(*ast.SelectorExpr) + if !ok || exprFun.Sel.Name != registerRoutesMethod { + continue + } + + exprSel, ok := exprFun.X.(*ast.SelectorExpr) + if !ok || exprSel.Sel.Name != "App" { + continue + } + + identType, ok := exprSel.X.(*ast.Ident) + if !ok || identType.Name != "app" { + continue + } + + return true + } + + return false +} diff --git a/ignite/pkg/cosmosanalysis/app/app_test.go b/ignite/pkg/cosmosanalysis/app/app_test.go index 35545e3959..be4cf1aeb7 100644 --- a/ignite/pkg/cosmosanalysis/app/app_test.go +++ b/ignite/pkg/cosmosanalysis/app/app_test.go @@ -85,6 +85,9 @@ func TestFindRegisteredModules(t *testing.T) { "github.com/cosmos/cosmos-sdk/x/staking", "github.com/cosmos/cosmos-sdk/x/gov", "github.com/username/test/x/foo", + "github.com/cosmos/cosmos-sdk/x/auth/tx", + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice", + "github.com/cosmos/cosmos-sdk/client/grpc/node", } cases := []struct { @@ -110,6 +113,8 @@ func TestFindRegisteredModules(t *testing.T) { "cosmossdk.io/x/evidence", "cosmossdk.io/x/feegrant/module", "cosmossdk.io/x/upgrade", + "github.com/cosmos/cosmos-sdk/x/auth", + "github.com/cosmos/cosmos-sdk/x/auth/tx", "github.com/cosmos/cosmos-sdk/x/auth/tx/config", "github.com/cosmos/cosmos-sdk/x/auth/vesting", "github.com/cosmos/cosmos-sdk/x/authz/module", @@ -125,6 +130,8 @@ func TestFindRegisteredModules(t *testing.T) { "github.com/ignite/mars/x/mars", "github.com/cosmos/cosmos-sdk/x/gov", "github.com/username/test/x/foo", + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice", + "github.com/cosmos/cosmos-sdk/client/grpc/node", }, }, { @@ -191,6 +198,9 @@ func TestFindRegisteredModules(t *testing.T) { path: "testdata/modules/spn", expectedModules: []string{ "github.com/cosmos/cosmos-sdk/x/auth", + "github.com/cosmos/cosmos-sdk/x/auth/tx", + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice", + "github.com/cosmos/cosmos-sdk/client/grpc/node", "github.com/cosmos/cosmos-sdk/x/bank", "github.com/cosmos/cosmos-sdk/x/capability", "github.com/cosmos/cosmos-sdk/x/staking", @@ -239,6 +249,9 @@ func TestFindRegisteredModules(t *testing.T) { "github.com/cosmos/cosmos-sdk/x/authz", "github.com/CosmWasm/wasmd/x/wasm", "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts", + "github.com/cosmos/cosmos-sdk/x/auth/tx", + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice", + "github.com/cosmos/cosmos-sdk/client/grpc/node", }, }, } @@ -252,13 +265,16 @@ func TestFindRegisteredModules(t *testing.T) { } } -func TestFindKeepersModules(t *testing.T) { +func TestDiscoverModules(t *testing.T) { basicModules := []string{ "github.com/cosmos/cosmos-sdk/x/auth", "github.com/cosmos/cosmos-sdk/x/bank", "github.com/cosmos/cosmos-sdk/x/staking", "github.com/cosmos/cosmos-sdk/x/gov", "github.com/username/test/x/foo", + "github.com/cosmos/cosmos-sdk/x/auth/tx", + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice", + "github.com/cosmos/cosmos-sdk/client/grpc/node", } cases := []struct { @@ -343,6 +359,9 @@ func TestFindKeepersModules(t *testing.T) { path: "testdata/modules/spn", expectedModules: []string{ "github.com/cosmos/cosmos-sdk/x/auth", + "github.com/cosmos/cosmos-sdk/x/auth/tx", + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice", + "github.com/cosmos/cosmos-sdk/client/grpc/node", "github.com/cosmos/cosmos-sdk/x/bank", "github.com/cosmos/cosmos-sdk/x/capability", "github.com/cosmos/cosmos-sdk/x/staking", @@ -391,6 +410,9 @@ func TestFindKeepersModules(t *testing.T) { "github.com/cosmos/cosmos-sdk/x/authz", "github.com/CosmWasm/wasmd/x/wasm", "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts", + "github.com/cosmos/cosmos-sdk/x/auth/tx", + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice", + "github.com/cosmos/cosmos-sdk/client/grpc/node", }, }, } @@ -403,7 +425,7 @@ func TestFindKeepersModules(t *testing.T) { got := make([]string, 0) for _, f := range appPkg.Files { fileImports := goanalysis.FormatImports(f) - modules, err := FindKeepersModules(f, fileImports) + modules, err := DiscoverModules(f, tt.path, fileImports) require.NoError(t, err) if modules != nil { got = append(got, modules...) @@ -414,122 +436,6 @@ func TestFindKeepersModules(t *testing.T) { } } -func Test_mergeImports(t *testing.T) { - tests := []struct { - name string - blankImports []string - discovered []string - want []string - }{ - { - name: "test nil imports", - blankImports: nil, - discovered: nil, - want: nil, - }, - { - name: "test empty imports", - blankImports: []string{}, - discovered: []string{}, - want: []string{}, - }, - { - name: "test only one blank import", - blankImports: []string{"github.com/cosmos/cosmos-sdk/x/auth"}, - discovered: []string{}, - want: []string{"github.com/cosmos/cosmos-sdk/x/auth"}, - }, - { - name: "test only one discovered import", - blankImports: []string{}, - discovered: []string{"github.com/cosmos/cosmos-sdk/x/auth"}, - want: []string{"github.com/cosmos/cosmos-sdk/x/auth"}, - }, - { - name: "test only one import", - blankImports: []string{"github.com/cosmos/cosmos-sdk/x/auth"}, - discovered: []string{"github.com/cosmos/cosmos-sdk/x/auth/keeper"}, - want: []string{"github.com/cosmos/cosmos-sdk/x/auth"}, - }, - { - name: "test only one keeper import", - blankImports: []string{"github.com/cosmos/cosmos-sdk/x/auth/module"}, - discovered: []string{"github.com/cosmos/cosmos-sdk/x/auth/keeper"}, - want: []string{"github.com/cosmos/cosmos-sdk/x/auth/module"}, - }, - { - name: "test two keeper import", - blankImports: []string{ - "github.com/cosmos/cosmos-sdk/x/auth/module", - "github.com/cosmos/cosmos-sdk/x/bank/module", - }, - discovered: []string{ - "github.com/cosmos/cosmos-sdk/x/auth/keeper", - "github.com/cosmos/cosmos-sdk/x/bank/keeper", - }, - want: []string{ - "github.com/cosmos/cosmos-sdk/x/auth/module", - "github.com/cosmos/cosmos-sdk/x/bank/module", - }, - }, - { - name: "test two keeper import", - blankImports: []string{ - "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts", - }, - discovered: []string{ - "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/keeper", - "github.com/cosmos/cosmos-sdk/x/bank/keeper", - }, - want: []string{ - "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts", - "github.com/cosmos/cosmos-sdk/x/bank/keeper", - }, - }, - { - name: "test keeper imports", - blankImports: []string{ - "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts", - "cosmossdk.io/x/feegrant/module", - }, - discovered: []string{ - "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/keeper", - "github.com/cosmos/cosmos-sdk/x/bank/keeper", - "cosmossdk.io/x/feegrant/types", - "cosmossdk.io/x/feegrant", - "cosmossdk.io/x/foo", - }, - want: []string{ - "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts", - "github.com/cosmos/cosmos-sdk/x/bank/keeper", - "cosmossdk.io/x/feegrant/module", - "cosmossdk.io/x/foo", - }, - }, - { - name: "test three keeper import", - blankImports: []string{ - "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts", - "github.com/cosmos/ibc-go/modules/capability", - }, - discovered: []string{ - "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts", - "github.com/cosmos/ibc-go/modules/capability", - }, - want: []string{ - "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts", - "github.com/cosmos/ibc-go/modules/capability", - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := mergeImports(tt.blankImports, tt.discovered) - require.ElementsMatch(t, tt.want, got) - }) - } -} - func Test_removeKeeperPkgPath(t *testing.T) { tests := []struct { name string diff --git a/ignite/pkg/cosmosanalysis/app/testdata/modules/app_config/go.mod b/ignite/pkg/cosmosanalysis/app/testdata/modules/app_config/go.mod new file mode 100644 index 0000000000..c740bc6ccb --- /dev/null +++ b/ignite/pkg/cosmosanalysis/app/testdata/modules/app_config/go.mod @@ -0,0 +1,30 @@ +module app + +go 1.20 + +require ( + cosmossdk.io/api v0.3.1 + cosmossdk.io/core v0.5.1 + cosmossdk.io/depinject v1.0.0-alpha.3 + cosmossdk.io/errors v1.0.0-beta.7 + cosmossdk.io/math v1.0.1 + github.com/bufbuild/buf v1.23.1 + github.com/cometbft/cometbft v0.37.2 + github.com/cometbft/cometbft-db v0.8.0 + github.com/cosmos/cosmos-proto v1.0.0-beta.2 + github.com/cosmos/cosmos-sdk v0.47.3 + github.com/cosmos/gogoproto v1.4.10 + github.com/cosmos/ibc-go/v7 v7.2.0 + github.com/golang/protobuf v1.5.3 + github.com/gorilla/mux v1.8.0 + github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 + github.com/spf13/cast v1.5.1 + github.com/spf13/cobra v1.7.0 + github.com/spf13/pflag v1.0.5 + github.com/stretchr/testify v1.8.4 + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 + google.golang.org/grpc v1.55.0 + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 + google.golang.org/protobuf v1.31.0 +) diff --git a/ignite/pkg/cosmosanalysis/app/testdata/modules/crescent/app.go b/ignite/pkg/cosmosanalysis/app/testdata/modules/crescent/app.go index 17455318e7..a01d492c2a 100644 --- a/ignite/pkg/cosmosanalysis/app/testdata/modules/crescent/app.go +++ b/ignite/pkg/cosmosanalysis/app/testdata/modules/crescent/app.go @@ -11,7 +11,6 @@ import ( "path/filepath" storetypes "cosmossdk.io/store/types" - "github.com/cosmos/cosmos-sdk/server" "cosmossdk.io/client/v2/autocli" "github.com/gorilla/mux" @@ -1031,13 +1030,3 @@ func (App) GetSubspace(moduleName string) paramstypes.Subspace { func (App) SimulationManager() *module.SimulationManager { return app.sm } - -// RegisterAPIRoutes registers all application module routes with the provided -// API server. -func (App) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) { - app.App.RegisterAPIRoutes(apiSvr, apiConfig) - // register swagger API in app.go so that other applications can override easily - if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil { - panic(err) - } -} diff --git a/ignite/pkg/cosmosanalysis/app/testdata/modules/crescent/go.mod b/ignite/pkg/cosmosanalysis/app/testdata/modules/crescent/go.mod new file mode 100644 index 0000000000..d0b47f88a3 --- /dev/null +++ b/ignite/pkg/cosmosanalysis/app/testdata/modules/crescent/go.mod @@ -0,0 +1,29 @@ +module github.com/crescent-network/crescent/v5 + +go 1.18 + +require ( + github.com/cosmos/cosmos-sdk v0.45.10 + github.com/cosmos/ibc-go/v3 v3.4.0 + github.com/gogo/protobuf v1.3.3 + github.com/golang/mock v1.6.0 + github.com/golang/protobuf v1.5.2 + github.com/golangci/golangci-lint v1.50.1 + github.com/gorilla/mux v1.8.0 + github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.13.0 + github.com/rakyll/statik v0.1.7 + github.com/regen-network/cosmos-proto v0.3.1 + github.com/spf13/cast v1.5.0 + github.com/spf13/cobra v1.6.0 + github.com/spf13/pflag v1.0.5 + github.com/stretchr/testify v1.8.0 + github.com/tendermint/tendermint v0.34.22 + github.com/tendermint/tm-db v0.6.7 + golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e + google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c + google.golang.org/grpc v1.50.1 + google.golang.org/protobuf v1.28.1 + gopkg.in/yaml.v2 v2.4.0 +) + diff --git a/ignite/pkg/cosmosanalysis/app/testdata/modules/gaia/app.go b/ignite/pkg/cosmosanalysis/app/testdata/modules/gaia/app.go index 27ee658340..e9c475528d 100644 --- a/ignite/pkg/cosmosanalysis/app/testdata/modules/gaia/app.go +++ b/ignite/pkg/cosmosanalysis/app/testdata/modules/gaia/app.go @@ -8,8 +8,6 @@ import ( "os" "path/filepath" - "github.com/cosmos/cosmos-sdk/server" - "cosmossdk.io/client/v2/autocli" sdkerrors "cosmossdk.io/errors" "github.com/cosmos/cosmos-sdk/baseapp" @@ -1096,13 +1094,3 @@ func (GaiaApp) GetSubspace(moduleName string) paramstypes.Subspace { func (GaiaApp) SimulationManager() *module.SimulationManager { return app.sm } - -// RegisterAPIRoutes registers all application module routes with the provided -// API server. -func (GaiaApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) { - app.App.RegisterAPIRoutes(apiSvr, apiConfig) - // register swagger API in app.go so that other applications can override easily - if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil { - panic(err) - } -} diff --git a/ignite/pkg/cosmosanalysis/app/testdata/modules/gaia/go.mod b/ignite/pkg/cosmosanalysis/app/testdata/modules/gaia/go.mod new file mode 100644 index 0000000000..0851601f21 --- /dev/null +++ b/ignite/pkg/cosmosanalysis/app/testdata/modules/gaia/go.mod @@ -0,0 +1,28 @@ +module github.com/cosmos/gaia/v14 + +go 1.20 + +require ( + cosmossdk.io/errors v1.0.0 + cosmossdk.io/math v1.2.0 + github.com/cosmos/cosmos-sdk v0.45.16 + github.com/cosmos/go-bip39 v1.0.0 + github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v4 v4.1.1 + github.com/cosmos/ibc-go/v4 v4.4.2 + github.com/cosmos/interchain-security/v2 v2.0.0 + github.com/gogo/protobuf v1.3.3 + github.com/golang/protobuf v1.5.3 + github.com/google/gofuzz v1.2.0 + github.com/gorilla/mux v1.8.1 + github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/ory/dockertest/v3 v3.10.0 + github.com/rakyll/statik v0.1.7 + github.com/spf13/cast v1.5.1 + github.com/spf13/cobra v1.8.0 + github.com/spf13/viper v1.17.0 + github.com/stretchr/testify v1.8.4 + github.com/tendermint/tendermint v0.34.27 + github.com/tendermint/tm-db v0.6.7 + google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb + google.golang.org/grpc v1.58.2 +) diff --git a/ignite/pkg/cosmosanalysis/app/testdata/modules/juno/go.mod b/ignite/pkg/cosmosanalysis/app/testdata/modules/juno/go.mod new file mode 100644 index 0000000000..c3c0312603 --- /dev/null +++ b/ignite/pkg/cosmosanalysis/app/testdata/modules/juno/go.mod @@ -0,0 +1,33 @@ +module github.com/CosmosContracts/juno/v18 + +go 1.21 + +require ( + cosmossdk.io/api v0.3.1 + cosmossdk.io/errors v1.0.0 + cosmossdk.io/log v1.2.1 + cosmossdk.io/math v1.1.2 + cosmossdk.io/tools/rosetta v0.2.1 + github.com/CosmWasm/wasmd v0.45.0 + github.com/CosmWasm/wasmvm v1.5.0 + github.com/cometbft/cometbft v0.37.2 + github.com/cometbft/cometbft-db v0.8.0 + github.com/cosmos/cosmos-sdk v0.47.5 + github.com/cosmos/gogoproto v1.4.10 + github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.0.1 + github.com/cosmos/ibc-apps/modules/async-icq/v7 v7.0.0 + github.com/cosmos/ibc-apps/modules/ibc-hooks/v7 v7.0.0-20230803181732-7c8f814d3b79 + github.com/cosmos/ibc-go/v7 v7.3.1 + github.com/golang/protobuf v1.5.3 + github.com/gorilla/mux v1.8.0 + github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/prometheus/client_golang v1.16.0 + github.com/skip-mev/pob v1.0.4 + github.com/spf13/cast v1.5.1 + github.com/spf13/cobra v1.7.0 + github.com/spf13/viper v1.16.0 + github.com/stretchr/testify v1.8.4 + google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 + google.golang.org/grpc v1.58.3 + gopkg.in/yaml.v2 v2.4.0 +) diff --git a/ignite/pkg/cosmosanalysis/app/testdata/modules/single_app/go.mod b/ignite/pkg/cosmosanalysis/app/testdata/modules/single_app/go.mod new file mode 100644 index 0000000000..5db6c247a4 --- /dev/null +++ b/ignite/pkg/cosmosanalysis/app/testdata/modules/single_app/go.mod @@ -0,0 +1,32 @@ +module app + +go 1.20 + +require ( + cosmossdk.io/api v0.3.1 + cosmossdk.io/core v0.5.1 + cosmossdk.io/depinject v1.0.0-alpha.3 + cosmossdk.io/errors v1.0.0-beta.7 + cosmossdk.io/math v1.0.1 + github.com/bufbuild/buf v1.23.1 + github.com/cometbft/cometbft v0.37.2 + github.com/cometbft/cometbft-db v0.8.0 + github.com/cosmos/cosmos-proto v1.0.0-beta.2 + github.com/cosmos/cosmos-sdk v0.47.3 + github.com/cosmos/gogoproto v1.4.10 + github.com/cosmos/ibc-go/v7 v7.2.0 + github.com/golang/protobuf v1.5.3 + github.com/gorilla/mux v1.8.0 + github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 + github.com/spf13/cast v1.5.1 + github.com/spf13/cobra v1.7.0 + github.com/spf13/pflag v1.0.5 + github.com/stretchr/testify v1.8.4 + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 + google.golang.org/grpc v1.55.0 + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 + google.golang.org/protobuf v1.31.0 +) + + diff --git a/ignite/pkg/cosmosanalysis/app/testdata/modules/spn/go.mod b/ignite/pkg/cosmosanalysis/app/testdata/modules/spn/go.mod new file mode 100644 index 0000000000..39414c01ea --- /dev/null +++ b/ignite/pkg/cosmosanalysis/app/testdata/modules/spn/go.mod @@ -0,0 +1,343 @@ +module github.com/tendermint/spn + +go 1.19 + +require ( + cosmossdk.io/api v0.3.1 + cosmossdk.io/errors v1.0.0-beta.7 + cosmossdk.io/math v1.0.1 + github.com/aws/smithy-go v1.8.0 + github.com/bufbuild/buf v1.22.0 + github.com/cometbft/cometbft v0.37.2 + github.com/cometbft/cometbft-db v0.8.0 + github.com/cosmos/cosmos-proto v1.0.0-beta.2 + github.com/cosmos/cosmos-sdk v0.47.3 + github.com/cosmos/gogoproto v1.4.10 + github.com/cosmos/ibc-go/v7 v7.2.0 + github.com/gogo/protobuf v1.3.2 + github.com/golang/protobuf v1.5.3 + github.com/golangci/golangci-lint v1.50.1 + github.com/gorilla/mux v1.8.0 + github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 + github.com/ignite/modules v0.0.2 + github.com/pkg/errors v0.9.1 + github.com/spf13/cast v1.5.1 + github.com/spf13/cobra v1.7.0 + github.com/spf13/pflag v1.0.5 + github.com/stretchr/testify v1.8.4 + github.com/tendermint/fundraising v0.4.1 + golang.org/x/tools v0.10.0 + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 + google.golang.org/grpc v1.55.0 + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 + google.golang.org/protobuf v1.31.0 + gopkg.in/yaml.v2 v2.4.0 + mvdan.cc/gofumpt v0.5.0 +) + +replace github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 + +require ( + 4d63.com/gochecknoglobals v0.1.0 // indirect + cloud.google.com/go v0.110.0 // indirect + cloud.google.com/go/compute v1.19.1 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + cloud.google.com/go/iam v1.0.0 // indirect + cloud.google.com/go/storage v1.30.1 // indirect + cosmossdk.io/core v0.5.1 // indirect + cosmossdk.io/depinject v1.0.0-alpha.3 // indirect + cosmossdk.io/log v1.1.0 // indirect + cosmossdk.io/simapp v0.0.0-20230323161446-0af178d721ff // indirect + cosmossdk.io/tools/rosetta v0.2.1 // indirect + filippo.io/edwards25519 v1.0.0 // indirect + github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect + github.com/99designs/keyring v1.2.1 // indirect + github.com/Abirdcfly/dupword v0.0.7 // indirect + github.com/Antonboom/errname v0.1.7 // indirect + github.com/Antonboom/nilnil v0.1.1 // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/BurntSushi/toml v1.2.1 // indirect + github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect + github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect + github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 // indirect + github.com/Masterminds/semver v1.5.0 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/OpenPeeDeeP/depguard v1.1.1 // indirect + github.com/alexkohler/prealloc v1.0.0 // indirect + github.com/alingse/asasalint v0.0.11 // indirect + github.com/armon/go-metrics v0.4.1 // indirect + github.com/ashanbrown/forbidigo v1.3.0 // indirect + github.com/ashanbrown/makezero v1.1.1 // indirect + github.com/aws/aws-sdk-go v1.44.244 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect + github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect + github.com/bkielbasa/cyclop v1.2.0 // indirect + github.com/blizzy78/varnamelen v0.8.0 // indirect + github.com/bombsimon/wsl/v3 v3.3.0 // indirect + github.com/breml/bidichk v0.2.3 // indirect + github.com/breml/errchkjson v0.3.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect + github.com/bufbuild/connect-go v1.8.0 // indirect + github.com/bufbuild/connect-opentelemetry-go v0.3.0 // indirect + github.com/bufbuild/protocompile v0.5.1 // indirect + github.com/butuzov/ireturn v0.1.1 // indirect + github.com/cenkalti/backoff/v4 v4.1.3 // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/charithe/durationcheck v0.0.9 // indirect + github.com/chavacava/garif v0.0.0-20220630083739-93517212f375 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/chzyer/readline v1.5.1 // indirect + github.com/cockroachdb/apd/v2 v2.0.2 // indirect + github.com/coinbase/rosetta-sdk-go/types v1.0.0 // indirect + github.com/confio/ics23/go v0.9.0 // indirect + github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect + github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/cosmos/gogogateway v1.2.0 // indirect + github.com/cosmos/iavl v0.20.0 // indirect + github.com/cosmos/ics23/go v0.10.0 // indirect + github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect + github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/creachadair/taskgroup v0.4.2 // indirect + github.com/curioswitch/go-reassign v0.2.0 // indirect + github.com/daixiang0/gci v0.8.1 // indirect + github.com/danieljoos/wincred v1.1.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect + github.com/denis-tingaikin/go-header v0.4.3 // indirect + github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect + github.com/dgraph-io/badger/v2 v2.2007.4 // indirect + github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/docker/cli v24.0.2+incompatible // indirect + github.com/docker/distribution v2.8.2+incompatible // indirect + github.com/docker/docker v24.0.2+incompatible // indirect + github.com/docker/docker-credential-helpers v0.7.0 // indirect + github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/dvsekhvalnov/jose2go v1.5.0 // indirect + github.com/esimonov/ifshort v1.0.4 // indirect + github.com/ettle/strcase v0.1.1 // indirect + github.com/fatih/color v1.13.0 // indirect + github.com/fatih/structtag v1.2.0 // indirect + github.com/felixge/fgprof v0.9.3 // indirect + github.com/felixge/httpsnoop v1.0.2 // indirect + github.com/firefart/nonamedreturns v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fzipp/gocyclo v0.6.0 // indirect + github.com/ghodss/yaml v1.0.0 // indirect + github.com/go-chi/chi/v5 v5.0.8 // indirect + github.com/go-critic/go-critic v0.6.5 // indirect + github.com/go-kit/kit v0.12.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-toolsmith/astcast v1.0.0 // indirect + github.com/go-toolsmith/astcopy v1.0.2 // indirect + github.com/go-toolsmith/astequal v1.0.3 // indirect + github.com/go-toolsmith/astfmt v1.0.0 // indirect + github.com/go-toolsmith/astp v1.0.0 // indirect + github.com/go-toolsmith/strparse v1.0.0 // indirect + github.com/go-toolsmith/typep v1.0.2 // indirect + github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b // indirect + github.com/gobwas/glob v0.2.3 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/gofrs/flock v0.8.1 // indirect + github.com/gofrs/uuid/v5 v5.0.0 // indirect + github.com/gogo/googleapis v1.4.1 // indirect + github.com/golang/glog v1.1.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect + github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect + github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe // indirect + github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 // indirect + github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 // indirect + github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca // indirect + github.com/golangci/misspell v0.3.5 // indirect + github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 // indirect + github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect + github.com/google/btree v1.1.2 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-containerregistry v0.15.2 // indirect + github.com/google/orderedcode v0.0.1 // indirect + github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 // indirect + github.com/google/s2a-go v0.1.3 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect + github.com/googleapis/gax-go/v2 v2.8.0 // indirect + github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8 // indirect + github.com/gorilla/handlers v1.5.1 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/gostaticanalysis/analysisutil v0.7.1 // indirect + github.com/gostaticanalysis/comment v1.4.2 // indirect + github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect + github.com/gostaticanalysis/nilerr v0.1.1 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/gtank/merlin v0.1.1 // indirect + github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-getter v1.7.1 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-safetemp v1.0.0 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hdevalence/ed25519consensus v0.1.0 // indirect + github.com/hexops/gotextdiff v1.0.3 // indirect + github.com/huandu/skiplist v1.2.0 // indirect + github.com/improbable-eng/grpc-web v0.15.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84 // indirect + github.com/jgautheron/goconst v1.5.1 // indirect + github.com/jingyugao/rowserrcheck v1.1.1 // indirect + github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/julz/importas v0.1.0 // indirect + github.com/kisielk/errcheck v1.6.2 // indirect + github.com/kisielk/gotool v1.0.0 // indirect + github.com/kkHAIKE/contextcheck v1.1.3 // indirect + github.com/klauspost/compress v1.16.6 // indirect + github.com/klauspost/pgzip v1.2.6 // indirect + github.com/kulti/thelper v0.6.3 // indirect + github.com/kunwardeep/paralleltest v1.0.6 // indirect + github.com/kyoh86/exportloopref v0.1.8 // indirect + github.com/ldez/gomoddirectives v0.2.3 // indirect + github.com/ldez/tagliatelle v0.3.1 // indirect + github.com/leonklingele/grouper v1.1.0 // indirect + github.com/lib/pq v1.10.7 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/linxGnu/grocksdb v1.7.16 // indirect + github.com/lufeee/execinquery v1.2.1 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/manifoldco/promptui v0.9.0 // indirect + github.com/maratori/testableexamples v1.0.0 // indirect + github.com/maratori/testpackage v1.1.0 // indirect + github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.18 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mbilski/exhaustivestruct v1.2.0 // indirect + github.com/mgechev/revive v1.2.4 // indirect + github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect + github.com/minio/highwayhash v1.0.2 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/moricho/tparallel v0.2.1 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/mtibben/percent v0.2.1 // indirect + github.com/nakabonne/nestif v0.3.1 // indirect + github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect + github.com/nishanths/exhaustive v0.8.3 // indirect + github.com/nishanths/predeclared v0.2.2 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0-rc3 // indirect + github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect + github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect + github.com/pkg/profile v1.7.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/polyfloyd/go-errorlint v1.0.5 // indirect + github.com/prometheus/client_golang v1.14.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect + github.com/quasilyte/go-ruleguard v0.3.18 // indirect + github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f // indirect + github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 // indirect + github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect + github.com/rakyll/statik v0.1.7 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/rs/cors v1.9.0 // indirect + github.com/rs/zerolog v1.29.1 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/ryancurrah/gomodguard v1.2.4 // indirect + github.com/ryanrolds/sqlclosecheck v0.3.0 // indirect + github.com/sanposhiho/wastedassign/v2 v2.0.6 // indirect + github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/sashamelentyev/interfacebloat v1.1.0 // indirect + github.com/sashamelentyev/usestdlibvars v1.20.0 // indirect + github.com/securego/gosec/v2 v2.13.1 // indirect + github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/sivchari/containedctx v1.0.2 // indirect + github.com/sivchari/nosnakecase v1.7.0 // indirect + github.com/sivchari/tenv v1.7.0 // indirect + github.com/sonatard/noctx v0.0.1 // indirect + github.com/sourcegraph/go-diff v0.6.1 // indirect + github.com/spf13/afero v1.9.5 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/viper v1.16.0 // indirect + github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect + github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect + github.com/stretchr/objx v0.5.0 // indirect + github.com/subosito/gotenv v1.4.2 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect + github.com/tdakkota/asciicheck v0.1.1 // indirect + github.com/tendermint/go-amino v0.16.0 // indirect + github.com/tetafro/godot v1.4.11 // indirect + github.com/tetratelabs/wazero v1.2.1 // indirect + github.com/tidwall/btree v1.6.0 // indirect + github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 // indirect + github.com/timonwong/loggercheck v0.9.3 // indirect + github.com/tomarrell/wrapcheck/v2 v2.7.0 // indirect + github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ulikunitz/xz v0.5.11 // indirect + github.com/ultraware/funlen v0.0.3 // indirect + github.com/ultraware/whitespace v0.0.5 // indirect + github.com/uudashr/gocognit v1.0.6 // indirect + github.com/vbatts/tar-split v0.11.3 // indirect + github.com/yagipy/maintidx v1.0.0 // indirect + github.com/yeya24/promlinter v0.2.0 // indirect + github.com/zondax/hid v0.9.1 // indirect + github.com/zondax/ledger-go v0.14.1 // indirect + gitlab.com/bosi/decorder v0.2.3 // indirect + go.etcd.io/bbolt v1.3.7 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/otel v1.16.0 // indirect + go.opentelemetry.io/otel/metric v1.16.0 // indirect + go.opentelemetry.io/otel/sdk v1.16.0 // indirect + go.opentelemetry.io/otel/trace v1.16.0 // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/crypto v0.10.0 // indirect + golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect + golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91 // indirect + golang.org/x/mod v0.11.0 // indirect + golang.org/x/net v0.11.0 // indirect + golang.org/x/oauth2 v0.7.0 // indirect + golang.org/x/sync v0.3.0 // indirect + golang.org/x/sys v0.9.0 // indirect + golang.org/x/term v0.9.0 // indirect + golang.org/x/text v0.10.0 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect + google.golang.org/api v0.122.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + honnef.co/go/tools v0.3.3 // indirect + mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect + mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect + mvdan.cc/unparam v0.0.0-20220706161116-678bad134442 // indirect + nhooyr.io/websocket v1.8.6 // indirect + pgregory.net/rapid v0.5.5 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) diff --git a/ignite/pkg/cosmosanalysis/module/module.go b/ignite/pkg/cosmosanalysis/module/module.go index ba6e98f1b1..cdfe90e9d6 100644 --- a/ignite/pkg/cosmosanalysis/module/module.go +++ b/ignite/pkg/cosmosanalysis/module/module.go @@ -14,6 +14,7 @@ import ( "github.com/ignite/cli/ignite/pkg/cosmosanalysis/app" "github.com/ignite/cli/ignite/pkg/gomodule" "github.com/ignite/cli/ignite/pkg/protoanalysis" + "github.com/ignite/cli/ignite/pkg/xstrings" ) // Msgs is a module import path-sdk msgs pair. @@ -83,6 +84,12 @@ type moduleDiscoverer struct { registeredModules []string } +// IsCosmosSDKModulePkg check if a Go import path is a Cosmos SDK package module. +// These type of package have the "cosmossdk.io/x" prefix. +func IsCosmosSDKModulePkg(path string) bool { + return strings.Contains(path, "cosmossdk.io/x/") +} + // Discover discovers and returns modules and their types that are registered in the app // chainRoot is the root path of the chain // sourcePath is the root path of the go module which the proto dir is from @@ -92,7 +99,12 @@ type moduleDiscoverer struct { // 1. Getting all the registered Go modules from the app. // 2. Parsing the proto files to find services and messages. // 3. Check if the proto services are implemented in any of the registered modules. -func Discover(ctx context.Context, chainRoot, sourcePath, protoDir string) ([]Module, error) { +func Discover(ctx context.Context, chainRoot, sourcePath string, options ...DiscoverOption) ([]Module, error) { + var o discoverOptions + for _, apply := range options { + apply(&o) + } + // find out base Go import path of the blockchain. gm, err := gomodule.ParseAt(sourcePath) if err != nil { @@ -124,8 +136,18 @@ func Discover(ctx context.Context, chainRoot, sourcePath, protoDir string) ([]Mo return []Module{}, nil } + // Switch the proto path for "cosmossdk.io" module packages to the official Cosmos + // SDK package because the module packages doesn't contain the proto files. These + // files are only available from the Cosmos SDK package. + var protoPath string + if o.sdkDir != "" && IsCosmosSDKModulePkg(sourcePath) { + protoPath = switchCosmosSDKPackagePath(sourcePath, o.sdkDir) + } else { + protoPath = filepath.Join(sourcePath, o.protoDir) + } + md := &moduleDiscoverer{ - protoPath: filepath.Join(sourcePath, protoDir), + protoPath: protoPath, sourcePath: sourcePath, basegopath: basegopath, registeredModules: appModules, @@ -420,3 +442,11 @@ func hasPagination(msg protoanalysis.Message) bool { return false } + +func switchCosmosSDKPackagePath(srcPath, sdkDir string) string { + modName := xstrings.StringBetween(srcPath, "/x/", "@") + if modName == "" { + return srcPath + } + return filepath.Join(sdkDir, "proto", "cosmos", modName) +} diff --git a/ignite/pkg/cosmosanalysis/module/module_test.go b/ignite/pkg/cosmosanalysis/module/module_test.go index 0ba79a2f15..2db58c75fd 100644 --- a/ignite/pkg/cosmosanalysis/module/module_test.go +++ b/ignite/pkg/cosmosanalysis/module/module_test.go @@ -156,7 +156,7 @@ func TestDiscover(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - modules, err := module.Discover(ctx, sourcePath, tt.sourcePath, tt.protoDir) + modules, err := module.Discover(ctx, sourcePath, tt.sourcePath, module.WithProtoDir(tt.protoDir)) require.NoError(t, err) require.Equal(t, tt.want, modules) @@ -193,7 +193,7 @@ func TestDiscoverWithAppV2(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - modules, err := module.Discover(ctx, sourcePath, sourcePath, tt.protoDir) + modules, err := module.Discover(ctx, sourcePath, sourcePath, module.WithProtoDir(tt.protoDir)) require.NoError(t, err) require.Equal(t, tt.want, modules) diff --git a/ignite/pkg/cosmosanalysis/module/options.go b/ignite/pkg/cosmosanalysis/module/options.go new file mode 100644 index 0000000000..20820785f8 --- /dev/null +++ b/ignite/pkg/cosmosanalysis/module/options.go @@ -0,0 +1,22 @@ +package module + +// DiscoverOption configures calls to Discovery function. +type DiscoverOption func(*discoverOptions) + +type discoverOptions struct { + protoDir, sdkDir string +} + +// WithProtoDir sets the relative proto directory path. +func WithProtoDir(path string) DiscoverOption { + return func(o *discoverOptions) { + o.protoDir = path + } +} + +// WithSDKDir sets the absolute directory path to the Cosmos SDK Go package. +func WithSDKDir(path string) DiscoverOption { + return func(o *discoverOptions) { + o.sdkDir = path + } +} diff --git a/ignite/pkg/cosmosgen/cosmosgen.go b/ignite/pkg/cosmosgen/cosmosgen.go index 507a90c369..89a188eea5 100644 --- a/ignite/pkg/cosmosgen/cosmosgen.go +++ b/ignite/pkg/cosmosgen/cosmosgen.go @@ -123,6 +123,7 @@ type generator struct { gomodPath string opts *generateOptions sdkImport string + sdkDir string deps []gomodule.Version appModules []module.Module appIncludes protoIncludes diff --git a/ignite/pkg/cosmosgen/generate.go b/ignite/pkg/cosmosgen/generate.go index 840b100a8d..a6402671a9 100644 --- a/ignite/pkg/cosmosgen/generate.go +++ b/ignite/pkg/cosmosgen/generate.go @@ -34,7 +34,8 @@ const ( ) var ( - ErrBufConfig = errors.New("invalid Buf config") + ErrBufConfig = errors.New("invalid Buf config") + ErrMissingSDKDep = errors.New("cosmos SDK dependency not found") protocGlobalInclude = xfilepath.List( xfilepath.JoinFromHome(xfilepath.Path("local/include")), @@ -112,8 +113,15 @@ func (g *generator) setup(ctx context.Context) (err error) { return err } - // Discover any custom modules defined by the user's app - g.appModules, err = g.discoverModules(ctx, g.appPath, g.protoDir) + // Discover any custom modules defined by the user's app. + // Use the configured proto directory to locate app's proto files. + g.appModules, err = module.Discover( + ctx, + g.appPath, + g.appPath, + module.WithProtoDir(g.protoDir), + module.WithSDKDir(g.sdkDir), + ) if err != nil { return err } @@ -123,6 +131,19 @@ func (g *generator) setup(ctx context.Context) (err error) { return err } + dep, found := filterCosmosSDKModule(g.deps) + if !found { + return ErrMissingSDKDep + } + + // Find the full path to the Cosmos SDK Go package. + // The path is required to be able to discover proto packages for the + // set of "cosmossdk.io" packages that doesn't contain the proto files. + g.sdkDir, err = gomodule.LocatePath(ctx, g.cacheStorage, g.appPath, dep) + if err != nil { + return err + } + // Go through the Go dependencies of the user's app within go.mod, some of them // might be hosting Cosmos SDK modules that could be in use by user's blockchain. // @@ -153,8 +174,10 @@ func (g *generator) setup(ctx context.Context) (err error) { return err } - // Discover any modules defined by the package - modules, err := g.discoverModules(ctx, path, "") + // Discover any modules defined by the package. + // Use an empty string for proto directory because it will be + // discovered automatically within the dependency package path. + modules, err := module.Discover(ctx, g.appPath, path, module.WithSDKDir(g.sdkDir)) if err != nil { return err } @@ -243,14 +266,21 @@ func (g *generator) resolveIncludes(ctx context.Context, path string) (protoIncl includes := protoIncludes{Paths: paths} - // Check that the app/package proto directory exists - protoPath := filepath.Join(path, g.protoDir) - fi, err := os.Stat(protoPath) - if err != nil && !os.IsNotExist(err) { - return protoIncludes{}, false, err - } else if !fi.IsDir() { - // Just return the global includes when a proto directory doesn't exist - return includes, true, nil + // The "cosmossdk.io" module packages must use SDK's proto path which is + // where all proto files for there type of Go package are. + var protoPath string + if module.IsCosmosSDKModulePkg(path) { + protoPath = filepath.Join(g.sdkDir, "proto") + } else { + // Check that the app/package proto directory exists + protoPath = filepath.Join(path, g.protoDir) + fi, err := os.Stat(protoPath) + if err != nil && !os.IsNotExist(err) { + return protoIncludes{}, false, err + } else if !fi.IsDir() { + // Just return the global includes when a proto directory doesn't exist + return includes, true, nil + } } // Add app's proto path to the list of proto paths @@ -285,24 +315,6 @@ func (g *generator) resolveIncludes(ctx context.Context, path string) (protoIncl return includes, true, nil } -func (g *generator) discoverModules(ctx context.Context, path, protoDir string) ([]module.Module, error) { - var filteredModules []module.Module - modules, err := module.Discover(ctx, g.appPath, path, protoDir) - if err != nil { - return nil, err - } - - protoPath := filepath.Join(path, g.protoDir) - for _, m := range modules { - if !strings.HasPrefix(m.Pkg.Path, protoPath) { - continue - } - filteredModules = append(filteredModules, m) - } - - return filteredModules, nil -} - func (g generator) updateBufModule(ctx context.Context) error { for pkgPath, includes := range g.thirdModuleIncludes { // Skip third party dependencies without proto files @@ -472,3 +484,12 @@ func (g generator) vendorProtoPackage(pkgName, protoPath string) (err error) { return nil } + +func filterCosmosSDKModule(versions []gomodule.Version) (gomodule.Version, bool) { + for _, v := range versions { + if strings.HasPrefix(v.Path, cosmosver.CosmosModulePath) { + return v, true + } + } + return gomodule.Version{}, false +} diff --git a/ignite/pkg/cosmosgen/generate_typescript.go b/ignite/pkg/cosmosgen/generate_typescript.go index 328eb69b51..80ecd12997 100644 --- a/ignite/pkg/cosmosgen/generate_typescript.go +++ b/ignite/pkg/cosmosgen/generate_typescript.go @@ -196,7 +196,14 @@ func (g *tsGenerator) generateModuleTemplate( return err } - pp := filepath.Join(appPath, g.g.protoDir) + // All "cosmossdk.io" module packages must use SDK's + // proto path which is where the proto files are stored. + var pp string + if module.IsCosmosSDKModulePkg(appPath) { + pp = filepath.Join(g.g.sdkDir, "proto") + } else { + pp = filepath.Join(appPath, g.g.protoDir) + } return templateTSClientModule.Write(out, pp, struct { Module module.Module diff --git a/ignite/pkg/cosmosgen/templates/module/index.ts.tpl b/ignite/pkg/cosmosgen/templates/module/index.ts.tpl index c9dfa159ec..11faba741d 100644 --- a/ignite/pkg/cosmosgen/templates/module/index.ts.tpl +++ b/ignite/pkg/cosmosgen/templates/module/index.ts.tpl @@ -1,6 +1,6 @@ -import Module from './module'; +import IgntModule from './module'; import { txClient, queryClient, registry } from './module'; import { msgTypes } from './registry'; export * from "./types"; -export { Module, msgTypes, txClient, queryClient, registry }; +export { IgntModule, msgTypes, txClient, queryClient, registry }; diff --git a/ignite/pkg/cosmosgen/templates/module/module.ts.tpl b/ignite/pkg/cosmosgen/templates/module/module.ts.tpl index 4797df2b06..abb378e19b 100644 --- a/ignite/pkg/cosmosgen/templates/module/module.ts.tpl +++ b/ignite/pkg/cosmosgen/templates/module/module.ts.tpl @@ -119,7 +119,7 @@ class SDKModule { } }; -const Module = (test: IgniteClient) => { +const IgntModule = (test: IgniteClient) => { return { module: { {{ camelCaseUpperSta .Module.Pkg.Name }}: new SDKModule(test) @@ -127,4 +127,4 @@ const Module = (test: IgniteClient) => { registry: msgTypes } } -export default Module; \ No newline at end of file +export default IgntModule; \ No newline at end of file diff --git a/ignite/pkg/cosmosgen/templates/root/client.ts.tpl b/ignite/pkg/cosmosgen/templates/root/client.ts.tpl index a7b30495b6..a9088ce67b 100644 --- a/ignite/pkg/cosmosgen/templates/root/client.ts.tpl +++ b/ignite/pkg/cosmosgen/templates/root/client.ts.tpl @@ -8,7 +8,7 @@ import { import { SigningStargateClient, StdFee } from "@cosmjs/stargate"; import { Env } from "./env"; import { UnionToIntersection, Return, Constructor } from "./helpers"; -import { Module } from "./modules"; +import { IgntModule } from "./modules"; import { EventEmitter } from "events"; import { ChainInfo } from "@keplr-wallet/types"; @@ -18,11 +18,11 @@ const defaultFee = { }; export class IgniteClient extends EventEmitter { - static plugins: Module[] = []; + static plugins: IgntModule[] = []; env: Env; signer?: OfflineSigner; registry: Array<[string, GeneratedType]> = []; - static plugin(plugin: T) { + static plugin(plugin: T) { const currentPlugins = this.plugins; class AugmentedClient extends this { diff --git a/ignite/pkg/cosmosgen/templates/root/index.ts.tpl b/ignite/pkg/cosmosgen/templates/root/index.ts.tpl index 8c71febfe1..b2cd682a81 100644 --- a/ignite/pkg/cosmosgen/templates/root/index.ts.tpl +++ b/ignite/pkg/cosmosgen/templates/root/index.ts.tpl @@ -2,7 +2,7 @@ import { Registry } from '@cosmjs/proto-signing' import { IgniteClient } from "./client"; import { MissingWalletError } from "./helpers"; -{{ range .Modules }}import { Module as {{ camelCaseUpperSta .Pkg.Name }}, msgTypes as {{ camelCaseUpperSta .Pkg.Name }}MsgTypes } from './{{ .Pkg.Name }}' +{{ range .Modules }}import { IgntModule as {{ camelCaseUpperSta .Pkg.Name }}, msgTypes as {{ camelCaseUpperSta .Pkg.Name }}MsgTypes } from './{{ .Pkg.Name }}' {{ end }} const Client = IgniteClient.plugin([ diff --git a/ignite/pkg/cosmosgen/templates/root/modules.ts.tpl b/ignite/pkg/cosmosgen/templates/root/modules.ts.tpl index 634b83c125..e8e4a78272 100644 --- a/ignite/pkg/cosmosgen/templates/root/modules.ts.tpl +++ b/ignite/pkg/cosmosgen/templates/root/modules.ts.tpl @@ -1,5 +1,5 @@ import { IgniteClient } from "./client"; import { GeneratedType } from "@cosmjs/proto-signing"; -export type ModuleInterface = { [key: string]: any } -export type Module = (instance: IgniteClient) => { module: ModuleInterface, registry: [string, GeneratedType][] } +export type IgntModuleInterface = { [key: string]: any } +export type IgntModule = (instance: IgniteClient) => { module: IgntModuleInterface, registry: [string, GeneratedType][] } diff --git a/ignite/pkg/cosmosgen/templates/root/package.json.tpl b/ignite/pkg/cosmosgen/templates/root/package.json.tpl index 8cd8cdea6b..b0babc1b29 100644 --- a/ignite/pkg/cosmosgen/templates/root/package.json.tpl +++ b/ignite/pkg/cosmosgen/templates/root/package.json.tpl @@ -15,8 +15,7 @@ "access": "public" }, "scripts": { - "build": "NODE_OPTIONS='--max-old-space-size=16384' tsc", - "postinstall": "npm run build" + "build": "NODE_OPTIONS='--max-old-space-size=16384' tsc" }, "dependencies": { "@cosmjs/proto-signing": "0.31.1", diff --git a/ignite/pkg/gocmd/gocmd.go b/ignite/pkg/gocmd/gocmd.go index f9a99c7330..0d043568cf 100644 --- a/ignite/pkg/gocmd/gocmd.go +++ b/ignite/pkg/gocmd/gocmd.go @@ -33,6 +33,9 @@ const ( // CommandModVerify represents go mod "verify" command. CommandModVerify = "verify" + // CommandModDownload represents go mod "download" command. + CommandModDownload = "download" + // CommandFmt represents go "fmt" command. CommandFmt = "fmt" @@ -105,6 +108,15 @@ func ModVerify(ctx context.Context, path string, options ...exec.Option) error { return exec.Exec(ctx, []string{Name(), CommandMod, CommandModVerify}, append(options, exec.StepOption(step.Workdir(path)))...) } +// ModDownload runs go mod download on a path with options. +func ModDownload(ctx context.Context, path string, json bool, options ...exec.Option) error { + command := []string{Name(), CommandMod, CommandModDownload} + if json { + command = append(command, "-json") + } + return exec.Exec(ctx, command, append(options, exec.StepOption(step.Workdir(path)))...) +} + // BuildPath runs go install on cmd folder with options. func BuildPath(ctx context.Context, output, binary, path string, flags []string, options ...exec.Option) error { binaryOutput, err := binaryPath(output, binary) diff --git a/ignite/pkg/gomodule/gomodule.go b/ignite/pkg/gomodule/gomodule.go index 1418079fcb..2c4d0af13a 100644 --- a/ignite/pkg/gomodule/gomodule.go +++ b/ignite/pkg/gomodule/gomodule.go @@ -10,19 +10,41 @@ import ( "io/fs" "os" "path/filepath" + "strings" "golang.org/x/mod/modfile" "golang.org/x/mod/module" "github.com/ignite/cli/ignite/pkg/cache" - "github.com/ignite/cli/ignite/pkg/cmdrunner" + "github.com/ignite/cli/ignite/pkg/cmdrunner/exec" "github.com/ignite/cli/ignite/pkg/cmdrunner/step" + "github.com/ignite/cli/ignite/pkg/gocmd" ) const pathCacheNamespace = "gomodule.path" -// ErrGoModNotFound returned when go.mod file cannot be found for an app. -var ErrGoModNotFound = errors.New("go.mod not found") +var ( + // ErrGoModNotFound returned when go.mod file cannot be found for an app. + ErrGoModNotFound = errors.New("go.mod not found") + + // ErrModuleNotFound is returned when a Go module is not found. + ErrModuleNotFound = errors.New("module not found") +) + +// Version is an alias to the module version type. +type Version = module.Version + +// Module contains Go module info. +type Module struct { + // Path is the Go module path. + Path string + + // Version is the module version. + Version string + + // Dir is the absolute path to the Go module. + Dir string +} // ParseAt finds and parses go.mod at app's path. func ParseAt(path string) (*modfile.File, error) { @@ -37,8 +59,8 @@ func ParseAt(path string) (*modfile.File, error) { } // FilterVersions filters dependencies under require section by their paths. -func FilterVersions(dependencies []module.Version, paths ...string) []module.Version { - var filtered []module.Version +func FilterVersions(dependencies []Version, paths ...string) []Version { + var filtered []Version for _, dep := range dependencies { for _, path := range paths { @@ -52,10 +74,10 @@ func FilterVersions(dependencies []module.Version, paths ...string) []module.Ver return filtered } -func ResolveDependencies(f *modfile.File, includeIndirect bool) ([]module.Version, error) { - var versions []module.Version +func ResolveDependencies(f *modfile.File, includeIndirect bool) ([]Version, error) { + var versions []Version - isReplacementAdded := func(rv module.Version) bool { + isReplacementAdded := func(rv Version) bool { for _, rep := range f.Replace { if rv.Path == rep.Old.Path { versions = append(versions, rep.New) @@ -80,7 +102,7 @@ func ResolveDependencies(f *modfile.File, includeIndirect bool) ([]module.Versio } // LocatePath locates pkg's absolute path managed by 'go mod' on the local filesystem. -func LocatePath(ctx context.Context, cacheStorage cache.Storage, src string, pkg module.Version) (path string, err error) { +func LocatePath(ctx context.Context, cacheStorage cache.Storage, src string, pkg Version) (path string, err error) { // can be a local package. if pkg.Version == "" { // indicates that this is a local package. if filepath.IsAbs(pkg.Path) { @@ -100,37 +122,72 @@ func LocatePath(ctx context.Context, cacheStorage cache.Storage, src string, pkg } // otherwise, it is hosted. - out := &bytes.Buffer{} - - if err := cmdrunner. - New(). - Run(ctx, step.New( - step.Exec("go", "mod", "download", "-json"), - step.Workdir(src), - step.Stdout(out), - )); err != nil { + m, err := FindModule(ctx, src, pkg.String()) + if err != nil { return "", err } - d := json.NewDecoder(out) + if err = pathCache.Put(cacheKey, m.Dir); err != nil { + return "", err + } + return m.Dir, nil +} - for { - var mod struct { - Path, Version, Dir string - } - if err := d.Decode(&mod); err != nil { +// SplitPath splits a Go import path into an URI path and version. +// Version is an empty string when the path doesn't contain a version suffix. +// Versioned paths use the "path@version" format. +func SplitPath(path string) (string, string) { + if len(path) == 0 || path[0] == '@' { + return "", "" + } + + parts := strings.SplitN(path, "@", 2) + if len(parts) == 2 { + return parts[0], parts[1] + } + return parts[0], "" +} + +// JoinPath joins a Go import path URI to a version. +// The result path have the "path@version" format. +func JoinPath(path, version string) string { + if path == "" { + return "" + } + + if version == "" { + return path + } + + return fmt.Sprintf("%s@%s", path, version) +} + +// FindModule returns the Go module info for an import path. +// The module is searched within the dependencies of the module defined in root dir. +func FindModule(ctx context.Context, rootDir, path string) (Module, error) { + var stdout bytes.Buffer + err := gocmd.ModDownload(ctx, rootDir, true, exec.StepOption(step.Stdout(&stdout))) + if err != nil { + return Module{}, err + } + + dec := json.NewDecoder(&stdout) + p, version := SplitPath(path) + + for dec.More() { + var m Module + if dec.Decode(&m); err != nil { if errors.Is(err, io.EOF) { break } - return "", err + + return Module{}, err } - if mod.Path == pkg.Path && mod.Version == pkg.Version { - if err := pathCache.Put(cacheKey, mod.Dir); err != nil { - return "", err - } - return mod.Dir, nil + + if m.Path == p && (version == "" || version == m.Version) { + return m, nil } } - return "", fmt.Errorf("module %q not found", pkg.Path) + return Module{}, fmt.Errorf("%w: %s", ErrModuleNotFound, path) } diff --git a/ignite/pkg/gomodule/gomodule_test.go b/ignite/pkg/gomodule/gomodule_test.go new file mode 100644 index 0000000000..42ff3e6d2a --- /dev/null +++ b/ignite/pkg/gomodule/gomodule_test.go @@ -0,0 +1,97 @@ +package gomodule_test + +import ( + "context" + "strings" + "testing" + + "github.com/ignite/cli/ignite/pkg/gomodule" + "github.com/stretchr/testify/require" +) + +func TestSplitPath(t *testing.T) { + cases := []struct { + name string + path string + wantPath string + wantVersion string + }{ + { + name: "path with version", + path: "foo@v0.1.0", + wantPath: "foo", + wantVersion: "v0.1.0", + }, + { + name: "path without version", + path: "foo", + wantPath: "foo", + }, + { + name: "invalid path", + path: "@v0.1.0", + }, + { + name: "empty path", + }, + } + + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + // Act + p, v := gomodule.SplitPath(tt.path) + + // Assert + require.Equal(t, tt.wantPath, p) + require.Equal(t, tt.wantVersion, v) + }) + } +} + +func TestJoinPath(t *testing.T) { + require.Equal(t, "foo@v0.1.0", gomodule.JoinPath("foo", "v0.1.0")) + require.Equal(t, "", gomodule.JoinPath("", "v0.1.0")) + require.Equal(t, "foo", gomodule.JoinPath("foo", "")) +} + +func TestFindModule(t *testing.T) { + cases := []struct { + name string + importPath string + version string + wantErr error + }{ + { + name: "module exists", + importPath: "github.com/gorilla/mux", + version: "v1.8.0", + }, + { + name: "module missing", + importPath: "github.com/foo/bar", + version: "v0.1.0", + wantErr: gomodule.ErrModuleNotFound, + }, + } + + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + // Arrange + ctx := context.Background() + path := gomodule.JoinPath(tt.importPath, tt.version) + + // Act + m, err := gomodule.FindModule(ctx, "testdata/module", path) + + // Assert + if tt.wantErr != nil { + require.ErrorIs(t, err, tt.wantErr) + } else { + require.NoError(t, err) + require.Equal(t, tt.importPath, m.Path) + require.Equal(t, tt.version, m.Version) + require.True(t, strings.HasSuffix(m.Dir, path)) + } + }) + } +} diff --git a/ignite/pkg/gomodule/testdata/module/go.mod b/ignite/pkg/gomodule/testdata/module/go.mod new file mode 100644 index 0000000000..6b0c1f1e4c --- /dev/null +++ b/ignite/pkg/gomodule/testdata/module/go.mod @@ -0,0 +1,8 @@ +module github.com/ignite/cli/ignite/pkg/gomodule + +go 1.21.0 + +require ( + github.com/gorilla/mux v1.8.0 + github.com/stretchr/testify v1.8.2 +) diff --git a/ignite/pkg/xstrings/xstrings.go b/ignite/pkg/xstrings/xstrings.go index ff038a95db..7924443e33 100644 --- a/ignite/pkg/xstrings/xstrings.go +++ b/ignite/pkg/xstrings/xstrings.go @@ -70,3 +70,25 @@ func Title(s string) string { func ToUpperFirst(s string) string { return strings.ToUpper(s[:1]) + s[1:] } + +// StringBetween returns the string between two other strings. +// The comparison is not greedy so the between result includes the +// string between the start value and the first match of the end value. +func StringBetween(s, start, end string) string { + if s == "" || start == "" || end == "" { + return "" + } + + i := strings.Index(s, start) + if i == -1 { + return "" + } + + s = s[i+len(start):] + i = strings.Index(s, end) + if i == -1 { + return "" + } + + return s[:i] +} diff --git a/ignite/pkg/xstrings/xstrings_test.go b/ignite/pkg/xstrings/xstrings_test.go index c2da08be2c..0087b4e6ce 100644 --- a/ignite/pkg/xstrings/xstrings_test.go +++ b/ignite/pkg/xstrings/xstrings_test.go @@ -18,3 +18,11 @@ func TestNoNumberPrefix(t *testing.T) { require.Equal(t, "_0foo", xstrings.NoNumberPrefix("0foo")) require.Equal(t, "_999foo", xstrings.NoNumberPrefix("999foo")) } + +func TestStringBetween(t *testing.T) { + require.Equal(t, "bar", xstrings.StringBetween("foobarbaz", "foo", "baz")) + require.Equal(t, "bar", xstrings.StringBetween("0foobarbaz1", "foo", "baz")) + require.Equal(t, "", xstrings.StringBetween("0foo", "0", "")) + require.Equal(t, "", xstrings.StringBetween("foo0", "", "0")) + require.Equal(t, "", xstrings.StringBetween("", "0", "1")) +}