You've already forked pocketbase
mirror of
https://github.com/pocketbase/pocketbase.git
synced 2025-11-27 00:20:27 +02:00
initial public commit
This commit is contained in:
205
pocketbase.go
Normal file
205
pocketbase.go
Normal file
@@ -0,0 +1,205 @@
|
||||
package pocketbase
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/pocketbase/pocketbase/cmd"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var _ core.App = (*PocketBase)(nil)
|
||||
|
||||
// Version of PocketBase
|
||||
const Version = "0.1.0"
|
||||
|
||||
// appWrapper serves as a private core.App instance wrapper.
|
||||
type appWrapper struct {
|
||||
core.App
|
||||
}
|
||||
|
||||
// PocketBase defines a PocketBase app launcher.
|
||||
//
|
||||
// It implements [core.App] via embedding and all of interface methods
|
||||
// could be accessed directly through the instance (eg. PocketBase.DataDir()).
|
||||
type PocketBase struct {
|
||||
*appWrapper
|
||||
|
||||
// RootCmd is the main cli command
|
||||
RootCmd *cobra.Command
|
||||
|
||||
// console flags
|
||||
debugFlag bool
|
||||
dataDirFlag string
|
||||
encryptionEnv string
|
||||
|
||||
// console flag fallback values
|
||||
defaultDebug bool
|
||||
defaultDataDir string
|
||||
defaultEncryptionEnv string
|
||||
|
||||
// serve start banner
|
||||
showStartBanner bool
|
||||
}
|
||||
|
||||
// New creates a new PocketBase instance.
|
||||
//
|
||||
// Note that the application will not be initialized/bootstrapped yet,
|
||||
// aka. DB connections, migrations, app settings, etc. will not be accessable.
|
||||
// Everything will be initialized when Start() is executed.
|
||||
// If you want initialize the application before calling Start(),
|
||||
// then you'll have to manually call Bootstrap().
|
||||
func New() *PocketBase {
|
||||
// try to find the base executable directory and how it was run
|
||||
var withGoRun bool
|
||||
var baseDir string
|
||||
if strings.HasPrefix(os.Args[0], os.TempDir()) {
|
||||
// probably ran with go run...
|
||||
withGoRun = true
|
||||
baseDir, _ = os.Getwd()
|
||||
} else {
|
||||
// probably ran with go build...
|
||||
withGoRun = false
|
||||
baseDir = filepath.Dir(os.Args[0])
|
||||
}
|
||||
|
||||
defaultDir := filepath.Join(baseDir, "pb_data")
|
||||
|
||||
pb := &PocketBase{
|
||||
RootCmd: &cobra.Command{
|
||||
Use: "pocketbase",
|
||||
Short: "PocketBase CLI",
|
||||
FParseErrWhitelist: cobra.FParseErrWhitelist{
|
||||
UnknownFlags: true,
|
||||
},
|
||||
},
|
||||
defaultDebug: withGoRun,
|
||||
defaultDataDir: defaultDir,
|
||||
defaultEncryptionEnv: "",
|
||||
showStartBanner: true,
|
||||
}
|
||||
|
||||
// no need to provide the default cobra completion command
|
||||
pb.RootCmd.CompletionOptions.DisableDefaultCmd = true
|
||||
|
||||
// parse base flags
|
||||
// (errors are ignored, since the full flags parsing happens on Execute())
|
||||
pb.eagerParseFlags()
|
||||
|
||||
pb.appWrapper = &appWrapper{core.NewBaseApp(
|
||||
pb.dataDirFlag,
|
||||
pb.encryptionEnv,
|
||||
pb.debugFlag,
|
||||
)}
|
||||
|
||||
return pb
|
||||
}
|
||||
|
||||
// DefaultDebug sets the default --debug flag value.
|
||||
func (pb *PocketBase) DefaultDebug(val bool) *PocketBase {
|
||||
pb.defaultDebug = val
|
||||
return pb
|
||||
}
|
||||
|
||||
// DefaultDataDir sets the default --dir flag value.
|
||||
func (pb *PocketBase) DefaultDataDir(val string) *PocketBase {
|
||||
pb.defaultDataDir = val
|
||||
return pb
|
||||
}
|
||||
|
||||
// DefaultEncryptionEnv sets the default --encryptionEnv flag value.
|
||||
func (pb *PocketBase) DefaultEncryptionEnv(val string) *PocketBase {
|
||||
pb.defaultEncryptionEnv = val
|
||||
return pb
|
||||
}
|
||||
|
||||
// ShowStartBanner shows/hides the web server start banner.
|
||||
func (pb *PocketBase) ShowStartBanner(val bool) *PocketBase {
|
||||
pb.showStartBanner = val
|
||||
return pb
|
||||
}
|
||||
|
||||
// Start starts the application, aka. registers the default system
|
||||
// commands (serve, migrate, version) and executes pb.RootCmd.
|
||||
func (pb *PocketBase) Start() error {
|
||||
// register system commands
|
||||
pb.RootCmd.AddCommand(cmd.NewServeCommand(pb, pb.showStartBanner))
|
||||
pb.RootCmd.AddCommand(cmd.NewVersionCommand(pb, Version))
|
||||
pb.RootCmd.AddCommand(cmd.NewMigrateCommand(pb))
|
||||
|
||||
return pb.Execute()
|
||||
}
|
||||
|
||||
// Execute initializes the application (if not already) and executes
|
||||
// the pb.RootCmd with graceful shutdown support.
|
||||
//
|
||||
// This method differs from pb.Start() by not registering the default
|
||||
// system commands!
|
||||
func (pb *PocketBase) Execute() error {
|
||||
if err := pb.Bootstrap(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
wg.Add(1)
|
||||
|
||||
// wait for interrupt signal to gracefully shutdown the application
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
quit := make(chan os.Signal, 1) // we need to reserve to buffer size 1, so the notifier are not blocked
|
||||
signal.Notify(quit, os.Interrupt, syscall.SIGTERM)
|
||||
<-quit
|
||||
}()
|
||||
|
||||
// execute the root command
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := pb.RootCmd.Execute(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
|
||||
// cleanup
|
||||
return pb.onTerminate()
|
||||
}
|
||||
|
||||
// onTerminate tries to release the app resources on app termination.
|
||||
func (pb *PocketBase) onTerminate() error {
|
||||
return pb.ResetBootstrapState()
|
||||
}
|
||||
|
||||
// eagerParseFlags parses the global app flags before calling pb.RootCmd.Execute().
|
||||
// so we can have all PocketBase flags ready for use on initialization.
|
||||
func (pb *PocketBase) eagerParseFlags() error {
|
||||
pb.RootCmd.PersistentFlags().StringVar(
|
||||
&pb.dataDirFlag,
|
||||
"dir",
|
||||
pb.defaultDataDir,
|
||||
"the PocketBase data directory",
|
||||
)
|
||||
|
||||
pb.RootCmd.PersistentFlags().StringVar(
|
||||
&pb.encryptionEnv,
|
||||
"encryptionEnv",
|
||||
pb.defaultEncryptionEnv,
|
||||
"the env variable whose value of 32 chars will be used \nas encryption key for the app settings (default none)",
|
||||
)
|
||||
|
||||
pb.RootCmd.PersistentFlags().BoolVar(
|
||||
&pb.debugFlag,
|
||||
"debug",
|
||||
pb.defaultDebug,
|
||||
"enable debug mode, aka. showing more detailed logs",
|
||||
)
|
||||
|
||||
return pb.RootCmd.ParseFlags(os.Args[1:])
|
||||
}
|
||||
Reference in New Issue
Block a user