Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

cloudant

Package Overview
Dependencies
Maintainers
4
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cloudant - npm Package Compare versions

Comparing version 1.8.0 to 1.9.0

.eslintignore

7

CHANGES.md

@@ -1,4 +0,9 @@

# UNRELEASED
# 1.9.0 (2017-10-20)
- [NEW] Add 'error' & 'response' events to 429 retry plugin stream.
- [FIXED] `{silent: true}` to dotenv to prevent `.env` warnings.
- [UPGRADED] Upgrade package: cloudant-nano@6.6.0.
- [UPGRADED] Upgrade package: debug@^3.1.0.
- [UPGRADED] Upgrade package: request@^2.81.0.
# 1.8.0 (2017-05-23)
- [UPGRADED] Using cloudant-nano==6.5.0 dependancy.

215

cloudant.js

@@ -0,17 +1,18 @@

// Copyright © 2015, 2017 IBM Corp. All rights reserved.
//
// 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.
'use strict';
module.exports = Cloudant;
/**
* Copyright (c) 2016 IBM Cloudant, Inc. All rights reserved.
*
* 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 Nano = require('cloudant-nano');

@@ -22,7 +23,6 @@ var debug = require('debug')('cloudant');

// function from the old Cloudant library to
// parse an object { account: "myaccount", password: "mypassword"}
// and return a URL
var reconfigure = require('./lib/reconfigure.js')
var reconfigure = require('./lib/reconfigure.js');

@@ -42,6 +42,12 @@ // This IS the Cloudant API. It is mostly nano, with a few functions.

var pkg = require('./package.json');
var useragent = "nodejs-cloudant/" + pkg.version + " (Node.js " + process.version + ")";
var requestDefaults = { headers: { "User-agent": useragent}, gzip:true };
var requestDefaults = {
gzip: true,
headers: {
// set library UA header
'User-Agent': `nodejs-cloudant/${pkg.version} (Node.js ${process.version})`
},
jar: false
};
var theurl = null;
if (typeof options == "object") {
if (typeof options === 'object') {
if (options.requestDefaults) {

@@ -52,9 +58,9 @@ requestDefaults = options.requestDefaults;

} else {
theurl = reconfigure({ url: options})
theurl = reconfigure({ url: options });
}
if (theurl === null) {
if (callback) {
return callback('invalid url', null);
return callback('invalid url', null); // eslint-disable-line standard/no-callback-literal
} else {
throw(new Error('invalid url'));
throw (new Error('invalid url'));
}

@@ -65,6 +71,10 @@ }

if (requestDefaults && !requestDefaults.agent) {
var protocol = (theurl.match(/^https/))? require('https') : require('http');
var agent = new protocol.Agent({ keepAlive:true });
var protocol = (theurl.match(/^https/)) ? require('https') : require('http');
var agent = new protocol.Agent({
keepAlive: true,
keepAliveMsecs: 30000,
maxSockets: 6
});
requestDefaults.agent = agent;
}
}

@@ -75,7 +85,7 @@ // plugin a request library

options.requestDefaults = requestDefaults;
if(typeof options.plugin === 'string') {
if (typeof options.plugin === 'string') {
var plugintype = options.plugin || 'default';
debug('Using the "' + plugintype + '" plugin');
plugin = require('./plugins/' + plugintype)(options);
} else if (typeof options.plugin === 'function') {
plugin = require('./plugins/' + plugintype)(options);
} else if (typeof options.plugin === 'function') {
debug('Using a custom plugin');

@@ -87,3 +97,3 @@ plugin = options.plugin;

debug('Create underlying Nano instance, options=%j requestDefaults=%j', options, requestDefaults);
var nano = Nano({url:theurl, request: plugin, requestDefaults: requestDefaults, cookie: cookie, log: nanodebug});
var nano = Nano({url: theurl, request: plugin, requestDefaults: requestDefaults, cookie: cookie, log: nanodebug});

@@ -93,3 +103,2 @@ // our own implementation of 'use' e.g. nano.use or nano.db.use

var use = function(db) {
// ****************

@@ -99,6 +108,6 @@ // Functions added to each db e.g. cloudant.use("mydb")

var bulk_get = function(options, callback) {
return nano.request( { path: encodeURIComponent(db) + "/_bulk_get",
method: "post",
body: options }, callback)
var bulk_get = function(options, callback) { // eslint-disable-line camelcase
return nano.request({ path: encodeURIComponent(db) + '/_bulk_get',
method: 'post',
body: options }, callback);
};

@@ -108,20 +117,20 @@

var geo = function(docName, indexName, query, callback) {
var path = encodeURIComponent(db) + "/_design/" +
encodeURIComponent(docName) + "/_geo/" +
var path = encodeURIComponent(db) + '/_design/' +
encodeURIComponent(docName) + '/_geo/' +
encodeURIComponent(indexName);
return nano.request({path:path, qs:query}, callback);
return nano.request({path: path, qs: query}, callback);
};
// https://docs.cloudant.com/api.html#viewing-permissions
var get_security = function(callback) {
var path = "_api/v2/db/" + encodeURIComponent(db) + "/_security";
return nano.request( { path: path}, callback);
var get_security = function(callback) { // eslint-disable-line camelcase
var path = '_api/v2/db/' + encodeURIComponent(db) + '/_security'; // eslint-disable-line camelcase
return nano.request({ path: path }, callback);
};
// https://docs.cloudant.com/api.html#modifying-permissions
var set_security = function(permissions, callback) {
var path = "_api/v2/db/" + encodeURIComponent(db) + "/_security";
return nano.request( { path: path,
method: "put",
body: {cloudant: permissions} }, callback);
var set_security = function(permissions, callback) { // eslint-disable-line camelcase
var path = '_api/v2/db/' + encodeURIComponent(db) + '/_security';
return nano.request({ path: path,
method: 'put',
body: {cloudant: permissions} }, callback);
};

@@ -132,12 +141,11 @@

var index = function(definition, callback) {
// if no definition is provided, then the user wants see all the indexes
if (typeof definition == "function") {
if (typeof definition === 'function') {
callback = definition;
nano.request({ path: encodeURIComponent(db) + "/_index" }, callback);
nano.request({ path: encodeURIComponent(db) + '/_index' }, callback);
} else {
// the user wants to create a new index
return nano.request({ path: encodeURIComponent(db) + "/_index",
method:"post",
body: definition}, callback);
return nano.request({ path: encodeURIComponent(db) + '/_index',
method: 'post',
body: definition}, callback);
}

@@ -147,14 +155,12 @@ };

// https://docs.cloudant.com/api.html#deleting-an-index
var index_del = function(spec, callback) {
var index_del = function(spec, callback) { // eslint-disable-line camelcase
spec = spec || {};
if (!spec.ddoc)
throw new Error('index.del() must specify a "ddoc" value');
if (!spec.name)
throw new Error('index.del() must specify a "name" value');
if (!spec.ddoc) { throw new Error('index.del() must specify a "ddoc" value'); }
if (!spec.name) { throw new Error('index.del() must specify a "name" value'); }
var type = spec.type || 'json';
var path = encodeURIComponent(db) + "/_index/" +
encodeURIComponent(spec.ddoc) + "/" +
encodeURIComponent(type) + "/" +
var path = encodeURIComponent(db) + '/_index/' +
encodeURIComponent(spec.ddoc) + '/' +
encodeURIComponent(type) + '/' +
encodeURIComponent(spec.name);
return nano.request({ path:path, method:"delete"}, callback);
return nano.request({ path: path, method: 'delete' }, callback);
};

@@ -164,5 +170,5 @@

var find = function(query, callback) {
return nano.request( { path: encodeURIComponent(db) + "/_find",
method: "post",
body: query}, callback);
return nano.request({ path: encodeURIComponent(db) + '/_find',
method: 'post',
body: query}, callback);
};

@@ -173,7 +179,7 @@

obj.geo = geo;
obj.bulk_get = bulk_get;
obj.get_security = get_security;
obj.set_security = set_security;
obj.bulk_get = bulk_get; // eslint-disable-line camelcase
obj.get_security = get_security; // eslint-disable-line camelcase
obj.set_security = set_security; // eslint-disable-line camelcase
obj.index = index;
obj.index.del = index_del;
obj.index.del = index_del; // eslint-disable-line camelcase
obj.find = find;

@@ -188,23 +194,22 @@

// https://docs.cloudant.com/api.html#creating-api-keys
var generate_api_key = function(callback) {
return nano.request({path: "_api/v2/api_keys", method: "post" }, callback);
var generate_api_key = function(callback) { // eslint-disable-line camelcase
return nano.request({ path: '_api/v2/api_keys', method: 'post' }, callback);
};
// https://docs.cloudant.com/api.html#reading-the-cors-configuration
var get_cors = function(callback) {
return nano.request({path: "_api/v2/user/config/cors" }, callback);
var get_cors = function(callback) { // eslint-disable-line camelcase
return nano.request({ path: '_api/v2/user/config/cors' }, callback);
};
// https://docs.cloudant.com/api.html#setting-the-cors-configuration
var set_cors = function(configuration, callback) {
return nano.request({path: "_api/v2/user/config/cors",
method: "put",
body: configuration }, callback);
var set_cors = function(configuration, callback) { // eslint-disable-line camelcase
return nano.request({path: '_api/v2/user/config/cors',
method: 'put',
body: configuration }, callback);
};
// the /set_permissions API call is deprecated
var set_permissions = function(opts, callback) {
console.error("set_permissions is deprecated. use set_security instead");
var set_permissions = function(opts, callback) { // eslint-disable-line camelcase
console.error('set_permissions is deprecated. use set_security instead');
callback(null, null);

@@ -214,23 +219,23 @@ };

// https://docs.cloudant.com/api.html#setting-the-cors-configuration
var set_cors = function(configuration, callback) {
return nano.request({path: "_api/v2/user/config/cors",
method: "put",
body: configuration }, callback);
set_cors = function(configuration, callback) { // eslint-disable-line camelcase
return nano.request({path: '_api/v2/user/config/cors',
method: 'put',
body: configuration }, callback);
};
var get_virtual_hosts = function(callback) {
return nano.request({path: "_api/v2/user/virtual_hosts",
method: "get"}, callback);
var get_virtual_hosts = function(callback) { // eslint-disable-line camelcase
return nano.request({path: '_api/v2/user/virtual_hosts',
method: 'get'}, callback);
};
var add_virtual_host = function(opts, callback) {
return nano.request({path: "_api/v2/user/virtual_hosts",
method: "post",
body: opts }, callback);
var add_virtual_host = function(opts, callback) { // eslint-disable-line camelcase
return nano.request({path: '_api/v2/user/virtual_hosts',
method: 'post',
body: opts }, callback);
};
var delete_virtual_host = function(opts, callback) {
return nano.request({path: "_api/v2/user/virtual_hosts",
method: "delete",
body: opts }, callback);
var delete_virtual_host = function(opts, callback) { // eslint-disable-line camelcase
return nano.request({path: '_api/v2/user/virtual_hosts',
method: 'delete',
body: opts }, callback);
};

@@ -240,9 +245,9 @@

nano.ping = ping;
nano.get_cors = get_cors;
nano.set_cors = set_cors;
nano.set_permissions = set_permissions;
nano.generate_api_key = generate_api_key;
nano.get_virtual_hosts = get_virtual_hosts;
nano.add_virtual_host = add_virtual_host;
nano.delete_virtual_host = delete_virtual_host;
nano.get_cors = get_cors; // eslint-disable-line camelcase
nano.set_cors = set_cors; // eslint-disable-line camelcase
nano.set_permissions = set_permissions; // eslint-disable-line camelcase
nano.generate_api_key = generate_api_key; // eslint-disable-line camelcase
nano.get_virtual_hosts = get_virtual_hosts; // eslint-disable-line camelcase
nano.add_virtual_host = add_virtual_host; // eslint-disable-line camelcase
nano.delete_virtual_host = delete_virtual_host; // eslint-disable-line camelcase

@@ -290,15 +295,13 @@ if (callback) {

});
},
},
function(done) {
nano.relax({db:''}, function(e, b, h) {
nano.relax({db: ''}, function(e, b, h) {
done(e, b);
})
});
}
], function(err, data) {
var body = (data && data[2]) || {};
body.userCtx = (data && data[1] && data[1].userCtx) || {};
body.userCtx = (data && data[1] && data[1].userCtx) || {};
callback(err, body, cookie);
});
}

@@ -1,2 +0,17 @@

// reconfigure deals with the various ways the credentials can be passed in
// Copyright © 2015, 2017 IBM Corp. All rights reserved.
//
// 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.
'use strict';
// reconfigure deals with the various ways the credentials can be passed in
// and returns an full URL

@@ -14,5 +29,5 @@ // e.g. { account:"myaccount", password: "mypassword"}

module.exports = function(config) {
config = JSON.parse(JSON.stringify(config)); //clone
config = JSON.parse(JSON.stringify(config)); // clone
var outUrl;
var outUrl;
// if a full URL is passed in

@@ -23,35 +38,32 @@ if (config.url) {

try {
var parsed = url.parse(config.url);
} catch(e) {
parsed = url.parse(config.url);
} catch (e) {
parsed = null;
};
}
if (!config.url || !parsed || !parsed.hostname || !parsed.protocol || !parsed.slashes) {
return null;
}
// enforce HTTPS for *cloudant.com domains
if (parsed.hostname.match(/cloudant\.com$/) && parsed.protocol == "http:") {
console.warn("WARNING: You are sending your password as plaintext over the HTTP; switching to HTTPS");
if (parsed.hostname.match(/cloudant\.com$/) && parsed.protocol === 'http:') {
console.warn('WARNING: You are sending your password as plaintext over the HTTP; switching to HTTPS');
// force HTTPS
parsed.protocol = 'https:';
// remove port number and path
parsed.host = parsed.host.replace(/:[0-9]*$/,'');
delete parsed.port;
parsed.host = parsed.host.replace(/:[0-9]*$/, '');
delete parsed.port;
delete parsed.pathname;
delete parsed.path;
// reconstruct the URL
config.url = url.format(parsed);
}
outUrl = config.url;
} else if (config.vcapServices) {
cloudantServices = config.vcapServices.cloudantNoSQLDB;
var cloudantServices = config.vcapServices.cloudantNoSQLDB;
if (!cloudantServices || cloudantServices.length == 0) {
if (!cloudantServices || cloudantServices.length === 0) {
throw new Error('Missing Cloudant service in vcapServices');

@@ -61,3 +73,3 @@ }

for (var i = 0; i < cloudantServices.length; i++) {
if (config.instanceName == undefined || cloudantServices[i].name == config.instanceName) {
if (config.instanceName === undefined || cloudantServices[i].name === config.instanceName) {
var credentials = cloudantServices[i].credentials;

@@ -76,3 +88,2 @@ if (credentials && credentials.url) {

}
} else {

@@ -83,4 +94,3 @@ // An account can be just the username, or the full cloudant URL.

config.account.match(/([^.]+)\.cloudant\.com/);
if (match)
config.account = match[1];
if (match) { config.account = match[1]; }

@@ -96,19 +106,18 @@ var options = getOptions(config);

encodeURIComponent(config.account) + '.cloudant.com';
}
else if (config.account) {
} else if (config.account) {
config.url = 'https://' + encodeURIComponent(config.account) +
'.cloudant.com';
}
outUrl = config.url;
}
// We trim out the trailing `/` because when the URL tracks down to `nano` we have to
// worry that the trailing `/` doubles up depending on how URLs are built, this creates
// "Database does not exist." errors.
// We trim out the trailing `/` because when the URL tracks down to `nano` we have to
// worry that the trailing `/` doubles up depending on how URLs are built, this creates
// "Database does not exist." errors.
// Issue: cloudant/nodejs-cloudant#129
if (outUrl && outUrl.slice(-1) == '/') {
if (outUrl && outUrl.slice(-1) === '/') {
outUrl = outUrl.slice(0, -1);
}
return (outUrl || null);

@@ -121,4 +130,4 @@ };

// or the third-party API key.
var result = {password:config.password, username: config.key || config.username || config.account};
var result = {password: config.password, username: config.key || config.username || config.account};
return result;
};
}

@@ -10,3 +10,3 @@ {

},
"version": "1.8.0",
"version": "1.9.0",
"author": {

@@ -28,7 +28,16 @@ "name": "IBM Cloudant",

"async": "2.1.2",
"debug": "2.2.0",
"cloudant-nano": "6.5.0",
"request": "2.76.0"
"cloudant-nano": "6.6.0",
"debug": "^3.1.0",
"request": "^2.81.0"
},
"devDependencies": {
"eslint": "^3.19.0",
"eslint-plugin-standard": "^3.0.1",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-node": "^5.1.0",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-react": "^7.0.0",
"eslint-config-standard": "^10.2.1",
"eslint-config-semistandard": "^11.0.0",
"eslint-plugin-header": "^1.0.0",
"dotenv": "2.0.0",

@@ -38,8 +47,9 @@ "mocha": "3.1.2",

"nsp": "^2.6.3",
"should": "6.0.3"
"should": "6.0.3",
"uuid": "^3.0.1"
},
"scripts": {
"test": "mocha tests/*.js && nsp check",
"test": "eslint --ignore-path .eslintignore . && mocha && nsp check",
"test-verbose": "env DEBUG='*,-mocha:*' npm run test",
"test-live": "NOCK_OFF=true mocha --timeout=5000 tests/*.js",
"test-live": "NOCK_OFF=true mocha",
"test-live-verbose": "env DEBUG='*,-mocha:*' npm run test-live"

@@ -46,0 +56,0 @@ },

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

/**
* Copyright (c) 2015 IBM Cloudant, Inc. All rights reserved.
*
* 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.
*/
// Copyright © 2015, 2017 IBM Corp. All rights reserved.
//
// 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.
'use strict';

@@ -35,4 +36,3 @@ // this the the 'cookieauth' request handler.

// 3) then try the request
var cookieRequest = function (req, callback) {
var cookieRequest = function(req, callback) {
// deal with absence of callback

@@ -60,3 +60,3 @@ if (typeof callback !== 'function') {

};
}
}
req.url = url;

@@ -66,3 +66,3 @@ delete req.uri;

delete parsed.pathname;
var stuburl = u.format(parsed).replace(/\/$/,'');
var stuburl = u.format(parsed).replace(/\/$/, '');

@@ -75,5 +75,4 @@ // to maintain streaming compatiblity, always return a PassThrough stream

// call the request being asked for
// call the request being asked for
function(done) {
// do we have cookie for this domain name?

@@ -92,10 +91,9 @@ var cookies = jar.getCookies(stuburl);

// we're good because we didn't get a 4** or 5**
done(true, [e,h,b]);
done(true, [e, h, b]);
} else {
// continue with the async chain
done(null, [e,h,b]);
done(null, [e, h, b]);
}
}).on('response', function(r) {
statusCode = r && r.statusCode || 500;
statusCode = (r && r.statusCode) || 500;
}).on('data', function(chunk) {

@@ -106,4 +104,3 @@ // only write to the output stream on success

}
});
});
} else {

@@ -115,3 +112,2 @@ debug('we have no cookies - need to authenticate first');

}
},

@@ -123,3 +119,3 @@

var r = {
url: stuburl + '/_session',
url: stuburl + '/_session',
method: 'post',

@@ -133,3 +129,3 @@ form: {

request(r, function(e, h, b) {
var statusCode = h && h.statusCode || 500;
var statusCode = (h && h.statusCode) || 500;
// if we sucessfully authenticate

@@ -152,7 +148,7 @@ if (statusCode >= 200 && statusCode < 400) {

done(null, [e,h,b]);
done(null, [e, h, b]);
} else {
// failed to authenticate - no point proceeding any further
debug('authentication failed');
done(true, [e,h,b]);
done(true, [e, h, b]);
}

@@ -168,5 +164,5 @@ });

request(req, function(e, h, b) {
done(null, [e,h,b]);
done(null, [e, h, b]);
}).on('response', function(r) {
statusCode = r && r.statusCode || 500;
statusCode = (r && r.statusCode) || 500;
}).on('data', function(chunk) {

@@ -176,13 +172,13 @@ if (statusCode < 400) {

}
});
});
}
], function(err, data) {
// callback with the last call we made
if (data && data.length > 0) {
var reply = data[data.length - 1];
if (data && data.length > 0) {
var reply = data[data.length - 1];
// error, headers, body
callback(reply[0], reply[1], reply[2]);
} else {
callback(err, { statusCode: 500 }, null);
}
callback(reply[0], reply[1], reply[2]);
} else {
callback(err, { statusCode: 500 }, null);
}
});

@@ -194,5 +190,3 @@

return cookieRequest;
};

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

/**
* Copyright (c) 2015 IBM Cloudant, Inc. All rights reserved.
*
* 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.
*/
// Copyright © 2015, 2017 IBM Corp. All rights reserved.
//
// 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.
'use strict';

@@ -23,2 +24,2 @@ // this the the 'default' request handler.

return require('request').defaults(requestDefaults);
}
};

@@ -1,17 +0,18 @@

/**
* Copyright (c) 2015 IBM Cloudant, Inc. All rights reserved.
*
* 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.
*/
// Copyright © 2015, 2017 IBM Corp. All rights reserved.
//
// 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.
'use strict';
// this the the 'promises' request handler.
// It is a function that returns a Promise and resolves the promise on success
// It is a function that returns a Promise and resolves the promise on success
// or rejects the Promise on failure

@@ -22,3 +23,2 @@

module.exports = function(options) {
var requestDefaults = options.requestDefaults || {jar: false};

@@ -32,5 +32,5 @@ var request = require('request').defaults(requestDefaults);

request(req, function(err, h, b) {
var statusCode = h && h.statusCode || 500;
var statusCode = (h && h.statusCode) || 500;
if (b) {
try { b = JSON.parse(b); } catch (err) { }
try { b = JSON.parse(b); } catch (err) { }
}

@@ -46,3 +46,3 @@ if (statusCode >= 200 && statusCode < 400) {

callback(err, h, b);
})
});
});

@@ -53,3 +53,1 @@ };

};

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

/**
* Copyright (c) 2015 IBM Cloudant, Inc. All rights reserved.
*
* 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.
*/
// Copyright © 2015, 2017 IBM Corp. All rights reserved.
//
// 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.
'use strict';

@@ -19,3 +20,2 @@ // this the the 'retry' request handler.

// times with exponential backoff.
// This module is unsuitable for streaming requests.
var async = require('async');

@@ -25,4 +25,2 @@ var debug = require('debug')('cloudant');

var nullcallback = function() {};
module.exports = function(options) {

@@ -37,8 +35,4 @@ var requestDefaults = options.requestDefaults || {jar: false};

var timeout = 0; // ms
var statusCode = null;
var retry;
if (typeof callback !== 'function') {
callback = nullcallback;
}
// create a pass-through stream in case the caller wishes

@@ -48,23 +42,46 @@ // to pipe data using Node.js streams

// do the first function until the second function returns true
async.doUntil(function(done) {
statusCode = 500;
// add error listener
s.on('error', function(err) {
debug(err);
});
// do the first function until the second function returns false
async.doWhilst(function(done) {
attempts++;
retry = false;
if (attempts >= 1) {
debug('attempt', attempts, 'timeout', timeout);
}
setTimeout(function() {
request(req, function(e, h, b) {
done(null, [e, h, b]);
}).on('response', function(r) {
statusCode = r && r.statusCode || 500;
}).on('data', function(chunk) {
if (statusCode !== 429) {
s.write(chunk);
}
});
var thisRequest = request(req, callback);
thisRequest
.on('error', function(err) {
s.emit('error', err);
s.end();
done();
})
.on('response', function(r) {
if (r.statusCode === 429 && attempts < maxAttempts) {
retry = true;
thisRequest.abort();
} else {
s.emit('response', r);
}
})
.on('data', function(chunk) {
if (!retry) {
s.write(chunk);
}
})
.on('end', function() {
if (!retry) {
s.end();
}
done();
});
}, timeout);
}, function() {
// this function returns false for the first 'maxAttempts' 429s receieved
if (statusCode === 429 && attempts < maxAttempts) {
if (retry) {
if (attempts === 1) {

@@ -75,8 +92,4 @@ timeout = firstTimeout;

}
return false;
}
return true;
}, function(e, results) {
s.end();
callback(results[0], results[1], results[2])
}
return retry;
});

@@ -90,4 +103,1 @@

};

@@ -210,6 +210,6 @@ # Cloudant Node.js Client

If you use Cloudant Local, everything works exactly the same, except you provide a *hostname* parameter to indicate which server to use:
If you use Cloudant Local, everything works exactly the same, except you provide a *url* parameter to indicate which server to use:
~~~ js
Cloudant({hostname:"companycloudant.local", username:"somebody", password:"somebody's secret"}, function(er, cloudant, reply) {
Cloudant({url:"companycloudant.local", username:"somebody", password:"somebody's secret"}, function(er, cloudant, reply) {
if (er)

@@ -226,7 +226,7 @@ throw er

1. `default` - the default [request](https://www.npmjs.com/package/request) library plugin. This uses Node.js's callbacks to communicate Cloudant's replies
1. `default` - the default [request](https://www.npmjs.com/package/request) library plugin. This uses Node.js's callbacks to communicate Cloudant's replies
back to your app and can be used to stream data using the Node.js [Stream API](https://nodejs.org/api/stream.html).
2. `promises` - if you'd prefer to write code in the Promises style then the "promises" plugin turns each request into a Promise. This plugin cannot be used
2. `promises` - if you'd prefer to write code in the Promises style then the "promises" plugin turns each request into a Promise. This plugin cannot be used to
stream data because instead of returning the HTTP request, we are simply returning a Promise instead.
3. `retry` - on occasion, Cloudant's multi-tenant offerring may reply with an HTTP 429 response because you've exceed the number of API requests in a given amount of time.
3. `retry` - on occasion, Cloudant's multi-tenant offerring may reply with an HTTP 429 response because you've exceed the number of API requests in a given amount of time.
The "retry" plugin will automatically retry your request with exponential back-off. The 'retry' plugin can be used to stream data.

@@ -277,3 +277,3 @@ 4. `cookieauth` - this plugin will automatically swap your Cloudant credentials for a cookie transparently for you. It will handle the authentication for you

When initialising the Cloudant library, you can opt to use the 'retry' plugin:
When initialising the Cloudant library, you can opt to use the 'cookieauth' plugin:

@@ -288,6 +288,6 @@ ```js

The above code will transparently call `POST /_session` to exchange your credentials for a cookie and then call `GET /mydoc` to fetch the document.
The above code will transparently call `POST /_session` to exchange your credentials for a cookie and then call `GET /mydoc` to fetch the document.
Subsequent calls to the same `cloudant` instance will simply use cookie authentication from that point. The library will automatically ensure that the cookie remains
up-to-date by calling Cloudant on an hourly basis to refresh the cookie.
Subsequent calls to the same `cloudant` instance will simply use cookie authentication from that point. The library will automatically ensure that the cookie remains
up-to-date by calling Cloudant on an hourly basis to refresh the cookie.

@@ -306,3 +306,3 @@ #### Custom plugin

Whenever the Cloudant library wishes to make an outgoing HTTP request, it will call your function instead of `request`.
Whenever the Cloudant library wishes to make an outgoing HTTP request, it will call your function instead of `request`.

@@ -816,3 +816,3 @@ ## API Reference

nano { method: 'POST', headers: { 'content-type': 'application/json', accept: 'application/json' }, uri: 'https://xxxx:yyyyy@xxxx.cloudant.com/woof', body: '{"a":1,"b":2}' } +3ms
nano { err: null, body: { ok: true, id: '98f178cb8f4fe089f70fa4c92a0c84b1', rev: '1-25f9b97d75a648d1fcd23f0a73d2776e' }, headers: { 'x-couch-request-id': '8220322dee', location: 'http://reader.cloudant.com/woof/98f178cb8f4fe089f70fa4c92a0c84b1', date: 'Mon, 07 Sep 2015 13:06:01 GMT', 'content-type': 'application/json', 'cache-control': 'must-revalidate', 'strict-transport-security': 'max-age=31536000', 'x-content-type-options': 'nosniff;', connection: 'close', statusCode: 201, uri: 'https://xxxx:yyyy@xxxx.cloudant.com/woof' } }
nano { err: null, body: { ok: true, id: '98f178cb8f4fe089f70fa4c92a0c84b1', rev: '1-25f9b97d75a648d1fcd23f0a73d2776e' }, headers: { 'x-couch-request-id': '8220322dee', location: 'http://reader.cloudant.com/woof/98f178cb8f4fe089f70fa4c92a0c84b1', date: 'Mon, 07 Sep 2015 13:06:01 GMT', 'content-type': 'application/json', 'cache-control': 'must-revalidate', 'strict-transport-security': 'max-age=31536000', 'x-content-type-options': 'nosniff;', connection: 'close', statusCode: 201, uri: 'https://xxxx:yyyy@xxxx.cloudant.com/woof' } }

@@ -904,3 +904,3 @@ Note that credentials used in the requests are also written to the log.

This is an open-source library, published under the Apache 2.0 license. We very much welcome contributions to the project so if you would like
This is an open-source library, published under the Apache 2.0 license. We very much welcome contributions to the project so if you would like
to contribute (even if it's fixing a typo in the README!) simply

@@ -907,0 +907,0 @@

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