diff --git a/changelog.md b/changelog.md index 2262c0061a..02dc56bcba 100644 --- a/changelog.md +++ b/changelog.md @@ -21,6 +21,7 @@ - [#4691](https://github.com/ignite/cli/pull/4691), [#4706](https://github.com/ignite/cli/pull/4706), [#4725](https://github.com/ignite/cli/pull/4725), [#4737](https://github.com/ignite/cli/pull/4737) Fix ts-client query template and solely Go template for `ts-client` generation. - [#4742](https://github.com/ignite/cli/pull/4742) Updates Vue composables template for new ts-client and tanstack/vue-query v5 +- [#4744](https://github.com/ignite/cli/pull/4744) Remove `react` frontend generation via `s react` command. Use the [Ignite CCA App](https://github.com/ignite/apps) instead. ## [`v29.0.0`](https://github.com/ignite/cli/releases/tag/v29.0.0) diff --git a/docs/docs/04-clients/03-vue.md b/docs/docs/04-clients/03-vue.md index f62f1f4e55..66f8d8fd9f 100644 --- a/docs/docs/04-clients/03-vue.md +++ b/docs/docs/04-clients/03-vue.md @@ -99,20 +99,22 @@ purposes, but you should not do this in production. In the `example` directory run the following command to start your blockchain: -``` +```bash ignite chain serve ``` To start your Vue application, go to the `vue` directory and run the following command in a separate terminal window: -``` -npm install && npm run dev +:::note +Make sure you have [pnpm](https://pnpm.io/) installed. +::: + +```bash +pnpm install && pnpm dev ``` -It is recommended to run `npm install` before starting your app with `npm run -dev` to ensure that all dependencies are installed (including the ones that the -API client has, see `vue/postinstall.js`). +It is recommended to run `pnpm install` before starting your app with `pnpm dev` to ensure that all dependencies are installed (including the ones that the API client has, see `vue/postinstall.js`). Open your browser and navigate to [http://localhost:5173/](http://localhost:5173/). diff --git a/docs/docs/04-clients/04-react.md b/docs/docs/04-clients/04-react.md deleted file mode 100644 index e915b3121e..0000000000 --- a/docs/docs/04-clients/04-react.md +++ /dev/null @@ -1,135 +0,0 @@ -# React frontend - -:::warning -The React frontend is being reworked and is not yet stable. -In the meantime, refer to the [Ignite CCA App](https://ignite.com/marketplace/cca). -::: - -Welcome to this tutorial on using Ignite to develop a web application for your -blockchain with React. Ignite is a tool that simplifies the process of building -a blockchain application by providing a set of templates and generators that can -be used to get up and running quickly. - -One of the features of Ignite is its support for [React](https://reactjs.org/), a -popular JavaScript framework for building user interfaces. In this tutorial, you -will learn how to use Ignite to create a new blockchain and scaffold a React -frontend template. This will give you a basic foundation for your web -application and make it easier to get started building out the rest of your -application. - -Once you have your blockchain and React template set up, the next step is to -generate an API client. This will allow you to easily interact with your -blockchain from your web application, enabling you to retrieve data and make -transactions. By the end of this tutorial, you will have a fully functional web -application that is connected to your own blockchain. - -Prerequisites: - -* [Node.js](https://nodejs.org/en/) -* [Keplr](https://www.keplr.app/) Chrome extension - -## Create a blockchain and a React app - -Create a new blockchain project: - -``` -ignite scaffold chain example -``` - -To create a React frontend template, go to the `example` directory and run the -following command: - -``` -ignite scaffold react -``` - -This will create a new React project in the `react` directory. This project can be -used with any blockchain, but it depends on an API client to interact with the -blockchain. To generate an API client, run the following command in the -`example` directory: - -``` -ignite generate hooks -``` - -This command generates two directories: - -* `ts-client`: a framework-agnostic TypeScript client that can be used to - interact with your blockchain. You can learn more about how to use this client - in the [TypeScript client tutorial](/clients/typescript). -* `react/src/hooks`: a collection of - [React Hooks](https://reactjs.org/docs/hooks-intro.html) that wrap - the TypeScript client and make it easier to interact with your blockchain from - your React application. - -## Set up Keplr and an account - -Open your browser with the Keplr wallet extension installed. Follow [the -instructions](https://keplr.crunch.help/en/getting-started/creating-a-new-keplr-account) -to create a new account or use an existing one. Make sure to save the mnemonic -phrase as you will need it in the next step. - -Do not use a mnemonic phrase that is associated with an account that holds -assets you care about. If you do, you risk losing those assets. It's a good -practice to create a new account for development purposes. - -Add the account you're using in Keplr to your blockchain's `config.yml` file: - -```yml -accounts: - - name: alice - coins: [20000token, 200000000stake] - - name: bob - coins: [10000token, 100000000stake] - # highlight-start - - name: frank - coins: [10000token, 100000000stake] - mnemonic: struggle since inmate safe logic kite tag web win stay security wonder - # highlight-end -``` - -Replace the `struggle since...` mnemonic with the one you saved in the previous -step. - -Adding an account with a mnemonic to the config file will tell Ignite CLI to add -the account to the blockchain when you start it. This is useful for development -purposes, but you should not do this in production. - -## Start a blockchain and a React app - -In the `example` directory run the following command to start your blockchain: - -``` -ignite chain serve -``` - -To start your React application, go to the `react` directory and run the following -command in a separate terminal window: - -``` -npm install && npm run dev -``` - -It is recommended to run `npm install` before starting your app with `npm run -dev` to ensure that all dependencies are installed (including the ones that the -API client has, see `react/postinstall.js`). - -Open your browser and navigate to -[http://localhost:5173/](http://localhost:5173/). - -![Web app](/img/web-1.png) - -Press "Connect wallet", enter your password into Keplr and press "Approve" to -add your blockchain to Keplr. - - - -Make sure to select the account you're using for development purposes and the -"Example Network" in Keplr's blockchain dropdown. You should see a list of -assets in your React app. - -![Web app](/img/web-5.png) - -Congratulations! You have successfully created a client-side React application and -connected it to your blockchain. You can modify the source code of your React -application to build out the rest of your project. \ No newline at end of file diff --git a/docs/versioned_docs/version-v29/04-clients/04-react.md b/docs/versioned_docs/version-v29/04-clients/04-react.md deleted file mode 100644 index e915b3121e..0000000000 --- a/docs/versioned_docs/version-v29/04-clients/04-react.md +++ /dev/null @@ -1,135 +0,0 @@ -# React frontend - -:::warning -The React frontend is being reworked and is not yet stable. -In the meantime, refer to the [Ignite CCA App](https://ignite.com/marketplace/cca). -::: - -Welcome to this tutorial on using Ignite to develop a web application for your -blockchain with React. Ignite is a tool that simplifies the process of building -a blockchain application by providing a set of templates and generators that can -be used to get up and running quickly. - -One of the features of Ignite is its support for [React](https://reactjs.org/), a -popular JavaScript framework for building user interfaces. In this tutorial, you -will learn how to use Ignite to create a new blockchain and scaffold a React -frontend template. This will give you a basic foundation for your web -application and make it easier to get started building out the rest of your -application. - -Once you have your blockchain and React template set up, the next step is to -generate an API client. This will allow you to easily interact with your -blockchain from your web application, enabling you to retrieve data and make -transactions. By the end of this tutorial, you will have a fully functional web -application that is connected to your own blockchain. - -Prerequisites: - -* [Node.js](https://nodejs.org/en/) -* [Keplr](https://www.keplr.app/) Chrome extension - -## Create a blockchain and a React app - -Create a new blockchain project: - -``` -ignite scaffold chain example -``` - -To create a React frontend template, go to the `example` directory and run the -following command: - -``` -ignite scaffold react -``` - -This will create a new React project in the `react` directory. This project can be -used with any blockchain, but it depends on an API client to interact with the -blockchain. To generate an API client, run the following command in the -`example` directory: - -``` -ignite generate hooks -``` - -This command generates two directories: - -* `ts-client`: a framework-agnostic TypeScript client that can be used to - interact with your blockchain. You can learn more about how to use this client - in the [TypeScript client tutorial](/clients/typescript). -* `react/src/hooks`: a collection of - [React Hooks](https://reactjs.org/docs/hooks-intro.html) that wrap - the TypeScript client and make it easier to interact with your blockchain from - your React application. - -## Set up Keplr and an account - -Open your browser with the Keplr wallet extension installed. Follow [the -instructions](https://keplr.crunch.help/en/getting-started/creating-a-new-keplr-account) -to create a new account or use an existing one. Make sure to save the mnemonic -phrase as you will need it in the next step. - -Do not use a mnemonic phrase that is associated with an account that holds -assets you care about. If you do, you risk losing those assets. It's a good -practice to create a new account for development purposes. - -Add the account you're using in Keplr to your blockchain's `config.yml` file: - -```yml -accounts: - - name: alice - coins: [20000token, 200000000stake] - - name: bob - coins: [10000token, 100000000stake] - # highlight-start - - name: frank - coins: [10000token, 100000000stake] - mnemonic: struggle since inmate safe logic kite tag web win stay security wonder - # highlight-end -``` - -Replace the `struggle since...` mnemonic with the one you saved in the previous -step. - -Adding an account with a mnemonic to the config file will tell Ignite CLI to add -the account to the blockchain when you start it. This is useful for development -purposes, but you should not do this in production. - -## Start a blockchain and a React app - -In the `example` directory run the following command to start your blockchain: - -``` -ignite chain serve -``` - -To start your React application, go to the `react` directory and run the following -command in a separate terminal window: - -``` -npm install && npm run dev -``` - -It is recommended to run `npm install` before starting your app with `npm run -dev` to ensure that all dependencies are installed (including the ones that the -API client has, see `react/postinstall.js`). - -Open your browser and navigate to -[http://localhost:5173/](http://localhost:5173/). - -![Web app](/img/web-1.png) - -Press "Connect wallet", enter your password into Keplr and press "Approve" to -add your blockchain to Keplr. - - - -Make sure to select the account you're using for development purposes and the -"Example Network" in Keplr's blockchain dropdown. You should see a list of -assets in your React app. - -![Web app](/img/web-5.png) - -Congratulations! You have successfully created a client-side React application and -connected it to your blockchain. You can modify the source code of your React -application to build out the rest of your project. \ No newline at end of file diff --git a/go.mod b/go.mod index 4aba4e2c46..660ccde906 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( github.com/hashicorp/go-hclog v1.6.3 github.com/hashicorp/go-plugin v1.6.3 github.com/iancoleman/strcase v0.3.0 - github.com/ignite/web v0.6.1 + github.com/ignite/web v1.0.8 github.com/lib/pq v1.10.9 github.com/mitchellh/mapstructure v1.5.0 github.com/muesli/reflow v0.3.0 diff --git a/go.sum b/go.sum index 08404755fb..07d09532a4 100644 --- a/go.sum +++ b/go.sum @@ -1107,8 +1107,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= -github.com/ignite/web v0.6.1 h1:kHG+T7NnR8cCPjAGxEFQD+njVYM08toeG57iYRXzpwo= -github.com/ignite/web v0.6.1/go.mod h1:WZWBaBYF8RazN7dE462BLpvXDY8ScacxcJ07BKwX/jY= +github.com/ignite/web v1.0.8 h1:St3L6UJj70+h16+No5em8Vn2Hx93tS2G1MyWO/Kt1cc= +github.com/ignite/web v1.0.8/go.mod h1:WZWBaBYF8RazN7dE462BLpvXDY8ScacxcJ07BKwX/jY= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= diff --git a/ignite/cmd/generate.go b/ignite/cmd/generate.go index 16ca7065e9..1fec283aa3 100644 --- a/ignite/cmd/generate.go +++ b/ignite/cmd/generate.go @@ -33,11 +33,12 @@ meant to be edited by hand. flagSetPath(c) flagSetClearCache(c) - c.AddCommand(NewGenerateGo()) - c.AddCommand(NewGenerateTSClient()) - c.AddCommand(NewGenerateComposables()) - c.AddCommand(NewGenerateHooks()) - c.AddCommand(NewGenerateOpenAPI()) + c.AddCommand( + NewGenerateGo(), + NewGenerateTSClient(), + NewGenerateComposables(), + NewGenerateOpenAPI(), + ) return c } diff --git a/ignite/cmd/generate_hooks.go b/ignite/cmd/generate_hooks.go deleted file mode 100644 index 91975278f5..0000000000 --- a/ignite/cmd/generate_hooks.go +++ /dev/null @@ -1,58 +0,0 @@ -package ignitecmd - -import ( - "github.com/spf13/cobra" - - "github.com/ignite/cli/v29/ignite/pkg/cliui" - "github.com/ignite/cli/v29/ignite/pkg/cliui/icons" - "github.com/ignite/cli/v29/ignite/services/chain" -) - -func NewGenerateHooks() *cobra.Command { - c := &cobra.Command{ - Use: "hooks", - Short: "TypeScript frontend client and React hooks", - RunE: generateHooksHandler, - } - - c.Flags().AddFlagSet(flagSetYes()) - c.Flags().StringP(flagOutput, "o", "", "React hooks output path") - - return c -} - -func generateHooksHandler(cmd *cobra.Command, _ []string) error { - session := cliui.New( - cliui.StartSpinnerWithText(statusGenerating), - cliui.WithoutUserInteraction(getYes(cmd)), - ) - defer session.End() - - c, err := chain.NewWithHomeFlags( - cmd, - chain.WithOutputer(session), - chain.CollectEvents(session.EventBus()), - chain.PrintGeneratedPaths()) - if err != nil { - return err - } - - cacheStorage, err := newCache(cmd) - if err != nil { - return err - } - - output, _ := cmd.Flags().GetString(flagOutput) - - var opts []chain.GenerateTarget - if flagGetEnableProtoVendor(cmd) { - opts = append(opts, chain.GenerateProtoVendor()) - } - - err = c.Generate(cmd.Context(), cacheStorage, chain.GenerateHooks(output), opts...) - if err != nil { - return err - } - - return session.Println(icons.OK, "Generated Typescript Client and React hooks") -} diff --git a/ignite/cmd/scaffold_react.go b/ignite/cmd/scaffold_react.go index dc26c49c1f..60a9dfd47d 100644 --- a/ignite/cmd/scaffold_react.go +++ b/ignite/cmd/scaffold_react.go @@ -2,40 +2,14 @@ package ignitecmd import ( "github.com/spf13/cobra" - - chainconfig "github.com/ignite/cli/v29/ignite/config/chain" - "github.com/ignite/cli/v29/ignite/pkg/cliui" - "github.com/ignite/cli/v29/ignite/pkg/cosmosgen" ) // NewScaffoldReact scaffolds a React app for a chain. func NewScaffoldReact() *cobra.Command { c := &cobra.Command{ - Hidden: true, // hidden util we have a better ts-client. - Use: "react", - Short: "React web app template", - Args: cobra.NoArgs, - PreRunE: migrationPreRunHandler, - RunE: scaffoldReactHandler, + Use: "react", + Deprecated: "the React scaffolding feature is removed from Ignite CLI.\nPlease use the Ignite CCA app to create a React app.\nFor more information, visit: https://ignite.com/marketplace/CCA", } - c.Flags().AddFlagSet(flagSetYes()) - c.Flags().StringP(flagPath, "p", "./"+chainconfig.DefaultReactPath, "path to scaffold content of the React app") - return c } - -func scaffoldReactHandler(cmd *cobra.Command, _ []string) error { - session := cliui.New( - cliui.StartSpinnerWithText(statusScaffolding), - cliui.WithoutUserInteraction(getYes(cmd)), - ) - defer session.End() - - path := flagGetPath(cmd) - if err := cosmosgen.React(path); err != nil { - return err - } - - return session.Printf("\nšŸŽ‰ Scaffolded a React app in %s.\n\n", path) -} diff --git a/ignite/cmd/scaffold_vue.go b/ignite/cmd/scaffold_vue.go index 2228979414..541b1e001e 100644 --- a/ignite/cmd/scaffold_vue.go +++ b/ignite/cmd/scaffold_vue.go @@ -1,6 +1,8 @@ package ignitecmd import ( + "path/filepath" + "github.com/spf13/cobra" chainconfig "github.com/ignite/cli/v29/ignite/config/chain" @@ -11,7 +13,6 @@ import ( // NewScaffoldVue scaffolds a Vue.js app for a chain. func NewScaffoldVue() *cobra.Command { c := &cobra.Command{ - Hidden: true, // hidden util we have a better ts-client. Use: "vue", Short: "Vue 3 web app template", Args: cobra.NoArgs, @@ -20,7 +21,6 @@ func NewScaffoldVue() *cobra.Command { } c.Flags().AddFlagSet(flagSetYes()) - c.Flags().StringP(flagPath, "p", "./"+chainconfig.DefaultVuePath, "path to scaffold content of the Vue.js app") return c } @@ -32,7 +32,7 @@ func scaffoldVueHandler(cmd *cobra.Command, _ []string) error { ) defer session.End() - path := flagGetPath(cmd) + path := filepath.Join(".", chainconfig.DefaultVuePath) if err := cosmosgen.Vue(path); err != nil { return err } diff --git a/ignite/config/chain/base/config.go b/ignite/config/chain/base/config.go index c2772f73f3..5b1cfdce4f 100644 --- a/ignite/config/chain/base/config.go +++ b/ignite/config/chain/base/config.go @@ -41,9 +41,6 @@ type Client struct { // Composables configures code generation for Vue 3 composables. Composables Composables `yaml:"composables,omitempty" doc:"Configures Vue 3 composables code generation."` - // Hooks configures code generation for React hooks. - Hooks Hooks `yaml:"hooks,omitempty" doc:"Configures React hooks code generation."` - // OpenAPI configures OpenAPI spec generation for API. OpenAPI OpenAPI `yaml:"openapi,omitempty" doc:"Configures OpenAPI spec generation for the API."` } @@ -60,12 +57,6 @@ type Composables struct { Path string `yaml:"path" doc:"Relative path where the application's composable files are located."` } -// Hooks configures code generation for react-query hooks. -type Hooks struct { - // Path configures out location for generated vue-query hooks. - Path string `yaml:"path" doc:"Relative path where the application's hooks files are located."` -} - // OpenAPI configures OpenAPI spec generation for API. type OpenAPI struct { Path string `yaml:"path" doc:"Relative path where the application's OpenAPI files are located."` diff --git a/ignite/config/chain/config.go b/ignite/config/chain/config.go index 778b5c6220..0fa14999bf 100644 --- a/ignite/config/chain/config.go +++ b/ignite/config/chain/config.go @@ -26,10 +26,6 @@ var ( // The path is relative to the app's directory. DefaultVuePath = "vue" - // DefaultReactPath defines the default relative path to use when scaffolding a React app. - // The path is relative to the app's directory. - DefaultReactPath = "react" - // DefaultComposablesPath defines the default relative path to use when generating useQuery composables for a Vue app. // The path is relative to the app's directory. DefaultComposablesPath = "vue/src/composables" @@ -37,10 +33,6 @@ var ( // DefaultVueTypesPath defines the default vue types path. DefaultVueTypesPath = "vue/src/views/Types.vue" - // DefaultHooksPath defines the default relative path to use when generating useQuery hooks for a React app. - // The path is relative to the app's directory. - DefaultHooksPath = "react/src/hooks" - // DefaultOpenAPIPath defines the default relative path to use when generating an OpenAPI schema. // The path is relative to the app's directory. DefaultOpenAPIPath = "docs/static/openapi.json" @@ -100,16 +92,6 @@ func ComposablesPath(conf *Config) string { return DefaultComposablesPath } -// HooksPath returns the relative path to the React useQuery hooks directory. -// Path is relative to the app's directory. -func HooksPath(conf *Config) string { - if path := strings.TrimSpace(conf.Client.Hooks.Path); path != "" { - return filepath.Clean(path) - } - - return DefaultHooksPath -} - // LocateDefault locates the default path for the config file. // Returns ErrConfigNotFound when no config file found. func LocateDefault(root string) (path string, err error) { diff --git a/ignite/pkg/cosmosgen/cosmosgen.go b/ignite/pkg/cosmosgen/cosmosgen.go index 15f9093136..6152fe16e9 100644 --- a/ignite/pkg/cosmosgen/cosmosgen.go +++ b/ignite/pkg/cosmosgen/cosmosgen.go @@ -29,9 +29,6 @@ type generateOptions struct { composablesOut func(module.Module) string composablesRootPath string - hooksOut func(module.Module) string - hooksRootPath string - specOut string } @@ -58,13 +55,6 @@ func WithComposablesGeneration(out ModulePathFunc, composablesRootPath string) O } } -func WithHooksGeneration(out ModulePathFunc, hooksRootPath string) Option { - return func(o *generateOptions) { - o.hooksOut = out - o.hooksRootPath = hooksRootPath - } -} - // WithGoGeneration adds protobuf (gogoproto) code generation. func WithGoGeneration() Option { return func(o *generateOptions) { @@ -102,6 +92,7 @@ type generator struct { appPath string protoDir string goModPath string + frontendPath string opts *generateOptions sdkImport string sdkDir string @@ -122,7 +113,7 @@ func (g *generator) cleanup() { // Generate generates code from protoDir of an SDK app residing at appPath with given options. // protoDir must be relative to the projectPath. -func Generate(ctx context.Context, cacheStorage cache.Storage, appPath, protoDir, goModPath string, options ...Option) error { +func Generate(ctx context.Context, cacheStorage cache.Storage, appPath, protoDir, goModPath string, frontendPath string, options ...Option) error { buf, err := cosmosbuf.New(cacheStorage, goModPath) if err != nil { return err @@ -133,6 +124,7 @@ func Generate(ctx context.Context, cacheStorage cache.Storage, appPath, protoDir appPath: appPath, protoDir: protoDir, goModPath: goModPath, + frontendPath: frontendPath, opts: &generateOptions{}, thirdModules: make(map[string][]module.Module), thirdModuleIncludes: make(map[string]protoIncludes), @@ -180,26 +172,14 @@ func Generate(ctx context.Context, cacheStorage cache.Storage, appPath, protoDir } if g.opts.composablesRootPath != "" { - if err := g.generateComposables("vue"); err != nil { + if err := g.generateComposables(); err != nil { return err } // Update Vue app dependencies when Vue composables are generated. // This update is required to link the "ts-client" folder so the // package is available during development before publishing it. - if err := g.updateComposableDependencies("vue"); err != nil { - return err - } - } - if g.opts.hooksRootPath != "" { - if err := g.generateComposables("react"); err != nil { - return err - } - - // Update React app dependencies when React hooks are generated. - // This update is required to link the "ts-client" folder so the - // package is available during development before publishing it. - if err := g.updateComposableDependencies("react"); err != nil { + if err := g.updateComposableDependencies(); err != nil { return err } } diff --git a/ignite/pkg/cosmosgen/generate_composables.go b/ignite/pkg/cosmosgen/generate_composables.go index 864dcd94af..98a642a815 100644 --- a/ignite/pkg/cosmosgen/generate_composables.go +++ b/ignite/pkg/cosmosgen/generate_composables.go @@ -15,31 +15,30 @@ import ( "github.com/ignite/cli/v29/ignite/pkg/gomodulepath" ) -type composablesGenerator struct { - g *generator - frontendType string -} +func (g *generator) checkVueExists() error { + _, err := os.Stat(filepath.Join(g.appPath, g.frontendPath)) + if errors.Is(err, os.ErrNotExist) { + return errors.New("frontend does not exist, please run `ignite scaffold vue` first") + } -func newComposablesGenerator(g *generator, frontendType string) *composablesGenerator { - return &composablesGenerator{g, frontendType} + return err } -func (g *generator) updateComposableDependencies(frontendType string) error { - // Init the path to the appropriate frontend folder inside the app - frontendPath := filepath.Join(g.appPath, frontendType) - packagesPath := filepath.Join(frontendPath, "package.json") - if _, err := os.Stat(packagesPath); errors.Is(err, os.ErrNotExist) { - return nil +func (g *generator) updateComposableDependencies() error { + if err := g.checkVueExists(); err != nil { + return err } - // Read the Vue app package file + // Init the path to the appropriate frontend folder inside the app + frontendPath := filepath.Join(g.appPath, g.frontendPath) + packagesPath := filepath.Join(g.appPath, g.frontendPath, "package.json") + b, err := os.ReadFile(packagesPath) if err != nil { return err } - var pkg map[string]interface{} - + var pkg map[string]any if err := json.Unmarshal(b, &pkg); err != nil { return errors.Errorf("error parsing %s: %w", packagesPath, err) } @@ -90,7 +89,11 @@ func (g *generator) updateComposableDependencies(frontendType string) error { return nil } -func (g *generator) generateComposables(frontendType string) error { +func (g *generator) generateComposables() error { + if err := g.checkVueExists(); err != nil { + return err + } + chainPath, _, err := gomodulepath.Find(g.appPath) if err != nil { return err @@ -106,7 +109,7 @@ func (g *generator) generateComposables(frontendType string) error { data.Modules = append(data.Modules, modules...) } - vsg := newComposablesGenerator(g, frontendType) + vsg := newComposablesGenerator(g) if err := vsg.generateComposableTemplates(data); err != nil { return err } @@ -114,6 +117,14 @@ func (g *generator) generateComposables(frontendType string) error { return vsg.generateRootTemplates(data) } +type composablesGenerator struct { + g *generator +} + +func newComposablesGenerator(g *generator) *composablesGenerator { + return &composablesGenerator{g} +} + func (g *composablesGenerator) generateComposableTemplates(p generatePayload) error { gg := &errgroup.Group{} @@ -127,35 +138,22 @@ func (g *composablesGenerator) generateComposableTemplates(p generatePayload) er } func (g *composablesGenerator) generateComposableTemplate(m module.Module, p generatePayload) error { - var outDir string - if g.frontendType == "vue" { - outDir = g.g.opts.composablesOut(m) - } else { - outDir = g.g.opts.hooksOut(m) - } - + outDir := g.g.opts.composablesOut(m) if err := os.MkdirAll(outDir, 0o766); err != nil { return err } return templateTSClientComposable.Write(outDir, "", struct { - Module module.Module - PackageNS string - FrontendType string + Module module.Module + PackageNS string }{ - Module: m, - PackageNS: p.PackageNS, - FrontendType: g.frontendType, + Module: m, + PackageNS: p.PackageNS, }) } func (g *composablesGenerator) generateRootTemplates(p generatePayload) error { - var outDir string - if g.frontendType == "vue" { - outDir = g.g.opts.composablesRootPath - } else { - outDir = g.g.opts.hooksRootPath - } + outDir := g.g.opts.composablesRootPath if err := os.MkdirAll(outDir, 0o766); err != nil { return err } diff --git a/ignite/pkg/cosmosgen/templates/composable/index.ts.tpl b/ignite/pkg/cosmosgen/templates/composable/index.ts.tpl index 352f128f56..4f3a97eb5a 100644 --- a/ignite/pkg/cosmosgen/templates/composable/index.ts.tpl +++ b/ignite/pkg/cosmosgen/templates/composable/index.ts.tpl @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import { useQuery, type UseQueryOptions, useInfiniteQuery, type UseInfiniteQueryOptions, type InfiniteData } from "@tanstack/{{- .FrontendType -}}-query"; +import { useQuery, type UseQueryOptions, useInfiniteQuery, type UseInfiniteQueryOptions, type InfiniteData } from "@tanstack/vue-query"; import { useClient } from '../useClient'; export default function use{{ camelCaseUpperSta $.Module.Pkg.Name }}() { diff --git a/ignite/pkg/cosmosgen/webtemplates.go b/ignite/pkg/cosmosgen/webtemplates.go index 3c3c2f3ea5..000e70096a 100644 --- a/ignite/pkg/cosmosgen/webtemplates.go +++ b/ignite/pkg/cosmosgen/webtemplates.go @@ -6,11 +6,6 @@ import ( "github.com/ignite/cli/v29/ignite/pkg/localfs" ) -// React scaffolds a React app for a chain. -func React(path string) error { - return localfs.Save(webtemplates.ReactBoilerplate(), path) -} - // Vue scaffolds a Vue.js app for a chain. func Vue(path string) error { return localfs.Save(webtemplates.VueBoilerplate(), path) diff --git a/ignite/services/chain/generate.go b/ignite/services/chain/generate.go index b9d68728d8..97c8f05cef 100644 --- a/ignite/services/chain/generate.go +++ b/ignite/services/chain/generate.go @@ -21,11 +21,9 @@ type generateOptions struct { isGoEnabled bool isTSClientEnabled bool isComposablesEnabled bool - isHooksEnabled bool isOpenAPIEnabled bool tsClientPath string composablesPath string - hooksPath string } // GenerateTarget is a target to generate code for from proto files. @@ -60,16 +58,6 @@ func GenerateComposables(path string) GenerateTarget { } } -// GenerateHooks enables generating proto based Typescript Client and React composables. -func GenerateHooks(path string) GenerateTarget { - return func(o *generateOptions) { - o.isOpenAPIEnabled = true - o.isTSClientEnabled = true - o.isHooksEnabled = true - o.hooksPath = path - } -} - // GenerateOpenAPI enables generating OpenAPI spec for your chain. func GenerateOpenAPI() GenerateTarget { return func(o *generateOptions) { @@ -111,10 +99,6 @@ func (c *Chain) generateFromConfig(ctx context.Context, cacheStorage cache.Stora if p := conf.Client.Composables.Path; p != "" { targets = append(targets, GenerateComposables(p)) } - - if p := conf.Client.Hooks.Path; p != "" { - targets = append(targets, GenerateHooks(p)) - } } // Generate proto based code for Go and optionally for any optional targets @@ -152,8 +136,8 @@ func (c *Chain) Generate( } var ( - openAPIPath, tsClientPath, composablesPath, hooksPath string - updateConfig bool + openAPIPath, tsClientPath, composablesPath string + updateConfig bool ) if targetOptions.isOpenAPIEnabled { @@ -222,36 +206,13 @@ func (c *Chain) Generate( ) } - if targetOptions.isHooksEnabled { - hooksPath = targetOptions.hooksPath - if hooksPath == "" { - hooksPath = chainconfig.HooksPath(conf) - - if conf.Client.Hooks.Path == "" { - conf.Client.Hooks.Path = hooksPath - updateConfig = true - } - } - - // Non-absolute Hooks output paths must be treated as relative to the app directory - if !filepath.IsAbs(hooksPath) { - hooksPath = filepath.Join(c.app.Path, hooksPath) - } - - options = append(options, - cosmosgen.WithHooksGeneration( - cosmosgen.ComposableModulePath(hooksPath), - hooksPath, - ), - ) - } - if err := cosmosgen.Generate( ctx, cacheStorage, c.app.Path, conf.Build.Proto.Path, c.app.ImportPath, + chainconfig.DefaultVuePath, options..., ); err != nil { return &CannotBuildAppError{err} @@ -281,14 +242,6 @@ func (c *Chain) Generate( ) } - if targetOptions.isHooksEnabled { - c.ev.Send( - fmt.Sprintf("React hooks path: %s", hooksPath), - events.Icon(icons.Bullet), - events.ProgressFinish(), - ) - } - if targetOptions.isOpenAPIEnabled { c.ev.Send( fmt.Sprintf("OpenAPI path: %s", openAPIPath), diff --git a/ignite/services/scaffolder/scaffolder.go b/ignite/services/scaffolder/scaffolder.go index a54d95639c..723a77b6bc 100644 --- a/ignite/services/scaffolder/scaffolder.go +++ b/ignite/services/scaffolder/scaffolder.go @@ -176,7 +176,15 @@ func protoc(ctx context.Context, cacheStorage cache.Storage, projectPath, protoD options = append(options, cosmosgen.WithOpenAPIGeneration(openAPIPath)) } - if err := cosmosgen.Generate(ctx, cacheStorage, projectPath, protoDir, goModPath, options...); err != nil { + if err := cosmosgen.Generate( + ctx, + cacheStorage, + projectPath, + protoDir, + goModPath, + chainconfig.DefaultVuePath, + options..., + ); err != nil { return err } diff --git a/ignite/templates/app/files/readme.md.plush b/ignite/templates/app/files/readme.md.plush index c480ea2870..c0e2c15248 100644 --- a/ignite/templates/app/files/readme.md.plush +++ b/ignite/templates/app/files/readme.md.plush @@ -15,11 +15,10 @@ Your blockchain in development can be configured with `config.yml`. To learn mor ### Web Frontend -Additionally, Ignite CLI offers both Vue and React options for frontend scaffolding: +Additionally, Ignite CLI offers a frontend scaffolding feature (based on Vue) to help you quickly build a web frontend for your blockchain: -For a Vue frontend, use: `ignite scaffold vue` -For a React frontend, use: `ignite scaffold react` -These commands can be run within your scaffolded blockchain project. +Use: `ignite scaffold vue` +This command can be run within your scaffolded blockchain project. For more information see the [monorepo for Ignite front-end development](https://github.com/ignite/web). diff --git a/integration/app.go b/integration/app.go index dc3aee6994..6de6125627 100644 --- a/integration/app.go +++ b/integration/app.go @@ -376,8 +376,15 @@ func (a *App) addScaffoldCmd(typeName string, args ...string) { index := "" response := "" params := "" - name := args[0] - args = args[1:] + name := typeName + + // in the case of scaffolding commands that do no take arguments + // we can skip the argument parsing + if len(args) > 0 { + name = args[0] + args = args[1:] + } + filteredArgs := make([]string, 0) // remove the flags from the args diff --git a/integration/client.go b/integration/client.go deleted file mode 100644 index c48df283f2..0000000000 --- a/integration/client.go +++ /dev/null @@ -1,156 +0,0 @@ -package envtest - -import ( - "bytes" - "maps" - "os" - "os/exec" - "path/filepath" - "runtime" - - "github.com/stretchr/testify/require" - - chainconfig "github.com/ignite/cli/v29/ignite/config/chain" - "github.com/ignite/cli/v29/ignite/pkg/cmdrunner" - "github.com/ignite/cli/v29/ignite/pkg/cmdrunner/step" -) - -type clientOptions struct { - env map[string]string - testName, testFilePath string -} - -// ClientOption defines options for the TS client test runner. -type ClientOption func(*clientOptions) - -// ClientEnv option defines environment values for the tests. -func ClientEnv(env map[string]string) ClientOption { - return func(o *clientOptions) { - maps.Copy(o.env, env) - } -} - -// ClientTestName option defines a pattern to match the test names that should be run. -func ClientTestName(pattern string) ClientOption { - return func(o *clientOptions) { - o.testName = pattern - } -} - -// ClientTestFile option defines the name of the file where to look for tests. -func ClientTestFile(filePath string) ClientOption { - return func(o *clientOptions) { - o.testFilePath = filePath - } -} - -// RunClientTests runs the Typescript client tests. -func (a App) RunClientTests(options ...ClientOption) bool { - npm, err := exec.LookPath("npm") - require.NoError(a.env.t, err, "npm binary not found") - - // The root dir for the tests must be an absolute path. - // It is used as the start search point to find test files. - rootDir, err := os.Getwd() - require.NoError(a.env.t, err) - - // The filename of this module is required to be able to define the location - // of the TS client test runner package to be used as working directory when - // running the tests. - _, filename, _, ok := runtime.Caller(0) - if !ok { - a.env.t.Fatal("failed to read file name") - } - - opts := clientOptions{ - env: map[string]string{ - // Absolute path to the blockchain app directory - "TEST_CHAIN_PATH": a.path, - // Absolute path to the TS client directory - "TEST_TSCLIENT_DIR": filepath.Join(a.path, chainconfig.DefaultTSClientPath), - }, - } - for _, o := range options { - o(&opts) - } - - var ( - output bytes.Buffer - env []string - ) - - // Install the dependencies needed to run TS client tests - ok = a.env.Exec("install client dependencies", step.NewSteps( - step.New( - step.Workdir(filepath.Join(a.path, chainconfig.DefaultTSClientPath)), - step.Stdout(&output), - step.Exec(npm, "install"), - step.PostExec(func(err error) error { - // Print the npm output when there is an error - if err != nil { - a.env.t.Log("\n", output.String()) - } - - return err - }), - ), - )) - if !ok { - return false - } - - output.Reset() - - args := []string{"run", "test", "--", "--dir", rootDir} - if opts.testName != "" { - args = append(args, "-t", opts.testName) - } - - if opts.testFilePath != "" { - args = append(args, opts.testFilePath) - } - - for k, v := range opts.env { - env = append(env, cmdrunner.Env(k, v)) - } - - // The tests are run from the TS client test runner package directory - runnerDir := filepath.Join(filepath.Dir(filename), "testdata/tstestrunner") - - // TODO: Ignore stderr ? Errors are already displayed with traceback in the stdout - return a.env.Exec("run client tests", step.NewSteps( - // Make sure the test runner dependencies are installed - step.New( - step.Workdir(runnerDir), - step.Stdout(&output), - step.Exec(npm, "install"), - step.PostExec(func(err error) error { - // Print the npm output when there is an error - if err != nil { - a.env.t.Log("\n", output.String()) - } - - return err - }), - ), - // Run the TS client tests - step.New( - step.Workdir(runnerDir), - step.Stdout(&output), - step.Env(env...), - step.PreExec(func() error { - // Clear the output from the previous step - output.Reset() - - return nil - }), - step.Exec(npm, args...), - step.PostExec(func(err error) error { - // Always print tests output to be available on errors or when verbose is enabled - a.env.t.Log("\n", output.String()) - - return err - }), - ), - )) -} diff --git a/integration/cosmosgen/bank_module_test.go b/integration/cosmosgen/bank_module_test.go deleted file mode 100644 index 53875f2211..0000000000 --- a/integration/cosmosgen/bank_module_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package cosmosgen_test - -import ( - "context" - "encoding/json" - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - chainconfig "github.com/ignite/cli/v29/ignite/config/chain" - "github.com/ignite/cli/v29/ignite/config/chain/base" - "github.com/ignite/cli/v29/ignite/pkg/xurl" - envtest "github.com/ignite/cli/v29/integration" -) - -// TestBankModule tests the bank module by creating accounts, transferring tokens between them, and querying the account balances. -func TestBankModule(t *testing.T) { - t.Skip() - - var ( - env = envtest.New(t) - app = env.ScaffoldApp("chain", "--no-module") - servers = app.RandomizeServerPorts() - ) - - queryAPI, err := xurl.HTTP(servers.API) - require.NoError(t, err) - - txAPI, err := xurl.HTTP(servers.RPC) - require.NoError(t, err) - - // Accounts to be included in the genesis - accounts := []base.Account{ - { - Name: "account1", - Address: "cosmos1j8hw8283hj80hhq8urxaj40syrzqp77dt8qwhm", - Mnemonic: fmt.Sprint( - "toe mail light plug pact length excess predict real artwork laundry when steel ", - "online adapt clutch debate vehicle dash alter rifle virtual season almost", - ), - Coins: []string{"10000token", "10000stake"}, - }, - { - Name: "account2", - Address: "cosmos19yy9sf00k00cjcwh532haeq8s63uhdy7qs5m2n", - Mnemonic: fmt.Sprint( - "someone major rule wrestle forget want job record coil table enter gold bracket ", - "zone tent music grow shiver width index radio matter asset when", - ), - Coins: []string{"100token", "100stake"}, - }, - { - Name: "account3", - Address: "cosmos10957ee377t2xpwyt4mlpedjldp592h0ylt8uz7", - Mnemonic: fmt.Sprint( - "edit effort own cat chuckle rookie mechanic side tool sausage other fade math ", - "joy midnight cabin act plastic spawn loud chest invest budget rebel", - ), - Coins: []string{"100token", "100stake"}, - }, - } - - app.EditConfig(func(cfg *chainconfig.Config) { - cfg.Accounts = append(cfg.Accounts, accounts...) - }) - - env.Must(app.GenerateTSClient()) - - ctx, cancel := context.WithTimeout(env.Ctx(), envtest.ServeTimeout) - defer cancel() - - go func() { - app.Serve("should serve app", envtest.ExecCtx(ctx)) - }() - - // Wait for the server to be up before running the client tests - app.WaitChainUp(ctx, servers.API) - - testAccounts, err := json.Marshal(accounts) - require.NoError(t, err) - - env.Must(app.RunClientTests( - envtest.ClientTestFile("bank_module_test.ts"), - envtest.ClientEnv(map[string]string{ - "TEST_QUERY_API": queryAPI, - "TEST_TX_API": txAPI, - "TEST_ACCOUNTS": string(testAccounts), - }), - )) -} diff --git a/integration/cosmosgen/bank_module_test.ts b/integration/cosmosgen/bank_module_test.ts deleted file mode 100644 index 8a6090ac97..0000000000 --- a/integration/cosmosgen/bank_module_test.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; -import { isDeliverTxSuccess } from "@cosmjs/stargate"; - -describe("bank module", async () => { - const { Client } = await import("client"); - - it("should transfer to two different addresses", async () => { - const { account1, account2, account3 } = globalThis.accounts; - - const mnemonic = account1["Mnemonic"]; - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic); - const [account] = await wallet.getAccounts(); - - const denom = "token"; - const env = { - denom, - rpcURL: globalThis.txApi, - apiURL: globalThis.queryApi, - }; - const client = new Client(env, wallet); - - const toAddresses = [account2["Address"], account3["Address"]]; - - // Both accounts start with 100token before the transfer - const result = await client.signAndBroadcast([ - client.CosmosBankV1Beta1.tx.msgSend({ - value: { - fromAddress: account.address, - toAddress: toAddresses[0], - amount: [{ denom, amount: "100" }], - }, - }), - client.CosmosBankV1Beta1.tx.msgSend({ - value: { - fromAddress: account.address, - toAddress: toAddresses[1], - amount: [{ denom, amount: "200" }], - }, - }), - ]); - - expect(isDeliverTxSuccess(result)).toEqual(true); - - // Check that the transfers were successful - const cases = [ - { address: toAddresses[0], wantAmount: "200" }, - { address: toAddresses[1], wantAmount: "300" }, - ]; - - for (let tc of cases) { - let response = await client.CosmosBankV1Beta1.query.queryBalance( - tc.address, - { denom } - ); - - expect(response.statusText).toEqual("OK"); - expect(response.data.balance.amount).toEqual(tc.wantAmount); - } - }); -}); diff --git a/integration/cosmosgen/cosmosgen_composables_test.go b/integration/cosmosgen/cosmosgen_composables_test.go index 37e62e2982..d7ecdb9fd5 100644 --- a/integration/cosmosgen/cosmosgen_composables_test.go +++ b/integration/cosmosgen/cosmosgen_composables_test.go @@ -12,7 +12,9 @@ import ( ) func TestCosmosGenScaffoldComposables(t *testing.T) { - t.Skip() + if envtest.IsCI { + t.Skip("Skipping TestCosmosGenScaffoldComposables test in CI environment") + } var ( env = envtest.New(t) @@ -67,6 +69,12 @@ func TestCosmosGenScaffoldComposables(t *testing.T) { composablesDirGenerated := filepath.Join(app.SourcePath(), "vue/src/composables") require.NoError(t, os.RemoveAll(composablesDirGenerated)) + app.Scaffold( + "scaffold vue", + false, + "vue", + ) + app.Generate( "generate composables", false, @@ -94,16 +102,25 @@ func TestCosmosGenScaffoldComposables(t *testing.T) { "useCosmosUpgradeV1Beta1", "useCosmosVestingV1Beta1", // custom modules - "useTestBlogBlog", - "useTestBlogWithmsg", - "useTestBlogWithoutmsg", + "useBlogBlogV1", + "useBlogWithmsgV1", + "useBlogWithoutmsgV1", } for _, mod := range expectedQueryModules { - _, err := os.Stat(filepath.Join(composablesDirGenerated, mod)) if assert.False(t, os.IsNotExist(err), "missing composable %q in %s", mod, composablesDirGenerated) { assert.NoError(t, err) } } + + if t.Failed() { + // list composables files + composablesFiles, err := os.ReadDir(composablesDirGenerated) + require.NoError(t, err) + t.Log("Composables files:", len(composablesFiles)) + for _, file := range composablesFiles { + t.Logf(" - %s", file.Name()) + } + } } diff --git a/integration/cosmosgen/cosmosgen_hooks_test.go b/integration/cosmosgen/cosmosgen_hooks_test.go deleted file mode 100644 index 352af6a4bf..0000000000 --- a/integration/cosmosgen/cosmosgen_hooks_test.go +++ /dev/null @@ -1,151 +0,0 @@ -package cosmosgen_test - -import ( - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/ignite/cli/v29/ignite/pkg/cmdrunner/step" - envtest "github.com/ignite/cli/v29/integration" -) - -func TestCosmosGenScaffoldHooks(t *testing.T) { - t.Skip() - - var ( - env = envtest.New(t) - app = env.ScaffoldApp("github.com/test/blog") - ) - - const ( - withMsgModuleName = "withmsg" - withoutMsgModuleName = "withoutmsg" - ) - - env.Must(env.Exec("add custom module with message", - step.NewSteps(step.New( - step.Exec( - envtest.IgniteApp, - "s", - "module", - "--yes", - withMsgModuleName, - ), - step.Workdir(app.SourcePath()), - )), - )) - - env.Must(env.Exec("create a message", - step.NewSteps(step.New( - step.Exec( - envtest.IgniteApp, - "s", - "message", - "--yes", - "mymessage", - "myfield1", - "myfield2:bool", - "--module", - withMsgModuleName, - ), - step.Workdir(app.SourcePath()), - )), - )) - - env.Must(env.Exec("add custom module without message", - step.NewSteps(step.New( - step.Exec( - envtest.IgniteApp, - "s", - "module", - "--yes", - withoutMsgModuleName, - ), - step.Workdir(app.SourcePath()), - )), - )) - - env.Must(env.Exec("create a type", - step.NewSteps(step.New( - step.Exec( - envtest.IgniteApp, - "s", - "type", - "--yes", - "mytype", - "mytypefield", - "--module", - withoutMsgModuleName, - ), - step.Workdir(app.SourcePath()), - )), - )) - - env.Must(env.Exec("create a query", - step.NewSteps(step.New( - step.Exec( - envtest.IgniteApp, - "s", - "query", - "--yes", - "myQuery", - "mytypefield", - "--module", - withoutMsgModuleName, - ), - step.Workdir(app.SourcePath()), - )), - )) - - hooksDireGenerated := filepath.Join(app.SourcePath(), "react/src/hooks") - require.NoError(t, os.RemoveAll(hooksDireGenerated)) - - env.Must(env.Exec("generate hooks", - step.NewSteps(step.New( - step.Exec( - envtest.IgniteApp, - "g", - "hooks", - "--yes", - "--clear-cache", - ), - step.Workdir(app.SourcePath()), - )), - )) - - expectedQueryModules := []string{ - "useCosmosAuthV1Beta1", - "useCosmosAuthzV1Beta1", - "useCosmosBankV1Beta1", - "useCosmosBaseTendermintV1Beta1", - "useCosmosDistributionV1Beta1", - "useCosmosEvidenceV1Beta1", - "useCosmosFeegrantV1Beta1", - "useCosmosGovV1Beta1", - "useCosmosGovV1", - "useCosmosGroupV1", - "useCosmosMintV1Beta1", - "useCosmosNftV1Beta1", - "useCosmosParamsV1Beta1", - "useCosmosSlashingV1Beta1", - "useCosmosStakingV1Beta1", - "useCosmosTxV1Beta1", - "useCosmosUpgradeV1Beta1", - "useCosmosVestingV1Beta1", - // custom modules - "useTestBlogBlog", - "useTestBlogWithmsg", - "useTestBlogWithoutmsg", - } - - for _, mod := range expectedQueryModules { - - _, err := os.Stat(filepath.Join(hooksDireGenerated, mod)) - if assert.False(t, os.IsNotExist(err), "missing hook %q in %s", mod, hooksDireGenerated) { - assert.NoError(t, err) - } - } -} diff --git a/integration/cosmosgen/cosmosgen_test.go b/integration/cosmosgen/cosmosgen_test.go index af1473e651..22f289432a 100644 --- a/integration/cosmosgen/cosmosgen_test.go +++ b/integration/cosmosgen/cosmosgen_test.go @@ -13,7 +13,9 @@ import ( ) func TestCosmosGenScaffold(t *testing.T) { - t.Skip("skip till we add a buf token into the CI") + if envtest.IsCI { + t.Skip("Skipping CosmosGenScaffold test in CI environment") + } var ( env = envtest.New(t) @@ -147,4 +149,14 @@ func TestCosmosGenScaffold(t *testing.T) { assert.NoError(t, err) } } + + if t.Failed() { + // list ts-client files + tsFiles, err := os.ReadDir(tsDirGenerated) + require.NoError(t, err) + t.Log("TS files:", len(tsFiles)) + for _, file := range tsFiles { + t.Logf(" - %s", file.Name()) + } + } } diff --git a/integration/cosmosgen/custom_module_test.go b/integration/cosmosgen/custom_module_test.go deleted file mode 100644 index e740c5dd84..0000000000 --- a/integration/cosmosgen/custom_module_test.go +++ /dev/null @@ -1,89 +0,0 @@ -package cosmosgen_test - -import ( - "context" - "encoding/json" - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - chainconfig "github.com/ignite/cli/v29/ignite/config/chain" - "github.com/ignite/cli/v29/ignite/config/chain/base" - "github.com/ignite/cli/v29/ignite/pkg/cmdrunner/step" - "github.com/ignite/cli/v29/ignite/pkg/xurl" - envtest "github.com/ignite/cli/v29/integration" -) - -func TestCustomModule(t *testing.T) { - t.Skip() - - var ( - env = envtest.New(t) - app = env.ScaffoldApp("chain", "--no-module") - servers = app.RandomizeServerPorts() - ) - - queryAPI, err := xurl.HTTP(servers.API) - require.NoError(t, err) - - txAPI, err := xurl.HTTP(servers.RPC) - require.NoError(t, err) - - // Accounts to be included in the genesis - accounts := []base.Account{ - { - Name: "account1", - Address: "cosmos1j8hw8283hj80hhq8urxaj40syrzqp77dt8qwhm", - Mnemonic: fmt.Sprint( - "toe mail light plug pact length excess predict real artwork laundry when ", - "steel online adapt clutch debate vehicle dash alter rifle virtual season almost", - ), - Coins: []string{"10000token", "10000stake"}, - }, - } - - app.EditConfig(func(cfg *chainconfig.Config) { - cfg.Accounts = append(cfg.Accounts, accounts...) - }) - - path := app.SourcePath() - - env.Must(env.Exec("create a module", - step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "disco", "--require-registration", "--yes"), - step.Workdir(path), - )), - )) - - env.Must(env.Exec("create a list type", - step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "entry", "name", "--module", "disco", "--yes"), - step.Workdir(path), - )), - )) - - env.Must(app.GenerateTSClient()) - - ctx, cancel := context.WithTimeout(env.Ctx(), envtest.ServeTimeout) - defer cancel() - - go func() { - app.Serve("serve app", envtest.ExecCtx(ctx)) - }() - - // Wait for the server to be up before running the client tests - app.WaitChainUp(ctx, servers.API) - - testAccounts, err := json.Marshal(accounts) - require.NoError(t, err) - - env.Must(app.RunClientTests( - envtest.ClientTestFile("custom_module_test.ts"), - envtest.ClientEnv(map[string]string{ - "TEST_QUERY_API": queryAPI, - "TEST_TX_API": txAPI, - "TEST_ACCOUNTS": string(testAccounts), - }), - )) -} diff --git a/integration/cosmosgen/custom_module_test.ts b/integration/cosmosgen/custom_module_test.ts deleted file mode 100644 index 4d51795238..0000000000 --- a/integration/cosmosgen/custom_module_test.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing' -import { isDeliverTxSuccess } from '@cosmjs/stargate' - -describe('custom module', async () => { - const { Client } = await import('client') - - it('should create a list entry', async () => { - const { account1 } = globalThis.accounts - - const mnemonic = account1['Mnemonic'] - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic) - const [account] = await wallet.getAccounts(); - - const denom = 'token' - const env = { - denom, - rpcURL: globalThis.txApi, - apiURL: globalThis.queryApi, - } - const client = new Client(env, wallet) - - const entry = { - id: '0', - creator: account.address, - name: "test", - } - - // Create a new list entry - const result = await client.ChainDisco.tx.sendMsgCreateEntry({ value: entry }) - - expect(isDeliverTxSuccess(result)).toEqual(true) - - // Check that the list entry is created - const response = await client.ChainDisco.query.queryEntryAll() - - expect(response.statusText).toEqual('OK') - expect(response.data['Entry']).toHaveLength(1) - expect(response.data['Entry'][0]).toEqual(entry) - }) -}) diff --git a/integration/env.go b/integration/env.go index 00406147e9..72767c4377 100644 --- a/integration/env.go +++ b/integration/env.go @@ -33,7 +33,7 @@ var ( // invoked. IgniteApp = path.Join(os.TempDir(), "ignite-tests", "ignite") - isCI, _ = strconv.ParseBool(os.Getenv("CI")) + IsCI, _ = strconv.ParseBool(os.Getenv("CI")) compileBinaryOnce sync.Once ) diff --git a/integration/exec.go b/integration/exec.go index 0e4d48869b..02d1fd11f3 100644 --- a/integration/exec.go +++ b/integration/exec.go @@ -81,7 +81,7 @@ func (e Env) Exec(msg string, steps step.Steps, options ...ExecOption) (ok bool) fmt.Printf("Executing %d step(s) for %q\n", len(steps), msg) copts = append(copts, cmdrunner.EnableDebug()) } - if isCI { + if IsCI { copts = append(copts, cmdrunner.EndSignal(os.Kill)) } err := cmdrunner.