Charbs 92cbdbbc09
Support pb_hooks directory introduced by PocketBase 0.17.0 (#272)
* Support pb_hooks directory introduced by PocketBase 0.17.0

See https://github.com/benallfree/pockethost/discussions/271

* Added simple documentation on pb_hooks

* Extended the hooks documentation to include some more samples.

* Updated the way "PocketBase" is spelt for consistency
2023-08-13 01:07:35 -07:00

165 lines
4.5 KiB
Markdown

# PocketBase Hooks
The prebuilt PocketBase v0.17+ executable comes with embedded ES5 JavaScript engine (goja) which enables you to write custom server-side code using plain JavaScript.
Every Pockethost instance comes with a `pb_hooks` directory which is mounted into the PocketBase instance at `/pb_hooks`. This directory is where you can place your custom server-side code.
For more information on PocketBase hooks, see the [PocketBase documentation](https://pocketbase.io/docs/js-overview/).
## Quickstart
You can start by creating `*.pb.js` file(s) inside the `pb_hooks` directory. The `*.pb.js` files are automatically loaded and executed by PocketBase.
## Code Samples
These are only a few simple and limited examples of what you can do with PocketBase hooks. There is lot more available to you. For more information, see the [PocketBase documentation](https://pocketbase.io/docs/js-overview/).
**Listen to the `onAfterBootstrap` hook handler and log a message to the console. This sample also shows how you can import utils or configs from another file.**
```
// pb_hooks/main.pb.js
// This runs when the PocketBase instance is first bootstrapped
onAfterBootstrap((e) => {
// You can load config or util files for your app
const config = require(`${__hooks}/config/config.js`);
const name = 'Hooks!'
const fxTest = config.hello(name);
console.log("App initialized!");
console.log(`fxTest: ${fxTest}`);
console.log(`App name: ${JSON.stringify(config)}`);
});
```
```
// pb_hooks/config/config.js
module.exports = {
appName: "pockethost-test",
appVersion: "0.0.1",
hello: (name) => {
return "Hello " + name
}
};
```
**Register a new route that you can interface with using the SDK**
```
// pb_hooks/somefile.pb.js
routerAdd("POST", "/test/:testId", (c) => {
const testId = c.pathParam("testId");
return c.json(200, {
testId
});
});
```
You can now interface with this route using the PocketBase SDK. Here's a JS SDK example:
```
const pb = new PocketBase('http://127.0.0.1:8090');
const response = await pb.send("/test/theTestId", {
method: "POST"
});
// response returns { testId: "theTestId" }
```
**Find a record and update it**
```
// pb_hooks/posts.update.pb.js
routerAdd("PATCH", "/posts/:postId", (c) => {
const postId = c.pathParam("postId");
// Get body data
const body = $apis.requestInfo(c).data;
const status = body.status;
// Find a record by ID on the "posts" collection
const record = $app.dao().findRecordById("posts", postId);
// If the record doesn't exist, return a 404
// Perhaps you can return a 40X if the user doesn't have permission to update the record etc
if (!record) {
return c.json(404, {
error: "Record not found"
});
}
// Update the record with the new status
record.set("status", status);
// Save the record
$app.dao().saveRecord(record);
// Expand record before we return it
$app.dao().expandRecord(record, ["user", "comments"], null);
// Return the record
return c.json(200, {
record
});
});
```
**Find a collection and create a new record**
```
// pb_hooks/posts.create.pb.js
routerAdd("POST", "/posts", (c) => {
// Get body data
const body = $apis.requestInfo(c).data;
// Get values from body
const { postTitle, postDescription } = body;
// Find the collection by name
const postsCollection = $app.dao().findCollectionByNameOrId("posts");
// Create a new post record
const record = new Record(postsCollection, {
title: postTitle,
description: postDescription
});
// Save the record
$app.dao().saveRecord(record);
// Return the record
return c.json(200, {
record
});
});
```
**Listen to record changes on a collection**
In this sample, we react to a user being registered and we create a new customer record in Stripe.
This is not tested, and is a fictional scenario. But the concept behind it is what we're trying to show.
```
// pb_hooks/users.onRegister.pb.js
onRecordAfterCreateRequest((e) => {
// Get the record
const record = e.record;
try {
// Invoke Stripe API to create a new customer
const response = $http.send({
url: "https://api.stripe.com/v1/customers", // Stripe API URL
method: "POST",
body: {
email: record.email
},
headers: {
// Provide Stripe API key or whatever else they require
}
})
if (response) {
console.log("Stripe customer created!", response.newCustomerId);
}
} catch (err) {
console.log(err)
}
}, "users") // This runs when a record is created on the "users" collection
```