From d763ad1ff4f6374f0c3ba56589a98b47bf85197b Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 9 Feb 2022 21:13:38 +0800 Subject: [PATCH] =?UTF-8?q?+=20init=20=E5=91=BD=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/init.go | 258 ++++++++++++++++++++++++++++++++++++++++++++++++++++ cmd/root.go | 31 ++++++- 2 files changed, 285 insertions(+), 4 deletions(-) create mode 100644 cmd/init.go diff --git a/cmd/init.go b/cmd/init.go new file mode 100644 index 00000000..06f576f9 --- /dev/null +++ b/cmd/init.go @@ -0,0 +1,258 @@ +package cmd + +import ( + "errors" + "fmt" + "os" + "path/filepath" + + "github.com/fatih/color" + "github.com/spf13/cobra" + "github.com/yaoapp/yao/config" +) + +var initCmd = &cobra.Command{ + Use: "init", + Short: L("Initialize project"), + Long: L("Initialize project"), + Run: func(cmd *cobra.Command, args []string) { + Boot() + checkDir() + makeDirs() + makeAppJSON() + makeEnv() + defaultApps() + }, +} + +func makeDirs() { + dirs := []string{"db", "models", "flows", "scripts", "tables", "libs", "ui"} + for _, name := range dirs { + dirname := filepath.Join(config.Conf.Root, name) + if _, err := os.Stat(dirname); errors.Is(err, os.ErrNotExist) { + if err := os.MkdirAll(dirname, os.ModePerm); err != nil { + fmt.Println(color.RedString(L("Fatal: %s"), err.Error())) + os.Exit(1) + } + } + } +} + +func defaultApps() { + makeFile(filepath.Join("models", "pet.mod.json"), `{ + "name": "Pet", + "table": { "name": "pet", "comment": "Pet" }, + "columns": [ + { "label": "ID", "name": "id", "type": "ID", "comment": "ID" }, + { "label": "SN", "name": "sn", "type": "string", "unique": true }, + { "label": "Name", "name": "name", "type": "string", "index": true }, + { + "label": "Kind", + "name": "kind", + "type": "enum", + "option": ["cat", "dog"], + "default": "cat", + "index": true + }, + { "label": "Description", "name": "desc", "type": "string", "comment": "Description" } + ], + "values": [ + { "sn": "100001", "name": "Cookie", "kind": "cat", "desc": "a cat" }, + { "sn": "100002", "name": "Beibei", "kind": "dog", "desc": "a dog" } + ], + "option": { "timestamps": true, "soft_deletes": true } +}`) + + makeFile(filepath.Join("tables", "pet.tab.json"), `{ + "name": "Pet", + "version": "1.0.0", + "decription": "Pet admin", + "bind": { "model": "pet" }, + "apis": {}, + "columns": { + "ID": { + "label": "ID", + "view": { "type": "label", "props": { "value": ":id" } } + }, + "SN": { + "label": "SN", + "view": { "type": "label", "props": { "value": ":sn" } }, + "edit": { "type": "input", "props": { "value": ":sn" } } + }, + "Name": { + "label": "Name", + "view": { "type": "label", "props": { "value": ":name" } }, + "edit": { "type": "input", "props": { "value": ":name" } } + }, + "Kind": { + "label": "Kind", + "view": { "type": "label", "props": { "value": ":kind" } }, + "edit": { + "type": "select", + "props": { + "value": ":kind", + "options": [ + { "label": "cat", "value": "cat" }, + { "label": "dog", "value": "dog" } + ] + } + } + }, + "Description": { + "label": "Description", + "view": { "type": "label", "props": { "value": ":desc" } }, + "edit": { "type": "textArea", "props": { "value": ":desc", "rows": 4 } } + } + }, + "filters": { + "Keywords": { "@": "f.Keywords", "in": ["where.name.match"]} + }, + "list": { + "primary": "id", + "layout": { + "columns": [ + { "name": "ID", "width": 80 }, + { "name": "SN", "width": 100 }, + { "name": "Name", "width": 200 }, + { "name": "Kind" } + ], + "filters": [{ "name": "Keywords" }] + }, + "actions": { "pagination": { "props": { "showTotal": true } } }, + "option": {} + }, + "edit": { + "primary": "id", + "layout": { + "fieldset": [ + { + "columns": [ + { "name": "SN", "width": 8 }, + { "name": "Name", "width": 8 }, + { "name": "Kind", "width": 8 }, + { "name": "Description", "width": 24 } + ] + } + ] + }, + "actions": { "cancel": {}, "save": {}, "delete": {} } + } + } + `) + + makeFile(filepath.Join("flows", "setmenu.flow.json"), `{ + "label": "System Menu", + "version": "1.0.0", + "description": "Initialize system menu", + "nodes": [ + { + "name": "Clean menu data", + "engine": "xiang", + "query": { + "sql": { "stmt": "delete from xiang_menu" } + } + }, + { + "name": "Add new menu", + "process": "models.xiang.menu.Save", + "args": [ + { + "name": "Pet", + "path": "/table/pet", + "icon": "icon-github", + "rank": 1, + "status": "enabled", + "visible_menu": 0, + "blocks": 0 + } + ] + } + ], + "output": "done" + } + `) + + makeFile(filepath.Join("scripts", "day.js"), ` +function NextDay(day) { + today = new Date(day); + today.setDate(today.getDate() + 1); + return today.toISOString().slice(0, 19).split("T")[0]; +} +`) + + makeFile(filepath.Join("ui", "index.html"), `It works! https://yaoapps.com`) + + makeFile(filepath.Join("libs", "f.json"), `{ + "Keywords": { + "__comment": "{ '@': 'f.Keywords', 'in': ['where.name.match']}", + "label": "Keywords", + "bind": "{{$in.0}}", + "input": { + "type": "input", + "props": { + "placeholder": "type Keywords..." + } + } + } + } + `) +} + +func makeEnv() { + makeFile(".env", ` +YAO_ENV=development # development | production +YAO_ROOT="`+config.Conf.Root+`" +YAO_HOST="0.0.0.0" +YAO_PORT="5099" +YAO_SESSION="memory" +YAO_LOG="`+config.Conf.Root+`/logs/application.log" +YAO_LOG_MODE="TEXT" # TEXT | JSON +YAO_JWT_SECRET="bLp@bi!oqo-2U+hoTRUG" +YAO_DB_DRIVER=sqlite3 # sqlite3 | mysql +YAO_DB_PRIMARY="`+config.Conf.Root+`/db/yao.db" +`) +} + +func makeAppJSON() { + makeFile("app.json", `{ + "name": "Yao", + "short": "Yao", + "description": "Another yao app", + "option": { + "nav_user": "xiang.user", + "nav_menu": "xiang.menu", + "hide_user": false, + "hide_menu": false, + "login": { + "entry": { + "admin": "/table/pet" + } + } + } +}`) +} + +func checkDir() { + dirs := []string{"db", "models", "flows", "scripts", "tables", "libs", "ui", ".env", "app.json"} + for _, name := range dirs { + dirname := filepath.Join(config.Conf.Root, name) + if _, err := os.Stat(dirname); !errors.Is(err, os.ErrNotExist) { + fmt.Println(color.RedString(L("Fatal: %s"), dirname+" already existed")) + os.Exit(1) + } + } +} + +func makeFile(name string, source string) { + filename := filepath.Join(config.Conf.Root, name) + if _, err := os.Stat(filename); !errors.Is(err, os.ErrNotExist) { + fmt.Println(color.RedString(L("Fatal: %s"), filename+" already existed")) + os.Exit(1) + } + content := []byte(source) + err := os.WriteFile(filename, content, 0644) + if err != nil { + fmt.Println(color.RedString(L("Fatal: %s"), err.Error())) + os.Exit(1) + } +} diff --git a/cmd/root.go b/cmd/root.go index 849085d5..8bc5de7c 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -6,6 +6,7 @@ import ( "path/filepath" "github.com/spf13/cobra" + "github.com/yaoapp/kun/exception" "github.com/yaoapp/yao/config" "github.com/yaoapp/yao/share" ) @@ -39,6 +40,7 @@ var langs = map[string]string{ "%s Response": "%s 返回结果", "Update schema model: %s (%s) ": "更新表结构 model: %s (%s)", "Model name": "模型名称", + "Initialize project": "项目初始化", } // L 多语言切换 @@ -75,6 +77,7 @@ func init() { inspectCmd, startCmd, runCmd, + initCmd, ) rootCmd.SetHelpCommand(helpCmd) rootCmd.PersistentFlags().StringVarP(&appPath, "app", "a", "", L("Application directory")) @@ -89,12 +92,22 @@ func Execute() { } } -// Boot 设定配置 +// Boot 设定配置 (这个逻辑有 BUG ) func Boot() { if envFile == "" && appPath != "" { - config.Conf = config.LoadFrom(filepath.Join(appPath, ".env")) - config.Conf.Root = appPath + root, err := filepath.Abs(appPath) + if err != nil { + exception.New("Root error %s", 500, err.Error()).Throw() + } + config.Conf = config.LoadFrom(filepath.Join(root, ".env")) + config.Conf.Root = root + if config.Conf.Mode == "production" { + config.Production() + } else if config.Conf.Mode == "development" { + config.Development() + } + return } @@ -104,7 +117,17 @@ func Boot() { } if envFile != "" && appPath != "" { + root, err := filepath.Abs(appPath) + if err != nil { + exception.New("Root error %s", 500, err.Error()).Throw() + } config.Conf = config.LoadFrom(envFile) - config.Conf.Root = appPath + config.Conf.Root = root + if config.Conf.Mode == "production" { + config.Production() + } else if config.Conf.Mode == "development" { + config.Development() + } + } }