DocsReference

Hooks

Every hook of a GoLocomotive app, its event fields and its default action, plus routes, middlewares and the request event.

A hook is app.<hook>(handler, ...collections). No collection means every collection. Handlers run in the order they were bound, and each one must await e.next() for the default action to run. A handler that skips next() stops the chain and answers with e.json(...) itself. How to choose between them: Server: hooks, routes, crons.

Record request hooks#

They fire on an HTTP request only, never on a write made by a hook or a script. They run BEFORE the rule check of the write.

hookevent, beside e.next()default action
onRecordsListRequestrequest, collection, resultanswer result
onRecordViewRequestrequest, collection, recordanswer record
onRecordCreateRequestrequest, collection, data (mutable), record (set by next)the rule, the write, the answer
onRecordUpdateRequestrequest, collection, original (stored, rule not checked yet), data, recordthe rule, the write, the answer
onRecordDeleteRequestrequest, collection, record (stored)the rule, the delete, 204

After success hooks#

They fire after the commit, for EVERY write: an HTTP request, a hook, a script, a cascade. A throw is logged and the write stays.

hookevent
onRecordAfterCreateSuccesscollection, record
onRecordAfterUpdateSuccesscollection, record, original
onRecordAfterDeleteSuccesscollection, record

Auth hooks#

hookeventdefault action
onRecordAuthRequestrequest, collection, record, token, authMethod (password, otp, or '' on a refresh)the second factor, the alert, then answer { token, record }
onRecordAuthWithPasswordRequestrequest, collection, identity, password, record (null when unknown)check the password, then auth
onRecordAuthWithOTPRequestrequest, collection, record, otpIduse the code, then auth
onRecordRequestOTPRequestrequest, collection, email, recordmake and mail the code
onRecordAuthRefreshRequestrequest, collection, recordanswer a fresh token
onRecordRequestPasswordResetRequestrequest, collection, recordmail the link
onRecordConfirmPasswordResetRequestrequest, collection, recordset the password
onRecordRequestEmailChangeRequestrequest, collection, record, newEmailmail the link to the new address
onRecordConfirmEmailChangeRequestrequest, collection, record, newEmailset email and verified

Mail and backup hooks#

hookeventdefault action
onMailerSendmessage (mutable); kind and record on auth mailssend
onBackupCreatename (mutable, '' for the default name), exclude (mutable: entries of the data folder to leave out)write the zip into the store
onBackupRestorename, exclude (mutable: entries to keep in place)stage, stop, swap, restart

app.db is always in a backup. backups and the temp folder are always out. Code after next() in onBackupRestore runs only when the restore failed before it stopped the app: on success the process restarts.

The request event#

memberwhat
requestthe Request
urlthe parsed URL
paramspath parameters
auththe signed in record, or null
isSuperusertrue for a _superusers record
realIpthe client IP, read from trustedProxy headers, else the socket's
remoteIpthe socket's address, always
body()the JSON or multipart body, parsed once
json(status, data)answer JSON
noContent()answer 204
responsewhat was answered, after next()

Routes and middlewares#

app.route('POST', '/api/orders/:id/close', async (e) => {
    const order = await app.records.getOne('orders', e.params.id ?? '')
    if (order.owner !== e.auth?.id) throw new ApiError(403, 'Not your order.')
    await app.records.update('orders', order.id, { status: 'done' })
    return e.noContent()
}, requireAuth('users'))
  • app.route(method, path, handler, ...middlewares). Paths take :name and a * wildcard.
  • requireAuth(...collections): 401 without a signed in record of those collections (any auth collection when none is named).
  • requireSuperuser(): 403 for anyone but a superuser.
  • bodyLimit(bytes): this route's body limit; 0 is none; a function of the app and the path parameters is read per request.
  • A middleware is a handler that calls e.next(). A handler can also return a Response.
  • ApiError(status, message, data?) thrown anywhere becomes PocketBase's error shape.

Crons#

callwhat
app.cron(name, spec, fn)five fields (* , - /) or @yearly @monthly @weekly @daily @hourly, UTC, checked each minute. The same name replaces. A throw is logged, the schedule goes on
__loco_cleanupbuilt in, hourly: expired codes and two factor sessions, idle rate limit clients
__loco_backupbuilt in when backups.cron is set

This page as markdown