github.com/kotovmak/go-admin@v1.1.1/adm/project.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"go/format"
     9  	"io/ioutil"
    10  	"os"
    11  	"path/filepath"
    12  	"runtime"
    13  	"strings"
    14  	"text/template"
    15  
    16  	"github.com/kotovmak/go-admin/modules/db"
    17  
    18  	"github.com/kotovmak/go-admin/modules/config"
    19  	"github.com/kotovmak/go-admin/modules/language"
    20  	template2 "github.com/kotovmak/go-admin/template"
    21  	"github.com/mgutz/ansi"
    22  	"gopkg.in/ini.v1"
    23  )
    24  
    25  type Project struct {
    26  	Port         string
    27  	Theme        string
    28  	Prefix       string
    29  	Language     string
    30  	Driver       string
    31  	DriverModule string
    32  	Framework    string
    33  	Module       string
    34  	Orm          string
    35  }
    36  
    37  func buildProject(cfgFile string) {
    38  
    39  	clear(runtime.GOOS)
    40  	cliInfo()
    41  
    42  	var (
    43  		p        Project
    44  		cfgModel *ini.File
    45  		err      error
    46  		info     = new(dbInfo)
    47  	)
    48  
    49  	if cfgFile != "" {
    50  		cfgModel, err = ini.Load(cfgFile)
    51  
    52  		if err != nil {
    53  			panic(errors.New("wrong config file path"))
    54  		}
    55  
    56  		languageCfg, err := cfgModel.GetSection("language")
    57  
    58  		if err == nil {
    59  			setDefaultLangSet(languageCfg.Key("language").Value())
    60  		}
    61  
    62  		projectCfgModel, err := cfgModel.GetSection("project")
    63  
    64  		if err == nil {
    65  			p.Theme = projectCfgModel.Key("theme").Value()
    66  			p.Framework = projectCfgModel.Key("framework").Value()
    67  			p.Language = projectCfgModel.Key("language").Value()
    68  			p.Port = projectCfgModel.Key("port").Value()
    69  			p.Driver = projectCfgModel.Key("driver").Value()
    70  			p.Prefix = projectCfgModel.Key("prefix").Value()
    71  			p.Module = projectCfgModel.Key("module").Value()
    72  			p.Orm = projectCfgModel.Key("orm").Value()
    73  		}
    74  
    75  		info = getDBInfoFromINIConfig(cfgModel, "default")
    76  	}
    77  
    78  	// generate main.go
    79  
    80  	initSurvey()
    81  
    82  	if p.Module == "" {
    83  		dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
    84  		if err != nil {
    85  			panic(err)
    86  		}
    87  		p.Module = promptWithDefault(getWord("module path"), filepath.Base(dir))
    88  	}
    89  	if p.Framework == "" {
    90  		p.Framework = singleSelect(getWord("choose framework"),
    91  			[]string{"gin", "beego", "buffalo", "fasthttp", "echo", "chi", "gf", "gorilla", "iris"}, "gin")
    92  	}
    93  	if p.Theme == "" {
    94  		p.Theme = singleSelect(getWord("choose a theme"), template2.DefaultThemeNames, "sword")
    95  	}
    96  	if p.Language == "" {
    97  		p.Language = singleSelect(getWord("choose language"),
    98  			[]string{getWord("cn"), getWord("en"), getWord("jp"), getWord("tc")},
    99  			getWord("cn"))
   100  		switch p.Language {
   101  		case getWord("cn"):
   102  			p.Language = language.CN
   103  		case getWord("en"):
   104  			p.Language = language.EN
   105  		case getWord("jp"):
   106  			p.Language = language.JP
   107  		case getWord("tc"):
   108  			p.Language = language.TC
   109  		}
   110  	}
   111  	if p.Port == "" {
   112  		p.Port = promptWithDefault(getWord("port"), "80")
   113  	}
   114  	if p.Prefix == "" {
   115  		p.Prefix = promptWithDefault(getWord("url prefix"), "admin")
   116  	}
   117  	if p.Driver == "" {
   118  		p.Driver = singleSelect(getWord("choose a driver"),
   119  			[]string{"mysql", "postgresql", "sqlite", "mssql"}, "mysql")
   120  	}
   121  	p.DriverModule = p.Driver
   122  	if p.Driver == db.DriverPostgresql {
   123  		p.DriverModule = "postgres"
   124  	}
   125  
   126  	rootPath, err := os.Getwd()
   127  
   128  	if err != nil {
   129  		rootPath = "."
   130  	} else {
   131  		rootPath = filepath.ToSlash(rootPath)
   132  	}
   133  
   134  	var cfg = config.SetDefault(&config.Config{
   135  		Debug: true,
   136  		Env:   config.EnvLocal,
   137  		Theme: p.Theme,
   138  		Store: config.Store{
   139  			Path:   "./uploads",
   140  			Prefix: "uploads",
   141  		},
   142  		Language:          p.Language,
   143  		UrlPrefix:         p.Prefix,
   144  		IndexUrl:          "/",
   145  		AccessLogPath:     rootPath + "/logs/access.log",
   146  		ErrorLogPath:      rootPath + "/logs/error.log",
   147  		InfoLogPath:       rootPath + "/logs/info.log",
   148  		BootstrapFilePath: rootPath + "/bootstrap.go",
   149  		GoModFilePath:     rootPath + "/go.mod",
   150  	})
   151  
   152  	if info.DriverName == "" && p.Driver != "" {
   153  		info.DriverName = p.Driver
   154  	}
   155  
   156  	cfg.Databases = askForDBConfig(info)
   157  
   158  	if p.Orm == "" {
   159  		p.Orm = singleSelect(getWord("choose a orm"),
   160  			[]string{getWord("none"), "gorm"}, getWord("none"))
   161  		if p.Orm == getWord("none") {
   162  			p.Orm = ""
   163  		}
   164  	}
   165  
   166  	installProjectTmpl(p, cfg, cfgFile, info)
   167  
   168  	fmt.Println()
   169  	fmt.Println()
   170  	fmt.Println(ansi.Color(getWord("Generate project template success~~🍺🍺"), "green"))
   171  	fmt.Println()
   172  	fmt.Println(getWord("1 Import and initialize database:"))
   173  	fmt.Println()
   174  	if defaultLang == "cn" || p.Language == language.CN || p.Language == "cn" {
   175  		fmt.Println("- sqlite: " + ansi.Color("https://gitee.com/go-admin/go-admin/raw/master/data/admin.db", "blue"))
   176  		fmt.Println("- mssql: " + ansi.Color("https://gitee.com/go-admin/go-admin/raw/master/data/admin.mssql", "blue"))
   177  		fmt.Println("- postgresql: " + ansi.Color("https://gitee.com/go-admin/go-admin/raw/master/data/admin.pgsql", "blue"))
   178  		fmt.Println("- mysql: " + ansi.Color("https://gitee.com/go-admin/go-admin/raw/master/data/admin.sql", "blue"))
   179  	} else {
   180  		fmt.Println("- sqlite: " + ansi.Color("https://github.com/kotovmak/go-admin/raw/master/data/admin.db", "blue"))
   181  		fmt.Println("- mssql: " + ansi.Color("https://raw.githubusercontent.com/GoAdminGroup/go-admin/master/data/admin.mssql", "blue"))
   182  		fmt.Println("- postgresql: " + ansi.Color("https://raw.githubusercontent.com/GoAdminGroup/go-admin/master/data/admin.pgsql", "blue"))
   183  		fmt.Println("- mysql: " + ansi.Color("https://raw.githubusercontent.com/GoAdminGroup/go-admin/master/data/admin.sql", "blue"))
   184  	}
   185  	fmt.Println()
   186  	fmt.Println(getWord("2 Execute the following command to run:"))
   187  	fmt.Println()
   188  	if runtime.GOOS == "windows" {
   189  		fmt.Println("> GO111MODULE=on go mod init " + p.Module)
   190  		if defaultLang == "cn" || p.Language == language.CN || p.Language == "cn" {
   191  			fmt.Println("> GORPOXY=https://goproxy.io GO111MODULE=on go mod tidy")
   192  		} else {
   193  			fmt.Println("> GO111MODULE=on go mod tidy")
   194  		}
   195  		fmt.Println("> GO111MODULE=on go run .")
   196  	} else {
   197  		fmt.Println("> make init module=" + p.Module)
   198  		if defaultLang == "cn" || p.Language == language.CN || p.Language == "cn" {
   199  			fmt.Println("> GORPOXY=https://goproxy.io make install")
   200  		} else {
   201  			fmt.Println("> make install")
   202  		}
   203  		fmt.Println("> make serve")
   204  	}
   205  	fmt.Println()
   206  	fmt.Println(getWord("3 Visit and login:"))
   207  	fmt.Println()
   208  	if p.Port != "80" {
   209  		fmt.Println("-  " + getWord("Login: ") + ansi.Color("http://127.0.0.1:"+p.Port+"/"+p.Prefix+"/login", "blue"))
   210  	} else {
   211  		fmt.Println("-  " + getWord("Login: ") + ansi.Color("http://127.0.0.1/"+p.Prefix+"/login", "blue"))
   212  	}
   213  	fmt.Println(getWord("account: admin  password: admin"))
   214  	fmt.Println()
   215  	fmt.Println("-  " + getWord("Generate CRUD models: ") + ansi.Color("http://127.0.0.1:"+p.Port+"/"+p.Prefix+"/info/generate/new", "blue"))
   216  	fmt.Println()
   217  	fmt.Println(getWord("4 See more in README.md"))
   218  	fmt.Println()
   219  	if defaultLang == "cn" {
   220  		fmt.Println(getWord("see the docs: ") + ansi.Color("http://doc.go-admin.cn",
   221  			"blue"))
   222  	} else {
   223  		fmt.Println(getWord("see the docs: ") + ansi.Color("https://book.go-admin.com",
   224  			"blue"))
   225  	}
   226  	fmt.Println(getWord("visit forum: ") + ansi.Color("http://discuss.go-admin.com",
   227  		"blue"))
   228  	fmt.Println()
   229  	fmt.Println()
   230  }
   231  
   232  func GetCurrentDirectory() string {
   233  	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
   234  	if err != nil {
   235  		panic(err)
   236  	}
   237  	return strings.ReplaceAll(dir, "\\", "/")
   238  }
   239  
   240  func installProjectTmpl(p Project, cfg *config.Config, cfgFile string, info *dbInfo) {
   241  
   242  	t, err := template.New("project").Funcs(map[string]interface{}{
   243  		"title": strings.Title,
   244  	}).Parse(projectTemplate[p.Framework])
   245  	checkError(err)
   246  	buf := new(bytes.Buffer)
   247  	checkError(t.Execute(buf, p))
   248  	c, err := format.Source(buf.Bytes())
   249  	checkError(err)
   250  	checkError(ioutil.WriteFile("./main.go", c, 0644))
   251  
   252  	checkError(os.Mkdir("pages", os.ModePerm))
   253  	checkError(os.Mkdir("tables", os.ModePerm))
   254  	checkError(os.Mkdir("logs", os.ModePerm))
   255  	checkError(os.Mkdir("uploads", os.ModePerm))
   256  	checkError(os.Mkdir("html", os.ModePerm))
   257  	checkError(os.Mkdir("build", os.ModePerm))
   258  	if p.Orm == "gorm" {
   259  		checkError(os.Mkdir("models", os.ModePerm))
   260  		checkError(ioutil.WriteFile("./models/base.go", []byte(`package models
   261  
   262  import (
   263  	"github.com/kotovmak/go-admin/modules/db"
   264  	"github.com/jinzhu/gorm"
   265  )
   266  
   267  var (
   268  	orm *gorm.DB
   269  	err error
   270  )
   271  
   272  func Init(c db.Connection) {
   273  	orm, err = gorm.Open("`+p.DriverModule+`", c.GetDB("default"))
   274  
   275  	if err != nil {
   276  		panic("initialize orm failed")
   277  	}
   278  }
   279  `), os.ModePerm))
   280  	}
   281  
   282  	checkError(ioutil.WriteFile("./logs/access.log", []byte{}, os.ModePerm))
   283  	checkError(ioutil.WriteFile("./logs/info.log", []byte{}, os.ModePerm))
   284  	checkError(ioutil.WriteFile("./logs/error.log", []byte{}, os.ModePerm))
   285  	checkError(ioutil.WriteFile("./bootstrap.go", []byte(`package main`), os.ModePerm))
   286  
   287  	if p.Theme == "sword" {
   288  		checkError(ioutil.WriteFile("./pages/index.go", swordIndexPage, 0644))
   289  	} else {
   290  		checkError(ioutil.WriteFile("./pages/index.go", adminlteIndexPage, 0644))
   291  	}
   292  
   293  	if defaultLang == "cn" || p.Language == language.CN || p.Language == "cn" {
   294  		checkError(ioutil.WriteFile("./main_test.go", mainTestCN, 0644))
   295  		checkError(ioutil.WriteFile("./README.md", []byte(fmt.Sprintf(readmeCN, p.Port+"/"+p.Prefix)), 0644))
   296  	} else {
   297  		checkError(ioutil.WriteFile("./main_test.go", mainTest, 0644))
   298  		checkError(ioutil.WriteFile("./README.md", []byte(fmt.Sprintf(readme, p.Port+"/"+p.Prefix)), 0644))
   299  	}
   300  
   301  	makefileContent := makefile
   302  	if p.Driver == db.DriverSqlite {
   303  		makefileContent = bytes.ReplaceAll(makefileContent, []byte("CGO_ENABLED=0"), []byte("CGO_ENABLED=1"))
   304  	}
   305  
   306  	checkError(ioutil.WriteFile("./Makefile", makefileContent, 0644))
   307  
   308  	checkError(ioutil.WriteFile("./html/hello.tmpl", []byte(`<div class="hello">
   309      <h1>{{index . "msg"}}</h1>
   310  </div>
   311  
   312  <style>
   313      .hello {
   314          padding: 50px;
   315          width: 100%;
   316          text-align: center;
   317      }
   318  </style>
   319  `), 0644))
   320  
   321  	checkError(ioutil.WriteFile("./tables/tables.go", []byte(`// This file is generated by GoAdmin CLI adm.
   322  package tables
   323  
   324  import "github.com/kotovmak/go-admin/plugins/admin/modules/table"
   325  
   326  // Generators is a map of table models.
   327  //
   328  // The key of Generators is the prefix of table info url.
   329  // The corresponding value is the Form and Table data.
   330  //
   331  // http://{{config.Domain}}:{{Port}}/{{config.Prefix}}/info/{{key}}
   332  //
   333  // example:
   334  //
   335  // example end
   336  //
   337  var Generators = map[string]table.Generator{
   338  
   339  	// generators end
   340  }
   341  `), 0644))
   342  
   343  	// generate config json
   344  
   345  	if cfgFile == "" {
   346  		t, err := template.New("ini").Parse(admINI)
   347  		checkError(err)
   348  		buf := new(bytes.Buffer)
   349  		checkError(t.Execute(buf, info))
   350  		checkError(ioutil.WriteFile("./adm.ini", buf.Bytes(), 0644))
   351  	}
   352  
   353  	configByte, err := json.MarshalIndent(cfg, "", "	")
   354  	configByte = bytes.ReplaceAll(configByte, []byte(`
   355  	"logger": {
   356  		"encoder": {},
   357  		"rotate": {}
   358  	},`), []byte{})
   359  	configByte = bytes.ReplaceAll(configByte, []byte(`,
   360  	"animation": {}`), []byte{})
   361  	checkError(err)
   362  	checkError(ioutil.WriteFile("./config.json", configByte, 0644))
   363  
   364  }