Skip to main content
PocketBase provides various utility packages and helpers for common tasks.

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")
}
Cron expression format:
┌───────────── 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)