this repo has no description smallweb.run
smallweb
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

add support for unix socket, fix config --json output

pomdtr c4bab95a cb3bb476

+53 -55
+5 -6
api/api.go
··· 44 44 server := &Server{k: k, httpWriter: httpWriter, cronWriter: cronWriter, consoleWriter: consoleWriter} 45 45 handler := Handler(server) 46 46 webdavHandler := webdav.Handler{ 47 - FileSystem: webdav.Dir(utils.ExpandTilde(k.String("dir"))), 47 + FileSystem: webdav.Dir(k.String("dir")), 48 48 LockSystem: webdav.NewMemLS(), 49 49 Prefix: "/webdav", 50 50 } ··· 63 63 } 64 64 65 65 appname := strings.TrimSuffix(domain, "."+k.String("domain")) 66 - appDir := filepath.Join(utils.ExpandTilde(k.String("dir")), appname) 66 + appDir := filepath.Join(k.String("dir"), appname) 67 67 if _, err := app.LoadApp(appDir, k.String("domain")); err != nil { 68 68 http.Error(w, err.Error(), http.StatusInternalServerError) 69 69 return ··· 129 129 130 130 // GetV0AppsAppEnv implements ServerInterface. 131 131 func (me *Server) GetApp(w http.ResponseWriter, r *http.Request, appname string) { 132 - rootDir := utils.ExpandTilde(me.k.String("dir")) 133 - a, err := app.LoadApp(filepath.Join(rootDir, appname), me.k.String("domain")) 132 + a, err := app.LoadApp(filepath.Join(me.k.String("dir"), appname), me.k.String("domain")) 134 133 if err != nil { 135 134 http.Error(w, err.Error(), http.StatusInternalServerError) 136 135 return ··· 177 176 } 178 177 179 178 func (me *Server) GetApps(w http.ResponseWriter, r *http.Request) { 180 - rootDir := utils.ExpandTilde(me.k.String("dir")) 181 - names, err := app.ListApps(rootDir) 179 + rootDir := me.k.String("dir") 180 + names, err := app.ListApps(me.k.String("dir")) 182 181 if err != nil { 183 182 http.Error(w, err.Error(), http.StatusInternalServerError) 184 183 return
+10 -11
cmd/app.go
··· 13 13 "github.com/cli/go-gh/v2/pkg/tableprinter" 14 14 "github.com/mattn/go-isatty" 15 15 "github.com/pomdtr/smallweb/app" 16 - "github.com/pomdtr/smallweb/utils" 17 16 "github.com/spf13/cobra" 18 17 "golang.org/x/term" 19 18 ) ··· 29 28 GroupID: CoreGroupID, 30 29 Args: cobra.ExactArgs(1), 31 30 RunE: func(cmd *cobra.Command, args []string) error { 32 - rootDir := utils.ExpandTilde(k.String("dir")) 31 + rootDir := k.String("dir") 33 32 appDir := filepath.Join(rootDir, args[0]) 34 33 if _, err := os.Stat(appDir); !os.IsNotExist(err) { 35 34 return fmt.Errorf("directory already exists: %s", appDir) ··· 58 57 Short: "Open an app in the browser", 59 58 GroupID: CoreGroupID, 60 59 Args: cobra.MaximumNArgs(1), 61 - ValidArgsFunction: completeApp(utils.ExpandTilde(k.String("dir"))), 60 + ValidArgsFunction: completeApp(k.String("dir")), 62 61 RunE: func(cmd *cobra.Command, args []string) error { 63 - rootDir := utils.ExpandTilde(k.String("dir")) 62 + rootDir := k.String("dir") 64 63 65 64 if len(args) == 0 { 66 65 cwd, err := os.Getwd() ··· 112 111 GroupID: CoreGroupID, 113 112 Aliases: []string{"ls"}, 114 113 RunE: func(cmd *cobra.Command, args []string) error { 115 - rootDir := utils.ExpandTilde(k.String("dir")) 114 + rootDir := k.String("dir") 116 115 names, err := app.ListApps(rootDir) 117 116 if err != nil { 118 117 return fmt.Errorf("failed to list apps: %w", err) ··· 183 182 Short: "Rename an app", 184 183 GroupID: CoreGroupID, 185 184 Aliases: []string{"move", "mv"}, 186 - ValidArgsFunction: completeApp(utils.ExpandTilde(k.String("dir"))), 185 + ValidArgsFunction: completeApp(k.String("dir")), 187 186 Args: cobra.ExactArgs(2), 188 187 RunE: func(cmd *cobra.Command, args []string) error { 189 - rootDir := utils.ExpandTilde(k.String("dir")) 188 + rootDir := k.String("dir") 190 189 src := filepath.Join(rootDir, args[0]) 191 190 dst := filepath.Join(rootDir, args[1]) 192 191 ··· 216 215 Short: "Clone an app", 217 216 GroupID: CoreGroupID, 218 217 Aliases: []string{"cp", "copy", "fork"}, 219 - ValidArgsFunction: completeApp(utils.ExpandTilde(k.String("dir"))), 218 + ValidArgsFunction: completeApp(k.String("dir")), 220 219 Args: cobra.ExactArgs(2), 221 220 RunE: func(cmd *cobra.Command, args []string) error { 222 - rootDir := utils.ExpandTilde(k.String("dir")) 221 + rootDir := k.String("dir") 223 222 src := filepath.Join(rootDir, args[0]) 224 223 dst := filepath.Join(rootDir, args[1]) 225 224 ··· 250 249 Short: "Delete an app", 251 250 GroupID: CoreGroupID, 252 251 Aliases: []string{"remove", "rm"}, 253 - ValidArgsFunction: completeApp(utils.ExpandTilde(k.String("dir"))), 252 + ValidArgsFunction: completeApp(k.String("dir")), 254 253 Args: cobra.ExactArgs(1), 255 254 RunE: func(cmd *cobra.Command, args []string) error { 256 - rootDir := utils.ExpandTilde(k.String("dir")) 255 + rootDir := k.String("dir") 257 256 p := filepath.Join(rootDir, args[0]) 258 257 if _, err := os.Stat(p); os.IsNotExist(err) { 259 258 return fmt.Errorf("app not found: %s", args[0])
+4 -5
cmd/cron.go
··· 10 10 "github.com/cli/go-gh/v2/pkg/tableprinter" 11 11 "github.com/mattn/go-isatty" 12 12 "github.com/pomdtr/smallweb/app" 13 - "github.com/pomdtr/smallweb/utils" 14 13 "github.com/pomdtr/smallweb/worker" 15 14 "github.com/spf13/cobra" 16 15 "golang.org/x/term" ··· 70 69 Args: cobra.NoArgs, 71 70 Short: "List cron jobs", 72 71 RunE: func(cmd *cobra.Command, args []string) error { 73 - rootDir := utils.ExpandTilde(k.String("dir")) 72 + rootDir := k.String("dir") 74 73 75 74 apps, err := app.ListApps(rootDir) 76 75 if err != nil { ··· 151 150 152 151 cmd.Flags().StringVar(&flags.app, "app", "", "filter by app") 153 152 cmd.Flags().BoolVar(&flags.json, "json", false, "output as json") 154 - cmd.RegisterFlagCompletionFunc("app", completeApp(utils.ExpandTilde(k.String("dir")))) 153 + cmd.RegisterFlagCompletionFunc("app", completeApp(k.String("dir"))) 155 154 156 155 return cmd 157 156 } ··· 162 161 Short: "Trigger a cron job", 163 162 Args: cobra.ExactArgs(1), 164 163 ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { 165 - rootDir := utils.ExpandTilde(k.String("dir")) 164 + rootDir := k.String("dir") 166 165 167 166 var completions []string 168 167 apps, err := app.ListApps(rootDir) ··· 189 188 return completions, cobra.ShellCompDirectiveDefault 190 189 }, 191 190 RunE: func(cmd *cobra.Command, args []string) error { 192 - rootDir := utils.ExpandTilde(k.String("dir")) 191 + rootDir := k.String("dir") 193 192 parts := strings.Split(args[0], ":") 194 193 if len(parts) != 2 { 195 194 return fmt.Errorf("invalid job name")
+1 -2
cmd/log.go
··· 10 10 "os" 11 11 12 12 "github.com/pomdtr/smallweb/api" 13 - "github.com/pomdtr/smallweb/utils" 14 13 "github.com/spf13/cobra" 15 14 ) 16 15 ··· 313 312 314 313 cmd.Flags().BoolVar(&flags.json, "json", false, "output logs in JSON format") 315 314 cmd.Flags().StringVar(&flags.app, "app", "", "filter logs by app") 316 - cmd.RegisterFlagCompletionFunc("app", completeApp(utils.ExpandTilde(k.String("dir")))) 315 + cmd.RegisterFlagCompletionFunc("app", completeApp(k.String("dir"))) 317 316 318 317 return cmd 319 318 }
+3 -2
cmd/root.go
··· 48 48 49 49 func NewCmdRoot(version string, changelog string) *cobra.Command { 50 50 defaultProvider := confmap.Provider(map[string]interface{}{ 51 - "host": "127.0.0.1", 52 - "port": 7777, 51 + "addr": ":7777", 53 52 "dir": "~/smallweb", 54 53 }, "") 55 54 ··· 73 72 k.Load(defaultProvider, nil) 74 73 k.Load(fileProvider, utils.ConfigParser()) 75 74 k.Load(envProvider, nil) 75 + k.Set("dir", utils.ExpandTilde(k.String("dir"))) 76 76 }) 77 77 78 78 k.Load(defaultProvider, nil) 79 79 k.Load(fileProvider, utils.ConfigParser()) 80 80 k.Load(envProvider, nil) 81 + k.Set("dir", utils.ExpandTilde(k.String("dir"))) 81 82 82 83 cmd := &cobra.Command{ 83 84 Use: "smallweb",
+2 -3
cmd/run.go
··· 7 7 "strings" 8 8 9 9 "github.com/pomdtr/smallweb/app" 10 - "github.com/pomdtr/smallweb/utils" 11 10 "github.com/pomdtr/smallweb/worker" 12 11 "github.com/spf13/cobra" 13 12 ) ··· 19 18 GroupID: CoreGroupID, 20 19 DisableFlagParsing: true, 21 20 SilenceErrors: true, 22 - ValidArgsFunction: completeApp(utils.ExpandTilde(k.String("dir"))), 21 + ValidArgsFunction: completeApp(k.String("dir")), 23 22 RunE: func(cmd *cobra.Command, args []string) error { 24 23 if len(args) == 0 { 25 24 return cmd.Help() ··· 29 28 return cmd.Help() 30 29 } 31 30 32 - rootDir := utils.ExpandTilde(k.String("dir")) 31 + rootDir := k.String("dir") 33 32 app, err := app.LoadApp(filepath.Join(rootDir, args[0]), k.String("domain")) 34 33 if err != nil { 35 34 return fmt.Errorf("failed to get app: %w", err)
+2 -3
cmd/tunnel.go
··· 12 12 "github.com/pomdtr/smallweb/api" 13 13 "github.com/pomdtr/smallweb/app" 14 14 "github.com/pomdtr/smallweb/database" 15 - "github.com/pomdtr/smallweb/utils" 16 15 "github.com/spf13/cobra" 17 16 ) 18 17 ··· 22 21 Short: "Start a tunnel to a remote server (powered by localhost.run)", 23 22 GroupID: CoreGroupID, 24 23 Args: cobra.ExactArgs(1), 25 - ValidArgsFunction: completeApp(utils.ExpandTilde(k.String("dir"))), 24 + ValidArgsFunction: completeApp(k.String("dir")), 26 25 RunE: func(cmd *cobra.Command, args []string) error { 27 26 db, err := database.OpenDB(filepath.Join(DataDir(), "smallweb.db")) 28 27 if err != nil { ··· 37 36 38 37 server := http.Server{ 39 38 Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 40 - rootDir := utils.ExpandTilde(k.String("dir")) 39 + rootDir := k.String("dir") 41 40 app, err := app.LoadApp(filepath.Join(rootDir, args[0]), k.String("domain")) 42 41 if err != nil { 43 42 w.WriteHeader(http.StatusNotFound)
+18 -12
cmd/up.go
··· 53 53 cronWriter := utils.NewMultiWriter() 54 54 consoleWriter := utils.NewMultiWriter() 55 55 56 - httpLogger := utils.NewLogger(httpWriter) 57 56 consoleLogger := slog.New(slog.NewJSONHandler(consoleWriter, nil)) 58 57 59 58 apiHandler := api.NewHandler(k, httpWriter, cronWriter, consoleWriter) 60 59 appHandler := &AppHandler{apiServer: apiHandler, db: db, logger: consoleLogger} 61 60 handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 62 - rootDir := utils.ExpandTilde(k.String("dir")) 61 + rootDir := k.String("dir") 63 62 64 63 if r.Host == k.String("domain") { 65 64 // if we are on the apex domain and www exists, redirect to www ··· 94 93 appHandler.ServeApp(w, r, a) 95 94 }) 96 95 97 - addr := fmt.Sprintf("%s:%d", k.String("host"), k.Int("port")) 98 - server := http.Server{ 99 - Addr: addr, 100 - Handler: httpLogger.Middleware(handler), 101 - } 102 - 103 96 parser := cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor) 104 97 c := cron.New(cron.WithParser(parser)) 105 98 cronLogger := slog.New(slog.NewJSONHandler(cronWriter, nil)) 106 99 c.AddFunc("* * * * *", func() { 107 100 rounded := time.Now().Truncate(time.Minute) 108 - rootDir := utils.ExpandTilde(k.String("dir")) 101 + rootDir := k.String("dir") 109 102 apps, err := app.ListApps(rootDir) 110 103 if err != nil { 111 104 fmt.Println(err) ··· 167 160 168 161 go c.Start() 169 162 170 - fmt.Fprintf(os.Stderr, "Serving *.%s from %s on %s\n", k.String("domain"), k.String("dir"), addr) 171 - go server.ListenAndServe() 163 + fmt.Fprintf(os.Stderr, "Serving *.%s from %s on %s\n", k.String("domain"), k.String("dir"), k.String("addr")) 164 + httpLogger := utils.NewLogger(httpWriter) 165 + server := http.Server{ 166 + Handler: httpLogger.Middleware(handler), 167 + } 168 + 169 + addr := k.String("addr") 170 + var ln net.Listener 171 + if strings.HasPrefix(addr, "unix/") { 172 + socketPath := strings.TrimPrefix(addr, "unix/") 173 + net.Listen("unix", utils.ExpandTilde(socketPath)) 174 + } else { 175 + net.Listen("tcp", addr) 176 + } 177 + 178 + go server.Serve(ln) 172 179 173 180 // start api server on unix socket 174 181 apiServer := http.Server{ ··· 202 209 <-sigint 203 210 204 211 log.Println("Shutting down server...") 205 - server.Shutdown(context.Background()) 206 212 apiServer.Shutdown(context.Background()) 207 213 c.Stop() 208 214 return nil
+8 -11
docs/src/reference/global_config.md
··· 8 8 9 9 ## Available Fields 10 10 11 - ### `host` 11 + ### `addr` 12 12 13 - The `host` field defines the host to bind to. By default, it is `127.0.0.1`. 13 + The `addr` field defines the addr to bind to. By default, it is `:7777`. 14 14 15 15 ```json 16 16 { 17 - "host": "0.0.0.0" 17 + "addr": "127.0.0.1:8000" 18 18 } 19 19 ``` 20 20 21 - ### `port` 22 - 23 - The `port` field defines the port to bind to. By default, it is `7777`. 21 + If you want to use an unix socket, you can use the `unix/` prefix. 24 22 25 23 ```json 26 24 { 27 - "port": 8000 25 + "addr": "unix/~/smallweb.sock" 28 26 } 29 27 ``` 30 28 ··· 68 66 69 67 ```json 70 68 { 71 - "host": "127.0.0.1", 72 - "port": 7777, 69 + "addr": ":7777", 73 70 "dir": "~/smallweb", 74 71 } 75 72 ``` ··· 87 84 ```json 88 85 { 89 86 "domain": "example.com", 90 - "host": "127.0.0.1", 91 - "port": 7777, 87 + "addr": ":7777", 92 88 "dir": "~/smallweb", 93 89 } 90 + ```