The standard way to modify PocketBase is through event hooks in your Go code.
All hooks have 3 main methods:
Bind(handler)
adds a new handler to the specified event hook. A handler has 3 fields:Id
(optional) - the name of the handler (could be used as argument forUnbind
)Priority
(optional) - the execution order of the handler (if empty fallbacks to the order of registration in the code).Func
(required) - the handler function.
BindFunc(func)
is similar toBind
but registers a new handler from just the provided function.
The registered handler is added with a default 0 priority and the id is autogenerated (the returned string value).Trigger(event, oneOffHandlerFuncs...)
triggers the event hook.
This method rarely has to be called manually by users.
To remove an already registered hook handler, you can use the handler id and pass it to
Unbind(id)
or remove all handlers with
UnbindAll()
(!including system handlers).
All hook handler functions share the same func(e T) error
signature and expect
the user to call e.Next()
if they want to proceed with the execution chain.
If you need to access the app instance from inside a hook handler prefer using the
e.App
field instead of reusing a parent scope app variable because the hook could be part
of a transaction and can cause deadlock.
You can explore all available hooks below:
App hooks
OnBootstrap
hook is triggered when initializing the main
application resources (db, app settings, etc).
Note that attempting to access the database before the e.Next()
call will result in an error.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnBootstrap().BindFunc(func(e *core.BootstrapEvent) error {
if err := e.Next(); err != nil {
return err
}
// e.App
return nil
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnServe
hook is triggered when the app web server is started
(after starting the TCP listener but before initializing the blocking serve task),
allowing you to adjust its options and attach new routes or middlewares.
package main
import (
"log"
"net/http"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/apis"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnServe().BindFunc(func(e *core.ServeEvent) error {
// register new "GET /hello" route
e.Router.GET("/hello", func(e *core.RequestEvent) error {
return e.String(200, "Hello world!")
}).Bind(apis.RequireAuth())
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnSettingsReload
hook is triggered every time when the App.Settings()
is being replaced with a new state.
Calling e.App.Settings()
after e.Next()
returns the new state.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnSettingsReload().BindFunc(func(e *core.SettingsReloadEvent) error {
if err := e.Next(); err != nil {
return err
}
// e.App.Settings()
return nil
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnBackupCreate
is triggered on each App.CreateBackup
call.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnBackupCreate().BindFunc(func(e *core.BackupEvent) error {
// e.App
// e.Name - the name of the backup to create
// e.Exclude - list of pb_data dir entries to exclude from the backup
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnBackupRestore
is triggered before app backup restore (aka. on App.RestoreBackup
call).
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnBackupRestore().BindFunc(func(e *core.BackupEvent) error {
// e.App
// e.Name - the name of the backup to restore
// e.Exclude - list of dir entries to exclude from the backup
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnTerminate
hook is triggered when the app is in the process
of being terminated (ex. on SIGTERM
signal).
Note that the app could be terminated abruptly without awaiting the hook completion.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnTerminate().BindFunc(func(e *core.TerminateEvent) error {
// e.App
// e.IsRestart
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Mailer hooks
OnMailerSend
hook is triggered every time when a new email is
being send using the App.NewMailClient()
instance.
It allows intercepting the email message or to use a custom mailer client.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnMailerSend().BindFunc(func(e *core.MailerEvent) error {
// e.App
// e.Mailer
// e.Message
// ex. change the mail subject
e.Message.Subject = "new subject"
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnMailerRecordAuthAlertSend
hook is triggered when
sending a new device login auth alert email, allowing you to
intercept and customize the email message that is being sent.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnMailerRecordAuthAlertSend().BindFunc(func(e *core.MailerRecordEvent) error {
// e.App
// e.Mailer
// e.Message
// e.Meta
// ex. change the mail subject
e.Message.Subject = "new subject"
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnMailerRecordPasswordResetSend
hook is triggered when
sending a password reset email to an auth record, allowing
you to intercept and customize the email message that is being sent.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnMailerRecordPasswordResetSend().BindFunc(func(e *core.MailerRecordEvent) error {
// e.App
// e.Mailer
// e.Message
// e.Meta
// ex. change the mail subject
e.Message.Subject = "new subject"
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnMailerRecordVerificationSend
hook is triggered when
sending a verification email to an auth record, allowing
you to intercept and customize the email message that is being sent.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnMailerRecordVerificationSend().BindFunc(func(e *core.MailerRecordEvent) error {
// e.App
// e.Mailer
// e.Message
// e.Meta
// ex. change the mail subject
e.Message.Subject = "new subject"
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnMailerRecordEmailChangeSend
hook is triggered when sending a
confirmation new address email to an auth record, allowing
you to intercept and customize the email message that is being sent.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnMailerRecordEmailChangeSend().BindFunc(func(e *core.MailerRecordEvent) error {
// e.App
// e.Mailer
// e.Message
// e.Meta
// ex. change the mail subject
e.Message.Subject = "new subject"
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnMailerRecordOTPSend
hook is triggered when sending an OTP email
to an auth record, allowing you to intercept and customize the
email message that is being sent.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnMailerRecordOTPSend().BindFunc(func(e *core.MailerRecordEvent) error {
// e.App
// e.Mailer
// e.Message
// e.Meta
// ex. change the mail subject
e.Message.Subject = "new subject"
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Realtime hooks
OnRealtimeConnectRequest
hook is triggered when establishing the SSE client connection.
Any execution after e.Next() of a hook handler happens after the client disconnects.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnRealtimeConnectRequest().BindFunc(func(e *core.RealtimeConnectRequestEvent) error {
// e.App
// e.Client
// e.IdleTimeout
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRealtimeSubscribeRequest
hook is triggered when updating the
client subscriptions, allowing you to further validate and
modify the submitted change.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnRealtimeSubscribeRequest().BindFunc(func(e *core.RealtimeSubscribeRequestEvent) error {
// e.App
// e.Client
// e.Subscriptions
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRealtimeMessageSend
hook is triggered when sending an SSE message to a client.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnRealtimeMessageSend().BindFunc(func(e *core.RealtimeMessageEvent) error {
// e.App
// e.Client
// e.Message
// and all original connect RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Record model hooks
These are lower level Record model hooks and could be triggered from anywhere (custom console command, scheduled cron job, when calling e.Save(record)
, etc.) and therefore they have no access to the request context!
If you want to intercept the builtin Web APIs and to access their request body, query parameters, headers or the request auth state, then please use the designated
Record *Request
hooks
.
OnRecordEnrich
is triggered every time when a record is enriched
- as part of the builtin Record responses, during realtime message serialization, or when apis.EnrichRecord
is invoked.
It could be used for example to redact/hide or add computed temporary Record model props only for the specific request info.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnRecordEnrich("posts").BindFunc(func(e core.*RecordEnrichEvent) {
// hide one or more fields
e.Record.Hide("role")
// add new custom field for registered users
if e.RequestInfo.Auth != nil && e.RequestInfo.Auth.Collection().Name == "users" {
e.Record.WithCustomData(true) // for security requires explicitly allowing it
e.Record.Set("computedScore", e.Record.GetInt("score") * e.RequestInfo.Auth.GetInt("base"))
}
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordValidate
is a Record proxy model hook of OnModelValidate
.
OnRecordValidate
is called every time when a Record is being validated,
e.g. triggered by App.Validate()
or App.Save()
.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every record
app.OnRecordValidate().BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
// fires only for "users" and "articles" records
app.OnRecordValidate("users", "articles").BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Record model create hooks
OnRecordCreate
is a Record proxy model hook of OnModelCreate
.
OnRecordCreate
is triggered every time when a new Record is being created,
e.g. triggered by App.Save()
.
Operations BEFORE the e.Next()
execute before the Record validation
and the INSERT DB statement.
Operations AFTER the e.Next()
execute after the Record validation
and the INSERT DB statement.
OnRecordAfterCreateSuccess
or OnRecordAfterCreateError
hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every record
app.OnRecordCreate().BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
// fires only for "users" and "articles" records
app.OnRecordCreate("users", "articles").BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordCreateExecute
is a Record proxy model hook of OnModelCreateExecute
.
OnRecordCreateExecute
is triggered after successful Record validation
and right before the model INSERT DB statement execution.
Usually it is triggered as part of the App.Save()
in the following firing order:
OnRecordCreate
->
OnRecordValidate
(skipped with App.SaveNoValidate()
)
->
OnRecordCreateExecute
OnRecordAfterCreateSuccess
or OnRecordAfterCreateError
hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every record
app.OnRecordCreateExecute().BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
// fires only for "users" and "articles" records
app.OnRecordCreateExecute("users", "articles").BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordAfterCreateSuccess
is a Record proxy model hook of OnModelAfterCreateSuccess
.
OnRecordAfterCreateSuccess
is triggered after each successful
Record DB create persistence.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every record
app.OnRecordAfterCreateSuccess().BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
// fires only for "users" and "articles" records
app.OnRecordAfterCreateSuccess("users", "articles").BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordAfterCreateError
is a Record proxy model hook of OnModelAfterCreateError
.
OnRecordAfterCreateError
is triggered after each failed
Record DB create persistence.
- immediate on
App.Save()
failure - delayed on transaction rollback
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every record
app.OnRecordAfterCreateError().BindFunc(func(e *core.RecordErrorEvent) error {
// e.App
// e.Record
// e.Error
return e.Next()
})
// fires only for "users" and "articles" records
app.OnRecordAfterCreateError("users", "articles").BindFunc(func(e *core.RecordErrorEvent) error {
// e.App
// e.Record
// e.Error
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Record model update hooks
OnRecordUpdate
is a Record proxy model hook of OnModelUpdate
.
OnRecordUpdate
is triggered every time when a new Record is being updated,
e.g. triggered by App.Save()
.
Operations BEFORE the e.Next()
execute before the Record validation
and the UPDATE DB statement.
Operations AFTER the e.Next()
execute after the Record validation
and the UPDATE DB statement.
OnRecordAfterUpdateSuccess
or OnRecordAfterUpdateError
hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every record
app.OnRecordUpdate().BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
// fires only for "users" and "articles" records
app.OnRecordUpdate("users", "articles").BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordUpdateExecute
is a Record proxy model hook of OnModelUpdateExecute
.
OnRecordUpdateExecute
is triggered after successful Record validation
and right before the model UPDATE DB statement execution.
Usually it is triggered as part of the App.Save()
in the following firing order:
OnRecordUpdate
->
OnRecordValidate
(skipped with App.SaveNoValidate()
)
->
OnRecordUpdateExecute
OnRecordAfterUpdateSuccess
or OnRecordAfterUpdateError
hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every record
app.OnRecordUpdateExecute().BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
// fires only for "users" and "articles" records
app.OnRecordUpdateExecute("users", "articles").BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordAfterUpdateSuccess
is a Record proxy model hook of OnModelAfterUpdateSuccess
.
OnRecordAfterUpdateSuccess
is triggered after each successful
Record DB update persistence.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every record
app.OnRecordAfterUpdateSuccess().BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
// fires only for "users" and "articles" records
app.OnRecordAfterUpdateSuccess("users", "articles").BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordAfterUpdateError
is a Record proxy model hook of OnModelAfterUpdateError
.
OnRecordAfterUpdateError
is triggered after each failed
Record DB update persistence.
- immediate on
App.Save()
failure - delayed on transaction rollback
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every record
app.OnRecordAfterUpdateError().BindFunc(func(e *core.RecordErrorEvent) error {
// e.App
// e.Record
// e.Error
return e.Next()
})
// fires only for "users" and "articles" records
app.OnRecordAfterUpdateError("users", "articles").BindFunc(func(e *core.RecordErrorEvent) error {
// e.App
// e.Record
// e.Error
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Record model delete hooks
OnRecordDelete
is a Record proxy model hook of OnModelDelete
.
OnRecordDelete
is triggered every time when a new Record is being deleted,
e.g. triggered by App.Delete()
.
Operations BEFORE the e.Next()
execute before the Record validation
and the UPDATE DB statement.
Operations AFTER the e.Next()
execute after the Record validation
and the UPDATE DB statement.
OnRecordAfterDeleteSuccess
or OnRecordAfterDeleteError
hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every record
app.OnRecordDelete().BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
// fires only for "users" and "articles" records
app.OnRecordDelete("users", "articles").BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordDeleteExecute
is a Record proxy model hook of OnModelDeleteExecute
.
OnRecordDeleteExecute
is triggered after the internal delete checks and
right before the Record the model DELETE DB statement execution.
Usually it is triggered as part of the App.Delete()
in the following firing order:
OnRecordDelete
->
internal delete checks
->
OnRecordDeleteExecute
OnRecordAfterDeleteSuccess
or OnRecordAfterDeleteError
hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every record
app.OnRecordDeleteExecute().BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
// fires only for "users" and "articles" records
app.OnRecordDeleteExecute("users", "articles").BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordAfterDeleteSuccess
is a Record proxy model hook of OnModelAfterDeleteSuccess
.
OnRecordAfterDeleteSuccess
is triggered after each successful
Record DB delete persistence.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every record
app.OnRecordAfterDeleteSuccess().BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
// fires only for "users" and "articles" records
app.OnRecordAfterDeleteSuccess("users", "articles").BindFunc(func(e *core.RecordEvent) error {
// e.App
// e.Record
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordAfterDeleteError
is a Record proxy model hook of OnModelAfterDeleteError
.
OnRecordAfterDeleteError
is triggered after each failed
Record DB delete persistence.
- immediate on
App.Delete()
failure - delayed on transaction rollback
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every record
app.OnRecordAfterDeleteError().BindFunc(func(e *core.RecordErrorEvent) error {
// e.App
// e.Record
// e.Error
return e.Next()
})
// fires only for "users" and "articles" records
app.OnRecordAfterDeleteError("users", "articles").BindFunc(func(e *core.RecordErrorEvent) error {
// e.App
// e.Record
// e.Error
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Collection model hooks
These are lower level Collection model hooks and could be triggered from anywhere (custom console command, scheduled cron job, when calling e.Save(collection)
, etc.) and therefore they have no access to the request context!
If you want to intercept the builtin Web APIs and to access their request body, query parameters, headers or the request auth state, then please use the designated
Collection *Request
hooks
.
OnCollectionValidate
is a Collection proxy model hook of OnModelValidate
.
OnCollectionValidate
is called every time when a Collection is being validated,
e.g. triggered by App.Validate()
or App.Save()
.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnCollectionValidate().BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnCollectionValidate("users", "articles").BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Collection mode create hooks
OnCollectionCreate
is a Collection proxy model hook of OnModelCreate
.
OnCollectionCreate
is triggered every time when a new Collection is being created,
e.g. triggered by App.Save()
.
Operations BEFORE the e.Next()
execute before the Collection validation
and the INSERT DB statement.
Operations AFTER the e.Next()
execute after the Collection validation
and the INSERT DB statement.
OnCollectionAfterCreateSuccess
or OnCollectionAfterCreateError
hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnCollectionCreate().BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnCollectionCreate("users", "articles").BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnCollectionCreateExecute
is a Collection proxy model hook of OnModelCreateExecute
.
OnCollectionCreateExecute
is triggered after successful Collection validation
and right before the model INSERT DB statement execution.
Usually it is triggered as part of the App.Save()
in the following firing order:
OnCollectionCreate
->
OnCollectionValidate
(skipped with App.SaveNoValidate()
)
->
OnCollectionCreateExecute
OnCollectionAfterCreateSuccess
or OnCollectionAfterCreateError
hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnCollectionCreateExecute().BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnCollectionCreateExecute("users", "articles").BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnCollectionAfterCreateSuccess
is a Collection proxy model hook of OnModelAfterCreateSuccess
.
OnCollectionAfterCreateSuccess
is triggered after each successful
Collection DB create persistence.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnCollectionAfterCreateSuccess().BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnCollectionAfterCreateSuccess("users", "articles").BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnCollectionAfterCreateError
is a Collection proxy model hook of OnModelAfterCreateError
.
OnCollectionAfterCreateError
is triggered after each failed
Collection DB create persistence.
- immediate on
App.Save()
failure - delayed on transaction rollback
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnCollectionAfterCreateError().BindFunc(func(e *core.CollectionErrorEvent) error {
// e.App
// e.Collection
// e.Error
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnCollectionAfterCreateError("users", "articles").BindFunc(func(e *core.CollectionErrorEvent) error {
// e.App
// e.Collection
// e.Error
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Collection mode update hooks
OnCollectionUpdate
is a Collection proxy model hook of OnModelUpdate
.
OnCollectionUpdate
is triggered every time when a new Collection is being updated,
e.g. triggered by App.Save()
.
Operations BEFORE the e.Next()
execute before the Collection validation
and the UPDATE DB statement.
Operations AFTER the e.Next()
execute after the Collection validation
and the UPDATE DB statement.
OnCollectionAfterUpdateSuccess
or OnCollectionAfterUpdateError
hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnCollectionUpdate().BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnCollectionUpdate("users", "articles").BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnCollectionUpdateExecute
is a Collection proxy model hook of OnModelUpdateExecute
.
OnCollectionUpdateExecute
is triggered after successful Collection validation
and right before the model UPDATE DB statement execution.
Usually it is triggered as part of the App.Save()
in the following firing order:
OnCollectionUpdate
->
OnCollectionValidate
(skipped with App.SaveNoValidate()
)
->
OnCollectionUpdateExecute
OnCollectionAfterUpdateSuccess
or OnCollectionAfterUpdateError
hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnCollectionUpdateExecute().BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnCollectionUpdateExecute("users", "articles").BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnCollectionAfterUpdateSuccess
is a Collection proxy model hook of OnModelAfterUpdateSuccess
.
OnCollectionAfterUpdateSuccess
is triggered after each successful
Collection DB update persistence.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnCollectionAfterUpdateSuccess().BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnCollectionAfterUpdateSuccess("users", "articles").BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnCollectionAfterUpdateError
is a Collection proxy model hook of OnModelAfterUpdateError
.
OnCollectionAfterUpdateError
is triggered after each failed
Collection DB update persistence.
- immediate on
App.Save()
failure - delayed on transaction rollback
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnCollectionAfterUpdateError().BindFunc(func(e *core.CollectionErrorEvent) error {
// e.App
// e.Collection
// e.Error
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnCollectionAfterUpdateError("users", "articles").BindFunc(func(e *core.CollectionErrorEvent) error {
// e.App
// e.Collection
// e.Error
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Collection mode delete hooks
OnCollectionDelete
is a Collection proxy model hook of OnModelDelete
.
OnCollectionDelete
is triggered every time when a new Collection is being deleted,
e.g. triggered by App.Delete()
.
Operations BEFORE the e.Next()
execute before the Collection validation
and the UPDATE DB statement.
Operations AFTER the e.Next()
execute after the Collection validation
and the UPDATE DB statement.
OnCollectionAfterDeleteSuccess
or OnCollectionAfterDeleteError
hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnCollectionDelete().BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnCollectionDelete("users", "articles").BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnCollectionDeleteExecute
is a Collection proxy model hook of OnModelDeleteExecute
.
OnCollectionDeleteExecute
is triggered after the internal delete checks and
right before the Collection the model DELETE DB statement execution.
Usually it is triggered as part of the App.Delete()
in the following firing order:
OnCollectionDelete
->
internal delete checks
->
OnCollectionDeleteExecute
OnCollectionAfterDeleteSuccess
or OnCollectionAfterDeleteError
hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnCollectionDeleteExecute().BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnCollectionDeleteExecute("users", "articles").BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnCollectionAfterDeleteSuccess
is a Collection proxy model hook of OnModelAfterDeleteSuccess
.
OnCollectionAfterDeleteSuccess
is triggered after each successful
Collection DB delete persistence.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnCollectionAfterDeleteSuccess().BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnCollectionAfterDeleteSuccess("users", "articles").BindFunc(func(e *core.CollectionEvent) error {
// e.App
// e.Collection
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnCollectionAfterDeleteError
is a Collection proxy model hook of OnModelAfterDeleteError
.
OnCollectionAfterDeleteError
is triggered after each failed
Collection DB delete persistence.
- immediate on
App.Delete()
failure - delayed on transaction rollback
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnCollectionAfterDeleteError().BindFunc(func(e *core.CollectionErrorEvent) error {
// e.App
// e.Collection
// e.Error
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnCollectionAfterDeleteError("users", "articles").BindFunc(func(e *core.CollectionErrorEvent) error {
// e.App
// e.Collection
// e.Error
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Request hooks
The request hooks are triggered only when the corresponding API request endpoint is accessed.
Record CRUD request hooks
OnRecordsListRequest
hook is triggered on each API Records list request.
Could be used to validate or modify the response before returning it to the client.
OnRecordEnrich
hook because it is less error-prone and it is triggered
by all builtin Record responses (including when sending realtime Record events).
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnRecordsListRequest().BindFunc(func(e *core.RecordsListRequestEvent) error {
// e.App
// e.Collection
// e.Records
// e.Result
// and all RequestEvent fields...
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnRecordsListRequest("users", "articles").BindFunc(func(e *core.RecordsListRequestEvent) error {
// e.App
// e.Collection
// e.Records
// e.Result
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordViewRequest
hook is triggered on each API Record view request.
Could be used to validate or modify the response before returning it to the client.
OnRecordEnrich
hook because it is less error-prone and it is triggered
by all builtin Record responses (including when sending realtime Record events).
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnRecordViewRequest().BindFunc(func(e *core.RecordRequestEvent) error {
// e.App
// e.Collection
// e.Record
// and all RequestEvent fields...
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnRecordViewRequest("users", "articles").BindFunc(func(e *core.RecordRequestEvent) error {
log.Println(e.HttpContext)
log.Println(e.Record)
return nil
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordCreateRequest
hook is triggered on each API Record create request.
Could be used to additionally validate the request data or implement
completely different persistence behavior.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnRecordCreateRequest().BindFunc(func(e *core.RecordRequestEvent) error {
// e.App
// e.Collection
// e.Record
// and all RequestEvent fields...
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnRecordCreateRequest("users", "articles").BindFunc(func(e *core.RecordRequestEvent) error {
// e.App
// e.Collection
// e.Record
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordUpdateRequest
hook is triggered on each API Record update request.
Could be used to additionally validate the request data or implement
completely different persistence behavior.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnRecordUpdateRequest().BindFunc(func(e *core.RecordRequestEvent) error {
// e.App
// e.Collection
// e.Record
// and all RequestEvent fields...
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnRecordUpdateRequest("users", "articles").BindFunc(func(e *core.RecordRequestEvent) error {
// e.App
// e.Collection
// e.Record
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordDeleteRequest
hook is triggered on each API Record delete request.
Could be used to additionally validate the request data or implement
completely different delete behavior.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every collection
app.OnRecordDeleteRequest().BindFunc(func(e *core.RecordRequestEvent) error {
// e.App
// e.Collection
// e.Record
// and all RequestEvent fields...
return e.Next()
})
// fires only for "users" and "articles" collections
app.OnRecordDeleteRequest("users", "articles").BindFunc(func(e *core.RecordRequestEvent) error {
// e.App
// e.Collection
// e.Record
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Record auth request hooks
OnRecordAuthRequest
hook is triggered on each successful API
record authentication request (sign-in, token refresh, etc.).
Could be used to additionally validate or modify the authenticated
record data and token.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every auth collection
app.OnRecordAuthRequest().BindFunc(func(e *core.RecordAuthRequestEvent) error {
// e.App
// e.Record
// e.Token
// e.Meta
// e.AuthMethod
// and all RequestEvent fields...
return e.Next()
})
// fires only for "users" and "managers" auth collections
app.OnRecordAuthRequest("users", "managers").BindFunc(func(e *core.RecordAuthRequestEvent) error {
// e.App
// e.Record
// e.Token
// e.Meta
// e.AuthMethod
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordAuthRefreshRequest
hook is triggered on each Record
auth refresh API request (right before generating a new auth token).
Could be used to additionally validate the request data or implement completely different auth refresh behavior.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every auth collection
app.OnRecordAuthRefreshRequest().BindFunc(func(e *core.RecordAuthWithOAuth2RequestEvent) error {
// e.App
// e.Collection
// e.Record
// and all RequestEvent fields...
return e.Next()
})
// fires only for "users" and "managers" auth collections
app.OnRecordAuthRefreshRequest("users", "managers").BindFunc(func(e *core.RecordAuthWithOAuth2RequestEvent) error {
// e.App
// e.Collection
// e.Record
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordAuthWithPasswordRequest
hook is triggered on each
Record auth with password API request.
e.Record
could be nil
if no matching identity is found, allowing
you to manually locate a different Record model (by reassigning e.Record
).
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every auth collection
app.OnRecordAuthWithPasswordRequest().BindFunc(func(e *core.RecordAuthWithPasswordRequestEvent) error {
// e.App
// e.Collection
// e.Record (could be nil)
// e.Identity
// e.IdentityField
// e.Password
// and all RequestEvent fields...
return e.Next()
})
// fires only for "users" and "managers" auth collections
app.OnRecordAuthWithPasswordRequest("users", "managers").BindFunc(func(e *core.RecordAuthWithPasswordRequestEvent) error {
// e.App
// e.Collection
// e.Record (could be nil)
// e.Identity
// e.IdentityField
// e.Password
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordAuthWithOAuth2Request
hook is triggered on each Record
OAuth2 sign-in/sign-up API request (after token exchange and before external provider linking).
If e.Record
is not set, then the OAuth2
request will try to create a new auth record.
To assign or link a different existing record model you can
change the e.Record
field.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every auth collection
app.OnRecordAuthWithOAuth2Request().BindFunc(func(e *core.RecordAuthWithOAuth2RequestEvent) error {
// e.App
// e.Collection
// e.ProviderName
// e.ProviderClient
// e.Record (could be nil)
// e.OAuth2User
// e.CreateData
// e.IsNewRecord
// and all RequestEvent fields...
return e.Next()
})
// fires only for "users" and "managers" auth collections
app.OnRecordAuthWithOAuth2Request("users", "managers").BindFunc(func(e *core.RecordAuthWithOAuth2RequestEvent) error {
// e.App
// e.Collection
// e.ProviderName
// e.ProviderClient
// e.Record (could be nil)
// e.OAuth2User
// e.CreateData
// e.IsNewRecord
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordRequestPasswordResetRequest
hook is triggered on
each Record request password reset API request.
Could be used to additionally validate the request data or implement completely different password reset behavior.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every auth collection
app.OnRecordRequestPasswordResetRequest().BindFunc(func(e *core.RecordRequestPasswordResetRequestEvent) error {
// e.App
// e.Collection
// e.Record
// and all RequestEvent fields...
return e.Next()
})
// fires only for "users" and "managers" auth collections
app.OnRecordRequestPasswordResetRequest("users", "managers").BindFunc(func(e *core.RecordRequestPasswordResetRequestEvent) error {
// e.App
// e.Collection
// e.Record
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordConfirmPasswordResetRequest
hook is triggered on
each Record confirm password reset API request.
Could be used to additionally validate the request data or implement completely different persistence behavior.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every auth collection
app.OnRecordConfirmPasswordResetRequest().BindFunc(func(e *core.RecordConfirmPasswordResetRequestEvent) error {
// e.App
// e.Collection
// e.Record
// and all RequestEvent fields...
return e.Next()
})
// fires only for "users" and "managers" auth collections
app.OnRecordConfirmPasswordResetRequest("users", "managers").BindFunc(func(e *core.RecordConfirmPasswordResetRequestEvent) error {
// e.App
// e.Collection
// e.Record
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordRequestVerificationRequest
hook is triggered on
each Record request verification API request.
Could be used to additionally validate the loaded request data or implement completely different verification behavior.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every auth collection
app.OnRecordRequestVerificationRequest().BindFunc(func(e *core.RecordRequestVerificationRequestEvent) error {
// e.App
// e.Collection
// e.Record
// and all RequestEvent fields...
return e.Next()
})
// fires only for "users" and "managers" auth collections
app.OnRecordRequestVerificationRequest("users", "managers").BindFunc(func(e *core.RecordRequestVerificationRequestEvent) error {
// e.App
// e.Collection
// e.Record
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordConfirmVerificationRequest
hook is triggered on each
Record confirm verification API request.
Could be used to additionally validate the request data or implement completely different persistence behavior.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every auth collection
app.OnRecordConfirmVerificationRequest().BindFunc(func(e *core.RecordConfirmVerificationRequestEvent) error {
// e.App
// e.Collection
// e.Record
// and all RequestEvent fields...
return e.Next()
})
// fires only for "users" and "managers" auth collections
app.OnRecordConfirmVerificationRequest("users", "managers").BindFunc(func(e *core.RecordConfirmVerificationRequestEvent) error {
// e.App
// e.Collection
// e.Record
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordRequestEmailChangeRequest
hook is triggered on each
Record request email change API request.
Could be used to additionally validate the request data or implement completely different request email change behavior.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every auth collection
app.OnRecordRequestEmailChangeRequest().BindFunc(func(e *core.RecordRequestEmailChangeRequestEvent) error {
// e.App
// e.Collection
// e.Record
// e.NewEmail
// and all RequestEvent fields...
return e.Next()
})
// fires only for "users" and "managers" auth collections
app.OnRecordRequestEmailChangeRequest("users", "managers").BindFunc(func(e *core.RecordRequestEmailChangeRequestEvent) error {
// e.App
// e.Collection
// e.Record
// e.NewEmail
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordConfirmEmailChangeRequest
hook is triggered on each
Record confirm email change API request.
Could be used to additionally validate the request data or implement completely different persistence behavior.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every auth collection
app.OnRecordConfirmEmailChangeRequest().BindFunc(func(e *core.RecordConfirmEmailChangeRequestEvent) error {
// e.App
// e.Collection
// e.Record
// e.NewEmail
// and all RequestEvent fields...
return e.Next()
})
// fires only for "users" and "managers" auth collections
app.OnRecordConfirmEmailChangeRequest("users", "managers").BindFunc(func(e *core.RecordConfirmEmailChangeRequestEvent) error {
// e.App
// e.Collection
// e.Record
// e.NewEmail
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordRequestOTPRequest
hook is triggered on each Record
request OTP API request.
e.Record
could be nil
if no user with the requested email is found, allowing
you to manually create a new Record or locate a different Record model (by reassigning e.Record
).
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every auth collection
app.OnRecordRequestOTPRequest().BindFunc(func(e *core.RecordCreateOTPRequestEvent) error {
// e.App
// e.Collection
// e.Record (could be nil)
// e.Password
// and all RequestEvent fields...
return e.Next()
})
// fires only for "users" and "managers" auth collections
app.OnRecordRequestOTPRequest("users", "managers").BindFunc(func(e *core.RecordCreateOTPRequestEvent) error {
// e.App
// e.Collection
// e.Record (could be nil)
// e.Password
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnRecordAuthWithOTPRequest
hook is triggered on each Record
auth with OTP API request.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every auth collection
app.OnRecordAuthWithOTPRequest().BindFunc(func(e *core.RecordAuthWithOTPRequestEvent) error {
// e.App
// e.Collection
// e.Record
// e.OTP
// and all RequestEvent fields...
return e.Next()
})
// fires only for "users" and "managers" auth collections
app.OnRecordAuthWithOTPRequest("users", "managers").BindFunc(func(e *core.RecordAuthWithOTPRequestEvent) error {
// e.App
// e.Collection
// e.Record
// e.OTP
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Batch request hooks
OnBatchRequest
hook is triggered on each API batch request.
Could be used to additionally validate or modify the submitted batch requests.
This hook will also fire the corresponding OnRecordCreateRequest
, OnRecordUpdateRequest
, OnRecordDeleteRequest
hooks, where e.App
is the batch transactional app.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnBatchRequest().BindFunc(func(e *core.BatchRequestEvent) error {
// e.App
// e.Batch
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
File request hooks
OnFileDownloadRequest
hook is triggered before each API File download request.
Could be used to validate or modify the file response before returning it to the client.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnFileDownloadRequest().BindFunc(func(e *core.FileDownloadRequestEvent) error {
// e.App
// e.Collection
// e.Record
// e.FileField
// e.ServedPath
// e.ServedName
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnFileTokenRequest
hook is triggered on each auth file token API request.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every auth model
app.OnFileTokenRequest().BindFunc(func(e *core.FileTokenRequestEvent) error {
// e.App
// e.Record
// e.Token
// and all RequestEvent fields...
return e.Next();
})
// fires only for "users"
app.OnFileTokenRequest("users").BindFunc(func(e *core.FileTokenRequestEvent) error {
// e.App
// e.Record
// e.Token
// and all RequestEvent fields...
return e.Next();
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Collection request hooks
OnCollectionsListRequest
hook is triggered on each API Collections list request.
Could be used to validate or modify the response before returning it to the client.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnCollectionsListRequest().BindFunc(func(e *core.CollectionsListRequestEvent) error {
// e.App
// e.Collections
// e.Result
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnCollectionViewRequest
hook is triggered on each API Collection view request.
Could be used to validate or modify the response before returning it to the client.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnCollectionViewRequest().BindFunc(func(e *core.CollectionRequestEvent) error {
// e.App
// e.Collection
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnCollectionCreateRequest
hook is triggered on each API Collection create request.
Could be used to additionally validate the request data or implement completely different persistence behavior.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnCollectionCreateRequest().BindFunc(func(e *core.CollectionRequestEvent) error {
// e.App
// e.Collection
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnCollectionUpdateRequest
hook is triggered on each API Collection update request.
Could be used to additionally validate the request data or implement completely different persistence behavior.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnCollectionUpdateRequest().BindFunc(func(e *core.CollectionRequestEvent) error {
// e.App
// e.Collection
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnCollectionDeleteRequest
hook is triggered on each API Collection delete request.
Could be used to additionally validate the request data or implement completely different delete behavior.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnCollectionDeleteRequest().BindFunc(func(e *core.CollectionRequestEvent) error {
// e.App
// e.Collection
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnCollectionsImportRequest
hook is triggered on each API
collections import request.
Could be used to additionally validate the imported collections or to implement completely different import behavior.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnCollectionsImportRequest().BindFunc(func(e *core.CollectionsImportRequestEvent) error {
// e.App
// e.CollectionsData
// e.DeleteMissing
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Settings request hooks
OnSettingsListRequest
hook is triggered on each API Settings list request.
Could be used to validate or modify the response before returning it to the client.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnSettingsListRequest().BindFunc(func(e *core.SettingsListRequestEvent) error {
// e.App
// e.Settings
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnSettingsUpdateRequest
hook is triggered on each API Settings update request.
Could be used to additionally validate the request data or implement completely different persistence behavior.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
app.OnSettingsUpdateRequest().BindFunc(func(e *core.SettingsUpdateRequestEvent) error {
// e.App
// e.OldSettings
// e.NewSettings
// and all RequestEvent fields...
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Base model hooks
The Model hooks are fired for all PocketBase structs that implements the Model DB interface - Record, Collection, Log, etc.
For convenience, if you want to listen to only the Record or Collection DB model
events without doing manual type assertion, you can use the
OnRecord*
and
OnCollection*
proxy hooks above.
OnModelValidate
is called every time when a Model is being validated,
e.g. triggered by App.Validate()
or App.Save()
.
For convenience, if you want to listen to only the Record or Collection models
events without doing manual type assertion, you can use the equivalent OnRecord*
and OnCollection*
proxy hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every model
app.OnModelValidate().BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
// fires only for "users" and "articles" models
app.OnModelValidate("users", "articles").BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Base model create hooks
OnModelCreate
is triggered every time when a new Model is being created,
e.g. triggered by App.Save()
.
Operations BEFORE the e.Next()
execute before the Model validation
and the INSERT DB statement.
Operations AFTER the e.Next()
execute after the Model validation
and the INSERT DB statement.
OnModelAfterCreateSuccess
or OnModelAfterCreateError
hooks.
For convenience, if you want to listen to only the Record or Collection models
events without doing manual type assertion, you can use the equivalent OnRecord*
and OnCollection*
proxy hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every model
app.OnModelCreate().BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
// fires only for "users" and "articles" models
app.OnModelCreate("users", "articles").BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnModelCreateExecute
is triggered after successful Model validation
and right before the model INSERT DB statement execution.
Usually it is triggered as part of the App.Save()
in the following firing order:
OnModelCreate
->
OnModelValidate
(skipped with App.SaveNoValidate()
)
->
OnModelCreateExecute
OnModelAfterCreateSuccess
or OnModelAfterCreateError
hooks.
For convenience, if you want to listen to only the Record or Collection models
events without doing manual type assertion, you can use the equivalent OnRecord*
and OnCollection*
proxy hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every model
app.OnModelCreateExecute().BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
// fires only for "users" and "articles" models
app.OnModelCreateExecute("users", "articles").BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnModelAfterCreateSuccess
is triggered after each successful
Model DB create persistence.
For convenience, if you want to listen to only the Record or Collection models
events without doing manual type assertion, you can use the equivalent OnRecord*
and OnCollection*
proxy hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every model
app.OnModelAfterCreateSuccess().BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
// fires only for "users" and "articles" models
app.OnModelAfterCreateSuccess("users", "articles").BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnModelAfterCreateError
is triggered after each failed
Model DB create persistence.
- immediate on
App.Save()
failure - delayed on transaction rollback
For convenience, if you want to listen to only the Record or Collection models
events without doing manual type assertion, you can use the equivalent OnRecord*
and OnCollection*
proxy hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every model
app.OnModelAfterCreateError().BindFunc(func(e *core.ModelErrorEvent) error {
// e.App
// e.Model
// e.Error
return e.Next()
})
// fires only for "users" and "articles" models
app.OnModelAfterCreateError("users", "articles").BindFunc(func(e *core.ModelErrorEvent) error {
// e.App
// e.Model
// e.Error
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Base model update hooks
OnModelUpdate
is triggered every time when a new Model is being updated,
e.g. triggered by App.Save()
.
Operations BEFORE the e.Next()
execute before the Model validation
and the UPDATE DB statement.
Operations AFTER the e.Next()
execute after the Model validation
and the UPDATE DB statement.
OnModelAfterUpdateSuccess
or OnModelAfterUpdateError
hooks.
For convenience, if you want to listen to only the Record or Collection models
events without doing manual type assertion, you can use the equivalent OnRecord*
and OnCollection*
proxy hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every model
app.OnModelUpdate().BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
// fires only for "users" and "articles" models
app.OnModelUpdate("users", "articles").BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnModelUpdateExecute
is triggered after successful Model validation
and right before the model UPDATE DB statement execution.
Usually it is triggered as part of the App.Save()
in the following firing order:
OnModelUpdate
->
OnModelValidate
(skipped with App.SaveNoValidate()
)
->
OnModelUpdateExecute
OnModelAfterUpdateSuccess
or OnModelAfterUpdateError
hooks.
For convenience, if you want to listen to only the Record or Collection models
events without doing manual type assertion, you can use the equivalent OnRecord*
and OnCollection*
proxy hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every model
app.OnModelUpdateExecute().BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
// fires only for "users" and "articles" models
app.OnModelUpdateExecute("users", "articles").BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnModelAfterUpdateSuccess
is triggered after each successful
Model DB update persistence.
For convenience, if you want to listen to only the Record or Collection models
events without doing manual type assertion, you can use the equivalent OnRecord*
and OnCollection*
proxy hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every model
app.OnModelAfterUpdateSuccess().BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
// fires only for "users" and "articles" models
app.OnModelAfterUpdateSuccess("users", "articles").BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnModelAfterUpdateError
is triggered after each failed
Model DB update persistence.
- immediate on
App.Save()
failure - delayed on transaction rollback
For convenience, if you want to listen to only the Record or Collection models
events without doing manual type assertion, you can use the equivalent OnRecord*
and OnCollection*
proxy hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every model
app.OnModelAfterUpdateError().BindFunc(func(e *core.ModelErrorEvent) error {
// e.App
// e.Model
// e.Error
return e.Next()
})
// fires only for "users" and "articles" models
app.OnModelAfterUpdateError("users", "articles").BindFunc(func(e *core.ModelErrorEvent) error {
// e.App
// e.Model
// e.Error
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Base model delete hooks
OnModelDelete
is triggered every time when a new Model is being deleted,
e.g. triggered by App.Delete()
.
Operations BEFORE the e.Next()
execute before the Model validation
and the UPDATE DB statement.
Operations AFTER the e.Next()
execute after the Model validation
and the UPDATE DB statement.
OnModelAfterDeleteSuccess
or OnModelAfterDeleteError
hooks.
For convenience, if you want to listen to only the Record or Collection models
events without doing manual type assertion, you can use the equivalent OnRecord*
and OnCollection*
proxy hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every model
app.OnModelDelete().BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
// fires only for "users" and "articles" models
app.OnModelDelete("users", "articles").BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnModelDeleteExecute
is triggered after the internal delete checks and
right before the Model the model DELETE DB statement execution.
Usually it is triggered as part of the App.Delete()
in the following firing order:
OnModelDelete
->
internal delete checks
->
OnModelDeleteExecute
OnModelAfterDeleteSuccess
or OnModelAfterDeleteError
hooks.
For convenience, if you want to listen to only the Record or Collection models
events without doing manual type assertion, you can use the equivalent OnRecord*
and OnCollection*
proxy hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every model
app.OnModelDeleteExecute().BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
// fires only for "users" and "articles" models
app.OnModelDeleteExecute("users", "articles").BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnModelAfterDeleteSuccess
is triggered after each successful
Model DB delete persistence.
For convenience, if you want to listen to only the Record or Collection models
events without doing manual type assertion, you can use the equivalent OnRecord*
and OnCollection*
proxy hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every model
app.OnModelAfterDeleteSuccess().BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
// fires only for "users" and "articles" models
app.OnModelAfterDeleteSuccess("users", "articles").BindFunc(func(e *core.ModelEvent) error {
// e.App
// e.Model
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
OnModelAfterDeleteError
is triggered after each failed
Model DB delete persistence.
- immediate on
App.Delete()
failure - delayed on transaction rollback
For convenience, if you want to listen to only the Record or Collection models
events without doing manual type assertion, you can use the equivalent OnRecord*
and OnCollection*
proxy hooks.
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// fires for every model
app.OnModelAfterDeleteError().BindFunc(func(e *core.ModelErrorEvent) error {
// e.App
// e.Model
// e.Error
return e.Next()
})
// fires only for "users" and "articles" models
app.OnModelAfterDeleteError("users", "articles").BindFunc(func(e *core.ModelErrorEvent) error {
// e.App
// e.Model
// e.Error
return e.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}