Overview
The Option type implements the functional options pattern for configuring Server instances. Options control PocketBase initialization, developer mode, and configuration injection.
Type Definition
type Option func(*options)
Location: core/server/server_options.go:23
The Option type is a function that modifies internal server options. Multiple options can be passed to New() and are applied in order.
Available Options
WithConfig
Sets the PocketBase configuration to use when creating a new PocketBase instance.
func WithConfig(config *pocketbase.Config) Option
Parameters:
config
*pocketbase.Config
required
PocketBase configuration object. Supports all standard PocketBase config options including DefaultDev, DefaultDataDir, DefaultDebug, etc.
Example:
import (
"github.com/magooney-loon/pb-ext/core"
"github.com/pocketbase/pocketbase"
)
config := &pocketbase.Config{
DefaultDev: true,
DefaultDataDir: "./custom_pb_data",
DefaultDebug: false,
}
srv := core.New(core.WithConfig(config))
Location: core/server/server_options.go:27
Cannot be used with WithPocketbase. These options are mutually exclusive. Using both will cause a panic with ErrConfigurationConflict.
WithPocketbase
Sets a fully initialized PocketBase instance to wrap instead of creating a new one.
func WithPocketbase(pb *pocketbase.PocketBase) Option
Parameters:
pb
*pocketbase.PocketBase
required
Pre-initialized PocketBase instance. Useful when you need full control over PocketBase initialization or want to share an instance.
Example:
import (
"github.com/magooney-loon/pb-ext/core"
"github.com/pocketbase/pocketbase"
)
// Create and configure PocketBase manually
pb := pocketbase.NewWithConfig(pocketbase.Config{
DefaultDev: true,
DefaultDataDir: "./pb_data",
})
// Add custom hooks before wrapping
pb.OnBootstrap().BindFunc(func(e *core.BootstrapEvent) error {
// Custom initialization
return e.Next()
})
srv := core.New(core.WithPocketbase(pb))
Location: core/server/server_options.go:35
Cannot be used with WithConfig. If a config is already set, this option will panic with ErrConfigurationConflict.
If you enable developer mode via InDeveloperMode() but the provided PocketBase instance was created in production mode, a warning will be logged and the mode will not be changed.
WithMode
Sets the developer mode flag programmatically.
func WithMode(developerMode bool) Option
Parameters:
true: Enable developer mode (auto-migrations, debug endpoints, verbose logging)
false: Production mode (migrations disabled, minimal logging)
Example:
import (
"flag"
"github.com/magooney-loon/pb-ext/core"
)
devMode := flag.Bool("dev", false, "Enable developer mode")
flag.Parse()
srv := core.New(core.WithMode(*devMode))
Location: core/server/server_options.go:46
InDeveloperMode
Convenience function to enable developer mode (equivalent to WithMode(true)).
func InDeveloperMode() Option
Example:
import "github.com/magooney-loon/pb-ext/core"
srv := core.New(core.InDeveloperMode())
// Outputs: 🔧 Developer mode
Location: core/server/server_options.go:53
Side Effects:
- Logs
"🔧 Developer mode" to stdout
- Enables PocketBase auto-migrations
- Enables debug endpoints
InNormalMode
Convenience function to explicitly disable developer mode (equivalent to WithMode(false)).
func InNormalMode() Option
Example:
import "github.com/magooney-loon/pb-ext/core"
srv := core.New(core.InNormalMode())
// Outputs: 🚀 Production mode
Location: core/server/server_options.go:61
Side Effects:
- Logs
"🚀 Production mode" to stdout
- Disables PocketBase auto-migrations
- Disables debug endpoints
Configuration Patterns
Pattern 1: Developer Mode Toggle
func main() {
devMode := flag.Bool("dev", false, "Run in developer mode")
flag.Parse()
var opts []core.Option
if *devMode {
opts = append(opts, core.InDeveloperMode())
} else {
opts = append(opts, core.InNormalMode())
}
srv := core.New(opts...)
srv.Start()
}
Pattern 2: Custom Data Directory
func main() {
config := &pocketbase.Config{
DefaultDataDir: "./custom_pb_data",
}
srv := core.New(
core.WithConfig(config),
core.InDeveloperMode(),
)
srv.Start()
}
Pattern 3: Shared PocketBase Instance
func main() {
// Initialize PocketBase with custom hooks
pb := pocketbase.New()
pb.OnBootstrap().BindFunc(func(e *core.BootstrapEvent) error {
// Custom early initialization
return e.Next()
})
// Wrap with pb-ext
srv := core.New(core.WithPocketbase(pb))
srv.Start()
}
Pattern 4: Environment-Based Configuration
func main() {
env := os.Getenv("ENV")
var opts []core.Option
switch env {
case "development":
opts = append(opts, core.InDeveloperMode())
opts = append(opts, core.WithConfig(&pocketbase.Config{
DefaultDataDir: "./dev_data",
DefaultDebug: true,
}))
case "staging":
opts = append(opts, core.InNormalMode())
opts = append(opts, core.WithConfig(&pocketbase.Config{
DefaultDataDir: "./staging_data",
}))
case "production":
opts = append(opts, core.InNormalMode())
opts = append(opts, core.WithConfig(&pocketbase.Config{
DefaultDataDir: "/var/lib/pb_data",
}))
}
srv := core.New(opts...)
srv.Start()
}
Error Handling
ErrConfigurationConflict
Panic error raised when both WithConfig and WithPocketbase are used together.
var ErrConfigurationConflict = errors.New(
"WithConfig cannot be used together with WithPocketbase, cause second contains already initialized pocketbase.Config instance. Just pass your config into pocketbase.NewWithConfig func, that's enough.",
)
Location: core/server/server_options.go:18
Example Error:
pb := pocketbase.New()
config := &pocketbase.Config{DefaultDev: true}
// This will panic!
srv := core.New(
core.WithConfig(config),
core.WithPocketbase(pb), // Conflict!
)
Solution:
// Option A: Configure PocketBase before wrapping
pb := pocketbase.NewWithConfig(pocketbase.Config{
DefaultDev: true,
})
srv := core.New(core.WithPocketbase(pb))
// Option B: Use WithConfig only
srv := core.New(core.WithConfig(&pocketbase.Config{
DefaultDev: true,
}))
Order of Operations
Options are applied in the order they are passed to New(). Later options override earlier ones:
// developerMode will be true (last wins)
srv := core.New(
core.InNormalMode(), // Sets developerMode = false
core.InDeveloperMode(), // Sets developerMode = true
)
While you can pass multiple mode options, it’s clearer to use only one. The last option always takes precedence.
See Also