{% 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](/external.html), or for a list of first-party plugins that you can
use to customize the PouchDB build, see [Custom Builds](/custom.html).

{% 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](https://github.com/pouchdb/plugin-seed), 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.
