Skip to content

Instantly share code, notes, and snippets.

@maietta
Last active November 3, 2024 01:54
Show Gist options
  • Save maietta/d4f7b75d5117c1739fe6af7addeeddf4 to your computer and use it in GitHub Desktop.
Save maietta/d4f7b75d5117c1739fe6af7addeeddf4 to your computer and use it in GitHub Desktop.
Watch for events on Pocketbase
import PocketBase from "pocketbase";
import eventsource from "eventsource";
global.EventSource = eventsource as unknown as typeof EventSource;
const pb = new PocketBase(process.env.POCKETBASE_URL);
// Store the initial states of all records in a cache
const previousRecords: { [recordId: string]: any } = {};
async function watchCollectionChanges(collection: string) {
// Optionally, pre-cache initial states of all records
const initialRecords = await pb.collection(collection).getFullList();
// Populate previousRecords cache
initialRecords.forEach(record => {
previousRecords[record.id] = record;
});
// Subscribe to real-time updates on all records in the collection
pb.collection(collection).subscribe("*", (e) => {
const updatedRecord = e.record;
if (e.action === "update" || e.action === "create") {
const recordId = updatedRecord.id;
const previousRecord = previousRecords[recordId] || {};
// Compare fields to detect changes
Object.keys(updatedRecord).forEach((field) => {
// Ignore `created`, `updated`, and `id` fields
if (["created", "updated", "id"].includes(field)) {
return;
}
switch (field) {
case "data":
case "photos":
if (updatedRecord[field] === null && previousRecord[field] === null) return;
// Handle `data` field logic here
if (field === "data" && updatedRecord[field] !== previousRecord[field]) {
if (updatedRecord[field] === null && previousRecord[field] !== null) {
console.log(`Record ID: ${recordId} - New record created.`);
return;
} else if (previousRecord[field] === null) {
console.log(`Record ID: ${recordId} - Record updated.`);
return;
} else {
const differences: string[] = [];
// Compare JSON objects
if (typeof updatedRecord[field] === "object" && typeof previousRecord[field] === "object") {
for (const key in updatedRecord[field]) {
if (Object.prototype.hasOwnProperty.call(updatedRecord[field], key)) {
if (updatedRecord[field][key] !== previousRecord[field][key]) {
differences.push(`${key}: ${previousRecord[field][key]} -> ${updatedRecord[field][key]}`);
}
}
}
}
if (differences.length > 0) {
if (differences.some((diff) => diff.includes("L_Photo_Updt_Date"))) {
console.log(`Time to update photos for record ID: ${recordId}.`);
//return;
}
console.log(`Record ID: ${recordId} - Field "${field}" changed: ${differences.join(", ")}`);
}
}
}
break;
case "class":
if (updatedRecord[field] !== previousRecord[field]) {
if (previousRecord[field] === undefined && updatedRecord[field] === "") return;
console.log(`Record ID: ${recordId} - Class Type changed from ${previousRecord[field]} to ${updatedRecord[field]}`);
}
break;
default:
if (updatedRecord[field] !== previousRecord[field]) {
console.log(`Record ID: ${recordId} - Field "${field}" changed from ${previousRecord[field]} to ${updatedRecord[field]}`);
}
break;
}
});
// Update the cache for this record
previousRecords[recordId] = updatedRecord;
}
if (e.action === "delete") {
console.log(`Record ID: ${e.record.id} was deleted.`);
delete previousRecords[e.record.id];
}
});
}
// Use the function to watch an entire collection
watchCollectionChanges("listings");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment