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 }