Add database setup commands
This commit is contained in:
125
serv/cmd.go
125
serv/cmd.go
@ -35,102 +35,98 @@ var (
|
||||
qcompile *qcode.Compiler
|
||||
pcompile *psql.Compiler
|
||||
authFailBlock int
|
||||
|
||||
rootCmd *cobra.Command
|
||||
servCmd *cobra.Command
|
||||
seedCmd *cobra.Command
|
||||
migrateCmd *cobra.Command
|
||||
statusCmd *cobra.Command
|
||||
newMigrationCmd *cobra.Command
|
||||
initCmd *cobra.Command
|
||||
)
|
||||
|
||||
func Init() {
|
||||
rootCmd = &cobra.Command{
|
||||
logger = initLog()
|
||||
|
||||
rootCmd := &cobra.Command{
|
||||
Use: "super-graph",
|
||||
Short: "An instant high-performance GraphQL API. No code needed. https://supergraph.dev",
|
||||
//Run: cmdServ,
|
||||
}
|
||||
|
||||
seedCmd = &cobra.Command{
|
||||
Use: "seed",
|
||||
Short: "Run the seed script to seed the database",
|
||||
Run: cmdSeed,
|
||||
}
|
||||
|
||||
servCmd = &cobra.Command{
|
||||
rootCmd.AddCommand(&cobra.Command{
|
||||
Use: "serv",
|
||||
Short: "Run the super-graph service",
|
||||
Run: cmdServ,
|
||||
}
|
||||
})
|
||||
|
||||
migrateCmd = &cobra.Command{
|
||||
Use: "migrate",
|
||||
rootCmd.AddCommand(&cobra.Command{
|
||||
Use: "db:create",
|
||||
Short: "Create database",
|
||||
Run: cmdDBCreate,
|
||||
})
|
||||
|
||||
rootCmd.AddCommand(&cobra.Command{
|
||||
Use: "db:drop",
|
||||
Short: "Drop database",
|
||||
Run: cmdDBDrop,
|
||||
})
|
||||
|
||||
rootCmd.AddCommand(&cobra.Command{
|
||||
Use: "db:seed",
|
||||
Short: "Run the seed script to seed the database",
|
||||
Run: cmdDBSeed,
|
||||
})
|
||||
|
||||
rootCmd.AddCommand(&cobra.Command{
|
||||
Use: "db:migrate",
|
||||
Short: "Migrate the database",
|
||||
Long: `Migrate the database to destination migration version.
|
||||
|
||||
Destination migration version can be one of the following value types:
|
||||
|
||||
An integer:
|
||||
Migrate to the most recent migration.
|
||||
e.g. migrate up
|
||||
|
||||
Rollback the most recent migration.
|
||||
e.g. migrate down
|
||||
|
||||
Migrate to a specific migration.
|
||||
e.g. tern migrate -d 42
|
||||
e.g. migrate 42
|
||||
|
||||
"+" and an integer:
|
||||
Migrate forward N steps.
|
||||
e.g. tern migrate -d +3
|
||||
e.g. migrate +3
|
||||
|
||||
"-" and an integer:
|
||||
Migrate backward N steps.
|
||||
e.g. tern migrate -d -2
|
||||
e.g. migrate -2
|
||||
|
||||
"-+" and an integer:
|
||||
Redo previous N steps (migrate backward N steps then forward N steps).
|
||||
e.g. tern migrate -d -+1
|
||||
|
||||
The word "last":
|
||||
Migrate to the most recent migration. This is the default value, so it is
|
||||
never needed to specify directly.
|
||||
e.g. tern migrate
|
||||
e.g. tern migrate -d last
|
||||
e.g. migrate -+1
|
||||
`,
|
||||
Run: cmdMigrate,
|
||||
}
|
||||
Run: cmdDBMigrate,
|
||||
})
|
||||
|
||||
statusCmd = &cobra.Command{
|
||||
Use: "status",
|
||||
rootCmd.AddCommand(&cobra.Command{
|
||||
Use: "db:status",
|
||||
Short: "Print current migration status",
|
||||
Run: cmdStatus,
|
||||
}
|
||||
Run: cmdDBStatus,
|
||||
})
|
||||
|
||||
newMigrationCmd = &cobra.Command{
|
||||
Use: "new NAME",
|
||||
rootCmd.AddCommand(&cobra.Command{
|
||||
Use: "db:new NAME",
|
||||
Short: "Generate a new migration",
|
||||
Long: "Generate a new migration with the next sequence number and provided name",
|
||||
Run: cmdNewMigration,
|
||||
}
|
||||
Run: cmdDBNew,
|
||||
})
|
||||
|
||||
initCmd = &cobra.Command{
|
||||
Use: "init APP-NAME",
|
||||
Short: "Initialize a new application",
|
||||
rootCmd.AddCommand(&cobra.Command{
|
||||
Use: "db:setup",
|
||||
Short: "Setup database",
|
||||
Long: "This command will create, migrate and seed the database",
|
||||
Run: cmdDBSetup,
|
||||
})
|
||||
|
||||
rootCmd.AddCommand(&cobra.Command{
|
||||
Use: "new APP-NAME",
|
||||
Short: "Create a new application",
|
||||
Long: "Generate all the required files to start on a new Super Graph app",
|
||||
Run: cmdInit,
|
||||
}
|
||||
|
||||
logger = initLog()
|
||||
Run: cmdNew,
|
||||
})
|
||||
|
||||
rootCmd.Flags().StringVar(&confPath,
|
||||
"path", "./config", "path to config files")
|
||||
|
||||
//cmdMigrate.Flags().StringVarP(&cliOptions.destinationVersion,
|
||||
// "destination", "d", "last", "destination migration version")
|
||||
|
||||
rootCmd.AddCommand(initCmd)
|
||||
rootCmd.AddCommand(servCmd)
|
||||
rootCmd.AddCommand(seedCmd)
|
||||
rootCmd.AddCommand(migrateCmd)
|
||||
rootCmd.AddCommand(statusCmd)
|
||||
rootCmd.AddCommand(newMigrationCmd)
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
logger.Fatal().Err(err).Send()
|
||||
}
|
||||
@ -209,11 +205,10 @@ func initConf() (*config, error) {
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func initDB(c *config) (*pgx.Conn, error) {
|
||||
func initDB(c *config, useDB bool) (*pgx.Conn, error) {
|
||||
config, _ := pgx.ParseConfig("")
|
||||
config.Host = c.DB.Host
|
||||
config.Port = c.DB.Port
|
||||
config.Database = c.DB.DBName
|
||||
config.User = c.DB.User
|
||||
config.Password = c.DB.Password
|
||||
config.RuntimeParams = map[string]string{
|
||||
@ -221,6 +216,10 @@ func initDB(c *config) (*pgx.Conn, error) {
|
||||
"search_path": c.DB.Schema,
|
||||
}
|
||||
|
||||
if useDB {
|
||||
config.Database = c.DB.DBName
|
||||
}
|
||||
|
||||
switch c.LogLevel {
|
||||
case "debug":
|
||||
config.LogLevel = pgx.LogLevelDebug
|
||||
|
@ -2,17 +2,19 @@ package serv
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
rice "github.com/GeertJohan/go.rice"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/valyala/fasttemplate"
|
||||
)
|
||||
|
||||
func cmdInit(cmd *cobra.Command, args []string) {
|
||||
func cmdNew(cmd *cobra.Command, args []string) {
|
||||
if len(args) != 1 {
|
||||
cmd.Help()
|
||||
os.Exit(1)
|
||||
@ -32,8 +34,8 @@ func cmdInit(cmd *cobra.Command, args []string) {
|
||||
return os.Mkdir(p, os.ModePerm)
|
||||
})
|
||||
|
||||
ifNotExists(path.Join(appPath, "seed.js"), func(p string) error {
|
||||
if v, err := tmpl.get("docker-compose.yml"); err == nil {
|
||||
ifNotExists(path.Join(appPath, "Dockerfile"), func(p string) error {
|
||||
if v, err := tmpl.get("Dockerfile"); err == nil {
|
||||
return ioutil.WriteFile(p, v, 0644)
|
||||
} else {
|
||||
return err
|
||||
@ -72,6 +74,14 @@ func cmdInit(cmd *cobra.Command, args []string) {
|
||||
}
|
||||
})
|
||||
|
||||
ifNotExists(path.Join(appConfigPath, "seed.js"), func(p string) error {
|
||||
if v, err := tmpl.get("docker-compose.yml"); err == nil {
|
||||
return ioutil.WriteFile(p, v, 0644)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
})
|
||||
|
||||
// Create app migrations folder and add relevant files
|
||||
|
||||
appMigrationsPath := path.Join(appConfigPath, "migrations")
|
||||
@ -103,11 +113,14 @@ func newTempl(data map[string]string) *Templ {
|
||||
func (t *Templ) get(name string) ([]byte, error) {
|
||||
v := t.MustString(name)
|
||||
b := bytes.Buffer{}
|
||||
tm := template.Must(template.New(name).Parse(v))
|
||||
tmpl := fasttemplate.New(v, "{%", "%}")
|
||||
|
||||
if err := tm.Execute(&b, t.data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tmpl.ExecuteFunc(&b, func(w io.Writer, tag string) (int, error) {
|
||||
if val, ok := t.data[strings.TrimSpace(tag)]; ok {
|
||||
return w.Write([]byte(val))
|
||||
}
|
||||
return 0, fmt.Errorf("unknown template variable '%s'", tag)
|
||||
})
|
||||
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
@ -34,7 +34,63 @@ var newMigrationText = `-- Write your migrate up statements here
|
||||
-- Then delete the separator line above.
|
||||
`
|
||||
|
||||
func cmdNewMigration(cmd *cobra.Command, args []string) {
|
||||
func cmdDBSetup(cmd *cobra.Command, args []string) {
|
||||
cmdDBCreate(cmd, []string{})
|
||||
cmdDBMigrate(cmd, []string{"up"})
|
||||
cmdDBSeed(cmd, []string{})
|
||||
}
|
||||
|
||||
func cmdDBCreate(cmd *cobra.Command, args []string) {
|
||||
var err error
|
||||
|
||||
if conf, err = initConf(); err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to read config")
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
conn, err := initDB(conf, false)
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to connect to database")
|
||||
}
|
||||
defer conn.Close(ctx)
|
||||
|
||||
sql := fmt.Sprintf("create database %s", conf.DB.DBName)
|
||||
|
||||
_, err = conn.Exec(ctx, sql)
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to create database")
|
||||
}
|
||||
|
||||
logger.Info().Msgf("created database '%s'", conf.DB.DBName)
|
||||
}
|
||||
|
||||
func cmdDBDrop(cmd *cobra.Command, args []string) {
|
||||
var err error
|
||||
|
||||
if conf, err = initConf(); err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to read config")
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
conn, err := initDB(conf, false)
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to connect to database")
|
||||
}
|
||||
defer conn.Close(ctx)
|
||||
|
||||
sql := fmt.Sprintf("drop database if exists %s", conf.DB.DBName)
|
||||
|
||||
_, err = conn.Exec(ctx, sql)
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to create database")
|
||||
}
|
||||
|
||||
logger.Info().Msgf("dropped database '%s'", conf.DB.DBName)
|
||||
}
|
||||
|
||||
func cmdDBNew(cmd *cobra.Command, args []string) {
|
||||
if len(args) != 1 {
|
||||
cmd.Help()
|
||||
os.Exit(1)
|
||||
@ -73,14 +129,21 @@ func cmdNewMigration(cmd *cobra.Command, args []string) {
|
||||
logger.Info().Msgf("created migration '%s'", mpath)
|
||||
}
|
||||
|
||||
func cmdMigrate(cmd *cobra.Command, args []string) {
|
||||
func cmdDBMigrate(cmd *cobra.Command, args []string) {
|
||||
var err error
|
||||
|
||||
if len(args) == 0 {
|
||||
cmd.Help()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
dest := args[0]
|
||||
|
||||
if conf, err = initConf(); err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to read config")
|
||||
}
|
||||
|
||||
conn, err := initDB(conf)
|
||||
conn, err := initDB(conf, true)
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to connect to database")
|
||||
}
|
||||
@ -90,7 +153,8 @@ func cmdMigrate(cmd *cobra.Command, args []string) {
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to initializing migrator")
|
||||
}
|
||||
//m.Data = config.Data
|
||||
|
||||
m.Data = getMigrationVars()
|
||||
|
||||
err = m.LoadMigrations(conf.MigrationsPath)
|
||||
if err != nil {
|
||||
@ -113,7 +177,6 @@ func cmdMigrate(cmd *cobra.Command, args []string) {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
dest := args[0]
|
||||
mustParseDestination := func(d string) int32 {
|
||||
var n int64
|
||||
n, err = strconv.ParseInt(d, 10, 32)
|
||||
@ -123,9 +186,12 @@ func cmdMigrate(cmd *cobra.Command, args []string) {
|
||||
return int32(n)
|
||||
}
|
||||
|
||||
if dest == "last" {
|
||||
if dest == "up" {
|
||||
err = m.Migrate()
|
||||
|
||||
} else if dest == "down" {
|
||||
err = m.MigrateTo(currentVersion - 1)
|
||||
|
||||
} else if len(dest) >= 3 && dest[0:2] == "-+" {
|
||||
err = m.MigrateTo(currentVersion - mustParseDestination(dest[2:]))
|
||||
if err == nil {
|
||||
@ -139,7 +205,8 @@ func cmdMigrate(cmd *cobra.Command, args []string) {
|
||||
err = m.MigrateTo(currentVersion + mustParseDestination(dest[1:]))
|
||||
|
||||
} else {
|
||||
//err = make(type, 0).MigrateTo(mustParseDestination(dest))
|
||||
cmd.Help()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@ -168,14 +235,14 @@ func cmdMigrate(cmd *cobra.Command, args []string) {
|
||||
|
||||
}
|
||||
|
||||
func cmdStatus(cmd *cobra.Command, args []string) {
|
||||
func cmdDBStatus(cmd *cobra.Command, args []string) {
|
||||
var err error
|
||||
|
||||
if conf, err = initConf(); err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to read config")
|
||||
}
|
||||
|
||||
conn, err := initDB(conf)
|
||||
conn, err := initDB(conf, true)
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to connect to database")
|
||||
}
|
||||
@ -185,7 +252,8 @@ func cmdStatus(cmd *cobra.Command, args []string) {
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to initialize migrator")
|
||||
}
|
||||
//m.Data = config.Data
|
||||
|
||||
m.Data = getMigrationVars()
|
||||
|
||||
err = m.LoadMigrations(conf.MigrationsPath)
|
||||
if err != nil {
|
||||
@ -247,3 +315,11 @@ func ExtractErrorLine(source string, position int) (ErrorLineExtract, error) {
|
||||
|
||||
return ele, nil
|
||||
}
|
||||
|
||||
func getMigrationVars() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"app_name": strings.Title(conf.AppName),
|
||||
"app_name_slug": strings.ToLower(strings.Replace(conf.AppName, " ", "_", -1)),
|
||||
"env": strings.ToLower(os.Getenv("GO_ENV")),
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func cmdSeed(cmd *cobra.Command, args []string) {
|
||||
func cmdDBSeed(cmd *cobra.Command, args []string) {
|
||||
var err error
|
||||
|
||||
if conf, err = initConf(); err != nil {
|
||||
|
@ -133,9 +133,12 @@ func getConfigName() string {
|
||||
|
||||
case strings.HasPrefix(ge, "tes"):
|
||||
return "test"
|
||||
|
||||
case strings.HasPrefix(ge, "dev"):
|
||||
return "dev"
|
||||
}
|
||||
|
||||
return "dev"
|
||||
return ge
|
||||
}
|
||||
|
||||
func getAuthFailBlock(c *config) int {
|
||||
|
Reference in New Issue
Block a user