Comparing version 1.8.0 to 1.9.0
@@ -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 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
75797
682
15
11
+ Addedcloudant-nano@6.6.0(transitive)
+ Addeddebug@2.6.93.2.7(transitive)
+ Addedms@2.0.02.1.3(transitive)
- Removedansi-regex@2.1.1(transitive)
- Removedansi-styles@2.2.1(transitive)
- Removedcaseless@0.11.0(transitive)
- Removedchalk@1.1.3(transitive)
- Removedcloudant-nano@6.5.0(transitive)
- Removedcommander@2.20.3(transitive)
- Removeddebug@2.2.0(transitive)
- Removedescape-string-regexp@1.0.5(transitive)
- Removedgenerate-function@2.3.1(transitive)
- Removedgenerate-object-property@1.2.0(transitive)
- Removedhar-validator@2.0.6(transitive)
- Removedhas-ansi@2.0.0(transitive)
- Removedis-my-ip-valid@1.0.1(transitive)
- Removedis-my-json-valid@2.20.6(transitive)
- Removedis-property@1.0.2(transitive)
- Removedjsonpointer@5.0.1(transitive)
- Removedms@0.7.1(transitive)
- Removednode-uuid@1.4.8(transitive)
- Removedpinkie@2.0.4(transitive)
- Removedpinkie-promise@2.0.1(transitive)
- Removedqs@6.3.3(transitive)
- Removedrequest@2.76.0(transitive)
- Removedstrip-ansi@3.0.1(transitive)
- Removedsupports-color@2.0.0(transitive)
- Removedtunnel-agent@0.4.3(transitive)
- Removedxtend@4.0.2(transitive)
Updatedcloudant-nano@6.6.0
Updateddebug@^3.1.0
Updatedrequest@^2.81.0