2018-06-24 16:40:48 +03:00
package commands
import (
"fmt"
2020-04-23 06:10:24 +03:00
"net/url"
2018-06-24 16:40:48 +03:00
"os"
"path/filepath"
"strings"
2021-10-07 17:23:19 +03:00
"github.com/hashicorp/go-multierror"
2022-03-10 11:12:55 +03:00
"github.com/hasura/graphql-engine/cli/v2"
"github.com/hasura/graphql-engine/cli/v2/internal/fsm"
2021-10-07 17:23:19 +03:00
"github.com/hasura/graphql-engine/cli/v2/internal/hasura"
2021-06-16 14:44:15 +03:00
"github.com/hasura/graphql-engine/cli/v2/internal/metadataobject"
"github.com/hasura/graphql-engine/cli/v2/internal/metadataobject/actions"
actionMetadataFileTypes "github.com/hasura/graphql-engine/cli/v2/internal/metadataobject/actions/types"
"github.com/hasura/graphql-engine/cli/v2/internal/metadataobject/allowlist"
2022-03-10 11:12:55 +03:00
crontriggers "github.com/hasura/graphql-engine/cli/v2/internal/metadataobject/cron_triggers"
"github.com/hasura/graphql-engine/cli/v2/internal/metadataobject/functions"
2021-06-16 14:44:15 +03:00
"github.com/hasura/graphql-engine/cli/v2/internal/metadataobject/querycollections"
"github.com/hasura/graphql-engine/cli/v2/internal/metadataobject/remoteschemas"
2022-03-10 11:12:55 +03:00
"github.com/hasura/graphql-engine/cli/v2/internal/metadataobject/sources"
"github.com/hasura/graphql-engine/cli/v2/internal/metadataobject/tables"
2021-06-16 14:44:15 +03:00
metadataVersion "github.com/hasura/graphql-engine/cli/v2/internal/metadataobject/version"
2022-03-10 11:12:55 +03:00
"github.com/hasura/graphql-engine/cli/v2/internal/metadatautil"
2021-06-16 14:44:15 +03:00
"github.com/hasura/graphql-engine/cli/v2/util"
2018-06-24 16:40:48 +03:00
"github.com/pkg/errors"
2022-03-10 11:12:55 +03:00
"github.com/sirupsen/logrus"
2018-06-24 16:40:48 +03:00
"github.com/spf13/cobra"
2019-01-28 16:55:28 +03:00
"github.com/spf13/viper"
2018-06-24 16:40:48 +03:00
)
const (
2020-02-24 19:14:46 +03:00
defaultDirectory string = "hasura"
2021-10-07 17:23:19 +03:00
defaultEndpoint string = "http://localhost:8080"
2018-06-24 16:40:48 +03:00
)
2018-06-27 15:04:09 +03:00
// NewInitCmd is the definition for init command
2018-06-24 16:40:48 +03:00
func NewInitCmd ( ec * cli . ExecutionContext ) * cobra . Command {
2020-02-24 19:14:46 +03:00
opts := & InitOptions {
2018-06-24 16:40:48 +03:00
EC : ec ,
}
initCmd := & cobra . Command {
2019-12-25 11:31:29 +03:00
Use : "init [directory-name]" ,
2021-03-15 18:40:52 +03:00
Short : "Initialize a directory for Hasura GraphQL engine migrations" ,
Long : "Create directories and files required for enabling migrations on the Hasura GraphQL engine" ,
2018-08-06 14:33:17 +03:00
Example : ` # Create a directory to store migrations
2019-12-25 11:31:29 +03:00
hasura init [ directory - name ]
2018-06-24 16:40:48 +03:00
2019-02-14 12:37:47 +03:00
# Now , edit < my - directory > / config . yaml to add endpoint and admin secret
2018-06-24 16:47:01 +03:00
2019-02-14 12:37:47 +03:00
# Create a directory with endpoint and admin secret configured :
2019-12-25 11:31:29 +03:00
hasura init < my - project > -- endpoint https : //my-graphql-engine.com --admin-secret adminsecretkey
2018-08-06 14:33:17 +03:00
2020-04-27 07:33:10 +03:00
# Create a hasura project in the current working directory
hasura init .
2021-03-01 21:50:24 +03:00
# See https : //hasura.io/docs/latest/graphql/core/migrations/index.html for more details`,
2018-06-24 16:40:48 +03:00
SilenceUsage : true ,
2019-12-25 11:31:29 +03:00
Args : cobra . MaximumNArgs ( 1 ) ,
2020-02-24 19:14:46 +03:00
PreRunE : func ( cmd * cobra . Command , args [ ] string ) error {
2019-01-28 16:55:28 +03:00
ec . Viper = viper . New ( )
2020-02-24 19:14:46 +03:00
err := ec . Prepare ( )
if err != nil {
return err
}
2021-04-21 10:26:17 +03:00
// show deprecation message if initializing a config v1 project
if opts . Version <= cli . V1 {
return fmt . Errorf ( "config v1 is deprecated, please consider using config v3" )
}
2021-11-10 12:21:06 +03:00
return nil
2018-06-27 15:04:09 +03:00
} ,
2018-06-24 16:40:48 +03:00
RunE : func ( cmd * cobra . Command , args [ ] string ) error {
2019-12-25 11:31:29 +03:00
if len ( args ) == 1 {
opts . InitDir = args [ 0 ]
}
2020-02-24 19:14:46 +03:00
return opts . Run ( )
2018-06-24 16:40:48 +03:00
} ,
}
f := initCmd . Flags ( )
2021-01-18 20:11:05 +03:00
f . Var ( cli . NewConfigVersionValue ( cli . V3 , & opts . Version ) , "version" , "config version to be used" )
2018-06-24 16:40:48 +03:00
f . StringVar ( & opts . InitDir , "directory" , "" , "name of directory where files will be created" )
2021-03-15 18:40:52 +03:00
f . StringVar ( & opts . Endpoint , "endpoint" , "" , "http(s) endpoint for Hasura GraphQL engine" )
f . StringVar ( & opts . AdminSecret , "admin-secret" , "" , "admin secret for Hasura GraphQL engine" )
f . StringVar ( & opts . AdminSecret , "access-key" , "" , "access key for Hasura GraphQL engine" )
2021-11-10 12:21:06 +03:00
f . String ( "install-manifest" , "" , "install manifest to be cloned" )
if err := f . MarkDeprecated ( "install-manifest" , "refer: https://github.com/hasura/graphql-engine/tree/stable/install-manifests" ) ; err != nil {
ec . Logger . Debugf ( "failed marking depricated flag" )
}
2021-10-13 17:38:07 +03:00
if err := f . MarkDeprecated ( "access-key" , "use --admin-secret instead" ) ; err != nil {
ec . Logger . WithError ( err ) . Errorf ( "error while using a dependency library" )
}
if err := f . MarkDeprecated ( "directory" , "use directory-name argument instead" ) ; err != nil {
ec . Logger . WithError ( err ) . Errorf ( "error while using a dependency library" )
}
2019-02-14 12:37:47 +03:00
2021-10-07 17:23:19 +03:00
// only used in tests
f . BoolVar ( & opts . GetMetadataMigrations , "fetch" , false , "It fetches the metadata and migrations from server without prompt" )
2021-10-13 17:38:07 +03:00
if err := f . MarkHidden ( "fetch" ) ; err != nil {
ec . Logger . WithError ( err ) . Errorf ( "error while using a dependency library" )
}
2021-10-07 17:23:19 +03:00
2018-06-24 16:40:48 +03:00
return initCmd
}
2020-02-24 19:14:46 +03:00
type InitOptions struct {
2018-06-24 16:40:48 +03:00
EC * cli . ExecutionContext
2021-10-07 17:23:19 +03:00
Version cli . ConfigVersion
Endpoint string
AdminSecret string
InitDir string
GetMetadataMigrations bool
2018-06-24 16:40:48 +03:00
}
2021-10-07 17:23:19 +03:00
func ( o * InitOptions ) InitRun ( ) error {
2020-04-27 05:49:26 +03:00
// prompt for init directory if it's not set already
if o . InitDir == "" {
2021-09-07 16:33:58 +03:00
r , err := util . GetInputPromptWithDefault ( "Name of project directory ?" , defaultDirectory )
2020-04-27 05:49:26 +03:00
if err != nil {
2021-09-07 16:33:58 +03:00
return fmt . Errorf ( "prompt exited: %w" , err )
2020-04-27 05:49:26 +03:00
}
if strings . TrimSpace ( r ) != "" {
o . InitDir = r
} else {
o . InitDir = defaultDirectory
}
}
2021-10-07 17:23:19 +03:00
if o . Endpoint != "" && ! o . GetMetadataMigrations && o . EC . IsTerminal {
r , err := util . GetYesNoPrompt ( fmt . Sprintf ( "Initialize project with metadata & migrations from %s ?" , o . Endpoint ) )
if err != nil {
return fmt . Errorf ( "prompt exited: %w" , err )
}
o . GetMetadataMigrations = r
}
if ! o . EC . IsTerminal {
o . GetMetadataMigrations = true
}
2020-04-27 10:56:34 +03:00
cwdir , err := os . Getwd ( )
if err != nil {
return errors . Wrap ( err , "error getting current working directory" )
}
initPath , err := filepath . Abs ( o . InitDir )
if err != nil {
return err
}
if initPath == cwdir {
2020-04-27 05:49:26 +03:00
// check if pwd is filesystem root
2020-04-27 10:56:34 +03:00
if err := cli . CheckFilesystemBoundary ( cwdir ) ; err != nil {
2020-04-27 05:49:26 +03:00
return errors . Wrap ( err , "can't initialise hasura project in filesystem root" )
}
// check if the current directory is already a hasura project
2020-04-27 10:56:34 +03:00
if err := cli . ValidateDirectory ( cwdir ) ; err == nil {
2020-04-27 05:49:26 +03:00
return errors . Errorf ( "current working directory is already a hasura project directory" )
2018-06-24 16:40:48 +03:00
}
2020-04-27 10:56:34 +03:00
o . EC . ExecutionDirectory = cwdir
2018-09-27 16:57:17 +03:00
} else {
2020-04-26 19:54:48 +03:00
// create execution directory
err := o . createExecutionDirectory ( )
if err != nil {
return err
}
}
2018-06-24 16:40:48 +03:00
2018-06-27 15:04:09 +03:00
// create other required files, like config.yaml, migrations directory
2018-08-06 14:33:17 +03:00
err = o . createFiles ( )
2018-06-24 16:40:48 +03:00
if err != nil {
return err
}
return nil
}
2020-04-26 19:54:48 +03:00
//create the execution directory
func ( o * InitOptions ) createExecutionDirectory ( ) error {
if o . EC . ExecutionDirectory == "" {
o . EC . ExecutionDirectory = o . InitDir
} else {
o . EC . ExecutionDirectory = filepath . Join ( o . EC . ExecutionDirectory , o . InitDir )
}
// create the execution directory
if _ , err := os . Stat ( o . EC . ExecutionDirectory ) ; err == nil {
2021-05-04 19:35:56 +03:00
return errors . Errorf ( "directory '%s' already exists" , o . EC . ExecutionDirectory )
2020-04-26 19:54:48 +03:00
}
err := os . MkdirAll ( o . EC . ExecutionDirectory , os . ModePerm )
if err != nil {
return errors . Wrap ( err , "error creating setup directories" )
}
return nil
}
2018-06-27 15:04:09 +03:00
// createFiles creates files required by the CLI in the ExecutionDirectory
2020-02-24 19:14:46 +03:00
func ( o * InitOptions ) createFiles ( ) error {
2018-06-27 15:04:09 +03:00
// create the directory
2018-06-24 16:40:48 +03:00
err := os . MkdirAll ( filepath . Dir ( o . EC . ExecutionDirectory ) , os . ModePerm )
if err != nil {
return errors . Wrap ( err , "error creating setup directories" )
}
2018-06-27 15:04:09 +03:00
// set config object
2021-10-13 17:38:07 +03:00
var config = & cli . Config {
Version : o . Version ,
ServerConfig : cli . ServerConfig {
Endpoint : defaultEndpoint ,
} ,
MetadataDirectory : "metadata" ,
ActionConfig : & actionMetadataFileTypes . ActionExecutionConfig {
Kind : "synchronous" ,
HandlerWebhookBaseURL : "http://localhost:3000" ,
} ,
2018-06-24 16:40:48 +03:00
}
2018-06-27 15:04:09 +03:00
if o . Endpoint != "" {
2020-04-23 06:10:24 +03:00
if _ , err := url . ParseRequestURI ( o . Endpoint ) ; err != nil {
return errors . Wrap ( err , "error validating endpoint URL" )
}
2020-02-24 19:14:46 +03:00
config . ServerConfig . Endpoint = o . Endpoint
2018-06-24 16:40:48 +03:00
}
2019-02-14 12:37:47 +03:00
if o . AdminSecret != "" {
2020-02-24 19:14:46 +03:00
config . ServerConfig . AdminSecret = o . AdminSecret
2018-06-27 15:04:09 +03:00
}
2018-06-24 16:40:48 +03:00
2018-06-27 15:04:09 +03:00
// write the config file
2020-02-24 19:14:46 +03:00
o . EC . Config = config
2018-06-27 15:04:09 +03:00
o . EC . ConfigFile = filepath . Join ( o . EC . ExecutionDirectory , "config.yaml" )
2020-02-24 19:14:46 +03:00
err = o . EC . WriteConfig ( nil )
2018-06-24 16:40:48 +03:00
if err != nil {
return errors . Wrap ( err , "cannot write config file" )
}
2018-06-27 15:04:09 +03:00
// create migrations directory
2020-06-16 15:15:04 +03:00
o . EC . MigrationDir = filepath . Join ( o . EC . ExecutionDirectory , cli . DefaultMigrationsDirectory )
2018-06-24 16:40:48 +03:00
err = os . MkdirAll ( o . EC . MigrationDir , os . ModePerm )
if err != nil {
return errors . Wrap ( err , "cannot write migration directory" )
}
2021-01-18 20:11:05 +03:00
if config . Version >= cli . V2 {
2020-02-24 19:14:46 +03:00
// create metadata directory
2020-06-16 15:15:04 +03:00
o . EC . MetadataDir = filepath . Join ( o . EC . ExecutionDirectory , cli . DefaultMetadataDirectory )
2020-02-24 19:14:46 +03:00
err = os . MkdirAll ( o . EC . MetadataDir , os . ModePerm )
if err != nil {
2020-11-24 09:11:30 +03:00
return errors . Wrap ( err , "cannot write metadata directory" )
2020-02-24 19:14:46 +03:00
}
2021-10-13 17:38:07 +03:00
err = o . EC . Version . GetServerFeatureFlags ( )
if err != nil {
o . EC . Logger . Warnf ( "error determining server feature flags: %v" , err )
}
2020-02-24 19:14:46 +03:00
// create metadata files
2021-04-01 08:13:24 +03:00
plugins := make ( metadataobject . Objects , 0 )
2020-02-24 19:14:46 +03:00
plugins = append ( plugins , querycollections . New ( o . EC , o . EC . MetadataDir ) )
plugins = append ( plugins , allowlist . New ( o . EC , o . EC . MetadataDir ) )
plugins = append ( plugins , remoteschemas . New ( o . EC , o . EC . MetadataDir ) )
plugins = append ( plugins , actions . New ( o . EC , o . EC . MetadataDir ) )
2020-06-16 12:08:36 +03:00
plugins = append ( plugins , crontriggers . New ( o . EC , o . EC . MetadataDir ) )
2021-01-18 20:11:05 +03:00
if config . Version == cli . V3 {
2022-02-23 13:51:52 +03:00
plugins = append ( plugins , metadataVersion . New ( o . EC , o . EC . MetadataDir ) )
2021-01-18 20:11:05 +03:00
plugins = append ( plugins , sources . New ( o . EC , o . EC . MetadataDir ) )
} else {
2022-02-23 13:51:52 +03:00
plugins = append ( plugins , metadataVersion . NewV3MetadataVersion ( o . EC , o . EC . MetadataDir ) )
2021-01-18 20:11:05 +03:00
plugins = append ( plugins , tables . New ( o . EC , o . EC . MetadataDir ) )
plugins = append ( plugins , functions . New ( o . EC , o . EC . MetadataDir ) )
}
2020-02-24 19:14:46 +03:00
for _ , plg := range plugins {
err := plg . CreateFiles ( )
if err != nil {
return errors . Wrap ( err , "cannot create metadata files" )
}
}
}
2020-06-16 15:15:04 +03:00
// create seeds directory
o . EC . SeedsDirectory = filepath . Join ( o . EC . ExecutionDirectory , cli . DefaultSeedsDirectory )
err = os . MkdirAll ( o . EC . SeedsDirectory , os . ModePerm )
if err != nil {
return errors . Wrap ( err , "cannot write seeds directory" )
}
2020-02-24 19:14:46 +03:00
return nil
}
2021-10-07 17:23:19 +03:00
func ( o * InitOptions ) Run ( ) error {
context := & initCtx {
ec : o . EC ,
initOps : o ,
logger : o . EC . Logger ,
err : nil ,
}
configInitFSM := newInitFSM ( )
if err := configInitFSM . SendEvent ( createProjectDirectory , context ) ; err != nil {
return err
}
if configInitFSM . Current == failedOperation {
return fmt . Errorf ( "operation failed: %w" , context . err )
}
return nil
}
const (
creatingProjectDirectory stateType = "Creating project directory"
failedCreatingProjectDir stateType = "Failed to create project directory"
validatingEndpoint stateType = "Validating Endpoint"
failedValidatingEndpoint stateType = "Failed validating endpoint"
exportingMetadata stateType = "Exporting Metadata"
failedExportingMetadata stateType = "Failed to export Metadata"
creatingMigration stateType = "Creating Migration"
failedCreatingMigration stateType = "Failed creating Migration"
endState stateType = "End State"
)
const (
createProjectDirectory eventType = "Create project directory"
createProjectDirectoryFailed eventType = "Create project directory failed"
validateEndpoint eventType = "Validate Endpoint"
validateEndpointFailed eventType = "Validate Endpoint Failed"
exportMetadata eventType = "Export Metadata"
exportMetadataFailed eventType = "Export Metadata Failed"
createMigration eventType = "Create migration from server"
createMigrationFailed eventType = "Create migration from server Failed"
gotoEndstate eventType = "Go to End State"
)
type initCtx struct {
ec * cli . ExecutionContext
initOps * InitOptions
logger * logrus . Logger
err error
}
type creatingDefaultDirAction struct { }
func ( a * creatingDefaultDirAction ) Execute ( ctx fsm . EventContext ) eventType {
context := ctx . ( * initCtx )
opts := context . initOps
context . logger . Debug ( creatingProjectDirectory )
if err := opts . InitRun ( ) ; err != nil {
context . err = err
return createProjectDirectoryFailed
}
if len ( opts . Endpoint ) > 0 && opts . GetMetadataMigrations {
return validateEndpoint
}
return gotoEndstate
}
type failedCreatingDefaultDirAction struct { }
func ( a * failedCreatingDefaultDirAction ) Execute ( ctx fsm . EventContext ) eventType {
context := ctx . ( * initCtx )
context . logger . Debug ( failedCreatingProjectDir )
if context . err != nil {
context . logger . Errorln ( "initializing project directory failed" )
}
return failOperation
}
type validatingEndpointAction struct { }
func ( a * validatingEndpointAction ) Execute ( ctx fsm . EventContext ) eventType {
context := ctx . ( * initCtx )
opts := context . initOps
context . logger . Debug ( validatingEndpoint )
2022-02-04 14:10:33 +03:00
if err := opts . EC . Validate ( ) ; err != nil {
context . err = err
return validateEndpointFailed
}
if err := util . GetServerStatus ( opts . EC . Config . GetVersionEndpoint ( ) , opts . EC . Config . HTTPClient ) ; err != nil {
2021-10-07 17:23:19 +03:00
context . err = err
return validateEndpointFailed
}
return exportMetadata
}
type failedValidatingEndpointAction struct { }
func ( a * failedValidatingEndpointAction ) Execute ( ctx fsm . EventContext ) eventType {
context := ctx . ( * initCtx )
context . logger . Debug ( failedValidatingEndpoint )
if context . err != nil {
2022-02-04 14:10:33 +03:00
context . logger . Debug ( context . err )
2021-10-07 17:23:19 +03:00
context . logger . Infoln ( "validating endpoint failed, server not reachable" )
}
return gotoEndstate
}
type exportingMetadataAction struct { }
func ( a * exportingMetadataAction ) Execute ( ctx fsm . EventContext ) eventType {
context := ctx . ( * initCtx )
opts := MetadataExportOptions {
EC : context . ec ,
}
context . logger . Debug ( exportingMetadata )
if err := context . ec . Validate ( ) ; err != nil {
context . err = err
return exportMetadataFailed
}
// Note: Here ec won't use the values from `--endpoint` and `--admin-secret` or `--access-key` flags
context . ec . Spin ( "Exporting metadata..." )
if err := opts . Run ( ) ; err != nil {
opts . EC . Spinner . Stop ( )
context . err = err
return exportMetadataFailed
}
opts . EC . Spinner . Stop ( )
opts . EC . Logger . Info ( "Metadata exported" )
return createMigration
}
type failedExportingMetadataAction struct { }
func ( a * failedExportingMetadataAction ) Execute ( ctx fsm . EventContext ) eventType {
context := ctx . ( * initCtx )
context . logger . Debug ( failedExportingMetadata )
if context . err != nil {
context . logger . Errorf ( "exporting metadata failed: \n%v\n%s" , context . err , "run `hasura metadata export` from your project directory to retry" )
}
return createMigration
}
type creatingMigrationAction struct { }
func ( a * creatingMigrationAction ) Execute ( ctx fsm . EventContext ) eventType {
context := ctx . ( * initCtx )
opts := migrateCreateOptions {
EC : context . ec ,
name : "init" ,
fromServer : true ,
}
context . logger . Debug ( creatingMigration )
if err := context . ec . Validate ( ) ; err != nil {
context . err = err
return createMigrationFailed
}
// Note: Here ec won't use the values from `--endpoint` and `--admin-secret` or `--access-key` flags
if opts . EC . Config . Version == cli . V2 {
source := cli . Source { Name : "" , Kind : hasura . SourceKindPG }
opts . Source = source
if _ , err := opts . run ( ) ; err != nil {
context . err = multierror . Append ( context . err , err )
}
} else {
sources , err := metadatautil . GetSourcesAndKind ( opts . EC . APIClient . V1Metadata . ExportMetadata )
if err != nil {
context . err = err
context . logger . Debugf ( "getting list of connected databases from server (%s) failed" , context . initOps . Endpoint )
return createMigrationFailed
}
for _ , source := range sources {
opts . EC . Logger . Infof ( "Creating migrations for source: %s" , source . Name )
opts . Source = cli . Source ( source )
if _ , err := opts . run ( ) ; err != nil {
context . err = multierror . Append ( context . err , fmt . Errorf ( "applying migrations on source: %s: %w" , source . Name , err ) )
}
}
}
if context . err != nil {
return createMigrationFailed
}
return gotoEndstate
}
type failedCreatingMigrationAction struct { }
func ( a * failedCreatingMigrationAction ) Execute ( ctx fsm . EventContext ) eventType {
context := ctx . ( * initCtx )
context . logger . Debug ( failedCreatingMigration )
if context . err != nil {
context . logger . Errorf ( "creating migrations failed: \n%v\n%s" , context . err , "run `hasura migrate create --from-server` from your project directory to retry" )
}
return gotoEndstate
}
type failedInitOperationAction struct { }
func ( a * failedInitOperationAction ) Execute ( ctx fsm . EventContext ) eventType {
context := ctx . ( * initCtx )
context . logger . Debug ( failedOperation )
return fsm . NoOp
}
type gotoEndstateAction struct { }
func ( a * gotoEndstateAction ) Execute ( ctx fsm . EventContext ) eventType {
context := ctx . ( * initCtx )
opts := context . initOps
cwdir , err := os . Getwd ( )
if err != nil {
context . logger . Errorf ( "error getting current working directory : %v" , err )
return fsm . NoOp
}
var infoMsg string
if opts . EC . ExecutionDirectory != cwdir {
infoMsg = fmt . Sprintf ( ` directory created . execute the following commands to continue :
cd % s
hasura console
` , opts . EC . ExecutionDirectory )
} else {
infoMsg = ` hasura project initialised . execute the following command to continue :
hasura console
`
}
context . logger . Infoln ( infoMsg )
return fsm . NoOp
}
func newInitFSM ( ) * fsm . StateMachine {
type State = fsm . State
type States = fsm . States
type Events = fsm . Events
return & fsm . StateMachine {
States : States {
fsm . Default : State {
Events : Events {
createProjectDirectory : creatingProjectDirectory ,
} ,
} ,
creatingProjectDirectory : State {
Action : & creatingDefaultDirAction { } ,
Events : Events {
createProjectDirectoryFailed : failedCreatingProjectDir ,
validateEndpoint : validatingEndpoint ,
gotoEndstate : endState ,
} ,
} ,
failedCreatingProjectDir : State {
Action : & failedCreatingDefaultDirAction { } ,
Events : Events {
failOperation : failedOperation ,
} ,
} ,
validatingEndpoint : State {
Action : & validatingEndpointAction { } ,
Events : Events {
validateEndpointFailed : failedValidatingEndpoint ,
exportMetadata : exportingMetadata ,
} ,
} ,
failedValidatingEndpoint : State {
Action : & failedValidatingEndpointAction { } ,
Events : Events {
gotoEndstate : endState ,
} ,
} ,
exportingMetadata : State {
Action : & exportingMetadataAction { } ,
Events : Events {
exportMetadataFailed : failedExportingMetadata ,
createMigration : creatingMigration ,
} ,
} ,
failedExportingMetadata : State {
Action : & failedExportingMetadataAction { } ,
Events : Events {
gotoEndstate : endState ,
createMigration : creatingMigration ,
} ,
} ,
creatingMigration : State {
Action : & creatingMigrationAction { } ,
Events : Events {
createMigrationFailed : failedCreatingMigration ,
gotoEndstate : endState ,
} ,
} ,
failedCreatingMigration : State {
Action : & failedCreatingMigrationAction { } ,
Events : Events {
gotoEndstate : endState ,
} ,
} ,
failedOperation : State {
Action : & failedInitOperationAction { } ,
} ,
endState : State {
Action : & gotoEndstateAction { } ,
Events : Events { } ,
} ,
} ,
}
}