start of creating a new project cmd

This commit is contained in:
cubixle
2022-07-22 13:15:26 +01:00
commit 2bd76a9b96
11 changed files with 410 additions and 0 deletions

8
README.md Normal file
View File

@@ -0,0 +1,8 @@
# Tuukoti CLI
## Commands
- `tuukoti new sitename` - creates a new project directory with "sitename".
- `tuukoti serve` - serves your app locally.
- `tuukoti build` - builds the binary and any resources.
- `tuukoti update`

3
go.mod Normal file
View File

@@ -0,0 +1,3 @@
module github.com/tuukoti/cli
go 1.18

106
main.go Normal file
View File

@@ -0,0 +1,106 @@
package main
import (
"embed"
"fmt"
"os"
"github.com/tuukoti/cli/maker"
)
const colorRed = "\033[0;31m"
const colorGreen = "\033[0;32m"
const colorBlue = "\033[0;34m"
const colorYellow = "\033[93m"
const colorNone = "\033[0m"
const newLine = "\n"
var Version = "develop"
//go:embed templates
var fs embed.FS
func main() {
if err := runCLI(); err != nil {
fmt.Printf("%s%s%s", colorRed, err, newLine)
}
fmt.Println("")
}
func runCLI() error {
fmt.Println("------------------")
fmt.Printf("Tuukoti CLI - %s%s", Version, newLine)
fmt.Println("------------------")
fmt.Println("")
args := os.Args
if len(args) == 1 {
err := fmt.Errorf("missing command, try `tuukoti list` to see what you can run.")
fmt.Println(err)
return nil
}
switch os.Args[1] {
case "list":
printCmd("new sitename", "create a new project within the directory of sitename")
printCmd("serve", "serves your app locally")
printCmd("build", "build the binary and any resources configured")
printCmd("list", "list displays a list of all commands")
printCmd("version", "displays the cli tools current version")
fmt.Println("")
printHeader("make")
printCmd("make resource", "creates a new route file and a ")
case "version":
fmt.Println("")
version()
case "new":
err := maker.Project(fs, os.Args[2])
if err != nil {
return err
}
fmt.Printf("%sproject %s has been created%s", colorGreen, os.Args[2], newLine)
case "serve":
case "build":
case "make":
if len(os.Args) == 2 {
fmt.Printf("missing what we should make %s", newLine)
return nil
}
switch os.Args[2] {
case "resource":
resourceName := os.Args[3]
err := maker.Resource(resourceName)
if err != nil {
return err
}
}
default:
err := fmt.Errorf("missing command, try `tuukoti list` to see what you can run.")
fmt.Println(err)
}
return nil
}
func version() {
fmt.Printf("Version: %s%s", Version, newLine)
}
func printCmd(commandName, desc string) {
fmt.Printf(" %s%-12s %s- %s.%s", colorGreen, commandName, colorNone, desc, newLine)
}
func printHeader(h string) {
fmt.Printf("%s%s%s", colorYellow, h, newLine)
}

189
maker/project.go Normal file
View File

@@ -0,0 +1,189 @@
package maker
import (
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
)
func Project(fs fs.FS, name string) error {
_, err := os.Stat(name)
if err != nil {
if !os.IsNotExist(err) {
return err
}
}
if err == nil {
return fmt.Errorf("project folder already exists")
}
absPath, err := filepath.Abs(name)
if err != nil {
return err
}
err = os.Mkdir(absPath, 0777)
if err != nil {
return fmt.Errorf("failed to create the project folder, %w", err)
}
err = makeProject(fs, absPath, name)
if err != nil {
rerr := os.RemoveAll(absPath)
if rerr != nil {
return rerr
}
return err
}
return nil
}
func makeProject(fs fs.FS, absPath, name string) error {
// check if folder already exists
err := mainfile(fs, absPath, name)
if err != nil {
return err
}
err = defaultHTTPRoutes(fs, absPath)
if err != nil {
return err
}
err = defaultHomepage(fs, absPath)
if err != nil {
return err
}
err = defaultConfig(fs, absPath)
if err != nil {
return err
}
return nil
}
func mainfile(fs fs.FS, path, projectName string) error {
path = filepath.Join(path, "cmd", projectName)
err := os.MkdirAll(path, 0777)
if err != nil {
return err
}
f, err := os.Create(filepath.Join(path, "main.go"))
if err != nil {
return err
}
tmpl, err := fs.Open("templates/main.go")
if err != nil {
return err
}
_, err = io.Copy(f, tmpl)
if err != nil {
return err
}
err = f.Close()
if err != nil {
return err
}
return nil
}
// defaultHTTPRoutes will create a ./http dir with a http.go file.
// In this file we will register 1 route and 2 route handlers.
// The first handle is the home "/" handler.
// The second handler is a 404 handler.
func defaultHTTPRoutes(fs fs.FS, path string) error {
path = filepath.Join(path, "internal", "http")
err := os.MkdirAll(path, 0777)
if err != nil {
return err
}
f, err := os.Create(filepath.Join(path, "http.go"))
if err != nil {
return err
}
tmpl, err := fs.Open("templates/http/http.go")
if err != nil {
return err
}
_, err = io.Copy(f, tmpl)
if err != nil {
return err
}
err = f.Close()
if err != nil {
return err
}
return nil
}
func defaultHomepage(fs fs.FS, path string) error {
err := os.Mkdir(filepath.Join(path, "template"), 0777)
if err != nil {
return err
}
f, err := os.Create(filepath.Join(path, "templates", "index.html"))
if err != nil {
return err
}
tmpl, err := fs.Open("templates/index.html")
if err != nil {
return err
}
_, err = io.Copy(f, tmpl)
if err != nil {
return err
}
err = f.Close()
if err != nil {
return err
}
return nil
}
func defaultConfig(fs fs.FS, path string) error {
f, err := os.Create(filepath.Join(path, "config.yml"))
if err != nil {
return err
}
tmpl, err := fs.Open("templates/config.yml")
if err != nil {
return err
}
_, err = io.Copy(f, tmpl)
if err != nil {
return err
}
err = f.Close()
if err != nil {
return err
}
return nil
}

5
maker/resource.go Normal file
View File

@@ -0,0 +1,5 @@
package maker
func Resource(name string) error {
return nil
}

2
templates/config.yml Normal file
View File

@@ -0,0 +1,2 @@
host: localhost:8080
debug: false

View File

@@ -0,0 +1,25 @@
package http
import (
"net/http"
"github.com/labstack/echo/v4"
)
func (h *HTTP) DefaultHandler(c echo.Context) error {
return c.Render(http.StatusOK, "index.html", nil)
}
func (h *HTTP) DefaultErrorHandler(err error, c echo.Context) {
code := http.StatusInternalServerError
if he, ok := err.(*echo.HTTPError); ok {
code = he.Code
}
h.log.Error(err)
err = c.Render(code, "error.html", nil)
if err != nil {
h.log.Error(err)
}
}

View File

@@ -0,0 +1,18 @@
package http
import (
"github.com/labstack/echo/v4"
"github.com/sirupsen/logrus"
)
type HTTP struct {
log *logrus.Logger
}
func RegisterRoutes(e *echo.Echo, log *logrus.Logger) {
h := HTTP{log: log}
e.HTTPErrorHandler = h.DefaultErrorHandler
e.GET("/", h.DefaultHandler)
}

43
templates/main.go.tmpl Normal file
View File

@@ -0,0 +1,43 @@
package main
import (
"log"
"os"
"github.com/cubixle/testing/internal/http"
"github.com/labstack/echo/v4"
"github.com/sirupsen/logrus"
"github.com/tuukoti/framework/config"
)
func main() {
if err := run(); err != nil {
log.Fatal(err)
}
}
func run() error {
cfgPath := getEnv("TUUKOTI_CONFIG", "./config.yml")
cfg, err := config.Load(cfgPath)
if err != nil {
return err
}
log := logrus.New()
e := echo.New()
http.RegisterRoutes(e, log)
return e.Start(cfg.Host)
}
func getEnv(name, defaultValue string) string {
v := os.Getenv(name)
if v == "" {
return defaultValue
}
return v
}

View File

View File

@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>Tuukoti</title>
</head>
<body>
<h1>Tuukoti</h1>
</body>
</html>