Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] feat(services): scaffold api #4130

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ignite/pkg/cosmosgen/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func (g *generator) setup(ctx context.Context) (err error) {
New(
cmdrunner.DefaultStderr(&errb),
cmdrunner.DefaultWorkdir(g.appPath),
).Run(ctx, step.New(step.Exec("go", "mod", "download"))); err != nil {
).Run(ctx, step.New(step.Exec("go", "mod", "download"))); err != nil { // TODO: use gocmd.ModDownload
return errors.Wrap(err, errb.String())
}

Expand Down
10 changes: 10 additions & 0 deletions ignite/services/injector/commands.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package injector

import "context"

type Command struct {
}

func (i *injector) AddCommand(ctx context.Context, c *Command) error {

Check failure on line 8 in ignite/services/injector/commands.go

View workflow job for this annotation

GitHub Actions / Lint Go code

unused-parameter: parameter 'ctx' seems to be unused, consider removing or renaming it as _ (revive)
panic("unimplemented")
}
31 changes: 31 additions & 0 deletions ignite/services/injector/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package injector

import (
"path/filepath"

"github.com/ignite/cli/v29/ignite/templates/module"
)

const (
PathAppConfigGo = module.PathAppConfigGo
PathAppGo = module.PathAppGo
PathCommands = "cmd/commands.go"
)

func (i *injector) appPath() string {
return filepath.Join(i.chain.AppPath(), PathAppGo)
}

func (i *injector) appConfigPath() string {
return filepath.Join(i.chain.AppPath(), PathAppConfigGo)
}

func (i *injector) commandsPath() (string, error) {

Check failure on line 23 in ignite/services/injector/helpers.go

View workflow job for this annotation

GitHub Actions / Lint Go code

func `(*injector).commandsPath` is unused (unused)
appPath := i.chain.AppPath()
binaryName, err := i.chain.Binary()
if err != nil {
return "", err
}

return filepath.Join(appPath, "cmd", binaryName, PathCommands), nil
}
66 changes: 66 additions & 0 deletions ignite/services/injector/injector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package injector

import (
"context"

"github.com/gobuffalo/genny/v2"
"github.com/gobuffalo/plush/v4"

"github.com/ignite/cli/v29/ignite/pkg/errors"
"github.com/ignite/cli/v29/ignite/pkg/gocmd"
"github.com/ignite/cli/v29/ignite/pkg/xgenny"
"github.com/ignite/cli/v29/ignite/services/chain"
"github.com/ignite/cli/v29/ignite/templates/field/plushhelpers"
)

// Injector allows to add modules, commands and other changes to the chain, using a convinient API.
// Once the wanted changes are added, the Inject method should be called to apply them.
type Injector interface {
AddModule(ctx context.Context, m *Module) error
AddNonDepinjectModule(ctx context.Context, m *Module) error
AddCommand(ctx context.Context, c *Command) error

Inject(ctx context.Context) error
}

// TODO: somewhere else, injector for modules to replace placeholders

type injector struct {
chain *chain.Chain
generator *genny.Generator
}

// NewInject creates an Injector.
func NewInjector(c *chain.Chain) Injector {
g := genny.New()
ctx := plush.NewContext()
plushhelpers.ExtendPlushContext(ctx)
g.Transformer(xgenny.Transformer(ctx))

return &injector{
chain: c,
generator: g,
}
}

// Inject runs the injector, adding all the changes to the chain.
func (i *injector) Inject(ctx context.Context) error {
appPath := i.chain.AppPath()

runner := xgenny.NewRunner(ctx, appPath)
if err := runner.Run(i.generator); err != nil {
return errors.Errorf("failed to execute generator: %w", err)
}

if err := gocmd.ModTidy(ctx, appPath); err != nil {
return err
}

if err := gocmd.Fmt(ctx, appPath); err != nil {
return err
}

_ = gocmd.GoImports(ctx, appPath) // goimports installation could fail, so ignore the error

return nil
}
129 changes: 129 additions & 0 deletions ignite/services/injector/module.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package injector

import (
"context"
"fmt"
"go/ast"
"io"
"path/filepath"
"strings"

"github.com/gobuffalo/genny/v2"
"github.com/ignite/cli/v29/ignite/pkg/cmdrunner/exec"
"github.com/ignite/cli/v29/ignite/pkg/cmdrunner/step"
"github.com/ignite/cli/v29/ignite/pkg/gocmd"
"github.com/ignite/cli/v29/ignite/pkg/goenv"
"github.com/ignite/cli/v29/ignite/pkg/xast"
)

// Modules should follow the recommended modules structure.
// See https://docs.cosmos.network/main/build/building-modules/structure#structure
type Module struct {
Name string // bank
Import string // cosmossdk.io/bank
Permissions string // TODO
}

type moduleConfig struct {
typePkg string
keeperPkg string
modulePkg string
apiPkg string

hasGenesis bool // TODO

Check failure on line 33 in ignite/services/injector/module.go

View workflow job for this annotation

GitHub Actions / Lint Go code

field `hasGenesis` is unused (unused)
hasPreBlocker bool

Check failure on line 34 in ignite/services/injector/module.go

View workflow job for this annotation

GitHub Actions / Lint Go code

field `hasPreBlocker` is unused (unused)
hasBeginBlocker bool

Check failure on line 35 in ignite/services/injector/module.go

View workflow job for this annotation

GitHub Actions / Lint Go code

field `hasBeginBlocker` is unused (unused)
hasEndBlocker bool

Check failure on line 36 in ignite/services/injector/module.go

View workflow job for this annotation

GitHub Actions / Lint Go code

field `hasEndBlocker` is unused (unused)
}

// downloadModule downloads the module and returns its path

Check failure on line 39 in ignite/services/injector/module.go

View workflow job for this annotation

GitHub Actions / Lint Go code

Comment should end in a period (godot)
func (i *injector) downloadModule(ctx context.Context, m *Module) (string, error) {
// TODO: allow to check local modules that aren't their own go modules
// inspect if module is in the chain.

if err := gocmd.ModDownload(ctx, m.Import, false, exec.StepOption(step.Stdout(io.Discard))); err != nil {
return "", fmt.Errorf("failed to download module: %w", err)

Check failure on line 45 in ignite/services/injector/module.go

View workflow job for this annotation

GitHub Actions / Lint Go code

use of `fmt.Errorf` forbidden because "fmt.Errorf should be replaced by '\"github.com/ignite/cli/ignite/pkg/errors\"'" (forbidigo)
}

return filepath.Join(append([]string{goenv.GoModCache()}, strings.Split(m.Import, "/")...)...), nil
}

// AddModule adds a new module to the chain.
func (i *injector) AddModule(ctx context.Context, m *Module) error {
mc := moduleConfig{
typePkg: fmt.Sprintf("%s/types", m.Import),
keeperPkg: fmt.Sprintf("%s/keeper", m.Import),
modulePkg: fmt.Sprintf("%s/module", m.Import),
apiPkg: fmt.Sprintf("%s/api", m.Import),
}

modulePath, err := i.downloadModule(ctx, m)
if err != nil {
return err
}

modulePkg, _, err := xast.ParseDir(modulePath)
if err != nil {
return err
}

for _, f := range modulePkg.Files {
ast.Inspect(f, func(x ast.Node) bool {

Check failure on line 71 in ignite/services/injector/module.go

View workflow job for this annotation

GitHub Actions / Lint Go code

unused-parameter: parameter 'x' seems to be unused, consider removing or renaming it as _ (revive)
// TODO find ModuleName and set moduleTypePackage
// TODO check depinject config and find api module package
// TODO check abci.go or module.go and find abci implementations
return true
})
}

appConfigFn := func(r *genny.Runner) error {
path := i.appConfigPath()

f, err := r.Disk.Find(path)
if err != nil {
return err
}

content, err := xast.AppendImports(
f.String(),
xast.WithLastNamedImport(fmt.Sprintf("%stypes", m.Name), mc.typePkg),
)
if err != nil {
return err
}

return r.File(genny.NewFileS(path, content))
}

appFn := func(r *genny.Runner) error {
path := i.appPath()

f, err := r.Disk.Find(path)
if err != nil {
return err
}

content, err := xast.AppendImports(
f.String(),
xast.WithLastNamedImport(fmt.Sprintf("%skeeper", m.Name), mc.keeperPkg),
xast.WithLastNamedImport("_", mc.modulePkg),
)
if err != nil {
return err
}

return r.File(genny.NewFileS(path, content))
}

i.generator.RunFn(appConfigFn)
i.generator.RunFn(appFn)

return nil
}

func (i *injector) AddNonDepinjectModule(ctx context.Context, m *Module) error {

Check failure on line 124 in ignite/services/injector/module.go

View workflow job for this annotation

GitHub Actions / Lint Go code

unused-parameter: parameter 'ctx' seems to be unused, consider removing or renaming it as _ (revive)
// append app.go or create custom.go
// do not break ibc.go

panic("not implemented")
}
Loading