124 lines
3.1 KiB
Go
124 lines
3.1 KiB
Go
package app
|
|
|
|
import (
|
|
"database/sql"
|
|
"net/http"
|
|
"path/filepath"
|
|
|
|
"forge.cadoles.com/arcad/edge/pkg/bus/memory"
|
|
appHTTP "forge.cadoles.com/arcad/edge/pkg/http"
|
|
"forge.cadoles.com/arcad/edge/pkg/module"
|
|
"forge.cadoles.com/arcad/edge/pkg/module/cast"
|
|
"forge.cadoles.com/arcad/edge/pkg/storage/sqlite"
|
|
"gitlab.com/wpetit/goweb/logger"
|
|
|
|
"forge.cadoles.com/arcad/edge/pkg/bundle"
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/go-chi/chi/v5/middleware"
|
|
"github.com/pkg/errors"
|
|
"github.com/urfave/cli/v2"
|
|
|
|
_ "modernc.org/sqlite"
|
|
)
|
|
|
|
func RunCommand() *cli.Command {
|
|
return &cli.Command{
|
|
Name: "run",
|
|
Usage: "Run the specified app bundle",
|
|
Flags: []cli.Flag{
|
|
&cli.StringFlag{
|
|
Name: "path",
|
|
Usage: "use `PATH` as app bundle (zipped bundle or directory)",
|
|
Aliases: []string{"p"},
|
|
Value: ".",
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "address",
|
|
Usage: "use `ADDRESS` as http server listening address",
|
|
Aliases: []string{"a"},
|
|
Value: ":8080",
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "log-format",
|
|
Usage: "use `LOG-FORMAT` ('json' or 'human')",
|
|
Value: "human",
|
|
},
|
|
&cli.IntFlag{
|
|
Name: "log-level",
|
|
Usage: "use `LOG-LEVEL` (0: debug -> 5: fatal)",
|
|
Value: 0,
|
|
},
|
|
&cli.StringFlag{
|
|
Name: "storage-file",
|
|
Usage: "use `FILE` for SQLite storage database",
|
|
Value: "data.sqlite",
|
|
},
|
|
},
|
|
Action: func(ctx *cli.Context) error {
|
|
address := ctx.String("address")
|
|
path := ctx.String("path")
|
|
logFormat := ctx.String("log-format")
|
|
logLevel := ctx.Int("log-level")
|
|
storageFile := ctx.String("storage-file")
|
|
|
|
logger.SetFormat(logger.Format(logFormat))
|
|
logger.SetLevel(logger.Level(logLevel))
|
|
|
|
cmdCtx := ctx.Context
|
|
|
|
absPath, err := filepath.Abs(path)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "could not resolve path '%s'", path)
|
|
}
|
|
|
|
logger.Info(cmdCtx, "opening app bundle", logger.F("path", absPath))
|
|
|
|
bundle, err := bundle.FromPath(path)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "could not open path '%s' as an app bundle", path)
|
|
}
|
|
|
|
mux := chi.NewMux()
|
|
|
|
mux.Use(middleware.Logger)
|
|
|
|
bus := memory.NewBus()
|
|
|
|
db, err := sql.Open("sqlite", storageFile)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "could not open database with path '%s'", storageFile)
|
|
}
|
|
|
|
documentStore := sqlite.NewDocumentStoreWithDB(db)
|
|
blobStore := sqlite.NewBlobStoreWithDB(db)
|
|
|
|
handler := appHTTP.NewHandler(
|
|
appHTTP.WithBus(bus),
|
|
appHTTP.WithServerModules(
|
|
module.ContextModuleFactory(),
|
|
module.ConsoleModuleFactory(),
|
|
cast.CastModuleFactory(),
|
|
module.LifecycleModuleFactory(bus),
|
|
module.NetModuleFactory(bus),
|
|
module.RPCModuleFactory(bus),
|
|
module.StoreModuleFactory(documentStore),
|
|
module.BlobModuleFactory(bus, blobStore),
|
|
),
|
|
)
|
|
if err := handler.Load(bundle); err != nil {
|
|
return errors.Wrap(err, "could not load app bundle")
|
|
}
|
|
|
|
mux.Handle("/*", handler)
|
|
|
|
logger.Info(cmdCtx, "listening", logger.F("address", address))
|
|
|
|
if err := http.ListenAndServe(address, mux); err != nil {
|
|
return errors.WithStack(err)
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
}
|