diff --git a/cmd/serve.go b/cmd/serve.go
index 646a7ed..f5d1910 100644
--- a/cmd/serve.go
+++ b/cmd/serve.go
@@ -7,6 +7,7 @@ import (
"github.com/criteo/command-launcher/internal/backend"
"github.com/criteo/command-launcher/internal/config"
"github.com/criteo/command-launcher/internal/context"
+ "github.com/criteo/command-launcher/internal/server"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
@@ -30,7 +31,7 @@ func AddServeCmd(rootCmd *cobra.Command, appCtx context.LauncherContext, back ba
port = serveFlags.port
}
fmt.Printf("Starting server on port %d", port)
- if err := back.Serve(port); err != nil {
+ if err := server.Serve(&back, port); err != nil {
fmt.Printf("Failed to start server: %s\n", err)
os.Exit(1)
}
diff --git a/internal/backend/api.go b/internal/backend/api.go
index 4bc0886..9511509 100644
--- a/internal/backend/api.go
+++ b/internal/backend/api.go
@@ -62,9 +62,6 @@ type Backend interface {
// Return dropin local repsository
DropinRepository() repository.PackageRepository
- // start the server as daemon
- Serve(port int) error
-
// Print out the command resolution details
Debug()
}
diff --git a/internal/backend/server.go b/internal/backend/server.go
deleted file mode 100644
index f3a2881..0000000
--- a/internal/backend/server.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package backend
-
-import (
- "fmt"
- "net/http"
-)
-
-func StartHttpServer(port int) error {
- http.HandleFunc("/", HelloHandler)
- http.HandleFunc("/health", HealthHandler)
- return http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
-}
-
-func HealthHandler(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte("OK"))
-}
-
-func HelloHandler(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte("Hello, world!"))
-}
-
-// Implement the serve funcation in default backend
-func (backend *DefaultBackend) Serve(port int) error {
- return StartHttpServer(port)
-}
diff --git a/internal/server/server.go b/internal/server/server.go
new file mode 100644
index 0000000..63b8126
--- /dev/null
+++ b/internal/server/server.go
@@ -0,0 +1,168 @@
+package server
+
+import (
+ "bytes"
+ "embed"
+ "fmt"
+ "html/template"
+ "net/http"
+ "sort"
+ "strings"
+
+ . "github.com/criteo/command-launcher/internal/backend"
+ "github.com/criteo/command-launcher/internal/command"
+)
+
+type Server struct {
+ backend *Backend
+}
+
+//go:embed static
+var fs embed.FS
+
+//go:embed templates
+var templates embed.FS
+
+func (server *Server) IndexHandler(w http.ResponseWriter, r *http.Request) {
+ index, _ := fs.ReadFile("static/index.html")
+ w.Write(index)
+}
+
+type Command struct {
+ FullName string
+ Group string
+ Name string
+ Package string
+ Registry string
+ Short string
+ Long string
+ Examples []command.ExampleEntry
+ Flags []command.Flag
+ SubCmds []*Command
+}
+
+type CommandIndex struct {
+ Commands []*Command
+}
+
+func (server *Server) CommandIndexHandler(w http.ResponseWriter, r *http.Request) {
+ repos := (*(server.backend)).AllRepositories()
+ cmdMap := map[string]*Command{}
+
+ for _, repo := range repos {
+ pkgs := repo.InstalledPackages()
+ for _, pkg := range pkgs {
+ cmds := pkg.Commands()
+ for _, cmd := range cmds {
+ if cmd.Name() == "__setup__" {
+ continue
+ }
+ if cmd.Group() == "" { // this is top level command
+ // add group command
+ if groupCmd, ok := cmdMap[cmd.FullName()]; !ok {
+ groupCmd = &Command{
+ FullName: cmd.FullName(),
+ Group: cmd.Group(),
+ Name: cmd.Name(),
+ Package: pkg.Name(),
+ Registry: repo.Name(),
+ SubCmds: []*Command{},
+ }
+ cmdMap[cmd.FullName()] = groupCmd
+ }
+ } else { // this is a sub command
+ // get the group command full name
+ groupCmdFullName := fmt.Sprintf("%s@@%s@%s", cmd.Group(), pkg.Name(), repo.Name())
+ if groupCmd, ok := cmdMap[groupCmdFullName]; !ok {
+ groupCmd = &Command{
+ FullName: groupCmdFullName,
+ Group: "",
+ Name: cmd.Group(),
+ Package: pkg.Name(),
+ Registry: repo.Name(),
+ SubCmds: []*Command{
+ &Command{
+ FullName: cmd.FullName(),
+ Group: cmd.Group(),
+ Name: cmd.Name(),
+ Package: pkg.Name(),
+ Registry: repo.Name(),
+ SubCmds: []*Command{},
+ },
+ },
+ }
+ cmdMap[groupCmdFullName] = groupCmd
+ } else {
+ groupCmd.SubCmds = append(groupCmd.SubCmds, &Command{
+ FullName: cmd.FullName(),
+ Group: cmd.Group(),
+ Name: cmd.Name(),
+ Package: pkg.Name(),
+ Registry: repo.Name(),
+ SubCmds: []*Command{},
+ })
+ }
+
+ }
+ }
+ }
+ }
+
+ // load the template
+ tmpl_text, _ := templates.ReadFile("templates/cmd_index.html")
+ tmpl, _ := template.New("command_index").Parse(string(tmpl_text))
+
+ groups := make([]*Command, 0, len(cmdMap))
+ for _, cmd := range cmdMap {
+ groups = append(groups, cmd)
+ }
+
+ sort.Slice(groups, func(i, j int) bool {
+ // return fmt.Sprintf("%s@%s", groups[i].Package, groups[i].Registry) < fmt.Sprintf("%s@%s", groups[j].Package, groups[j].Registry)
+ return groups[i].FullName < groups[j].FullName
+ })
+
+ var tpl bytes.Buffer
+ tmpl.Execute(&tpl, CommandIndex{Commands: groups})
+
+ html_wrapper, _ := templates.ReadFile("templates/html_wrapper.html")
+ content := strings.ReplaceAll(string(html_wrapper), "#INPUT#", tpl.String())
+ w.Write([]byte(content))
+}
+
+func (server *Server) CommandHandler(w http.ResponseWriter, r *http.Request) {
+ fullName := strings.TrimPrefix(r.URL.Path, "/command/")
+ fmt.Println(r.URL.Path, fullName)
+ cmd, _ := (*(server.backend)).FindCommandByFullName(fullName)
+
+ tmpl_text, _ := templates.ReadFile("templates/command.html")
+ tmpl, _ := template.New("command").Parse(string(tmpl_text))
+ command := Command{
+ FullName: cmd.FullName(),
+ Group: cmd.Group(),
+ Name: cmd.Name(),
+ Package: cmd.PackageName(),
+ Registry: cmd.RepositoryID(),
+ Short: cmd.ShortDescription(),
+ Long: cmd.LongDescription(),
+ Examples: cmd.Examples(),
+ Flags: cmd.Flags(),
+ }
+
+ tmpl.Execute(w, command)
+}
+
+func (server *Server) HealthHandler(w http.ResponseWriter, r *http.Request) {
+ w.Write([]byte("OK"))
+}
+
+// Implement the serve funcation in default backend
+func Serve(backend *Backend, port int) error {
+ server := Server{backend: backend}
+
+ http.HandleFunc("/", server.CommandIndexHandler)
+ http.HandleFunc("/test", server.CommandIndexHandler)
+ http.HandleFunc("/command/", server.CommandHandler)
+ http.HandleFunc("/health", server.HealthHandler)
+ return http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
+}
diff --git a/internal/server/static/index.html b/internal/server/static/index.html
new file mode 100644
index 0000000..828579c
--- /dev/null
+++ b/internal/server/static/index.html
@@ -0,0 +1,112 @@
+
+
+
+ Command Launcher
+
+
+
+
+
+
+ Index
+
+
+
+
+
+
+
+ moab init 🔗
+ full name:init@moab@moab@dropinpackage:moabregistry:dropin
+ Initiate a moab workspace
+
+ Examples
+
+
Initiate a java moab workspace and checkout one repository
+
moab init java software-factory/example-projects
+
+
+
+ Try it out
+
+ Output
+
+ npm install -g @command-launcher/cli
+ another line
+ $ls -la
+ .
+ ..
+ .git
+
+
+
+
+
+ moab build
+ package:moabregistry:dropin
+ Build all the projects in current folder
+
+ Examples
+
+
Initiate a java moab workspace and checkout one repository
+
moab init java software-factory/example-projects
+
+
+
+ Try it out
+
+ Output
+
+ npm install -g @command-launcher/cli
+ another line
+ $ls -la
+ .
+ ..
+ .git
+
+
+
+
+
+
+
+
diff --git a/internal/server/templates/cmd_index.html b/internal/server/templates/cmd_index.html
new file mode 100644
index 0000000..081602f
--- /dev/null
+++ b/internal/server/templates/cmd_index.html
@@ -0,0 +1,13 @@
+
+ Index
+ {{range .Commands}}
+
+ {{end}}
+
diff --git a/internal/server/templates/command.html b/internal/server/templates/command.html
new file mode 100644
index 0000000..dbb6ebd
--- /dev/null
+++ b/internal/server/templates/command.html
@@ -0,0 +1,76 @@
+
+
+
+ {{.Group}} {{.Name}}
+
+
+
+
+
+
+
+
+ {{.Group}} {{.Name}}
+ full name:{{.FullName}}package:{{.Package}}registry:{{.Registry}}
+ {{.Short}}
+
+ Examples
+ {{range .Examples}}
+
+
{{.Scenario}}
+
{{.Command}}
+
+ {{end}}
+
+
+ Try it out
+
+ Output
+
+ npm install -g @command-launcher/cli
+ another line
+ $ls -la
+ .
+ ..
+ .git
+
+
+
+
+
+
+
diff --git a/internal/server/templates/html_wrapper.html b/internal/server/templates/html_wrapper.html
new file mode 100644
index 0000000..3e34c96
--- /dev/null
+++ b/internal/server/templates/html_wrapper.html
@@ -0,0 +1,17 @@
+
+
+
+ Test Page
+
+
+
+
+
+
+#INPUT#
+
+
+
+
+
diff --git a/internal/server/templates/index.html b/internal/server/templates/index.html
new file mode 100644
index 0000000..21a85e5
--- /dev/null
+++ b/internal/server/templates/index.html
@@ -0,0 +1,23 @@
+
+
+
+ Command Launcher
+
+
+
+
+
+ {{.Index}}
+ {{range .Commands}}
+ {{.}}
+ {{end}}
+
+
+