Merged
Conversation
Add `POST /api/flush` route to clear cache using a collection path as a pattern, or "*" for all cache documents.
For example, sending the following as the request body
```
{ "path":"/1.0/library/book" }
```
…i/api into feature/12_add_logging_level
Add logging level configuration
Standard log rotation
…than each collection connection
…than each collection connection
…to feature/connect_once
Create connections at database level, not collection level
This commit also ensures the hook is called for an array of documents passed to model.create()
Contributor
|
@eduardoboucas I believe we can close this PR, as everything here is covered by #42. What do you think? |
Contributor
Author
|
@jimlambie #42 is actually trying to merge the new hooks into this branch ( |
Add before and after hooks
Contributor
Author
|
@jimlambie This commit fixes the bug with Let me know what you think. |
This commit also ensures the hook is called for an array of documents passed to model.create()
Contributor
Author
|
…ure/hooks Conflicts: dadi/lib/model/index.js
Contributor
Author
|
🎉 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR proposes the introduction of hooks — pieces of logic that are executed at specific points when documents are created, updated or deleted.
Overview
In its essence, a hook is simply a function that intercepts a document/query before it's executed, having the option to modify it before returning it back to the model.
A hook is stored as an individual file on a
hooksdirectory (defaulting to/workspace/hooks) and can be used by being attached to acreate,updateordeleteoperation in thesettingssection of the schema definition.collections.user.json:
This means that whenever a new user is created, the document that is about to be inserted will be passed to
myhook1, its return value will then be passed on tomyhook2and so on. After all the hooks finish executing, the final document will be returned to the model to be inserted in the database.The order in which hooks are executed is defined by the order of the items in the array.
Anatomy of a hook
A simple hook can be defined as following:
This particular hook will receive a document, change a property (
name) and return it back. So if attached to thecreateevent, it will make all the created documents havenameset toModified by the hook.However, this logic ties the hook to the schema — what happens if we want to modify a property other than
name? Hooks are supposed to be able to add functionality to a document, and should be approached as interchangeable building blocks rather than pieces of functionality tightly coupled with a schema.For that reason, developers might have the need to pass extra information to the hook — e.g. inform the hook the name of the properties that should be modified. As such, in addition to the syntax shown above for declaring a hook (an array of strings), an alternative one allows data to be passed through a
optionsobject.In this example we implement a hook that populates a field (
slug) with a URL-friendly version of another field (title). The hook is created in such a way that the properties it reads from and writes to are dynamic, passed through asfromandtoinsideoptions. Theslugifyhook could then be written as follows:A hook always receives 3 arguments:
obj: The main object, which the hook is able to modify. It must always return it back. It can be a document (oncreate) or a query (onupdateordelete);type: The type of hook. Can be0(create),1(update) or2(delete);data: Object that passed additional data, such as theoptionsobject that may be declared with the hook, or other objects depending on the type of hook (e.g.updatedDocswill be passed if it's aupdatehook).Use cases
Further considerations
Hookprototype.create,updateanddelete) are fired before operations take place, giving developers power to change their course. But it also means that they happen at a point where there's no guarantee the operation will completely, especially because they are fired before validation. Would there be a need for more granular events likebeforeCreateandafterCreate, where the former could be used to change the behaviour of an operation and the latter would be used to trigger something when the operation has definitely finished? Is this going too far?Testing
I have some tests but they still need some love, so I haven't included them in this PR. If you think this feature is worth implementing, I'll polish them up and add to the PR.
@jimlambie @josephdenne what do you think?