
Research
2025 Report: Destructive Malware in Open Source Packages
Destructive malware is rising across open source registries, using delays and kill switches to wipe code, break builds, and disrupt CI/CD.
cloudant-follow
Advanced tools
This is a fork of the Iris Couch follow project.
This fork is maintained by IBM Cloudant in order to provide fixes for the nodejs-cloudant library.
This looks much like the request API.
var follow = require('cloudant-follow');
follow("https://example.iriscouch.com/boogie", function(error, change) {
if(!error) {
console.log("Got change number " + change.seq + ": " + change.id);
}
})
The error parameter to the callback will basically always be null.
The API must be very simple: notify me every time a change happens in the DB. Also, never fail.
If an error occurs, Follow will internally retry without notifying your code.
Specifically, this should be possible:
If CouchDB permanently crashes, there is an option of failure modes:
If the db url ends with /_db_updates, Follow will provide a
_db_updates feed.
For each change, Follow will emit a change event containing:
type: created, updated or deleted.db_name: Name of the database where the change occoured.ok: Event operation status (boolean).Note that this feature is available as of CouchDB 1.4.
The first argument is an options object. The only required option is db. Instead of an object, you can use a string to indicate the db value.
follow({db:"https://example.iriscouch.com/boogie", include_docs:true}, function(error, change) {
if(!error) {
console.log("Change " + change.seq + " has " + Object.keys(change.doc).length + " fields");
}
})
All of the CouchDB _changes options are allowed. See http://guide.couchdb.org/draft/notifications.html.
db | Fully-qualified URL of a couch database. (Basic auth URLs are ok.)since | The sequence number to start from. Use "now" to start from the latest change in the DB.heartbeat | Milliseconds within which CouchDB must respond (default: 30000 or 30 seconds)feed | Optional but only "continuous" is allowedfilter |
app/importantfunction(doc, req) { ... } which should return true or falseview | a path to design document view, e.g. app/myViewquery_params | Optional for use in with filter functions, passed as req.query to the filter functionBesides the CouchDB options, more are available:
headers | Object with HTTP headers to add to the requestinactivity_ms | Maximum time to wait between changes. Omitting this means no maximum.max_retry_seconds | Maximum time to wait between retries (default: 360 seconds)initial_retry_delay | Time to wait before the first retry, in milliseconds (default 1000 milliseconds)response_grace_time | Extra time to wait before timing out, in milliseconds (default 5000 milliseconds)httpAgent | Specify a custom HTTP agent to use for all requests (default: request).The main API is a thin wrapper around the EventEmitter API.
var follow = require('cloudant-follow');
var opts = {}; // Same options paramters as before
var feed = new follow.Feed(opts);
// You can also set values directly.
feed.db = "http://example.iriscouch.com/boogie";
feed.since = 3;
feed.heartbeat = 30 * 1000
feed.inactivity_ms = 86400 * 1000;
feed.filter = function(doc, req) {
// req.query is the parameters from the _changes request and also feed.query_params.
console.log('Filtering for query: ' + JSON.stringify(req.query));
if(doc.stinky || doc.ugly)
return false;
return true;
}
feed.on('change', function(change) {
console.log('Doc ' + change.id + ' in change ' + change.seq + ' is neither stinky nor ugly.');
})
feed.on('error', function(er) {
console.error('Since Follow always retries on errors, this must be serious');
throw er;
})
feed.follow();
A Follow feed is a Node.js stream. If you get lots of changes and processing them takes a while, use .pause() and .resume() as needed. Pausing guarantees that no new events will fire. Resuming guarantees you'll pick up where you left off.
follow("https://example.iriscouch.com/boogie", function(error, change) {
var feed = this
if(change.seq == 1) {
console.log('Uh oh. The first change takes 30 hours to process. Better pause.')
feed.pause()
setTimeout(function() { feed.resume() }, 30 * 60 * 60 * 1000)
}
// ... 30 hours with no events ...
else
console.log('No need to pause for normal change: ' + change.id)
})
The feed object is an EventEmitter. There are a few ways to get a feed object:
follow()follow(), the this variable is bound to the feed object.Once you've got one, you can subscribe to these events:
function(req) | The database confirmation request is sent; passed the request objectfunction(db_obj) | The database is confirmed; passed the couch database objectfunction(change) | A change occured; passed the change object from CouchDBfunction(seq_id) | The feed has caught up to the update_seq from the confirm step. Assuming no subsequent changes, you have seen all the data.function(info) | Follow did not receive a heartbeat from couch in time. The passed object has .elapsed_ms set to the elapsed timefunction(info) | A retry is scheduled (usually after a timeout or disconnection). The passed object has
.since the current sequence id.after the milliseconds to wait before the request occurs (on an exponential fallback schedule).db the database url (scrubbed of basic auth credentials)feed.stop()function(err) | An error occursFollow is happy to retry over and over, for all eternity. It will only emit an error if it thinks your whole application might be in trouble.
Follow uses node-tap. If you clone this Git repository, tap is included.
$ ./node_modules/.bin/tap test/*.js test/issues/*.js
ok test/couch.js ...................................... 11/11
ok test/follow.js ..................................... 69/69
ok test/issues.js ..................................... 44/44
ok test/stream.js ................................... 300/300
ok test/issues/10.js .................................. 11/11
total ............................................... 435/435
ok
Apache 2.0
FAQs
Extremely robust, fault-tolerant Cloudant/CouchDB changes follower
We found that cloudant-follow demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
Destructive malware is rising across open source registries, using delays and kill switches to wipe code, break builds, and disrupt CI/CD.

Security News
Socket CTO Ahmad Nassri shares practical AI coding techniques, tools, and team workflows, plus what still feels noisy and why shipping remains human-led.

Research
/Security News
A five-month operation turned 27 npm packages into durable hosting for browser-run lures that mimic document-sharing portals and Microsoft sign-in, targeting 25 organizations across manufacturing, industrial automation, plastics, and healthcare for credential theft.