Security utilities
Random string generation
import "github.com/pocketbase/pocketbase/tools/security"
// Generate random string with default alphabet
randomStr := security.RandomString(32)
// Generate with custom alphabet
customStr := security.RandomStringWithAlphabet(16, "0123456789ABCDEF")
// Pseudorandom (not cryptographically secure, but faster)
pseudoStr := security.PseudorandomString(32)
Hashing
import "github.com/pocketbase/pocketbase/tools/security"
// MD5 hash
hash := security.MD5("text to hash")
// SHA256 hash
hash := security.SHA256("text to hash")
// SHA512 hash
hash := security.SHA512("text to hash")
Password hashing
import "github.com/pocketbase/pocketbase/tools/security"
// Hash a password (uses bcrypt)
hashed, err := security.HashPassword("mypassword123")
if err != nil {
log.Fatal(err)
}
// Verify password
if security.CompareHashAndPassword(hashed, "mypassword123") {
log.Println("Password is correct")
}
JWT tokens
Creating tokens
import (
"time"
"github.com/pocketbase/pocketbase/tools/security"
)
// Create a JWT token
token, err := security.NewJWT(
map[string]any{
"userId": "123",
"email": "user@example.com",
},
"your-secret-key",
time.Now().Add(24 * time.Hour).Unix(), // expiry
)
if err != nil {
log.Fatal(err)
}
log.Println("Token:", token)
Parsing tokens
import "github.com/pocketbase/pocketbase/tools/security"
tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
token, err := security.ParseUnverifiedJWT(tokenString)
if err != nil {
log.Fatal(err)
}
// Access claims
userId := token.Get("userId")
email := token.Get("email")
Verifying tokens
import "github.com/pocketbase/pocketbase/tools/security"
token, err := security.ParseJWT(tokenString, "your-secret-key")
if err != nil {
log.Fatal("Invalid or expired token")
}
log.Println("Valid token for:", token.Get("userId"))
List utilities
Working with slices
import "github.com/pocketbase/pocketbase/tools/list"
// Check if item exists in slice
slice := []string{"apple", "banana", "orange"}
if list.ExistInSlice("banana", slice) {
log.Println("Found banana")
}
// Convert to unique string slice
data := []any{"a", "b", "a", "c", "b"}
unique := list.ToUniqueStringSlice(data)
// Result: ["a", "b", "c"]
// Subtract slices
slice1 := []string{"a", "b", "c"}
slice2 := []string{"b", "d"}
result := list.SubtractSlice(slice1, slice2)
// Result: ["a", "c"]
Type utilities
DateTime
import "github.com/pocketbase/pocketbase/tools/types"
// Create DateTime from string
dt, err := types.ParseDateTime("2024-01-15 14:30:00.000Z")
if err != nil {
log.Fatal(err)
}
// Current DateTime
now := types.NowDateTime()
// Convert to time.Time
timeObj := dt.Time()
// Format as string
str := dt.String()
JSON types
import "github.com/pocketbase/pocketbase/tools/types"
// JSONArray
jsonArray := types.JSONArray[string]{"a", "b", "c"}
// JSONMap
jsonMap := types.JSONMap[any]{
"key1": "value1",
"key2": 123,
}
// JSONRaw (for storing raw JSON)
raw := types.JSONRaw(`{"custom": "data"}`)
Pointer helper
import "github.com/pocketbase/pocketbase/tools/types"
// Create pointer to value
strPtr := types.Pointer("hello")
intPtr := types.Pointer(123)
boolPtr := types.Pointer(true)
// Useful for optional fields
collection.ListRule = types.Pointer("@request.auth.id != ''")
Store
Thread-safe in-memory key-value store:import "github.com/pocketbase/pocketbase/tools/store"
// Create store
s := store.New[string, any](nil)
// Set values
s.Set("key1", "value1")
s.Set("key2", 123)
// Get value
value := s.Get("key1")
// Get with existence check
value, exists := s.GetOk("key1")
if exists {
log.Println("Found:", value)
}
// Get all
allData := s.GetAll()
// Has key
if s.Has("key1") {
log.Println("Key exists")
}
// Remove
s.Remove("key1")
// Reset with new data
s.Reset(map[string]any{
"new_key": "new_value",
})
Filesystem utilities
File upload from URL
import "github.com/pocketbase/pocketbase/tools/filesystem"
file, err := filesystem.NewFileFromURL(
"https://example.com/image.jpg",
)
if err != nil {
log.Fatal(err)
}
// Use with record
record.Set("avatar", file)
app.Save(record)
Template utilities
Template rendering
import "github.com/pocketbase/pocketbase/tools/template"
registry := template.NewRegistry()
// Load templates
tpl, err := registry.LoadFiles(
"templates/welcome.html",
"templates/footer.html",
)
if err != nil {
log.Fatal(err)
}
// Render with data
html, err := tpl.Render(map[string]any{
"name": "John",
"title": "Welcome",
})
if err != nil {
log.Fatal(err)
}
Template from string
import "github.com/pocketbase/pocketbase/tools/template"
registry := template.NewRegistry()
tpl, err := registry.LoadString("Hello {{.name}}!")
if err != nil {
log.Fatal(err)
}
result, _ := tpl.Render(map[string]any{
"name": "World",
})
// Result: "Hello World!"
Inflector
String manipulation utilities:import "github.com/pocketbase/pocketbase/tools/inflector"
// Columnify - format for SQL column names
colName := inflector.Columnify("UserName")
// Result: "userName"
// Sentenize - convert to sentence
sentence := inflector.Sentenize("hello_world")
// Result: "Hello world"
// Pluralize
plural := inflector.Pluralize("post")
// Result: "posts"
// Singularize
singular := inflector.Singularize("users")
// Result: "user"
Search utilities
Building search providers
import "github.com/pocketbase/pocketbase/tools/search"
// Create search provider
provider := search.NewProvider(fieldResolver)
// Parse search/filter string
result, err := provider.Parse("title ~ 'test' && status = 'active'")
if err != nil {
log.Fatal(err)
}
// Apply to query
app.DB().Select("*").From("posts").AndWhere(result.BuildExpr())
Cron utilities
Scheduling tasks
// Add cron job
app.Cron().Add("daily_cleanup", "0 0 * * *", func() {
log.Println("Running daily cleanup")
// Cleanup logic
})
// Remove job
app.Cron().Remove("daily_cleanup")
// Check if job exists
if app.Cron().Has("daily_cleanup") {
log.Println("Job is scheduled")
}
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 6) (Sunday = 0)
│ │ │ │ │
* * * * *
Common cron patterns
// Every minute
app.Cron().Add("task", "* * * * *", handler)
// Every hour
app.Cron().Add("task", "0 * * * *", handler)
// Every day at midnight
app.Cron().Add("task", "0 0 * * *", handler)
// Every Monday at 9 AM
app.Cron().Add("task", "0 9 * * 1", handler)
// First day of month
app.Cron().Add("task", "0 0 1 * *", handler)
Routine utilities
Background task execution:import "github.com/pocketbase/pocketbase/tools/routine"
// Fire and forget
routine.FireAndForget(func() {
// Long-running task
time.Sleep(5 * time.Second)
log.Println("Background task completed")
})
Archive utilities
Create and extract archives:import "github.com/pocketbase/pocketbase/tools/archive"
// Create ZIP archive
err := archive.Create(
[]string{"file1.txt", "file2.txt"},
"archive.zip",
)
if err != nil {
log.Fatal(err)
}
// Extract archive
err = archive.Extract("archive.zip", "./destination")
if err != nil {
log.Fatal(err)
}
Tokenizer
Parse and tokenize strings:import "github.com/pocketbase/pocketbase/tools/tokenizer"
tokenizer := tokenizer.NewFromString("hello world test")
for {
token := tokenizer.Scan()
if token.Type == tokenizer.EOF {
break
}
log.Println("Token:", token.Literal)
}
Best practices
Use appropriate utilities
// Good - use list utilities
if list.ExistInSlice(item, slice) {
// ...
}
// Bad - manual loop
found := false
for _, v := range slice {
if v == item {
found = true
break
}
}
Cache expensive operations
// Cache in app store
key := "expensive_result"
if !app.Store().Has(key) {
result := expensiveOperation()
app.Store().Set(key, result)
}
result := app.Store().Get(key)
Use type-safe stores
// Good - type-safe
type UserCache struct {
*store.Store[string, *core.Record]
}
cache := &UserCache{
Store: store.New[string, *core.Record](nil),
}
cache.Set("user_123", userRecord)