docs/_includes/api/plugins.html
{% include anchor.html edit="true" title="Plugins" hash="plugins" %} {% include alert/start.html variant="info"%} {% markdown %} **This section covers _authoring_ plugins.** For a list of third-party plugins, see Plugins, or for a list of first-party plugins that you can use to customize the PouchDB build, see Custom Builds. {% endmarkdown %} {% include alert/end.html%} Writing a plugin is easy! The API is: {% highlight "js" %} PouchDB.plugin({ methodName: myFunction }); {% endhighlight %} This will add a db.methodName() to all databases, which runs myFunction.It will always be called in context, so that within the function, this refers to the database object. There is a PouchDB Plugin Seed project, which is the fastest way to get started writing, building and testing your very own plugin. #### Example Usage: {% highlight "js" %} PouchDB.plugin({ sayHello : function () { console.log("Hello!"); } }); new PouchDB('foobar').sayHello(); // prints "Hello!" {% endhighlight %} Alternatively, instead of passing in an object to .plugin(), you can pass in a function that takes the PouchDB object and performs whatever operations you want on it. You can use this to load multiple plugins, add adapters, or attach event listeners to the PouchDB object. #### Example Usage: {% highlight "js" %} PouchDB.plugin(function (PouchDB) { PouchDB.hello = 'world'; }); console.log(PouchDB.hello); // prints "world" {% endhighlight %} (Most likely, if you are writing a PouchDB plugin, you will export either the object-style or the function-style plugin, so that your users can then attach it to their PouchDB object.) #### Load Plugins from require() You can load plugins into PouchDB when you load it via require(). {% highlight "js" %} const greet = {sayHello: function() { console.log("Hello!"); }}; const PouchDB = require('pouchdb').plugin(greet); const db = new PouchDB('foobar'); db.sayHello(); // prints "Hello!" {% endhighlight %} You can chain plugins, as well: {% highlight "js" %} const greet = {sayHello: function() { console.log("Hello!"); }}; const manners = {thank: function(name) { console.log("Thank you, " + name); }}; const PouchDB = require('pouchdb') .plugin(greet) .plugin(manners); const db = new PouchDB('foobar'); db.sayHello(); // prints "Hello!" db.thank('Mom'); // prints "Thank you, Mom" {% endhighlight %} #### Example Plugin: Intercept Updates A useful feature of plugins is to intercept updates before they are stored in PouchDB. In this way, a plugin might validate that the data is correct for the application, or even alter documents before they are committed to the database. The best way to intercept all updates to a PouchDB database is to **override the bulkDocs() method**. All changes to PouchDB documents ultimately pass through the bulkDocs() method. For example, a call to put() will become a bulkDocs() call with a "batch" of one document. Because PouchDB guarantees to plugin authors that all data changes ultimately happen via bulkDocs(), it is the ideal place for an application or plugin to intercept updates. {% highlight "js" %} // Keep a reference to the "upstream" function. const pouchBulkDocs = PouchDB.prototype.bulkDocs; PouchDB.plugin({bulkDocs: validBulkDocs}); function validBulkDocs(body, options, callback) { if (typeof options == 'function') { callback = options options = {} } let docs; if (Array.isArray(body)) { docs = body; } else { docs = body.docs; } // All documents must have a .name field. for (let i = 0; i < docs.length; i++) { if (!docs[i].name) { const id = doc._id || '(no _id given)'; return callback(new Error('Document is missing .name field: ' + id)); } } // All documents check out. Pass them to PouchDB. return pouchBulkDocs.call(this, docs, options, callback); } {% endhighlight %} The above plugin would return an error if anything ever attempts to store an unnamed document, including documents which change during replication. Note: this is a very, very simple validation example. It does not behave, for example, like the Apache CouchDB validate_doc_update() API.