Socket
Socket
Sign inDemoInstall

follow

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

follow - npm Package Compare versions

Comparing version 0.1.0 to 0.2.0

browser/eventemitter2.js

13

api.js
// The changes_couchdb API
//
// Copyright 2011 Iris Couch
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

@@ -4,0 +17,0 @@ var feed = require('./feed');

107

cli.js
#!/usr/bin/env node
// The changes_couchdb command-line interface.
// The follow command-line interface.
//
// Copyright 2011 Iris Couch
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

@@ -9,46 +22,70 @@ var lib = require('./lib')

function usage() {
console.log([ 'usage: changes_couchdb <URL>'
, ''
].join("\n"));
function puts(str) {
process.stdout.write(str + "\n");
}
var db = process.argv[2];
if(! /^https?:\/\//.test(db))
db = 'http://' + db;
function main() {
var db = require.isBrowser ? (process.env.db || '/_users') : process.argv[2];
puts('Watching: ' + db);
console.log('Watching:', db);
var feed = new couch_changes.Feed();
feed.db = db;
feed.since = (process.env.since === 'now') ? 'now' : parseInt(process.env.since || '0');
var feed = new couch_changes.Feed();
feed.db = db;
feed.since = (process.env.since === 'now') ? 'now' : parseInt(process.env.since || '0');
feed.heartbeat = parseInt(process.env.heartbeat || '3000');
feed.heartbeat = (process.env.heartbeat || '3000').replace(/s$/, '000');
feed.heartbeat = parseInt(feed.heartbeat);
if(process.env.host)
feed.headers.host = process.env.host;
if(require.isBrowser)
feed.feed = 'longpoll';
if(process.env.host)
feed.headers.host = process.env.host;
if(process.env.inactivity)
feed.inactivity_ms = parseInt(process.env.inactivity);
if(process.env.filter)
feed.filter = process.env.filter;
if(process.env.limit)
feed.limit = parseInt(process.env.limit);
if(process.env.inactivity)
feed.inactivity_ms = parseInt(process.env.inactivity);
feed.on('confirm', function() {
puts('Database confirmed: ' + db);
})
feed.filter = function(doc, req) {
// This is a local filter. It runs on the client side.
return true;
}
feed.on('change', function(change) {
puts('Change:' + JSON.stringify(change));
})
feed.on('change', function(change) {
console.log('Change:' + JSON.stringify(change));
})
feed.on('timeout', function(state) {
var seconds = state.elapsed_ms / 1000;
var hb = state.heartbeat / 1000;
puts('Timeout after ' + seconds + 's inactive, heartbeat=' + hb + 's');
})
feed.on('error', function(er) {
//console.error(er);
console.error('Changes error ============\n' + er.stack);
setTimeout(function() { process.exit(0) }, 100);
})
feed.on('retry', function(state) {
if(require.isBrowser)
puts('Long polling since ' + state.since);
else
puts('Retry since ' + state.since + ' after ' + state.after + 'ms');
})
process.on('uncaughtException', function(er) {
console.log('========= UNCAUGHT EXCEPTION; This is bad');
console.log(er.stack);
setTimeout(function() { process.exit(1) }, 100);
})
feed.on('response', function() {
puts('Streaming response:');
})
feed.follow();
feed.on('error', function(er) {
//console.error(er);
console.error('Changes error ============\n' + er.stack);
setTimeout(function() { process.exit(0) }, 100);
})
process.on('uncaughtException', function(er) {
puts('========= UNCAUGHT EXCEPTION; This is bad');
puts(er.stack);
setTimeout(function() { process.exit(1) }, 100);
})
feed.follow();
}
exports.main = main;
if(!require.isBrowser && process.argv[1] == module.filename)
main();
// Core routines for event emitters
//
// Copyright 2011 Iris Couch
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
var lib = require('./lib')
, url = require('url')
, util = require('util')
, events = require('events')
, request = require('request')

@@ -18,8 +31,7 @@ , querystring = require('querystring')

var SUPER_CLASS = require('events').EventEmitter;
//var SUPER_CLASS = require('stream').Stream;
var EventEmitter = events.EventEmitter2 || events.EventEmitter;
function Feed (opts) {
var self = this;
SUPER_CLASS.call(self);
EventEmitter.call(self);

@@ -63,3 +75,3 @@ self.feed = 'continuous';

} // Feed
util.inherits(Feed, SUPER_CLASS);
util.inherits(Feed, EventEmitter);

@@ -73,4 +85,4 @@ Feed.prototype.start =

if(self.feed !== 'continuous')
throw new Error('The only valid feed option is "continuous"');
if(self.feed !== 'continuous' && self.feed !== 'longpoll')
throw new Error('The only valid feed options are "continuous" and "longpoll"');

@@ -80,6 +92,6 @@ if(typeof self.heartbeat !== 'number')

var parsed = url.parse(self.db);
self.log = lib.log4js().getLogger(parsed.hostname + parsed.pathname);
self.log.setLevel(process.env.changes_level || "info");
self.log = lib.log4js().getLogger(self.db);
self.log.setLevel(process.env.log || "info");
self.emit('start');
return self.confirm();

@@ -94,3 +106,2 @@ }

self.log.debug('Checking database: ' + self.db_safe);
self.emit('confirm');

@@ -128,2 +139,3 @@ var confirm_timeout = self.heartbeat * 3; // Give it time to look up the name, connect, etc.

self.emit('confirm');
return self.query();

@@ -145,2 +157,12 @@ })

if(typeof self.filter === 'function' && !query_params.include_docs) {
self.log.debug('Enabling include_docs for client-side filter');
query_params.include_docs = true;
}
// Limit the response size for longpoll.
var poll_size = 100;
if(query_params.feed == 'longpoll' && (!query_params.limit || query_params.limit > poll_size))
query_params.limit = poll_size;
var feed_url = self.db + '/_changes?' + querystring.stringify(query_params);

@@ -173,3 +195,3 @@

function on_response(er, resp) {
function on_response(er, resp, body) {
clearTimeout(timeout_id);

@@ -196,3 +218,5 @@

self.retry_delay = INITIAL_RETRY_DELAY;
return self.prep(in_flight);
self.emit('response');
return self.prep(in_flight, body);
}

@@ -212,3 +236,3 @@

Feed.prototype.prep = function prep_request(req) {
Feed.prototype.prep = function prep_request(req, body) {
var self = this;

@@ -222,2 +246,36 @@

// The inactivity timer is for time between *changes*, or time between the
// initial connection and the first change. Therefore it goes here.
self.change_at = now;
if(self.inactivity_ms) {
clearTimeout(self.inactivity_timer);
self.inactivity_timer = setTimeout(function() { self.on_inactivity() }, self.inactivity_ms);
}
var a, change;
if(body) {
// Some changes are already in the body.
try {
body = JSON.parse(body);
} catch(er) {
return self.die(er);
}
body.results = body.results || [];
for(a = 0; a < body.results.length; a++) {
change = body.results[a];
if(!change.seq)
return self.die(new Error('Change has no .seq field: ' + json));
self.on_change(change);
}
return self.retry();
}
var handlers = ['data', 'end', 'error'];
handlers.forEach(function(ev) {
req.on(ev, handler_for(ev));
})
return self.wait();
function handler_for(ev) {

@@ -227,2 +285,3 @@ var name = 'on_couch_' + ev;

return handle_confirmed_req_event;
function handle_confirmed_req_event() {

@@ -254,18 +313,3 @@ if(self.pending.request === req)

}
return handle_confirmed_req_event;
}
var handlers = ['data', 'end', 'error'];
handlers.forEach(function(ev) {
req.on(ev, handler_for(ev));
})
// The inactivity timer is for time between *changes*, or time between the
// initial connection and the first change. Therefore it goes here.
self.change_at = now;
if(self.inactivity_ms)
self.inactivity_timer = setTimeout(function() { self.on_inactivity() }, self.inactivity_ms);
return self.wait();
}

@@ -339,6 +383,14 @@

var elapsed_ms = now - self.pending.activity_at;
self.log.warn('Closing req ' + self.pending.request.id() + ' for timeout after ' + elapsed_ms + 'ms; heartbeat=' + self.heartbeat);
self.emit('timeout', {elapsed_ms:elapsed_ms, heartbeat:self.heartbeat, id:self.pending.request.id});
/*
var msg = ' for timeout after ' + elapsed_ms + 'ms; heartbeat=' + self.heartbeat;
if(!self.pending.request.id)
self.log.warn('Closing req (no id) ' + msg + ' req=' + util.inspect(self.pending.request));
else
self.log.warn('Closing req ' + self.pending.request.id() + msg);
*/
return destroy_req(self.pending.request);
//return self.retry();
}

@@ -352,4 +404,4 @@

self.log.info('Retrying since=' + self.since + ' after ' + self.retry_delay + 'ms: ' + self.db_safe);
self.emit('retry');
self.log.debug('Retrying since=' + self.since + ' after ' + self.retry_delay + 'ms: ' + self.db_safe);
self.emit('retry', {since:self.since, after:self.retry_delay, db:self.db_safe});

@@ -379,8 +431,8 @@ setTimeout(function() { self.query() }, self.retry_delay);

Feed.prototype.stop =
Feed.prototype.die = function(er) {
var self = this;
self.log.fatal('Fatal error: ' + er.stack);
self.emit('error', er);
if(er)
self.log.fatal('Fatal error: ' + er.stack);

@@ -394,3 +446,5 @@ var req = self.pending.request;

//throw er;
self.emit('stop', er);
if(er)
self.emit('error', er);
}

@@ -412,5 +466,16 @@

var req = { 'query': lib.JDUP(self.pending.request.changes_query) };
var f_change = lib.JDUP(change); // Don't let the filter mutate the real data.
var result = self.filter.apply(null, [f_change, req]);
if(!change.doc)
return self.die(new Error('Internal filter needs .doc in change ' + change.seq));
// Don't let the filter mutate the real data.
var doc = lib.JDUP(change.doc);
var req = lib.JDUP({'query': self.pending.request.changes_query});
var result = false;
try {
result = self.filter.apply(null, [doc, req]);
} catch (er) {
self.log.debug('Filter error', er);
}
result = (result && true) || false;

@@ -466,4 +531,9 @@ if(result) {

response.connection.end();
response.connection.destroy();
if(typeof response.abort === 'function')
response.abort();
if(response.connection) {
response.connection.end();
response.connection.destroy();
}
}

@@ -0,1 +1,15 @@

// Copyright 2011 Iris Couch
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
exports.scrub_creds = function scrub_creds(url) {

@@ -10,3 +24,7 @@ return url.replace(/^(https?:\/\/)[^:]+:[^@]+@(.*)$/, '$1$2'); // Scrub username and password

// Wrap log4js so it will not be a dependency.
var VERBOSE = (process.env.verbose === 'true');
var VERBOSE;
if(require.isBrowser)
VERBOSE = true;
else
verbose = (process.env.verbose === 'true');

@@ -27,2 +45,6 @@ var noop = function() {};

} catch(e) {
exports.log4js = null;
}
if(typeof exports.log4js !== 'function')
exports.log4js = function() {

@@ -32,2 +54,1 @@ return { 'getLogger': function() { return noops }

}
}
{ "name": "follow"
, "version": "0.1.0"
, "version": "0.2.0"
, "author": { "name": "Jason Smith"

@@ -13,2 +13,3 @@ , "email": "jhs@iriscouch.com" }

, "main": "api"
, "bin": {"follow": "./cli.js"}
}

@@ -32,4 +32,4 @@ # Follow: CouchDB changes notifier for NodeJS

var follow_couchdb = require('follow_couchdb');
follow_couchdb("https://example.iriscouch.com/boogie", function(error, change) {
var follow = require('follow');
follow("https://example.iriscouch.com/boogie", function(error, change) {
if(!error) {

@@ -44,3 +44,3 @@ console.log("Got change number " + change.seq + ": " + change.id);

follow_couchdb({db:"https://example.iriscouch.com/boogie", include_docs:true}, function(error, change) {
follow({db:"https://example.iriscouch.com/boogie", include_docs:true}, function(error, change) {
if(!error) {

@@ -51,5 +51,5 @@ console.log("Change " + change.seq + " has " + Object.keys(change.doc).length + " fields");

### follow_couchdb(options, callback)
### follow(options, callback)
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.
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.

@@ -75,6 +75,6 @@ All of the CouchDB _changes options are allowed. See http://guide.couchdb.org/draft/notifications.html.

var follow_couchdb = require('follow_couchdb');
var follow = require('follow');
var opts = {}; // Same options paramters as before
var feed = new follow_couchdb.Feed(opts);
var feed = new follow.Feed(opts);

@@ -81,0 +81,0 @@ // You can also set values directly.

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc