package commands import ( "fmt" "strings" "github.com/hasura/graphql-engine/cli/v2" "github.com/hasura/graphql-engine/cli/v2/internal/metadataobject/actions" "github.com/hasura/graphql-engine/cli/v2/internal/metadataobject/actions/types" "github.com/pkg/errors" "github.com/spf13/cobra" ) func newActionsCodegenCmd(ec *cli.ExecutionContext) *cobra.Command { opts := &actionsCodegenOptions{ EC: ec, } actionsCodegenCmd := &cobra.Command{ Use: "codegen [action-name]", Short: "Generate code for actions", Example: ` # Generate code for all actions hasura actions codegen # Generate code for an action hasura actions codegen [action-name] # Generate code for two or more actions hasura actions codegen [action-name] [action-name...] # Derive an action from a hasura operation hasura actions codegen [action-name] --derive-from ""`, SilenceUsage: true, PreRunE: func(cmd *cobra.Command, args []string) error { if err := ec.SetupCodegenAssetsRepo(); err != nil { return fmt.Errorf("setting up codegen-assets repo failed (this is required for automatically generating actions code): %w", err) } // ensure codegen-assets repo exists if err := ec.CodegenAssetsRepo.EnsureCloned(); err != nil { return fmt.Errorf("pulling latest actions codegen files from internet failed: %w", err) } return nil }, RunE: func(cmd *cobra.Command, args []string) error { opts.actions = args return opts.run() }, } f := actionsCodegenCmd.Flags() f.StringVar(&opts.deriveFrom, "derive-from", "", "derive action from a hasura operation") return actionsCodegenCmd } type actionsCodegenOptions struct { EC *cli.ExecutionContext actions []string deriveFrom string } func (o *actionsCodegenOptions) run() (err error) { var derivePayload types.DerivePayload if o.deriveFrom != "" { derivePayload.Operation = strings.TrimSpace(o.deriveFrom) o.EC.Spin("Deriving a Hasura operation...") introSchema, err := o.EC.APIClient.V1Graphql.GetIntrospectionSchema() if err != nil { return errors.Wrap(err, "unable to fetch introspection schema") } derivePayload.IntrospectionSchema = introSchema o.EC.Spinner.Stop() } if o.EC.Config.ActionConfig.Codegen.Framework == "" { return fmt.Errorf(`could not find codegen config. For adding codegen config, run: hasura actions use-codegen`) } // if no actions are passed, perform codegen for all actions o.EC.Spin("Generating code...") var codegenActions []string actionCfg := actions.New(o.EC, o.EC.MetadataDir) if len(o.actions) == 0 { actionsFileContent, err := actionCfg.GetActionsFileContent() if err != nil { return errors.Wrap(err, "error getting actions file content") } for _, action := range actionsFileContent.Actions { codegenActions = append(codegenActions, action.Name) } } else { codegenActions = o.actions } for _, actionName := range codegenActions { err = actionCfg.Codegen(actionName, derivePayload) if err != nil { return errors.Wrapf(err, "error generating codegen for action %s", actionName) } } o.EC.Spinner.Stop() o.EC.Logger.Info("Codegen files generated at " + o.EC.Config.ActionConfig.Codegen.OutputDir) return nil }