Getting Started
About
feathers-trigger provides a hook called trigger. This hook is meant to be used for a subscription pattern. It's inspired by services like IFTTT or Zapier where you automate things by providing a trigger and an action. The hook trigger can be used for methods create, update, patch and remove. While configuring the trigger hook you provide a subscription which checks for context.data and context.result and if the check is fulfilled, it runs an action callback function you provide.
Use cases are notifications or logs like:
'A todo was created/updated/removed''User "xy" assigned the todo "get things done" to you''The due date of a todo "procrastinate" was delayed by more than 3 days'
Features:
- check for conditions with sift.js
- check for changes like:
{ publishedAt: { $lt: before.publishedAt } } subscriptionscan be stored in a database- check for populations or something.
- Written in Typescript
Installation
npm i feathers-triggerSimple example
Imagine you want to notify users when a post gets published.
How can this be done? In this example a post has a publishedAt property which shows when a post was published. A post with publishedAt === null means that the post is not published yet. A post can be created as a draft which is not published.
But how do you know when a post gets published? Sounds silly, but there are three possibilities:
- A
postgets created withpublishedAt: { $ne: null }. - A
postgets updated by datapublishedAt: { $ne: null }, it hadpublishedAt: nullbefore and the result really haspublishedAt: { $ne: null }. - A
postgets patched by datapublishedAt: { $ne: null }, it hadpublishedAt: nullbefore and the result really haspublishedAt: { $ne: null }.
How can this be accomplished?
- Check
context.dataforpublishedAt: { $ne: null }and if that's not true, the subscription is not true. - Check if the post in the database has
publishedAt === nulland therefore is not published yet. You need to check that in abeforehook. If that's not true, the subscription is not true. - Check if the
context.resultreally haspublishedAt: { $ne: null }(maybe it's handled by another permission hook, or something). If that's not true, the subscription is not true. - If all three checks are true, run the
notifyfunction.
It's up to you how you define the notify action. For the example above the solution with feathers-trigger looks like the following:
// posts.hooks.js
import { trigger } from "feathers-trigger";
const notifyPublished = trigger({
data: { publishedAt: { $ne: null } },
before: { publishedAt: null },
result: { publishedAt: { $ne: null } },
action: ({ item }, { context }) => {
return context.app.service("/notify").create(item);
},
});
export default {
before: {
create: [notifyPublished],
update: [notifyPublished],
patch: [notifyPublished],
},
after: {
create: [notifyPublished],
update: [notifyPublished],
patch: [notifyPublished],
},
};// examples
const postsService = app.service("posts");
// scenario 1:
const post = await postsService.create({
title: "hello",
publishedAt: new Date(),
});
// notification called
await postsService.patch(post.id, { publishedAt: new Date() });
// notification not called again
// scenario 2:
const post = await postsService.create({ title: "hello", publishedAt: null });
// notification not called yet
await postsService.update(post.id, { title: "ciao", publishedAt: null });
// notification not called yet
await postsService.update(post.id, { title: "hello", publishedAt: new Date() });
// notification called
await postsService.update(post.id, { title: "hello", publishedAt: new Date() });
// notification not called again
// scenario 3:
const post = await postsService.create({ title: "hello", publishedAt: null });
// notification not called yet
await postsService.patch(post.id, { title: "ciao" });
// notification not called yet
await postsService.patch(post.id, { publishedAt: new Date() });
// notification called
await postsService.patch(post.id, { publishedAt: new Date() });
// notification not called againComplex example
Imagine you want to notify a user when his todo gets delayed. And only when it gets delayed! Todos can be changed by all members of a team. The user only needs to get notified, if another person changes the date of the todo. If he changes the data himself, we can assume he noticed the change and doesn't need an annoying notification, right?
How can this be done? Each todo has at least two properties:
userId: shows who is responsible for thetododueAt: show when the todo needs to be done at the latest
// todos.hooks.js
import { trigger } from "feathers-trigger";
const notifyDelay = trigger([
{
fetchBefore: true,
result: ({ before }, context) => ({
startsAt: { $gt: before.startsAt },
userId: { $ne: context.params.user.id },
}),
action: ({ item }, { context }) => {
return context.app.service("/notify").create(item);
},
},
]);
export default {
before: {
create: [notifyDelay],
update: [notifyDelay],
patch: [notifyDelay],
},
after: {
create: [notifyDelay],
update: [notifyDelay],
patch: [notifyDelay],
},
};Testing
Simply run npm test and all your tests in the test/ directory will be run. The project has full support for Visual Studio Code. You can use the debugger to set breakpoints.
Help
For more information on all the things you can do, visit FeathersJS.
License
Licensed under the MIT license.