couchr-browser
Advanced tools
Comparing version 2.0.0 to 3.0.0
411
index.js
@@ -1,4 +0,1 @@ | ||
// have to use the built version of component-ajax because otherwise webpack | ||
// complains about 'type' module being missing | ||
var ajax = require('component-ajax/ajax.min.js'); | ||
var events = require('events'); | ||
@@ -8,234 +5,248 @@ | ||
/** | ||
* Returns a function for handling ajax responses and calls the | ||
* callback with the data or appropriate error. | ||
* | ||
* @param {Function} callback(err,response) | ||
* @api private | ||
* Initialize module with your choice of ajax function | ||
* eg, jQuery.ajax, reqwest.compat etc. | ||
*/ | ||
function onComplete(options, callback) { | ||
return function (req) { | ||
var resp; | ||
if (ctype = req.getResponseHeader('Content-Type')) { | ||
ctype = ctype.split(';')[0]; | ||
} | ||
if (ctype === 'application/json' || ctype === 'text/json') { | ||
try { | ||
// Support: Android 2.3 | ||
// Workaround failure to string-cast null input | ||
resp = JSON.parse(req.responseText + ""); | ||
module.exports = function (ajax) { | ||
// public API | ||
var couchr = {}; | ||
/** | ||
* Returns a function for handling ajax responses and calls the | ||
* callback with the data or appropriate error. | ||
* | ||
* @param {Function} callback(err,response) | ||
* @api private | ||
*/ | ||
function onComplete(options, callback) { | ||
return function (req) { | ||
var resp; | ||
if (ctype = req.getResponseHeader('Content-Type')) { | ||
ctype = ctype.split(';')[0]; | ||
} | ||
catch (e) { | ||
return callback(e, null, req); | ||
if (ctype === 'application/json' || ctype === 'text/json') { | ||
try { | ||
// Support: Android 2.3 | ||
// Workaround failure to string-cast null input | ||
resp = JSON.parse(req.responseText + ""); | ||
} | ||
catch (e) { | ||
return callback(e, null, req); | ||
} | ||
} | ||
} | ||
else { | ||
var ct = req.getResponseHeader("content-type") || ""; | ||
var xml = ct.indexOf("xml") >= 0; | ||
resp = xml ? req.responseXML : req.responseText; | ||
} | ||
if (req.status == 200 || req.status == 201 || req.status == 202) { | ||
callback(null, resp, req); | ||
} | ||
else if (resp && (resp.error || resp.reason)) { | ||
var err = new Error(resp.reason || resp.error); | ||
err.error = resp.error; | ||
err.reason = resp.reason; | ||
err.code = resp.code; | ||
err.status = req.status; | ||
callback(err, null, req); | ||
} | ||
else { | ||
// TODO: map status code to meaningful error message | ||
var msg = req.statusText; | ||
if (!msg || msg === 'error') { | ||
msg = 'Returned status code: ' + req.status; | ||
else { | ||
var ct = req.getResponseHeader("content-type") || ""; | ||
var xml = ct.indexOf("xml") >= 0; | ||
resp = xml ? req.responseXML : req.responseText; | ||
} | ||
var err2 = new Error(msg); | ||
err2.status = req.status; | ||
callback(err2, null, req); | ||
if (req.status == 200 || req.status == 201 || req.status == 202) { | ||
callback(null, resp, req); | ||
} | ||
else if (resp && (resp.error || resp.reason)) { | ||
var err = new Error(resp.reason || resp.error); | ||
err.error = resp.error; | ||
err.reason = resp.reason; | ||
err.code = resp.code; | ||
err.status = req.status; | ||
callback(err, null, req); | ||
} | ||
else { | ||
// TODO: map status code to meaningful error message | ||
var msg = req.statusText; | ||
if (!msg || msg === 'error') { | ||
msg = 'Returned status code: ' + req.status; | ||
} | ||
var err2 = new Error(msg); | ||
err2.status = req.status; | ||
callback(err2, null, req); | ||
} | ||
}; | ||
} | ||
/** | ||
* Properly encodes query parameters to CouchDB views etc. Handle complex | ||
* keys and other non-string parameters by passing through JSON.stringify. | ||
* Returns a shallow-copied clone of the original query after complex values | ||
* have been stringified. | ||
* | ||
* @name stringifyQuery(query) | ||
* @param {Object} query | ||
* @returns {Object} | ||
* @api public | ||
*/ | ||
couchr.stringifyQuery = function (query) { | ||
var q = {}; | ||
for (var k in query) { | ||
if (typeof query[k] !== 'string') { | ||
q[k] = JSON.stringify(query[k]); | ||
} | ||
else { | ||
q[k] = query[k]; | ||
} | ||
} | ||
return q; | ||
}; | ||
} | ||
/** | ||
* Properly encodes query parameters to CouchDB views etc. Handle complex | ||
* keys and other non-string parameters by passing through JSON.stringify. | ||
* Returns a shallow-copied clone of the original query after complex values | ||
* have been stringified. | ||
* | ||
* @name stringifyQuery(query) | ||
* @param {Object} query | ||
* @returns {Object} | ||
* @api public | ||
*/ | ||
/** | ||
* Make a request using component-ajax, with some default settings and | ||
* proper callback handling. | ||
* | ||
* @name ajax(options, callback) | ||
* @param {Object} options | ||
* @param {Function} callback(err,response) | ||
* @api public | ||
*/ | ||
exports.stringifyQuery = function (query) { | ||
var q = {}; | ||
for (var k in query) { | ||
if (typeof query[k] !== 'string') { | ||
q[k] = JSON.stringify(query[k]); | ||
couchr.ajax = function (options, callback) { | ||
options.complete = onComplete(options, callback); | ||
options.dataType = 'json'; | ||
if (!options.hasOwnProperty('cache')) { | ||
// IE has a tendency to cache /_session and other things stupidly | ||
// so turning it off by default | ||
options.cache = false; | ||
} | ||
else { | ||
q[k] = query[k]; | ||
} | ||
} | ||
return q; | ||
}; | ||
return ajax(options); | ||
}; | ||
/** | ||
* Make a request using component-ajax, with some default settings and | ||
* proper callback handling. | ||
* | ||
* @name ajax(options, callback) | ||
* @param {Object} options | ||
* @param {Function} callback(err,response) | ||
* @api public | ||
*/ | ||
exports.ajax = function (options, callback) { | ||
options.complete = onComplete(options, callback); | ||
options.dataType = 'json'; | ||
if (!options.hasOwnProperty('cache')) { | ||
// IE has a tendency to cache /_session and other things stupidly | ||
// so turning it off by default | ||
options.cache = false; | ||
} | ||
return ajax(options); | ||
}; | ||
couchr.request = function (method, url, /*o*/data, /*o*/opt, callback) { | ||
if (!callback) { | ||
callback = opt; | ||
opt = null; | ||
} | ||
if (!callback) { | ||
callback = data; | ||
data = null; | ||
} | ||
var options = opt || {}; | ||
options.type = method; | ||
options.url = url; | ||
exports.request = function (method, url, /*o*/data, /*o*/opt, callback) { | ||
if (!callback) { | ||
callback = opt; | ||
opt = null; | ||
} | ||
if (!callback) { | ||
callback = data; | ||
data = null; | ||
} | ||
var options = opt || {}; | ||
options.type = method; | ||
options.url = url; | ||
if (data) { | ||
try { | ||
if (method === 'GET' || method === 'HEAD') { | ||
options.data = exports.stringifyQuery(data); | ||
if (data) { | ||
try { | ||
if (method === 'GET' || method === 'HEAD') { | ||
options.data = couchr.stringifyQuery(data); | ||
} | ||
else { | ||
options.data = JSON.stringify(data); | ||
options.processData = false; | ||
options.contentType = 'application/json'; | ||
} | ||
} | ||
else { | ||
options.data = JSON.stringify(data); | ||
options.processData = false; | ||
options.contentType = 'application/json'; | ||
catch (e) { | ||
return callback(e); | ||
} | ||
} | ||
catch (e) { | ||
return callback(e); | ||
} | ||
} | ||
return exports.ajax(options, callback); | ||
}; | ||
return couchr.ajax(options, callback); | ||
}; | ||
function makeRequest(method) { | ||
return function () { | ||
var args = Array.prototype.slice.call(arguments); | ||
return exports.request.apply(this, [method].concat(args)); | ||
function makeRequest(method) { | ||
return function () { | ||
var args = Array.prototype.slice.call(arguments); | ||
return couchr.request.apply(this, [method].concat(args)); | ||
}; | ||
}; | ||
}; | ||
exports.get = makeRequest('GET'); | ||
exports.post = makeRequest('POST'); | ||
exports.head = makeRequest('HEAD'); | ||
exports.put = makeRequest('PUT'); | ||
couchr.get = makeRequest('GET'); | ||
couchr.post = makeRequest('POST'); | ||
couchr.head = makeRequest('HEAD'); | ||
couchr.put = makeRequest('PUT'); | ||
// data.rev should be in query part of URL | ||
exports.del = function (url, data, callback) { | ||
if (!callback) { | ||
callback = data; | ||
data = null; | ||
} | ||
if (data && data.rev && !/\?rev=/.test(url)) { | ||
url += (url.indexOf('?') === -1) ? '?': '&'; | ||
url += 'rev=' + encodeURIComponent(data.rev); | ||
} | ||
return exports.request('DELETE', url, data, callback); | ||
}; | ||
// data.rev should be in query part of URL | ||
couchr.del = function (url, data, callback) { | ||
if (!callback) { | ||
callback = data; | ||
data = null; | ||
} | ||
if (data && data.rev && !/\?rev=/.test(url)) { | ||
url += (url.indexOf('?') === -1) ? '?': '&'; | ||
url += 'rev=' + encodeURIComponent(data.rev); | ||
} | ||
return couchr.request('DELETE', url, data, callback); | ||
}; | ||
// non-standard HTTP method, may not work in all browsers | ||
exports.copy = function (from, to, callback) { | ||
var opt = { | ||
headers: {'Destination': to} | ||
// non-standard HTTP method, may not work in all browsers | ||
couchr.copy = function (from, to, callback) { | ||
var opt = { | ||
headers: {'Destination': to} | ||
}; | ||
return couchr.request('COPY', from, null, opt, callback); | ||
}; | ||
return exports.request('COPY', from, null, opt, callback); | ||
}; | ||
exports.changes = function (dburl, q) { | ||
q = q || {}; | ||
q.feed = q.feed || 'longpoll'; | ||
q.heartbeat = q.heartbeat || 10000; | ||
couchr.changes = function (dburl, q) { | ||
q = q || {}; | ||
q.feed = q.feed || 'longpoll'; | ||
q.heartbeat = q.heartbeat || 10000; | ||
var ev = new events.EventEmitter(); | ||
var request_in_progress = false; | ||
var paused = false; | ||
var ev = new events.EventEmitter(); | ||
var request_in_progress = false; | ||
var paused = false; | ||
ev.pause = function () { | ||
paused = true; | ||
}; | ||
ev.pause = function () { | ||
paused = true; | ||
}; | ||
ev.resume = function () { | ||
paused = false; | ||
if (!request_in_progress) { | ||
getChanges(); | ||
} | ||
}; | ||
ev.resume = function () { | ||
paused = false; | ||
if (!request_in_progress) { | ||
getChanges(); | ||
} | ||
}; | ||
function getChanges() { | ||
if (paused) { | ||
return; | ||
} | ||
try { | ||
var data = exports.stringifyQuery(q); | ||
} | ||
catch (e) { | ||
return ev.emit('error', e); | ||
} | ||
var url = dburl + '/_changes'; | ||
request_in_progress = true; | ||
exports.request('GET', url, data, function (err, data) { | ||
request_in_progress = false; | ||
if (err) { | ||
ev.emit('error', err); | ||
// retry after 1 sec | ||
setTimeout(getChanges, 1000); | ||
function getChanges() { | ||
if (paused) { | ||
return; | ||
} | ||
if (!paused) { | ||
for (var i = 0, len = data.results.length; i < len; i++) { | ||
ev.emit('change', data.results[i]); | ||
} | ||
q.since = data.last_seq; | ||
getChanges(); | ||
try { | ||
var data = couchr.stringifyQuery(q); | ||
} | ||
}); | ||
} | ||
catch (e) { | ||
return ev.emit('error', e); | ||
} | ||
var url = dburl + '/_changes'; | ||
request_in_progress = true; | ||
// use setTimeout to pass control back to the browser briefly to | ||
// allow the loading spinner to stop on page load | ||
setTimeout(function () { | ||
if (q.hasOwnProperty('since')) { | ||
getChanges(); | ||
} | ||
else { | ||
exports.get(dburl, function (err, info) { | ||
couchr.request('GET', url, data, function (err, data) { | ||
request_in_progress = false; | ||
if (err) { | ||
// no retry, just fail | ||
return ev.emit('error', err); | ||
ev.emit('error', err); | ||
// retry after 1 sec | ||
setTimeout(getChanges, 1000); | ||
} | ||
q.since = info.update_seq; | ||
getChanges(); | ||
if (!paused) { | ||
for (var i = 0, len = data.results.length; i < len; i++) { | ||
ev.emit('change', data.results[i]); | ||
} | ||
q.since = data.last_seq; | ||
getChanges(); | ||
} | ||
}); | ||
} | ||
}, 0); | ||
return ev; | ||
// use setTimeout to pass control back to the browser briefly to | ||
// allow the loading spinner to stop on page load | ||
setTimeout(function () { | ||
if (q.hasOwnProperty('since')) { | ||
getChanges(); | ||
} | ||
else { | ||
couchr.get(dburl, function (err, info) { | ||
if (err) { | ||
// no retry, just fail | ||
return ev.emit('error', err); | ||
} | ||
q.since = info.update_seq; | ||
getChanges(); | ||
}); | ||
} | ||
}, 0); | ||
return ev; | ||
}; | ||
// return public API | ||
return couchr; | ||
}; |
{ | ||
"name": "couchr-browser", | ||
"description": "Lightweight library for making CouchDB requests in the browser (no jquery required)", | ||
"version": "2.0.0", | ||
"dependencies": { | ||
"component-ajax": "*" | ||
}, | ||
"description": "Lightweight library for making CouchDB requests in the browser", | ||
"version": "3.0.0", | ||
"github": "https://github.com/caolan/couchr-browser", | ||
"bugs": { | ||
"web": "https://github.com/caolan/couchr-browser/issues" | ||
"url": "https://github.com/caolan/couchr-browser/issues" | ||
}, | ||
"repositories": [ | ||
{ | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/caolan/couchr-browser.git" | ||
} | ||
], | ||
}, | ||
"licenses": [ | ||
@@ -19,0 +14,0 @@ { |
# couchr-browser | ||
Simple stand-alone request library for CouchDB. Provides a browser-compatible | ||
Lightweight request library for CouchDB. Provides a browser-compatible | ||
module, with better CouchDB error reporting and a simpler API than making XHR | ||
@@ -8,5 +8,8 @@ requests directly in the browser or using jQuery.ajax. | ||
This package is designed to be suitable for use with webpack or browserify, | ||
and makes use of the 'events' and 'component-ajax' modules. | ||
and makes use of the events module (for the changes feed). You can pass in any | ||
jQuery.ajax compatible API to initialize the module (allowing you to use your | ||
favourite library for this). I suggest taking a look at | ||
[reqwest](https://github.com/ded/reqwest) if you don't need full jQuery. | ||
Comes in around 11kb minified (4.2kb gzipped) | ||
Comes in around 5.9kb minified (2.2kb gzipped) | ||
@@ -17,3 +20,3 @@ | ||
```javascript | ||
var couchr = require('couchr-browser'); | ||
var couchr = require('couchr-browser')(jQuery.ajax); | ||
@@ -28,2 +31,5 @@ couchr.get('http://hostname:port/dbname/docid', function (err, doc) { | ||
```javascript | ||
var couchr = require('couchr-browser')(jQuery.ajax); | ||
var couchr = require('couchr-browser')(reqwest.compat); | ||
couchr.get (url, /*optional*/params, function (err, res, req) { ... }) | ||
@@ -30,0 +36,0 @@ couchr.post(url, /*optional*/data, function (err, res, req) { ... }) |
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
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
Wildcard dependency
QualityPackage has a dependency with a floating version range. This can cause issues if the dependency publishes a new major version.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
10023
0
225
2
1
55
0
- Removedcomponent-ajax@*
- Removedcomponent-ajax@0.0.2(transitive)
- Removedtype-of@2.0.1(transitive)