Writing your own plugins
Learn how to write your own plugins in ZBSearch.
With ZBSearch v2.0.0-beta.5, we introduced the new plugin system. This allows you to write your own plugins and use them in your ZBSearch project.
The ZBSearch plugin system is meant to replace the old hooks system, which is now deprecated.
If you had any custom hook, it would be incredibly easy to migrate it to a plugin, as the APIs are 100% backward compatible.
Creating a plugin
A plugin is essentially a JavaScript object with a name and a series of hook functions.
An example plugin could look like this:
function loggerPlugin() {
return {
name: "logger",
beforeSearch: (orama, query) => {
console.log(
`About to search for ${query.term} on ZBSearch instance ${orama.id}`
);
},
};
}And you can then use it in your ZBSearch instance like this:
import { create, insert, search } from "zbsearch";
function loggerPlugin() {
return {
name: "logger",
beforeSearch: (orama, query) => {
console.log(
`About to search for ${query.term} on ZBSearch instance ${orama.id}`
);
},
};
}
const orama = create({
id: "my-instance", // Remember, IDs are automatically generated if not provided
schema: {
name: "string",
},
plugins: [loggerPlugin()],
});
insert(orama, { name: "John" });
search(orama, { term: "John" });
// Console logs: "About to search for john on ZBSearch instance my-instance"Every plugin should have:
- A
nameproperty, which is a string (mandatory) - Any hook function you want to use (optional)
When working with async hooks remember to always use the async keyword modifier.
async function afterInsertPluginExample() {
return {
name: "after-insert-plugin",
afterInsert: async (orama, id, document) => {
console.log("ZBSearch instance: ", orama);
console.log("Document id: ", id);
console.log("Document inserted: ", document);
},
};
}Plugin hooks
With v2.0.0-beta.5, we essentially moved the hooks from the components property of the ZBSearch instance to the plugins property.
The available hooks are:
beforeInsertafterInsertbeforeRemoveafterRemovebeforeUpdateafterUpdatebeforeSearchafterSearchbeforeInsertMultipleafterInsertMultiplebeforeRemoveMultipleafterRemoveMultiplebeforeUpdateMultipleafterUpdateMultiple
beforeInsert
Runs before an insert operation. Receives the ZBSearch instance, the document ID, and the entire document to be inserted as arguments.
function beforeInsertPluginExample() {
return {
name: "before-insert-plugin",
beforeInsert: (orama, id, document) => {
console.log("ZBSearch instance: ", orama);
console.log("Document id: ", id);
console.log("Document to be inserted: ", document);
},
};
}afterInsert
Runs after an insert operation. Receives the ZBSearch instance, the document ID, and the entire document as arguments.
function afterInsertPluginExample() {
return {
name: "after-insert-plugin",
afterInsert: (orama, id, document) => {
console.log("ZBSearch instance: ", orama);
console.log("Document id: ", id);
console.log("Document inserted: ", document);
},
};
}beforeRemove
Runs before a remove operation. Receives the ZBSearch instance and the document ID to be removed as arguments.
function beforeRemovePluginExample() {
return {
name: "before-remove-plugin",
beforeRemove: (orama, id) => {
console.log("ZBSearch instance: ", orama);
console.log("Document id: ", id);
},
};
}afterRemove
Runs after a remove operation. Receives the ZBSearch instance and the document ID removed as arguments.
function afterRemovePluginExample() {
return {
name: "after-remove-plugin",
afterRemove: (orama, id) => {
console.log("ZBSearch instance: ", orama);
console.log("Document id: ", id);
},
};
}beforeUpdate
Runs before an update operation. Receives the ZBSearch instance and the document ID to be updated as arguments.
function beforeUpdatePluginExample() {
return {
name: "before-update-plugin",
beforeUpdate: (orama, id) => {
console.log("ZBSearch instance: ", orama);
console.log("Document id: ", id);
},
};
}afterUpdate
Runs after an update operation. Receives the ZBSearch instance and the document ID as arguments.
function afterUpdatePluginExample() {
return {
name: "after-update-plugin",
afterUpdate: (orama, id) => {
console.log("ZBSearch instance: ", orama);
console.log("Document id: ", id);
},
};
}beforeSearch
Runs before a search operation. Receives the ZBSearch instance and the query object as arguments.
function beforeSearchPluginExample() {
return {
name: "before-search-plugin",
beforeSearch: (orama, query) => {
console.log("ZBSearch instance: ", orama);
console.log("Query: ", query);
},
};
}afterSearch
Runs after a search operation. Receives the ZBSearch instance, the query object, and the search results as arguments.
function afterSearchPluginExample() {
return {
name: "after-search-plugin",
afterSearch: (orama, query, result) => {
console.log("ZBSearch instance: ", orama);
console.log("Query: ", query);
console.log("Search result: ", result);
},
};
}beforeInsertMultiple
Runs before an insertMultiple operation. Receives the ZBSearch instance and the documents to be inserted as arguments.
Since the insertMultiple operation is calling the insert operation underneath,
the beforeInsertMultiple hook will be called for each document.
If there's an existing beforeInsert hook in the plugin, it will be called for each document as well.
function beforeInsertMultiplePluginExample() {
return {
name: "before-insert-multiple-plugin",
beforeInsertMultiple: (orama, documents) => {
console.log("ZBSearch instance: ", orama);
console.log("Documents to be inserted: ", documents);
},
};
}afterInsertMultiple
Runs after an insertMultiple operation. Receives the ZBSearch instance and the documents inserted as arguments.
Since the insertMultiple operation is calling the insert operation underneath,
the afterInsertMultiple hook will be called for each document.
If there's an existing afterInsert hook in the plugin, it will be called for each document as well.
function afterInsertMultiplePluginExample() {
return {
name: "after-insert-multiple-plugin",
afterInsertMultiple: (orama, documents) => {
console.log("ZBSearch instance: ", orama);
console.log("Documents inserted: ", documents);
},
};
}beforeRemoveMultiple
Runs before a removeMultiple operation. Receives the ZBSearch instance and the IDs of the documents to be removed as arguments.
Since the removeMultiple operation is calling the remove operation underneath,
the beforeRemoveMultiple hook will be called for each document.
If there's an existing beforeRemove hook in the plugin, it will be called for each document as well.
function beforeRemoveMultiplePluginExample() {
return {
name: "before-remove-multiple-plugin",
beforeRemoveMultiple: (orama, ids) => {
console.log("ZBSearch instance: ", orama);
console.log("Document IDs to be removed: ", ids);
},
};
}afterRemoveMultiple
Runs after a removeMultiple operation. Receives the ZBSearch instance and the IDs of the documents removed as arguments.
Since the removeMultiple operation is calling the remove operation underneath,
the afterRemoveMultiple hook will be called for each document.
If there's an existing afterRemove hook in the plugin, it will be called for each document as well.
function afterRemoveMultiplePluginExample() {
return {
name: "after-remove-multiple-plugin",
afterRemoveMultiple: (orama, ids) => {
console.log("ZBSearch instance: ", orama);
console.log("Document IDs removed: ", ids);
},
};
}beforeUpdateMultiple
Runs before an updateMultiple operation. Receives the ZBSearch instance and the IDs of the documents to be updated as arguments.
Since the updateMultiple operation is calling the update operation underneath,
the beforeUpdateMultiple hook will be called for each document.
If there's an existing beforeUpdate hook in the plugin, it will be called for each document as well.
Also, consider that the update operation is a shorthand for the remove and insert operations.
This means that the beforeRemove and beforeInsert hooks will be called for each document as well.
function beforeUpdateMultiplePluginExample() {
return {
name: "before-update-multiple-plugin",
beforeUpdateMultiple: (orama, ids) => {
console.log("ZBSearch instance: ", orama);
console.log("Document IDs to be updated: ", ids);
},
};
}afterUpdateMultiple
Runs after an updateMultiple operation. Receives the ZBSearch instance and the IDs of the documents updated as arguments.
Since the updateMultiple operation is calling the update operation underneath,
the afterUpdateMultiple hook will be called for each document.
If there's an existing afterUpdate hook in the plugin, it will be called for each document as well.
Also, consider that the update operation is a shorthand for the remove and insert operations.
This means that the afterRemove and afterInsert hooks will be called for each document as well.
function afterUpdateMultiplePluginExample() {
return {
name: "after-update-multiple-plugin",
afterUpdateMultiple: (orama, ids) => {
console.log("ZBSearch instance: ", orama);
console.log("Document IDs updated: ", ids);
},
};
}Migrating from hooks to plugins
If you were using the old hooks system, you can easily migrate to the new plugin system by moving your hooks to a single plugin.
For instance, if you had a beforeInsert hook, you can migrate it to a plugin like this:
import { create } from 'zbsearch'
const db = create({
schema: {
name: 'string'
},
- components: {
- beforeInsert: (orama, id, document) => {
- console.log('ZBSearch instance: ', orama)
- console.log('Document id: ', id)
- console.log('Document to be inserted: ', document)
- }
- }
+ plugins: [
+ {
+ name: 'before-insert-plugin',
+ beforeInsert: (orama, id, document) => {
+ console.log('ZBSearch instance: ', orama)
+ console.log('Document id: ', id)
+ console.log('Document to be inserted: ', document)
+ }
+ }
+ ]
})Types, behavior, and arguments are 100% backward compatible, so you don't need to change anything else.