mirror of
https://github.com/pocketbase/pocketbase.git
synced 2025-01-09 10:07:17 +02:00
[#409] added pocketbase.NewWithConfig factory
This commit is contained in:
parent
4b64e0910b
commit
8c11e2ef01
139
pocketbase.go
139
pocketbase.go
@ -26,50 +26,60 @@ type appWrapper struct {
|
|||||||
|
|
||||||
// PocketBase defines a PocketBase app launcher.
|
// PocketBase defines a PocketBase app launcher.
|
||||||
//
|
//
|
||||||
// It implements [core.App] via embedding and all of interface methods
|
// It implements [core.App] via embedding and all of the app interface methods
|
||||||
// could be accessed directly through the instance (eg. PocketBase.DataDir()).
|
// could be accessed directly through the instance (eg. PocketBase.DataDir()).
|
||||||
type PocketBase struct {
|
type PocketBase struct {
|
||||||
*appWrapper
|
*appWrapper
|
||||||
|
|
||||||
// RootCmd is the main cli command
|
debugFlag bool
|
||||||
|
dataDirFlag string
|
||||||
|
encryptionEnvFlag string
|
||||||
|
hideStartBanner bool
|
||||||
|
|
||||||
|
// RootCmd is the main console command
|
||||||
RootCmd *cobra.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.
|
// Config is the PocketBase initialization config struct.
|
||||||
|
type Config struct {
|
||||||
|
// optional default values for the console flags
|
||||||
|
DefaultDebug bool
|
||||||
|
DefaultDataDir string // if not set, it will fallback to "./pb_data"
|
||||||
|
DefaultEncryptionEnv string
|
||||||
|
|
||||||
|
// hide the default console server info on app startup
|
||||||
|
HideStartBanner bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new PocketBase instance with the default configuration.
|
||||||
|
// Use [NewWithConfig()] if you want to provide a custom configuration.
|
||||||
//
|
//
|
||||||
// Note that the application will not be initialized/bootstrapped yet,
|
// Note that the application will not be initialized/bootstrapped yet,
|
||||||
// aka. DB connections, migrations, app settings, etc. will not be accessible.
|
// aka. DB connections, migrations, app settings, etc. will not be accessible.
|
||||||
// Everything will be initialized when Start() is executed.
|
// Everything will be initialized when [Start()] is executed.
|
||||||
// If you want to initialize the application before calling Start(),
|
// If you want to initialize the application before calling [Start()],
|
||||||
// then you'll have to manually call Bootstrap().
|
// then you'll have to manually call [Bootstrap()].
|
||||||
func New() *PocketBase {
|
func New() *PocketBase {
|
||||||
// try to find the base executable directory and how it was run
|
_, isUsingGoRun := inspectRuntime()
|
||||||
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")
|
return NewWithConfig(Config{
|
||||||
|
DefaultDebug: isUsingGoRun,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithConfig creates a new PocketBase instance with the provided config.
|
||||||
|
//
|
||||||
|
// Note that the application will not be initialized/bootstrapped yet,
|
||||||
|
// aka. DB connections, migrations, app settings, etc. will not be accessible.
|
||||||
|
// Everything will be initialized when [Start()] is executed.
|
||||||
|
// If you want to initialize the application before calling [Start()],
|
||||||
|
// then you'll have to manually call [Bootstrap()].
|
||||||
|
func NewWithConfig(config Config) *PocketBase {
|
||||||
|
// initialize a default data directory based on the executable baseDir
|
||||||
|
if config.DefaultDataDir == "" {
|
||||||
|
baseDir, _ := inspectRuntime()
|
||||||
|
config.DefaultDataDir = filepath.Join(baseDir, "pb_data")
|
||||||
|
}
|
||||||
|
|
||||||
pb := &PocketBase{
|
pb := &PocketBase{
|
||||||
RootCmd: &cobra.Command{
|
RootCmd: &cobra.Command{
|
||||||
@ -84,19 +94,20 @@ func New() *PocketBase {
|
|||||||
DisableDefaultCmd: true,
|
DisableDefaultCmd: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultDebug: withGoRun,
|
debugFlag: config.DefaultDebug,
|
||||||
defaultDataDir: defaultDir,
|
dataDirFlag: config.DefaultDataDir,
|
||||||
defaultEncryptionEnv: "",
|
encryptionEnvFlag: config.DefaultEncryptionEnv,
|
||||||
showStartBanner: true,
|
hideStartBanner: config.HideStartBanner,
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse base flags
|
// parse base flags
|
||||||
// (errors are ignored, since the full flags parsing happens on Execute())
|
// (errors are ignored, since the full flags parsing happens on Execute())
|
||||||
pb.eagerParseFlags()
|
pb.eagerParseFlags(config)
|
||||||
|
|
||||||
|
// initialize the app instance
|
||||||
pb.appWrapper = &appWrapper{core.NewBaseApp(
|
pb.appWrapper = &appWrapper{core.NewBaseApp(
|
||||||
pb.dataDirFlag,
|
pb.dataDirFlag,
|
||||||
pb.encryptionEnv,
|
pb.encryptionEnvFlag,
|
||||||
pb.debugFlag,
|
pb.debugFlag,
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -111,35 +122,11 @@ func New() *PocketBase {
|
|||||||
return pb
|
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
|
// Start starts the application, aka. registers the default system
|
||||||
// commands (serve, migrate, version) and executes pb.RootCmd.
|
// commands (serve, migrate, version) and executes pb.RootCmd.
|
||||||
func (pb *PocketBase) Start() error {
|
func (pb *PocketBase) Start() error {
|
||||||
// register system commands
|
// register system commands
|
||||||
pb.RootCmd.AddCommand(cmd.NewServeCommand(pb, pb.showStartBanner))
|
pb.RootCmd.AddCommand(cmd.NewServeCommand(pb, !pb.hideStartBanner))
|
||||||
pb.RootCmd.AddCommand(cmd.NewMigrateCommand(pb))
|
pb.RootCmd.AddCommand(cmd.NewMigrateCommand(pb))
|
||||||
|
|
||||||
return pb.Execute()
|
return pb.Execute()
|
||||||
@ -184,27 +171,41 @@ func (pb *PocketBase) onTerminate() error {
|
|||||||
|
|
||||||
// eagerParseFlags parses the global app flags before calling pb.RootCmd.Execute().
|
// eagerParseFlags parses the global app flags before calling pb.RootCmd.Execute().
|
||||||
// so we can have all PocketBase flags ready for use on initialization.
|
// so we can have all PocketBase flags ready for use on initialization.
|
||||||
func (pb *PocketBase) eagerParseFlags() error {
|
func (pb *PocketBase) eagerParseFlags(config Config) error {
|
||||||
pb.RootCmd.PersistentFlags().StringVar(
|
pb.RootCmd.PersistentFlags().StringVar(
|
||||||
&pb.dataDirFlag,
|
&pb.dataDirFlag,
|
||||||
"dir",
|
"dir",
|
||||||
pb.defaultDataDir,
|
config.DefaultDataDir,
|
||||||
"the PocketBase data directory",
|
"the PocketBase data directory",
|
||||||
)
|
)
|
||||||
|
|
||||||
pb.RootCmd.PersistentFlags().StringVar(
|
pb.RootCmd.PersistentFlags().StringVar(
|
||||||
&pb.encryptionEnv,
|
&pb.encryptionEnvFlag,
|
||||||
"encryptionEnv",
|
"encryptionEnv",
|
||||||
pb.defaultEncryptionEnv,
|
config.DefaultEncryptionEnv,
|
||||||
"the env variable whose value of 32 chars will be used \nas encryption key for the app settings (default none)",
|
"the env variable whose value of 32 characters will be used \nas encryption key for the app settings (default none)",
|
||||||
)
|
)
|
||||||
|
|
||||||
pb.RootCmd.PersistentFlags().BoolVar(
|
pb.RootCmd.PersistentFlags().BoolVar(
|
||||||
&pb.debugFlag,
|
&pb.debugFlag,
|
||||||
"debug",
|
"debug",
|
||||||
pb.defaultDebug,
|
config.DefaultDebug,
|
||||||
"enable debug mode, aka. showing more detailed logs",
|
"enable debug mode, aka. showing more detailed logs",
|
||||||
)
|
)
|
||||||
|
|
||||||
return pb.RootCmd.ParseFlags(os.Args[1:])
|
return pb.RootCmd.ParseFlags(os.Args[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tries to find the base executable directory and how it was run
|
||||||
|
func inspectRuntime() (baseDir string, withGoRun bool) {
|
||||||
|
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])
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
@ -6,14 +6,19 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestNew(t *testing.T) {
|
func TestNew(t *testing.T) {
|
||||||
testDir := "./pb_test_data_dir"
|
// copy os.Args
|
||||||
defer os.RemoveAll(testDir)
|
originalArgs := []string{}
|
||||||
|
copy(originalArgs, os.Args)
|
||||||
|
defer func() {
|
||||||
|
// restore os.Args
|
||||||
|
copy(os.Args, originalArgs)
|
||||||
|
}()
|
||||||
|
|
||||||
// reset os.Args
|
// change os.Args
|
||||||
os.Args = os.Args[0:1]
|
os.Args = os.Args[0:1]
|
||||||
os.Args = append(
|
os.Args = append(
|
||||||
os.Args,
|
os.Args,
|
||||||
"--dir="+testDir,
|
"--dir=test_dir",
|
||||||
"--encryptionEnv=test_encryption_env",
|
"--encryptionEnv=test_encryption_env",
|
||||||
"--debug=true",
|
"--debug=true",
|
||||||
)
|
)
|
||||||
@ -32,8 +37,8 @@ func TestNew(t *testing.T) {
|
|||||||
t.Fatal("Expected appWrapper to be initialized, got nil")
|
t.Fatal("Expected appWrapper to be initialized, got nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
if app.DataDir() != testDir {
|
if app.DataDir() != "test_dir" {
|
||||||
t.Fatalf("Expected app.DataDir() %q, got %q", testDir, app.DataDir())
|
t.Fatalf("Expected app.DataDir() %q, got %q", "test_dir", app.DataDir())
|
||||||
}
|
}
|
||||||
|
|
||||||
if app.EncryptionEnv() != "test_encryption_env" {
|
if app.EncryptionEnv() != "test_encryption_env" {
|
||||||
@ -45,52 +50,93 @@ func TestNew(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDefaultDebug(t *testing.T) {
|
func TestNewWithConfig(t *testing.T) {
|
||||||
app := New()
|
app := NewWithConfig(Config{
|
||||||
|
DefaultDebug: true,
|
||||||
|
DefaultDataDir: "test_dir",
|
||||||
|
DefaultEncryptionEnv: "test_encryption_env",
|
||||||
|
HideStartBanner: true,
|
||||||
|
})
|
||||||
|
|
||||||
app.DefaultDebug(true)
|
if app == nil {
|
||||||
if app.defaultDebug != true {
|
t.Fatal("Expected initialized PocketBase instance, got nil")
|
||||||
t.Fatalf("Expected defaultDebug %v, got %v", true, app.defaultDebug)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
app.DefaultDebug(false)
|
if app.RootCmd == nil {
|
||||||
if app.defaultDebug != false {
|
t.Fatal("Expected RootCmd to be initialized, got nil")
|
||||||
t.Fatalf("Expected defaultDebug %v, got %v", false, app.defaultDebug)
|
}
|
||||||
|
|
||||||
|
if app.appWrapper == nil {
|
||||||
|
t.Fatal("Expected appWrapper to be initialized, got nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if app.hideStartBanner != true {
|
||||||
|
t.Fatal("Expected app.hideStartBanner to be true, got false")
|
||||||
|
}
|
||||||
|
|
||||||
|
if app.DataDir() != "test_dir" {
|
||||||
|
t.Fatalf("Expected app.DataDir() %q, got %q", "test_dir", app.DataDir())
|
||||||
|
}
|
||||||
|
|
||||||
|
if app.EncryptionEnv() != "test_encryption_env" {
|
||||||
|
t.Fatalf("Expected app.DataDir() %q, got %q", "test_encryption_env", app.EncryptionEnv())
|
||||||
|
}
|
||||||
|
|
||||||
|
if app.IsDebug() != true {
|
||||||
|
t.Fatal("Expected app.IsDebug() true, got false")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDefaultDataDir(t *testing.T) {
|
func TestNewWithConfigAndFlags(t *testing.T) {
|
||||||
app := New()
|
// copy os.Args
|
||||||
|
originalArgs := []string{}
|
||||||
|
copy(originalArgs, os.Args)
|
||||||
|
defer func() {
|
||||||
|
// restore os.Args
|
||||||
|
copy(os.Args, originalArgs)
|
||||||
|
}()
|
||||||
|
|
||||||
expected := "test_default"
|
// change os.Args
|
||||||
|
os.Args = os.Args[0:1]
|
||||||
|
os.Args = append(
|
||||||
|
os.Args,
|
||||||
|
"--dir=test_dir_flag",
|
||||||
|
"--encryptionEnv=test_encryption_env_flag",
|
||||||
|
"--debug=false",
|
||||||
|
)
|
||||||
|
|
||||||
app.DefaultDataDir(expected)
|
app := NewWithConfig(Config{
|
||||||
if app.defaultDataDir != expected {
|
DefaultDebug: true,
|
||||||
t.Fatalf("Expected defaultDataDir %v, got %v", expected, app.defaultDataDir)
|
DefaultDataDir: "test_dir",
|
||||||
}
|
DefaultEncryptionEnv: "test_encryption_env",
|
||||||
}
|
HideStartBanner: true,
|
||||||
|
})
|
||||||
func TestDefaultEncryptionEnv(t *testing.T) {
|
|
||||||
app := New()
|
if app == nil {
|
||||||
|
t.Fatal("Expected initialized PocketBase instance, got nil")
|
||||||
expected := "test_env"
|
}
|
||||||
|
|
||||||
app.DefaultEncryptionEnv(expected)
|
if app.RootCmd == nil {
|
||||||
if app.defaultEncryptionEnv != expected {
|
t.Fatal("Expected RootCmd to be initialized, got nil")
|
||||||
t.Fatalf("Expected defaultEncryptionEnv %v, got %v", expected, app.defaultEncryptionEnv)
|
}
|
||||||
}
|
|
||||||
}
|
if app.appWrapper == nil {
|
||||||
|
t.Fatal("Expected appWrapper to be initialized, got nil")
|
||||||
func TestShowStartBanner(t *testing.T) {
|
}
|
||||||
app := New()
|
|
||||||
|
if app.hideStartBanner != true {
|
||||||
app.ShowStartBanner(true)
|
t.Fatal("Expected app.hideStartBanner to be true, got false")
|
||||||
if app.showStartBanner != true {
|
}
|
||||||
t.Fatalf("Expected showStartBanner %v, got %v", true, app.showStartBanner)
|
|
||||||
}
|
if app.DataDir() != "test_dir_flag" {
|
||||||
|
t.Fatalf("Expected app.DataDir() %q, got %q", "test_dir_flag", app.DataDir())
|
||||||
app.ShowStartBanner(false)
|
}
|
||||||
if app.showStartBanner != false {
|
|
||||||
t.Fatalf("Expected showStartBanner %v, got %v", false, app.showStartBanner)
|
if app.EncryptionEnv() != "test_encryption_env_flag" {
|
||||||
|
t.Fatalf("Expected app.DataDir() %q, got %q", "test_encryption_env_flag", app.EncryptionEnv())
|
||||||
|
}
|
||||||
|
|
||||||
|
if app.IsDebug() != false {
|
||||||
|
t.Fatal("Expected app.IsDebug() false, got true")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user