From 7038454d1b4c79ffc73e67bc1c4f4bdadfe27f05 Mon Sep 17 00:00:00 2001 From: Marten de Vries Date: Fri, 19 Dec 2014 14:21:15 +0100 Subject: [PATCH 01/23] 1.0.0 --- .gitignore | 2 + .jshintrc | 9 + .travis.yml | 5 + README.md | 46 ++ dist/http-pouchdb.js | 1098 ++++++++++++++++++++++++++++++++++++++ dist/http-pouchdb.min.js | 1 + index.js | 51 ++ package.json | 58 ++ test/test.js | 85 +++ 9 files changed, 1355 insertions(+) create mode 100644 .gitignore create mode 100644 .jshintrc create mode 100644 .travis.yml create mode 100644 README.md create mode 100644 dist/http-pouchdb.js create mode 100644 dist/http-pouchdb.min.js create mode 100644 index.js create mode 100644 package.json create mode 100644 test/test.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..ba2a97b5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +coverage diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 00000000..47e484ef --- /dev/null +++ b/.jshintrc @@ -0,0 +1,9 @@ +{ + "undef": true, + "unused": "vars", + "predef": ["-Promise"], + "node": true, + "strict": true, + "indent": 2, + "maxlen": 100 +} diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..58c5363e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - "0.10" +services: + - couchdb diff --git a/README.md b/README.md new file mode 100644 index 00000000..757c2034 --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +http-pouchdb +============ + +[![Build Status](https://travis-ci.org/marten-de-vries/http-pouchdb.svg?branch=master)](https://travis-ci.org/marten-de-vries/http-pouchdb) +[![Dependency Status](https://david-dm.org/marten-de-vries/http-pouchdb.svg)](https://david-dm.org/marten-de-vries/http-pouchdb) +[![devDependency Status](https://david-dm.org/marten-de-vries/http-pouchdb/dev-status.svg)](https://david-dm.org/marten-de-vries/http-pouchdb#info=devDependencies) + +Access remote CouchDB databases like you would access your local PouchDB +ones. Tested support for ``new PouchDB('name')``, +``PouchDB.replicate('name', 'name')``, ``PouchDB.destroy('name')`` and, +as a bonus, ``PouchDB.allDbs()``. + +Example +------- + +```bash +npm install pouchdb http-pouchdb +``` + +```javascript +var PouchDB = require('pouchdb'); +var HTTPPouchDB = require('http-pouchdb')(PouchDB, 'http://localhost:5984'); + +var db = new PouchDB('_users'); +// 'db' will be backed by http://localhost:5984/_users ; You can use it +// like any PouchDB database. +``` + +Browser usage +------------- + +```html + + + +``` + +API +--- + +- ``module.exports = function (PouchDB, name, opts) -> PouchDB2`` + - ``name``: The base url you want to use. Needs a trailing '/'. + - ``opts``: ``opts.headers`` and ``opts.auth``. diff --git a/dist/http-pouchdb.js b/dist/http-pouchdb.js new file mode 100644 index 00000000..1afb9808 --- /dev/null +++ b/dist/http-pouchdb.js @@ -0,0 +1,1098 @@ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.buildHTTPPouchDB=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o element; its readystatechange event will be fired asynchronously once it is inserted + // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called. + var scriptEl = global.document.createElement('script'); + scriptEl.onreadystatechange = function () { + handle(); + + scriptEl.onreadystatechange = null; + scriptEl.parentNode.removeChild(scriptEl); + scriptEl = null; + }; + global.document.documentElement.appendChild(scriptEl); + + return handle; + }; +}; +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],21:[function(require,module,exports){ +'use strict'; +exports.test = function () { + return true; +}; + +exports.install = function (t) { + return function () { + setTimeout(t, 0); + }; +}; +},{}],22:[function(require,module,exports){ +/* + Copyright 2014, Marten de Vries + + 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"; + +var nodify = require("promise-nodify"); + +exports.installStaticWrapperMethods = function (PouchDB, handlers) { + //set an 'alternative constructor' so the constructor can be easily + //wrapped, since wrapping 'real' constructors is hard. + PouchDB["new"] = PouchDB["new"] || function (name, options, callback) { + return new PouchDB(name, options, callback); + }; + + installWrappers(PouchDB, handlers, exports.createStaticWrapperMethod); +}; + +exports.installWrapperMethods = function (db, handlers) { + installWrappers(db, handlers, exports.createWrapperMethod); +}; + +function installWrappers(base, handlers, createWrapperMethod) { + for (var name in handlers) { + if (!handlers.hasOwnProperty(name)) { + continue; + } + var info = getBaseAndName(base, name); + var original = info.base[info.name]; + if (!original) { + //no method to wrap + continue; + } + if (original.hasOwnProperty("_handlers")) { + if (original._handlers.indexOf(handlers[name]) !== -1) { + throw new Error("Wrapper method for '" + name + "' already installed: " + handlers[name]); + } + original._handlers.push(handlers[name]); + } else { + info.base[info.name] = createWrapperMethod(name, original, handlers[name], base); + } + } +} + +function getBaseAndName(base, name) { + name = name.split("."); + while (name.length > 1) { + base = base[name.shift(0)]; + } + return { + base: base, + name: name[0] + }; +} + +exports.createStaticWrapperMethod = function (name, original, handler, PouchDB) { + //PouchDB is optional + return createWrapper(name, original, handler, staticWrapperBuilders, PouchDB); +}; + +exports.createWrapperMethod = function (name, original, handler, db) { + //db is optional + return createWrapper(name, original, handler, wrapperBuilders, db); +}; + +function createWrapper(name, original, handler, theWrapperBuilders, thisVal) { + //thisVal is optional + var buildWrapper = theWrapperBuilders[name]; + if (typeof createWrapper === "undefined") { + throw new Error("No known wrapper for method name: " + name); //coverage: ignore + } + var handlers = [handler]; + var wrapper = buildWrapper(thisVal, original, handlers); + wrapper._original = original; + wrapper._handlers = handlers; + return wrapper; +} + +var wrapperBuilders = {}; + +wrapperBuilders.destroy = function (db, destroy, handlers) { + return function (options, callback) { + var args = parseBaseArgs(db, this, options, callback); + return callHandlers(handlers, args, makeCall(destroy)); + }; +}; + +wrapperBuilders.put = function (db, put, handlers) { + return function (doc, docId, docRev, options, callback) { + var args = {}; + args.base = db || this; + args.db = db || this; //backwards compatibility + var argsList = Array.prototype.slice.call(arguments); + //parsing code borrowed from PouchDB (adapted). + args.doc = argsList.shift(); + var id = '_id' in args.doc; + while (true) { + var temp = argsList.shift(); + var temptype = typeof temp; + if (temptype === "string" && !id) { + args.doc._id = temp; + id = true; + } else if (temptype === "string" && id && !('_rev' in args.doc)) { + args.doc._rev = temp; + } else if (temptype === "object") { + args.options = temp; + } else if (temptype === "function") { + args.callback = temp; + } + if (!argsList.length) { + break; + } + } + args.options = args.options || {}; + return callHandlers(handlers, args, function () { + return put.call(this, args.doc, args.options); + }); + }; +}; + +wrapperBuilders.post = function (db, post, handlers) { + return function (doc, options, callback) { + var args = parseBaseArgs(db, this, options, callback); + args.doc = doc; + return callHandlers(handlers, args, function () { + return post.call(this, args.doc, args.options); + }); + }; +}; + +wrapperBuilders.get = function (db, get, handlers) { + return function(docId, options, callback) { + var args = parseBaseArgs(db, this, options, callback); + args.docId = docId; + return callHandlers(handlers, args, function () { + return get.call(this, args.docId, args.options); + }); + }; +}; + +wrapperBuilders.remove = function (db, remove, handlers) { + return function (docOrId, optsOrRev, opts, callback) { + var args; + + //originally borrowed from PouchDB + if (typeof optsOrRev === 'string') { + // id, rev, opts, callback style + args = parseBaseArgs(db, this, opts, callback); + args.doc = { + _id: docOrId, + _rev: optsOrRev + }; + } else { + // doc, opts, callback style + args = parseBaseArgs(db, this, optsOrRev, opts); + args.doc = docOrId; + } + + return callHandlers(handlers, args, function () { + return remove.call(this, args.doc, args.options); + }); + }; +}; + +wrapperBuilders.bulkDocs = function (db, bulkDocs, handlers) { + return function (docs, options, callback) { + var args = parseBaseArgs(db, this, options, callback); + //support the deprecated signature. + args.docs = docs.docs || docs; + return callHandlers(handlers, args, function () { + return bulkDocs.call(this, args.docs, args.options); + }); + }; +}; + +wrapperBuilders.allDocs = function (db, allDocs, handlers) { + return function (options, callback) { + var args = parseBaseArgs(db, this, options, callback); + return callHandlers(handlers, args, makeCallWithOptions(allDocs, args)); + }; +}; + +wrapperBuilders.changes = function (db, changes, handlers) { + return function (options, callback) { + //the callback argument is no longer documented. (And deprecated?) + var args = parseBaseArgs(db, this, options, callback); + return callHandlers(handlers, args, makeCallWithOptions(changes, args)); + }; +}; + +wrapperBuilders.sync = function (db, replicate, handlers) { + return function (url, options, callback) { + var args = parseBaseArgs(db, this, options, callback); + args.url = url; + return callHandlers(handlers, args, function () { + return replicate.call(this, args.url, args.options); + }); + }; +}; + +wrapperBuilders["replicate.from"] = wrapperBuilders.sync; +wrapperBuilders["replicate.to"] = wrapperBuilders.sync; + +wrapperBuilders.putAttachment = function (db, putAttachment, handlers) { + return function (docId, attachmentId, rev, doc, type, options, callback) { + //options is not an 'official' argument. But some plug-ins need it + //and maybe (?) also the http adapter. + + //valid calls: + //- "id", "aid", "rev", new Blob(), "text/plain", {}, function () {} + //- "id", "aid", new Blob(), "text/plain", {}, function () {} + //- "id", "aid", new Blob(), "text/plain" + var args; + if (typeof type === "string") { + //rev is specified + args = parseBaseArgs(db, this, options, callback); + args.rev = rev; + args.doc = doc; + args.type = type; + } else { + //rev is unspecified + args = parseBaseArgs(db, this, type, options); + args.rev = null; + args.doc = rev; + args.type = doc; + } + //fixed arguments + args.docId = docId; + args.attachmentId = attachmentId; + + return callHandlers(handlers, args, function () { + return putAttachment.call(this, args.docId, args.attachmentId, args.rev, args.doc, args.type); + }); + }; +}; + +wrapperBuilders.getAttachment = function (db, getAttachment, handlers) { + return function (docId, attachmentId, options, callback) { + var args = parseBaseArgs(db, this, options, callback); + args.docId = docId; + args.attachmentId = attachmentId; + return callHandlers(handlers, args, function () { + return getAttachment.call(this, args.docId, args.attachmentId, args.options); + }); + }; +}; + +wrapperBuilders.removeAttachment = function (db, removeAttachment, handlers) { + return function (docId, attachmentId, rev, options, callback) { + //see note on the options argument at putAttachment. + var args = parseBaseArgs(db, this, options, callback); + args.docId = docId; + args.attachmentId = attachmentId; + args.rev = rev; + return callHandlers(handlers, args, function () { + return removeAttachment.call(this, args.docId, args.attachmentId, args.rev); + }); + }; +}; + +wrapperBuilders.query = function (db, query, handlers) { + return function (fun, options, callback) { + var args = parseBaseArgs(db, this, options, callback); + args.fun = fun; + return callHandlers(handlers, args, function () { + return query.call(this, args.fun, args.options); + }); + }; +}; + +wrapperBuilders.viewCleanup = function (db, viewCleanup, handlers) { + return function (options, callback) { + var args = parseBaseArgs(db, this, options, callback); + return callHandlers(handlers, args, makeCallWithOptions(viewCleanup, args)); + }; +}; + +wrapperBuilders.info = function (db, info, handlers) { + return function (options, callback) { + //see note on the options argument at putAttachment. + var args = parseBaseArgs(db, this, options, callback); + return callHandlers(handlers, args, makeCall(info)); + }; +}; + +wrapperBuilders.compact = function (db, compact, handlers) { + return function (options, callback) { + var args = parseBaseArgs(db, this, options, callback); + return callHandlers(handlers, args, makeCallWithOptions(compact, args)); + }; +}; + +wrapperBuilders.revsDiff = function (db, revsDiff, handlers) { + return function (diff, options, callback) { + //see note on the options argument at putAttachment. + var args = parseBaseArgs(db, this, options, callback); + args.diff = diff; + return callHandlers(handlers, args, function () { + return revsDiff.call(this, args.diff); + }); + }; +}; + +//Plug-in wrapperBuilders; only of the plug-ins for which a wrapper +//has been necessary. + +wrapperBuilders.list = function (db, orig, handlers) { + return function (path, options, callback) { + var args = parseBaseArgs(db, this, options, callback); + args.path = path; + + return callHandlers(handlers, args, function () { + return orig.call(this, args.path, args.options); + }); + }; +}; + +wrapperBuilders.rewriteResultRequestObject = wrapperBuilders.list; +wrapperBuilders.show = wrapperBuilders.list; +wrapperBuilders.update = wrapperBuilders.list; + +wrapperBuilders.getSecurity = function (db, getSecurity, handlers) { + return function (options, callback) { + var args = parseBaseArgs(db, this, options, callback); + return callHandlers(handlers, args, makeCallWithOptions(getSecurity, args)); + }; +}; + +wrapperBuilders.putSecurity = function (db, putSecurity, handlers) { + return function (secObj, options, callback) { + //see note on the options argument at putAttachment. + var args = parseBaseArgs(db, this, options, callback); + args.secObj = secObj; + return callHandlers(handlers, args, function () { + return putSecurity.call(this, args.secObj); + }); + }; +}; + +//static +var staticWrapperBuilders = {}; + +staticWrapperBuilders["new"] = function (PouchDB, construct, handlers) { + return function (name, options, callback) { + var args; + if (typeof name === "object") { + args = parseBaseArgs(PouchDB, this, name, options); + } else { + args = parseBaseArgs(PouchDB, this, options, callback); + args.options.name = name; + } + return callHandlers(handlers, args, function () { + return construct.call(this, args.options); + }); + }; +}; + +staticWrapperBuilders.destroy = function (PouchDB, destroy, handlers) { + return function (name, options, callback) { + var args; + if (typeof name === "object") { + args = parseBaseArgs(PouchDB, this, name, options); + } else { + args = parseBaseArgs(PouchDB, this, options, callback); + args.options.name = name; + } + return callHandlers(handlers, args, function () { + var name = args.options.name; + delete args.options.name; + return destroy.call(this, name, args.options); + }); + }; +}; + +staticWrapperBuilders.replicate = function (PouchDB, replicate, handlers) { + return function (source, target, options, callback) { + //no callback + var args = parseBaseArgs(PouchDB, this, options, callback); + args.source = source; + args.target = target; + return callHandlers(handlers, args, function () { + return replicate.call(this, args.source, args.target, args.options); + }); + }; +}; + +staticWrapperBuilders.allDbs = function (PouchDB, allDbs, handlers) { + return function (options, callback) { + var args = parseBaseArgs(PouchDB, this, options, callback); + return callHandlers(handlers, args, makeCall(allDbs)); + } +}; + +//Wrap .plugin()? .on()? .defaults()? No use case yet, but it's +//possible... + +function parseBaseArgs(thisVal1, thisVal2, options, callback) { + if (typeof options === "function") { + callback = options; + options = {}; + } + return { + base: thisVal1 || thisVal2, + db: thisVal1 || thisVal2, //backwards compatibility + options: options || {}, + callback: callback + }; +} + +function callHandlers(handlers, args, method) { + var callback = args.callback; + delete args.callback; + + //build a chain of handlers: the bottom handler calls the 'real' + //method, the other handlers call other handlers. + method = method.bind(args.base); + for (var i = handlers.length - 1; i >= 0; i -= 1) { + method = handlers[i].bind(null, method, args); + } + //start running the chain. + var promise = method(); + nodify(promise, callback); + return promise; +} + +function makeCall(func) { + return function () { + return func.call(this); + }; +} + +function makeCallWithOptions(func, args) { + return function () { + return func.call(this, args.options); + }; +} + +exports.uninstallWrapperMethods = function (db, handlers) { + uninstallWrappers(db, handlers); +}; + +exports.uninstallStaticWrapperMethods = function (PouchDB, handlers) { + uninstallWrappers(PouchDB, handlers); +}; + +function uninstallWrappers(base, handlers) { + for (var name in handlers) { + if (!handlers.hasOwnProperty(name)) { + continue; + } + var info = getBaseAndName(base, name); + var wrapper = info.base[info.name]; + if (typeof wrapper === "undefined") { + //method doesn't exist, so was never wrapped in the first place. + continue; + } + + var idx; + try { + idx = wrapper._handlers.indexOf(handlers[name]); + } catch (err) { + idx = -1; + } + if (idx === -1) { + throw new Error("Wrapper method for '" + name + "' not installed: " + handlers[name]); + } + wrapper._handlers.splice(idx, 1); + if (!wrapper._handlers.length) { + //fall back to the original on the prototype. + delete info.base[info.name]; + if (info.base[info.name] !== wrapper._original) { + //nothing or something unexpected was on the prototype. (E.g. + //replicate.to). Reset the original manually. + info.base[info.name] = wrapper._original; + } + } + } +} + +},{"promise-nodify":23}],23:[function(require,module,exports){ +/* + Copyright 2013-2014, Marten de Vries + + 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 = function nodify(promise, callback) { + if (typeof callback === "function") { + promise.then(function (resp) { + callback(null, resp); + }, function (err) { + callback(err, null); + }); + } +}; + +},{}]},{},[1])(1) +}); \ No newline at end of file diff --git a/dist/http-pouchdb.min.js b/dist/http-pouchdb.min.js new file mode 100644 index 00000000..155e8782 --- /dev/null +++ b/dist/http-pouchdb.min.js @@ -0,0 +1 @@ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.buildHTTPPouchDB=e()}}(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o1){base=base[name.shift(0)]}return{base:base,name:name[0]}}exports.createStaticWrapperMethod=function(name,original,handler,PouchDB){return createWrapper(name,original,handler,staticWrapperBuilders,PouchDB)};exports.createWrapperMethod=function(name,original,handler,db){return createWrapper(name,original,handler,wrapperBuilders,db)};function createWrapper(name,original,handler,theWrapperBuilders,thisVal){var buildWrapper=theWrapperBuilders[name];if(typeof createWrapper==="undefined"){throw new Error("No known wrapper for method name: "+name)}var handlers=[handler];var wrapper=buildWrapper(thisVal,original,handlers);wrapper._original=original;wrapper._handlers=handlers;return wrapper}var wrapperBuilders={};wrapperBuilders.destroy=function(db,destroy,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCall(destroy))}};wrapperBuilders.put=function(db,put,handlers){return function(doc,docId,docRev,options,callback){var args={};args.base=db||this;args.db=db||this;var argsList=Array.prototype.slice.call(arguments);args.doc=argsList.shift();var id="_id"in args.doc;while(true){var temp=argsList.shift();var temptype=typeof temp;if(temptype==="string"&&!id){args.doc._id=temp;id=true}else if(temptype==="string"&&id&&!("_rev"in args.doc)){args.doc._rev=temp}else if(temptype==="object"){args.options=temp}else if(temptype==="function"){args.callback=temp}if(!argsList.length){break}}args.options=args.options||{};return callHandlers(handlers,args,function(){return put.call(this,args.doc,args.options)})}};wrapperBuilders.post=function(db,post,handlers){return function(doc,options,callback){var args=parseBaseArgs(db,this,options,callback);args.doc=doc;return callHandlers(handlers,args,function(){return post.call(this,args.doc,args.options)})}};wrapperBuilders.get=function(db,get,handlers){return function(docId,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docId=docId;return callHandlers(handlers,args,function(){return get.call(this,args.docId,args.options)})}};wrapperBuilders.remove=function(db,remove,handlers){return function(docOrId,optsOrRev,opts,callback){var args;if(typeof optsOrRev==="string"){args=parseBaseArgs(db,this,opts,callback);args.doc={_id:docOrId,_rev:optsOrRev}}else{args=parseBaseArgs(db,this,optsOrRev,opts);args.doc=docOrId}return callHandlers(handlers,args,function(){return remove.call(this,args.doc,args.options)})}};wrapperBuilders.bulkDocs=function(db,bulkDocs,handlers){return function(docs,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docs=docs.docs||docs;return callHandlers(handlers,args,function(){return bulkDocs.call(this,args.docs,args.options)})}};wrapperBuilders.allDocs=function(db,allDocs,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(allDocs,args))}};wrapperBuilders.changes=function(db,changes,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(changes,args))}};wrapperBuilders.sync=function(db,replicate,handlers){return function(url,options,callback){var args=parseBaseArgs(db,this,options,callback);args.url=url;return callHandlers(handlers,args,function(){return replicate.call(this,args.url,args.options)})}};wrapperBuilders["replicate.from"]=wrapperBuilders.sync;wrapperBuilders["replicate.to"]=wrapperBuilders.sync;wrapperBuilders.putAttachment=function(db,putAttachment,handlers){return function(docId,attachmentId,rev,doc,type,options,callback){var args;if(typeof type==="string"){args=parseBaseArgs(db,this,options,callback);args.rev=rev;args.doc=doc;args.type=type}else{args=parseBaseArgs(db,this,type,options);args.rev=null;args.doc=rev;args.type=doc}args.docId=docId;args.attachmentId=attachmentId;return callHandlers(handlers,args,function(){return putAttachment.call(this,args.docId,args.attachmentId,args.rev,args.doc,args.type)})}};wrapperBuilders.getAttachment=function(db,getAttachment,handlers){return function(docId,attachmentId,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docId=docId;args.attachmentId=attachmentId;return callHandlers(handlers,args,function(){return getAttachment.call(this,args.docId,args.attachmentId,args.options)})}};wrapperBuilders.removeAttachment=function(db,removeAttachment,handlers){return function(docId,attachmentId,rev,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docId=docId;args.attachmentId=attachmentId;args.rev=rev;return callHandlers(handlers,args,function(){return removeAttachment.call(this,args.docId,args.attachmentId,args.rev)})}};wrapperBuilders.query=function(db,query,handlers){return function(fun,options,callback){var args=parseBaseArgs(db,this,options,callback);args.fun=fun;return callHandlers(handlers,args,function(){return query.call(this,args.fun,args.options)})}};wrapperBuilders.viewCleanup=function(db,viewCleanup,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(viewCleanup,args))}};wrapperBuilders.info=function(db,info,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCall(info))}};wrapperBuilders.compact=function(db,compact,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(compact,args))}};wrapperBuilders.revsDiff=function(db,revsDiff,handlers){return function(diff,options,callback){var args=parseBaseArgs(db,this,options,callback);args.diff=diff;return callHandlers(handlers,args,function(){return revsDiff.call(this,args.diff)})}};wrapperBuilders.list=function(db,orig,handlers){return function(path,options,callback){var args=parseBaseArgs(db,this,options,callback);args.path=path;return callHandlers(handlers,args,function(){return orig.call(this,args.path,args.options)})}};wrapperBuilders.rewriteResultRequestObject=wrapperBuilders.list;wrapperBuilders.show=wrapperBuilders.list;wrapperBuilders.update=wrapperBuilders.list;wrapperBuilders.getSecurity=function(db,getSecurity,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(getSecurity,args))}};wrapperBuilders.putSecurity=function(db,putSecurity,handlers){return function(secObj,options,callback){var args=parseBaseArgs(db,this,options,callback);args.secObj=secObj;return callHandlers(handlers,args,function(){return putSecurity.call(this,args.secObj)})}};var staticWrapperBuilders={};staticWrapperBuilders["new"]=function(PouchDB,construct,handlers){return function(name,options,callback){var args;if(typeof name==="object"){args=parseBaseArgs(PouchDB,this,name,options)}else{args=parseBaseArgs(PouchDB,this,options,callback);args.options.name=name}return callHandlers(handlers,args,function(){return construct.call(this,args.options)})}};staticWrapperBuilders.destroy=function(PouchDB,destroy,handlers){return function(name,options,callback){var args;if(typeof name==="object"){args=parseBaseArgs(PouchDB,this,name,options)}else{args=parseBaseArgs(PouchDB,this,options,callback);args.options.name=name}return callHandlers(handlers,args,function(){var name=args.options.name;delete args.options.name;return destroy.call(this,name,args.options)})}};staticWrapperBuilders.replicate=function(PouchDB,replicate,handlers){return function(source,target,options,callback){var args=parseBaseArgs(PouchDB,this,options,callback);args.source=source;args.target=target;return callHandlers(handlers,args,function(){return replicate.call(this,args.source,args.target,args.options)})}};staticWrapperBuilders.allDbs=function(PouchDB,allDbs,handlers){return function(options,callback){var args=parseBaseArgs(PouchDB,this,options,callback);return callHandlers(handlers,args,makeCall(allDbs))}};function parseBaseArgs(thisVal1,thisVal2,options,callback){if(typeof options==="function"){callback=options;options={}}return{base:thisVal1||thisVal2,db:thisVal1||thisVal2,options:options||{},callback:callback}}function callHandlers(handlers,args,method){var callback=args.callback;delete args.callback;method=method.bind(args.base);for(var i=handlers.length-1;i>=0;i-=1){method=handlers[i].bind(null,method,args)}var promise=method();nodify(promise,callback);return promise}function makeCall(func){return function(){return func.call(this)}}function makeCallWithOptions(func,args){return function(){return func.call(this,args.options)}}exports.uninstallWrapperMethods=function(db,handlers){uninstallWrappers(db,handlers)};exports.uninstallStaticWrapperMethods=function(PouchDB,handlers){uninstallWrappers(PouchDB,handlers)};function uninstallWrappers(base,handlers){for(var name in handlers){if(!handlers.hasOwnProperty(name)){continue}var info=getBaseAndName(base,name);var wrapper=info.base[info.name];if(typeof wrapper==="undefined"){continue}var idx;try{idx=wrapper._handlers.indexOf(handlers[name])}catch(err){idx=-1}if(idx===-1){throw new Error("Wrapper method for '"+name+"' not installed: "+handlers[name])}wrapper._handlers.splice(idx,1);if(!wrapper._handlers.length){delete info.base[info.name];if(info.base[info.name]!==wrapper._original){info.base[info.name]=wrapper._original}}}}},{"promise-nodify":23}],23:[function(require,module,exports){"use strict";module.exports=function nodify(promise,callback){if(typeof callback==="function"){promise.then(function(resp){callback(null,resp)},function(err){callback(err,null)})}}},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 00000000..75fc9105 --- /dev/null +++ b/index.js @@ -0,0 +1,51 @@ +"use strict"; + +var XHR = global.XMLHttpRequest; + +/* istanbul ignore else */ +if (typeof XHR === "undefined") { + XHR = require('xhr2'); +} +var Promise = require('pouchdb-promise'); +var extend = require('extend'); +var wrappers = require('pouchdb-wrappers'); + +module.exports = function (PouchDB, url, opts) { + var api = {}; + + api.allDbs = function () { + return new Promise(function (resolve, reject) { + var xhr = new XHR(); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + resolve(JSON.parse(xhr.responseText)); + } + }; + xhr.open('GET', url + '_all_dbs'); + xhr.send(); + }); + }; + + api.destroy = function (orig, args) { + args.options.name = getName(args.options.name); + + return orig(); + }; + + function getName(name) { + if (!/https?:/.test(name)) { + name = url + name; + } + return name; + } + + var getHost = new PouchDB('test', {adapter: 'http'}).getHost; + var HTTPPouchDB = PouchDB.defaults({ + adapter: 'http', + getHost: function (name, specificOpts) { + return getHost(getName(name), extend({}, opts, specificOpts)); + } + }); + wrappers.installStaticWrapperMethods(HTTPPouchDB, api); + return HTTPPouchDB; +}; diff --git a/package.json b/package.json new file mode 100644 index 00000000..391a35b1 --- /dev/null +++ b/package.json @@ -0,0 +1,58 @@ +{ + "name": "http-pouchdb", + "version": "1.0.0", + "description": "Access remote CouchDB databases like you would access your local PouchDB ones.", + "main": "index.js", + "scripts": { + "release": "npm run test && npm run build && npm publish", + "test": "npm run jshint && npm run coverage", + "jshint": "./node_modules/.bin/jshint index.js test", + "coverage": "npm run collect-coverage && npm run check-coverage", + "collect-coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha", + "check-coverage": "./node_modules/.bin/istanbul check-coverage --statement 100 --branch 100 --function 100", + "build": "npm run build-js && ./node_modules/.bin/uglifyjs dist/http-pouchdb.js -o dist/http-pouchdb.min.js", + "build-js": "mkdir -p dist && ./node_modules/.bin/browserify index.js -s buildHTTPPouchDB -o dist/http-pouchdb.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/marten-de-vries/http-pouchdb.git" + }, + "keywords": [ + "http", + "couchdb", + "pouchdb", + "pouch", + "couch", + "remote", + "local" + ], + "author": "Marten de Vries", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/marten-de-vries/http-pouchdb/issues" + }, + "browserify": { + "transform": [ + "es3ify" + ] + }, + "browser": { + "xhr2": false + }, + "devDependencies": { + "browserify": "^7.0.3", + "chai": "^1.10.0", + "es3ify": "^0.1.3", + "istanbul": "^0.3.5", + "jshint": "^2.5.11", + "mocha": "^2.0.1", + "pouchdb": "^3.2.0", + "uglify-js": "^2.4.16" + }, + "dependencies": { + "extend": "^2.0.0", + "pouchdb-promise": "0.0.0", + "pouchdb-wrappers": "^1.3.0", + "xhr2": "^0.1.0" + } +} diff --git a/test/test.js b/test/test.js new file mode 100644 index 00000000..bf667388 --- /dev/null +++ b/test/test.js @@ -0,0 +1,85 @@ +"use strict"; + +/* global describe, it */ + +var PouchDB = require('pouchdb'); +//var buildHTTPPouchDB = require('http-pouchdb'); +var buildHTTPPouchDB = require('../index.js'); +var should = require('chai').should(); + +var HTTPPouchDB = buildHTTPPouchDB(PouchDB, 'http://localhost:5984/'); +var XMLHttpRequest = require('xhr2'); +var Promise = require('pouchdb-promise'); + +describe('constructor', function () { + it('should create remote databases for normal db names', function (done) { + var users = new HTTPPouchDB('_users'); + users.info().then(function (info) { + // a couchdb-only property. Even pouchdb-size doesn't provide it. + info.should.have.property('data_size'); + }).then(done); + }); + + it('should still accept http urls', function (done) { + var replicator = new HTTPPouchDB('http://localhost:5984/_replicator'); + replicator.allDocs(function (err, resp) { + should.not.exist(err); + resp.should.have.property('rows'); + // there's always the design doc + resp.total_rows.should.be.greaterThan(0); + + done(); + }); + }); +}); + +describe('destroy', function () { + it("should be possible using the 'class method'", function (done) { + new HTTPPouchDB('test'); + PouchDB.destroy('test', done); + }); + it('should be possible using the method', function (done) { + var db = new HTTPPouchDB('test'); + db.destroy(done); + }); +}); + +describe('replicate', function () { + it('should work', function (done) { + HTTPPouchDB.replicate('test-a', 'test-b').on('complete', function (resp) { + resp.status.should.equal('complete'); + + dbShouldExist('test-a').then(function () { + return dbShouldExist('test-b'); + }).then(function () { + return HTTPPouchDB.destroy('http://localhost:5984/test-a'); + }).then(function () { + HTTPPouchDB.destroy('test-b', done); + }); + }); + }); +}); + +function dbShouldExist(name) { + return new Promise(function (resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.onload = function () { + xhr.status.should.equal(200); + resolve(); + }; + xhr.open('HEAD', 'http://localhost:5984/' + name); + xhr.send(); + }); +} + +describe('allDbs', function () { + it('should return the remote db list', function (done) { + HTTPPouchDB.allDbs(function (err, dbs) { + should.not.exist(err); + dbs.should.contain('_users'); + dbs.should.contain('_replicator'); + + done(); + }); + }); +}); From 91fb2abdf134c8b93f14251afefc9562012c2a7a Mon Sep 17 00:00:00 2001 From: Marten de Vries Date: Sat, 20 Dec 2014 23:09:31 +0100 Subject: [PATCH 02/23] 1.1.0 - adds .isHTTPPouchDB property --- README.md | 3 ++- dist/http-pouchdb.js | 3 ++- dist/http-pouchdb.min.js | 2 +- index.js | 1 + package.json | 2 +- test/test.js | 9 +++++++++ 6 files changed, 16 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 757c2034..52b21691 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,8 @@ npm install pouchdb http-pouchdb var PouchDB = require('pouchdb'); var HTTPPouchDB = require('http-pouchdb')(PouchDB, 'http://localhost:5984'); -var db = new PouchDB('_users'); +var db = new HTTPPouchDB('_users'); +console.log(HTTPPouchDB.isHTTPPouchDB) //-> true // 'db' will be backed by http://localhost:5984/_users ; You can use it // like any PouchDB database. ``` diff --git a/dist/http-pouchdb.js b/dist/http-pouchdb.js index 1afb9808..b70739d7 100644 --- a/dist/http-pouchdb.js +++ b/dist/http-pouchdb.js @@ -2,9 +2,9 @@ (function (global){ "use strict"; - var XHR = global.XMLHttpRequest; +/* istanbul ignore else */ if (typeof XHR === "undefined") { XHR = require('xhr2'); } @@ -49,6 +49,7 @@ module.exports = function (PouchDB, url, opts) { } }); wrappers.installStaticWrapperMethods(HTTPPouchDB, api); + HTTPPouchDB.isHTTPPouchDB = true; return HTTPPouchDB; }; diff --git a/dist/http-pouchdb.min.js b/dist/http-pouchdb.min.js index 155e8782..6d96b5ef 100644 --- a/dist/http-pouchdb.min.js +++ b/dist/http-pouchdb.min.js @@ -1 +1 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.buildHTTPPouchDB=e()}}(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o1){base=base[name.shift(0)]}return{base:base,name:name[0]}}exports.createStaticWrapperMethod=function(name,original,handler,PouchDB){return createWrapper(name,original,handler,staticWrapperBuilders,PouchDB)};exports.createWrapperMethod=function(name,original,handler,db){return createWrapper(name,original,handler,wrapperBuilders,db)};function createWrapper(name,original,handler,theWrapperBuilders,thisVal){var buildWrapper=theWrapperBuilders[name];if(typeof createWrapper==="undefined"){throw new Error("No known wrapper for method name: "+name)}var handlers=[handler];var wrapper=buildWrapper(thisVal,original,handlers);wrapper._original=original;wrapper._handlers=handlers;return wrapper}var wrapperBuilders={};wrapperBuilders.destroy=function(db,destroy,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCall(destroy))}};wrapperBuilders.put=function(db,put,handlers){return function(doc,docId,docRev,options,callback){var args={};args.base=db||this;args.db=db||this;var argsList=Array.prototype.slice.call(arguments);args.doc=argsList.shift();var id="_id"in args.doc;while(true){var temp=argsList.shift();var temptype=typeof temp;if(temptype==="string"&&!id){args.doc._id=temp;id=true}else if(temptype==="string"&&id&&!("_rev"in args.doc)){args.doc._rev=temp}else if(temptype==="object"){args.options=temp}else if(temptype==="function"){args.callback=temp}if(!argsList.length){break}}args.options=args.options||{};return callHandlers(handlers,args,function(){return put.call(this,args.doc,args.options)})}};wrapperBuilders.post=function(db,post,handlers){return function(doc,options,callback){var args=parseBaseArgs(db,this,options,callback);args.doc=doc;return callHandlers(handlers,args,function(){return post.call(this,args.doc,args.options)})}};wrapperBuilders.get=function(db,get,handlers){return function(docId,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docId=docId;return callHandlers(handlers,args,function(){return get.call(this,args.docId,args.options)})}};wrapperBuilders.remove=function(db,remove,handlers){return function(docOrId,optsOrRev,opts,callback){var args;if(typeof optsOrRev==="string"){args=parseBaseArgs(db,this,opts,callback);args.doc={_id:docOrId,_rev:optsOrRev}}else{args=parseBaseArgs(db,this,optsOrRev,opts);args.doc=docOrId}return callHandlers(handlers,args,function(){return remove.call(this,args.doc,args.options)})}};wrapperBuilders.bulkDocs=function(db,bulkDocs,handlers){return function(docs,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docs=docs.docs||docs;return callHandlers(handlers,args,function(){return bulkDocs.call(this,args.docs,args.options)})}};wrapperBuilders.allDocs=function(db,allDocs,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(allDocs,args))}};wrapperBuilders.changes=function(db,changes,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(changes,args))}};wrapperBuilders.sync=function(db,replicate,handlers){return function(url,options,callback){var args=parseBaseArgs(db,this,options,callback);args.url=url;return callHandlers(handlers,args,function(){return replicate.call(this,args.url,args.options)})}};wrapperBuilders["replicate.from"]=wrapperBuilders.sync;wrapperBuilders["replicate.to"]=wrapperBuilders.sync;wrapperBuilders.putAttachment=function(db,putAttachment,handlers){return function(docId,attachmentId,rev,doc,type,options,callback){var args;if(typeof type==="string"){args=parseBaseArgs(db,this,options,callback);args.rev=rev;args.doc=doc;args.type=type}else{args=parseBaseArgs(db,this,type,options);args.rev=null;args.doc=rev;args.type=doc}args.docId=docId;args.attachmentId=attachmentId;return callHandlers(handlers,args,function(){return putAttachment.call(this,args.docId,args.attachmentId,args.rev,args.doc,args.type)})}};wrapperBuilders.getAttachment=function(db,getAttachment,handlers){return function(docId,attachmentId,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docId=docId;args.attachmentId=attachmentId;return callHandlers(handlers,args,function(){return getAttachment.call(this,args.docId,args.attachmentId,args.options)})}};wrapperBuilders.removeAttachment=function(db,removeAttachment,handlers){return function(docId,attachmentId,rev,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docId=docId;args.attachmentId=attachmentId;args.rev=rev;return callHandlers(handlers,args,function(){return removeAttachment.call(this,args.docId,args.attachmentId,args.rev)})}};wrapperBuilders.query=function(db,query,handlers){return function(fun,options,callback){var args=parseBaseArgs(db,this,options,callback);args.fun=fun;return callHandlers(handlers,args,function(){return query.call(this,args.fun,args.options)})}};wrapperBuilders.viewCleanup=function(db,viewCleanup,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(viewCleanup,args))}};wrapperBuilders.info=function(db,info,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCall(info))}};wrapperBuilders.compact=function(db,compact,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(compact,args))}};wrapperBuilders.revsDiff=function(db,revsDiff,handlers){return function(diff,options,callback){var args=parseBaseArgs(db,this,options,callback);args.diff=diff;return callHandlers(handlers,args,function(){return revsDiff.call(this,args.diff)})}};wrapperBuilders.list=function(db,orig,handlers){return function(path,options,callback){var args=parseBaseArgs(db,this,options,callback);args.path=path;return callHandlers(handlers,args,function(){return orig.call(this,args.path,args.options)})}};wrapperBuilders.rewriteResultRequestObject=wrapperBuilders.list;wrapperBuilders.show=wrapperBuilders.list;wrapperBuilders.update=wrapperBuilders.list;wrapperBuilders.getSecurity=function(db,getSecurity,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(getSecurity,args))}};wrapperBuilders.putSecurity=function(db,putSecurity,handlers){return function(secObj,options,callback){var args=parseBaseArgs(db,this,options,callback);args.secObj=secObj;return callHandlers(handlers,args,function(){return putSecurity.call(this,args.secObj)})}};var staticWrapperBuilders={};staticWrapperBuilders["new"]=function(PouchDB,construct,handlers){return function(name,options,callback){var args;if(typeof name==="object"){args=parseBaseArgs(PouchDB,this,name,options)}else{args=parseBaseArgs(PouchDB,this,options,callback);args.options.name=name}return callHandlers(handlers,args,function(){return construct.call(this,args.options)})}};staticWrapperBuilders.destroy=function(PouchDB,destroy,handlers){return function(name,options,callback){var args;if(typeof name==="object"){args=parseBaseArgs(PouchDB,this,name,options)}else{args=parseBaseArgs(PouchDB,this,options,callback);args.options.name=name}return callHandlers(handlers,args,function(){var name=args.options.name;delete args.options.name;return destroy.call(this,name,args.options)})}};staticWrapperBuilders.replicate=function(PouchDB,replicate,handlers){return function(source,target,options,callback){var args=parseBaseArgs(PouchDB,this,options,callback);args.source=source;args.target=target;return callHandlers(handlers,args,function(){return replicate.call(this,args.source,args.target,args.options)})}};staticWrapperBuilders.allDbs=function(PouchDB,allDbs,handlers){return function(options,callback){var args=parseBaseArgs(PouchDB,this,options,callback);return callHandlers(handlers,args,makeCall(allDbs))}};function parseBaseArgs(thisVal1,thisVal2,options,callback){if(typeof options==="function"){callback=options;options={}}return{base:thisVal1||thisVal2,db:thisVal1||thisVal2,options:options||{},callback:callback}}function callHandlers(handlers,args,method){var callback=args.callback;delete args.callback;method=method.bind(args.base);for(var i=handlers.length-1;i>=0;i-=1){method=handlers[i].bind(null,method,args)}var promise=method();nodify(promise,callback);return promise}function makeCall(func){return function(){return func.call(this)}}function makeCallWithOptions(func,args){return function(){return func.call(this,args.options)}}exports.uninstallWrapperMethods=function(db,handlers){uninstallWrappers(db,handlers)};exports.uninstallStaticWrapperMethods=function(PouchDB,handlers){uninstallWrappers(PouchDB,handlers)};function uninstallWrappers(base,handlers){for(var name in handlers){if(!handlers.hasOwnProperty(name)){continue}var info=getBaseAndName(base,name);var wrapper=info.base[info.name];if(typeof wrapper==="undefined"){continue}var idx;try{idx=wrapper._handlers.indexOf(handlers[name])}catch(err){idx=-1}if(idx===-1){throw new Error("Wrapper method for '"+name+"' not installed: "+handlers[name])}wrapper._handlers.splice(idx,1);if(!wrapper._handlers.length){delete info.base[info.name];if(info.base[info.name]!==wrapper._original){info.base[info.name]=wrapper._original}}}}},{"promise-nodify":23}],23:[function(require,module,exports){"use strict";module.exports=function nodify(promise,callback){if(typeof callback==="function"){promise.then(function(resp){callback(null,resp)},function(err){callback(err,null)})}}},{}]},{},[1])(1)}); \ No newline at end of file +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.buildHTTPPouchDB=e()}}(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o1){base=base[name.shift(0)]}return{base:base,name:name[0]}}exports.createStaticWrapperMethod=function(name,original,handler,PouchDB){return createWrapper(name,original,handler,staticWrapperBuilders,PouchDB)};exports.createWrapperMethod=function(name,original,handler,db){return createWrapper(name,original,handler,wrapperBuilders,db)};function createWrapper(name,original,handler,theWrapperBuilders,thisVal){var buildWrapper=theWrapperBuilders[name];if(typeof createWrapper==="undefined"){throw new Error("No known wrapper for method name: "+name)}var handlers=[handler];var wrapper=buildWrapper(thisVal,original,handlers);wrapper._original=original;wrapper._handlers=handlers;return wrapper}var wrapperBuilders={};wrapperBuilders.destroy=function(db,destroy,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCall(destroy))}};wrapperBuilders.put=function(db,put,handlers){return function(doc,docId,docRev,options,callback){var args={};args.base=db||this;args.db=db||this;var argsList=Array.prototype.slice.call(arguments);args.doc=argsList.shift();var id="_id"in args.doc;while(true){var temp=argsList.shift();var temptype=typeof temp;if(temptype==="string"&&!id){args.doc._id=temp;id=true}else if(temptype==="string"&&id&&!("_rev"in args.doc)){args.doc._rev=temp}else if(temptype==="object"){args.options=temp}else if(temptype==="function"){args.callback=temp}if(!argsList.length){break}}args.options=args.options||{};return callHandlers(handlers,args,function(){return put.call(this,args.doc,args.options)})}};wrapperBuilders.post=function(db,post,handlers){return function(doc,options,callback){var args=parseBaseArgs(db,this,options,callback);args.doc=doc;return callHandlers(handlers,args,function(){return post.call(this,args.doc,args.options)})}};wrapperBuilders.get=function(db,get,handlers){return function(docId,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docId=docId;return callHandlers(handlers,args,function(){return get.call(this,args.docId,args.options)})}};wrapperBuilders.remove=function(db,remove,handlers){return function(docOrId,optsOrRev,opts,callback){var args;if(typeof optsOrRev==="string"){args=parseBaseArgs(db,this,opts,callback);args.doc={_id:docOrId,_rev:optsOrRev}}else{args=parseBaseArgs(db,this,optsOrRev,opts);args.doc=docOrId}return callHandlers(handlers,args,function(){return remove.call(this,args.doc,args.options)})}};wrapperBuilders.bulkDocs=function(db,bulkDocs,handlers){return function(docs,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docs=docs.docs||docs;return callHandlers(handlers,args,function(){return bulkDocs.call(this,args.docs,args.options)})}};wrapperBuilders.allDocs=function(db,allDocs,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(allDocs,args))}};wrapperBuilders.changes=function(db,changes,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(changes,args))}};wrapperBuilders.sync=function(db,replicate,handlers){return function(url,options,callback){var args=parseBaseArgs(db,this,options,callback);args.url=url;return callHandlers(handlers,args,function(){return replicate.call(this,args.url,args.options)})}};wrapperBuilders["replicate.from"]=wrapperBuilders.sync;wrapperBuilders["replicate.to"]=wrapperBuilders.sync;wrapperBuilders.putAttachment=function(db,putAttachment,handlers){return function(docId,attachmentId,rev,doc,type,options,callback){var args;if(typeof type==="string"){args=parseBaseArgs(db,this,options,callback);args.rev=rev;args.doc=doc;args.type=type}else{args=parseBaseArgs(db,this,type,options);args.rev=null;args.doc=rev;args.type=doc}args.docId=docId;args.attachmentId=attachmentId;return callHandlers(handlers,args,function(){return putAttachment.call(this,args.docId,args.attachmentId,args.rev,args.doc,args.type)})}};wrapperBuilders.getAttachment=function(db,getAttachment,handlers){return function(docId,attachmentId,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docId=docId;args.attachmentId=attachmentId;return callHandlers(handlers,args,function(){return getAttachment.call(this,args.docId,args.attachmentId,args.options)})}};wrapperBuilders.removeAttachment=function(db,removeAttachment,handlers){return function(docId,attachmentId,rev,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docId=docId;args.attachmentId=attachmentId;args.rev=rev;return callHandlers(handlers,args,function(){return removeAttachment.call(this,args.docId,args.attachmentId,args.rev)})}};wrapperBuilders.query=function(db,query,handlers){return function(fun,options,callback){var args=parseBaseArgs(db,this,options,callback);args.fun=fun;return callHandlers(handlers,args,function(){return query.call(this,args.fun,args.options)})}};wrapperBuilders.viewCleanup=function(db,viewCleanup,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(viewCleanup,args))}};wrapperBuilders.info=function(db,info,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCall(info))}};wrapperBuilders.compact=function(db,compact,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(compact,args))}};wrapperBuilders.revsDiff=function(db,revsDiff,handlers){return function(diff,options,callback){var args=parseBaseArgs(db,this,options,callback);args.diff=diff;return callHandlers(handlers,args,function(){return revsDiff.call(this,args.diff)})}};wrapperBuilders.list=function(db,orig,handlers){return function(path,options,callback){var args=parseBaseArgs(db,this,options,callback);args.path=path;return callHandlers(handlers,args,function(){return orig.call(this,args.path,args.options)})}};wrapperBuilders.rewriteResultRequestObject=wrapperBuilders.list;wrapperBuilders.show=wrapperBuilders.list;wrapperBuilders.update=wrapperBuilders.list;wrapperBuilders.getSecurity=function(db,getSecurity,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(getSecurity,args))}};wrapperBuilders.putSecurity=function(db,putSecurity,handlers){return function(secObj,options,callback){var args=parseBaseArgs(db,this,options,callback);args.secObj=secObj;return callHandlers(handlers,args,function(){return putSecurity.call(this,args.secObj)})}};var staticWrapperBuilders={};staticWrapperBuilders["new"]=function(PouchDB,construct,handlers){return function(name,options,callback){var args;if(typeof name==="object"){args=parseBaseArgs(PouchDB,this,name,options)}else{args=parseBaseArgs(PouchDB,this,options,callback);args.options.name=name}return callHandlers(handlers,args,function(){return construct.call(this,args.options)})}};staticWrapperBuilders.destroy=function(PouchDB,destroy,handlers){return function(name,options,callback){var args;if(typeof name==="object"){args=parseBaseArgs(PouchDB,this,name,options)}else{args=parseBaseArgs(PouchDB,this,options,callback);args.options.name=name}return callHandlers(handlers,args,function(){var name=args.options.name;delete args.options.name;return destroy.call(this,name,args.options)})}};staticWrapperBuilders.replicate=function(PouchDB,replicate,handlers){return function(source,target,options,callback){var args=parseBaseArgs(PouchDB,this,options,callback);args.source=source;args.target=target;return callHandlers(handlers,args,function(){return replicate.call(this,args.source,args.target,args.options)})}};staticWrapperBuilders.allDbs=function(PouchDB,allDbs,handlers){return function(options,callback){var args=parseBaseArgs(PouchDB,this,options,callback);return callHandlers(handlers,args,makeCall(allDbs))}};function parseBaseArgs(thisVal1,thisVal2,options,callback){if(typeof options==="function"){callback=options;options={}}return{base:thisVal1||thisVal2,db:thisVal1||thisVal2,options:options||{},callback:callback}}function callHandlers(handlers,args,method){var callback=args.callback;delete args.callback;method=method.bind(args.base);for(var i=handlers.length-1;i>=0;i-=1){method=handlers[i].bind(null,method,args)}var promise=method();nodify(promise,callback);return promise}function makeCall(func){return function(){return func.call(this)}}function makeCallWithOptions(func,args){return function(){return func.call(this,args.options)}}exports.uninstallWrapperMethods=function(db,handlers){uninstallWrappers(db,handlers)};exports.uninstallStaticWrapperMethods=function(PouchDB,handlers){uninstallWrappers(PouchDB,handlers)};function uninstallWrappers(base,handlers){for(var name in handlers){if(!handlers.hasOwnProperty(name)){continue}var info=getBaseAndName(base,name);var wrapper=info.base[info.name];if(typeof wrapper==="undefined"){continue}var idx;try{idx=wrapper._handlers.indexOf(handlers[name])}catch(err){idx=-1}if(idx===-1){throw new Error("Wrapper method for '"+name+"' not installed: "+handlers[name])}wrapper._handlers.splice(idx,1);if(!wrapper._handlers.length){delete info.base[info.name];if(info.base[info.name]!==wrapper._original){info.base[info.name]=wrapper._original}}}}},{"promise-nodify":23}],23:[function(require,module,exports){"use strict";module.exports=function nodify(promise,callback){if(typeof callback==="function"){promise.then(function(resp){callback(null,resp)},function(err){callback(err,null)})}}},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/index.js b/index.js index 75fc9105..4d248846 100644 --- a/index.js +++ b/index.js @@ -47,5 +47,6 @@ module.exports = function (PouchDB, url, opts) { } }); wrappers.installStaticWrapperMethods(HTTPPouchDB, api); + HTTPPouchDB.isHTTPPouchDB = true; return HTTPPouchDB; }; diff --git a/package.json b/package.json index 391a35b1..ffdd8149 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "http-pouchdb", - "version": "1.0.0", + "version": "1.1.0", "description": "Access remote CouchDB databases like you would access your local PouchDB ones.", "main": "index.js", "scripts": { diff --git a/test/test.js b/test/test.js index bf667388..c35606d1 100644 --- a/test/test.js +++ b/test/test.js @@ -11,6 +11,15 @@ var HTTPPouchDB = buildHTTPPouchDB(PouchDB, 'http://localhost:5984/'); var XMLHttpRequest = require('xhr2'); var Promise = require('pouchdb-promise'); +describe('isHTTPPouchDB', function () { + it('should be set on the HTTPPouchDB object', function () { + HTTPPouchDB.isHTTPPouchDB.should.be.ok(); + }); + it('should not be set on the PouchDB object', function () { + should.not.exist(PouchDB.isHTTPPouchDB); + }); +}); + describe('constructor', function () { it('should create remote databases for normal db names', function (done) { var users = new HTTPPouchDB('_users'); From 839360a7e00b0c51f2d56de72a100536f927b1b0 Mon Sep 17 00:00:00 2001 From: Marten de Vries Date: Tue, 30 Jun 2015 21:47:49 +0200 Subject: [PATCH 03/23] (#1) - Make http-pouchdb work with a recent PouchDB Version 1.1.1 --- index.js | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 4d248846..5208c81e 100644 --- a/index.js +++ b/index.js @@ -46,7 +46,15 @@ module.exports = function (PouchDB, url, opts) { return getHost(getName(name), extend({}, opts, specificOpts)); } }); + + // https://github.com/marten-de-vries/http-pouchdb/issues/1 + HTTPPouchDB.adapters.http.use_prefix = false; + + /* istanbul ignore next */ + // noop that can be 'wrapped' soon + HTTPPouchDB.allDbs = function () {}; wrappers.installStaticWrapperMethods(HTTPPouchDB, api); + HTTPPouchDB.isHTTPPouchDB = true; return HTTPPouchDB; }; diff --git a/package.json b/package.json index ffdd8149..0d0a91ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "http-pouchdb", - "version": "1.1.0", + "version": "1.1.1", "description": "Access remote CouchDB databases like you would access your local PouchDB ones.", "main": "index.js", "scripts": { From a7e1f9d69c9e51802739314bd8b3cc42f259ae35 Mon Sep 17 00:00:00 2001 From: Marten de Vries Date: Tue, 18 Aug 2015 17:23:55 +0200 Subject: [PATCH 04/23] 1.1.2; fixes #2 --- dist/http-pouchdb.js | 84 +++++++++++++++++++++++++++++++++------- dist/http-pouchdb.min.js | 2 +- package.json | 9 +---- 3 files changed, 74 insertions(+), 21 deletions(-) diff --git a/dist/http-pouchdb.js b/dist/http-pouchdb.js index b70739d7..09b3a4f9 100644 --- a/dist/http-pouchdb.js +++ b/dist/http-pouchdb.js @@ -48,7 +48,15 @@ module.exports = function (PouchDB, url, opts) { return getHost(getName(name), extend({}, opts, specificOpts)); } }); + + // https://github.com/marten-de-vries/http-pouchdb/issues/1 + HTTPPouchDB.adapters.http.use_prefix = false; + + /* istanbul ignore next */ + // noop that can be 'wrapped' soon + HTTPPouchDB.allDbs = function () {}; wrappers.installStaticWrapperMethods(HTTPPouchDB, api); + HTTPPouchDB.isHTTPPouchDB = true; return HTTPPouchDB; }; @@ -58,12 +66,20 @@ module.exports = function (PouchDB, url, opts) { },{}],3:[function(require,module,exports){ var hasOwn = Object.prototype.hasOwnProperty; -var toString = Object.prototype.toString; +var toStr = Object.prototype.toString; var undefined; +var isArray = function isArray(arr) { + if (typeof Array.isArray === 'function') { + return Array.isArray(arr); + } + + return toStr.call(arr) === '[object Array]'; +}; + var isPlainObject = function isPlainObject(obj) { 'use strict'; - if (!obj || toString.call(obj) !== '[object Object]') { + if (!obj || toStr.call(obj) !== '[object Object]') { return false; } @@ -115,10 +131,10 @@ module.exports = function extend() { } // Recurse if we're merging plain objects or arrays - if (deep && copy && (isPlainObject(copy) || (copyIsArray = Array.isArray(copy)))) { + if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) { if (copyIsArray) { copyIsArray = false; - clone = src && Array.isArray(src) ? src : []; + clone = src && isArray(src) ? src : []; } else { clone = src && isPlainObject(src) ? src : {}; } @@ -458,38 +474,73 @@ var types = [ require('./timeout') ]; var draining; +var currentQueue; +var queueIndex = -1; var queue = []; +var scheduled = false; +function cleanUpNextTick() { + draining = false; + if (currentQueue && currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + nextTick(); + } +} + //named nextTick for less confusing stack traces function nextTick() { + scheduled = false; draining = true; - var i, oldQueue; var len = queue.length; + var timeout = setTimeout(cleanUpNextTick); while (len) { - oldQueue = queue; + currentQueue = queue; queue = []; - i = -1; - while (++i < len) { - oldQueue[i](); + while (++queueIndex < len) { + currentQueue[queueIndex].run(); } + queueIndex = -1; len = queue.length; } + queueIndex = -1; draining = false; + clearTimeout(timeout); } var scheduleDrain; var i = -1; var len = types.length; -while (++ i < len) { +while (++i < len) { if (types[i] && types[i].test && types[i].test()) { scheduleDrain = types[i].install(nextTick); break; } } +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; module.exports = immediate; function immediate(task) { - if (queue.push(task) === 1 && !draining) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(task, args)); + if (!scheduled && !draining) { + scheduled = true; scheduleDrain(); } } + },{"./messageChannel":18,"./mutation.js":19,"./nextTick":2,"./stateChange":20,"./timeout":21}],18:[function(require,module,exports){ (function (global){ 'use strict'; @@ -576,7 +627,7 @@ exports.install = function (t) { }; },{}],22:[function(require,module,exports){ /* - Copyright 2014, Marten de Vries + Copyright 2014-2015, Marten de Vries Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -755,6 +806,9 @@ wrapperBuilders.bulkDocs = function (db, bulkDocs, handlers) { return function (docs, options, callback) { var args = parseBaseArgs(db, this, options, callback); //support the deprecated signature. + if ('new_edits' in docs) { + args.options.new_edits = docs.new_edits; + } args.docs = docs.docs || docs; return callHandlers(handlers, args, function () { return bulkDocs.call(this, args.docs, args.options); @@ -953,9 +1007,13 @@ staticWrapperBuilders.destroy = function (PouchDB, destroy, handlers) { args = parseBaseArgs(PouchDB, this, options, callback); args.options.name = name; } + if (args.options.internal) { + return destroy.apply(PouchDB, arguments); + } return callHandlers(handlers, args, function () { var name = args.options.name; delete args.options.name; + return destroy.call(this, name, args.options); }); }; @@ -977,7 +1035,7 @@ staticWrapperBuilders.allDbs = function (PouchDB, allDbs, handlers) { return function (options, callback) { var args = parseBaseArgs(PouchDB, this, options, callback); return callHandlers(handlers, args, makeCall(allDbs)); - } + }; }; //Wrap .plugin()? .on()? .defaults()? No use case yet, but it's diff --git a/dist/http-pouchdb.min.js b/dist/http-pouchdb.min.js index 6d96b5ef..23b063d6 100644 --- a/dist/http-pouchdb.min.js +++ b/dist/http-pouchdb.min.js @@ -1 +1 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.buildHTTPPouchDB=e()}}(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o1){base=base[name.shift(0)]}return{base:base,name:name[0]}}exports.createStaticWrapperMethod=function(name,original,handler,PouchDB){return createWrapper(name,original,handler,staticWrapperBuilders,PouchDB)};exports.createWrapperMethod=function(name,original,handler,db){return createWrapper(name,original,handler,wrapperBuilders,db)};function createWrapper(name,original,handler,theWrapperBuilders,thisVal){var buildWrapper=theWrapperBuilders[name];if(typeof createWrapper==="undefined"){throw new Error("No known wrapper for method name: "+name)}var handlers=[handler];var wrapper=buildWrapper(thisVal,original,handlers);wrapper._original=original;wrapper._handlers=handlers;return wrapper}var wrapperBuilders={};wrapperBuilders.destroy=function(db,destroy,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCall(destroy))}};wrapperBuilders.put=function(db,put,handlers){return function(doc,docId,docRev,options,callback){var args={};args.base=db||this;args.db=db||this;var argsList=Array.prototype.slice.call(arguments);args.doc=argsList.shift();var id="_id"in args.doc;while(true){var temp=argsList.shift();var temptype=typeof temp;if(temptype==="string"&&!id){args.doc._id=temp;id=true}else if(temptype==="string"&&id&&!("_rev"in args.doc)){args.doc._rev=temp}else if(temptype==="object"){args.options=temp}else if(temptype==="function"){args.callback=temp}if(!argsList.length){break}}args.options=args.options||{};return callHandlers(handlers,args,function(){return put.call(this,args.doc,args.options)})}};wrapperBuilders.post=function(db,post,handlers){return function(doc,options,callback){var args=parseBaseArgs(db,this,options,callback);args.doc=doc;return callHandlers(handlers,args,function(){return post.call(this,args.doc,args.options)})}};wrapperBuilders.get=function(db,get,handlers){return function(docId,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docId=docId;return callHandlers(handlers,args,function(){return get.call(this,args.docId,args.options)})}};wrapperBuilders.remove=function(db,remove,handlers){return function(docOrId,optsOrRev,opts,callback){var args;if(typeof optsOrRev==="string"){args=parseBaseArgs(db,this,opts,callback);args.doc={_id:docOrId,_rev:optsOrRev}}else{args=parseBaseArgs(db,this,optsOrRev,opts);args.doc=docOrId}return callHandlers(handlers,args,function(){return remove.call(this,args.doc,args.options)})}};wrapperBuilders.bulkDocs=function(db,bulkDocs,handlers){return function(docs,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docs=docs.docs||docs;return callHandlers(handlers,args,function(){return bulkDocs.call(this,args.docs,args.options)})}};wrapperBuilders.allDocs=function(db,allDocs,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(allDocs,args))}};wrapperBuilders.changes=function(db,changes,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(changes,args))}};wrapperBuilders.sync=function(db,replicate,handlers){return function(url,options,callback){var args=parseBaseArgs(db,this,options,callback);args.url=url;return callHandlers(handlers,args,function(){return replicate.call(this,args.url,args.options)})}};wrapperBuilders["replicate.from"]=wrapperBuilders.sync;wrapperBuilders["replicate.to"]=wrapperBuilders.sync;wrapperBuilders.putAttachment=function(db,putAttachment,handlers){return function(docId,attachmentId,rev,doc,type,options,callback){var args;if(typeof type==="string"){args=parseBaseArgs(db,this,options,callback);args.rev=rev;args.doc=doc;args.type=type}else{args=parseBaseArgs(db,this,type,options);args.rev=null;args.doc=rev;args.type=doc}args.docId=docId;args.attachmentId=attachmentId;return callHandlers(handlers,args,function(){return putAttachment.call(this,args.docId,args.attachmentId,args.rev,args.doc,args.type)})}};wrapperBuilders.getAttachment=function(db,getAttachment,handlers){return function(docId,attachmentId,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docId=docId;args.attachmentId=attachmentId;return callHandlers(handlers,args,function(){return getAttachment.call(this,args.docId,args.attachmentId,args.options)})}};wrapperBuilders.removeAttachment=function(db,removeAttachment,handlers){return function(docId,attachmentId,rev,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docId=docId;args.attachmentId=attachmentId;args.rev=rev;return callHandlers(handlers,args,function(){return removeAttachment.call(this,args.docId,args.attachmentId,args.rev)})}};wrapperBuilders.query=function(db,query,handlers){return function(fun,options,callback){var args=parseBaseArgs(db,this,options,callback);args.fun=fun;return callHandlers(handlers,args,function(){return query.call(this,args.fun,args.options)})}};wrapperBuilders.viewCleanup=function(db,viewCleanup,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(viewCleanup,args))}};wrapperBuilders.info=function(db,info,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCall(info))}};wrapperBuilders.compact=function(db,compact,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(compact,args))}};wrapperBuilders.revsDiff=function(db,revsDiff,handlers){return function(diff,options,callback){var args=parseBaseArgs(db,this,options,callback);args.diff=diff;return callHandlers(handlers,args,function(){return revsDiff.call(this,args.diff)})}};wrapperBuilders.list=function(db,orig,handlers){return function(path,options,callback){var args=parseBaseArgs(db,this,options,callback);args.path=path;return callHandlers(handlers,args,function(){return orig.call(this,args.path,args.options)})}};wrapperBuilders.rewriteResultRequestObject=wrapperBuilders.list;wrapperBuilders.show=wrapperBuilders.list;wrapperBuilders.update=wrapperBuilders.list;wrapperBuilders.getSecurity=function(db,getSecurity,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(getSecurity,args))}};wrapperBuilders.putSecurity=function(db,putSecurity,handlers){return function(secObj,options,callback){var args=parseBaseArgs(db,this,options,callback);args.secObj=secObj;return callHandlers(handlers,args,function(){return putSecurity.call(this,args.secObj)})}};var staticWrapperBuilders={};staticWrapperBuilders["new"]=function(PouchDB,construct,handlers){return function(name,options,callback){var args;if(typeof name==="object"){args=parseBaseArgs(PouchDB,this,name,options)}else{args=parseBaseArgs(PouchDB,this,options,callback);args.options.name=name}return callHandlers(handlers,args,function(){return construct.call(this,args.options)})}};staticWrapperBuilders.destroy=function(PouchDB,destroy,handlers){return function(name,options,callback){var args;if(typeof name==="object"){args=parseBaseArgs(PouchDB,this,name,options)}else{args=parseBaseArgs(PouchDB,this,options,callback);args.options.name=name}return callHandlers(handlers,args,function(){var name=args.options.name;delete args.options.name;return destroy.call(this,name,args.options)})}};staticWrapperBuilders.replicate=function(PouchDB,replicate,handlers){return function(source,target,options,callback){var args=parseBaseArgs(PouchDB,this,options,callback);args.source=source;args.target=target;return callHandlers(handlers,args,function(){return replicate.call(this,args.source,args.target,args.options)})}};staticWrapperBuilders.allDbs=function(PouchDB,allDbs,handlers){return function(options,callback){var args=parseBaseArgs(PouchDB,this,options,callback);return callHandlers(handlers,args,makeCall(allDbs))}};function parseBaseArgs(thisVal1,thisVal2,options,callback){if(typeof options==="function"){callback=options;options={}}return{base:thisVal1||thisVal2,db:thisVal1||thisVal2,options:options||{},callback:callback}}function callHandlers(handlers,args,method){var callback=args.callback;delete args.callback;method=method.bind(args.base);for(var i=handlers.length-1;i>=0;i-=1){method=handlers[i].bind(null,method,args)}var promise=method();nodify(promise,callback);return promise}function makeCall(func){return function(){return func.call(this)}}function makeCallWithOptions(func,args){return function(){return func.call(this,args.options)}}exports.uninstallWrapperMethods=function(db,handlers){uninstallWrappers(db,handlers)};exports.uninstallStaticWrapperMethods=function(PouchDB,handlers){uninstallWrappers(PouchDB,handlers)};function uninstallWrappers(base,handlers){for(var name in handlers){if(!handlers.hasOwnProperty(name)){continue}var info=getBaseAndName(base,name);var wrapper=info.base[info.name];if(typeof wrapper==="undefined"){continue}var idx;try{idx=wrapper._handlers.indexOf(handlers[name])}catch(err){idx=-1}if(idx===-1){throw new Error("Wrapper method for '"+name+"' not installed: "+handlers[name])}wrapper._handlers.splice(idx,1);if(!wrapper._handlers.length){delete info.base[info.name];if(info.base[info.name]!==wrapper._original){info.base[info.name]=wrapper._original}}}}},{"promise-nodify":23}],23:[function(require,module,exports){"use strict";module.exports=function nodify(promise,callback){if(typeof callback==="function"){promise.then(function(resp){callback(null,resp)},function(err){callback(err,null)})}}},{}]},{},[1])(1)}); \ No newline at end of file +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.buildHTTPPouchDB=e()}}(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o1){for(var i=1;i1){base=base[name.shift(0)]}return{base:base,name:name[0]}}exports.createStaticWrapperMethod=function(name,original,handler,PouchDB){return createWrapper(name,original,handler,staticWrapperBuilders,PouchDB)};exports.createWrapperMethod=function(name,original,handler,db){return createWrapper(name,original,handler,wrapperBuilders,db)};function createWrapper(name,original,handler,theWrapperBuilders,thisVal){var buildWrapper=theWrapperBuilders[name];if(typeof createWrapper==="undefined"){throw new Error("No known wrapper for method name: "+name)}var handlers=[handler];var wrapper=buildWrapper(thisVal,original,handlers);wrapper._original=original;wrapper._handlers=handlers;return wrapper}var wrapperBuilders={};wrapperBuilders.destroy=function(db,destroy,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCall(destroy))}};wrapperBuilders.put=function(db,put,handlers){return function(doc,docId,docRev,options,callback){var args={};args.base=db||this;args.db=db||this;var argsList=Array.prototype.slice.call(arguments);args.doc=argsList.shift();var id="_id"in args.doc;while(true){var temp=argsList.shift();var temptype=typeof temp;if(temptype==="string"&&!id){args.doc._id=temp;id=true}else if(temptype==="string"&&id&&!("_rev"in args.doc)){args.doc._rev=temp}else if(temptype==="object"){args.options=temp}else if(temptype==="function"){args.callback=temp}if(!argsList.length){break}}args.options=args.options||{};return callHandlers(handlers,args,function(){return put.call(this,args.doc,args.options)})}};wrapperBuilders.post=function(db,post,handlers){return function(doc,options,callback){var args=parseBaseArgs(db,this,options,callback);args.doc=doc;return callHandlers(handlers,args,function(){return post.call(this,args.doc,args.options)})}};wrapperBuilders.get=function(db,get,handlers){return function(docId,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docId=docId;return callHandlers(handlers,args,function(){return get.call(this,args.docId,args.options)})}};wrapperBuilders.remove=function(db,remove,handlers){return function(docOrId,optsOrRev,opts,callback){var args;if(typeof optsOrRev==="string"){args=parseBaseArgs(db,this,opts,callback);args.doc={_id:docOrId,_rev:optsOrRev}}else{args=parseBaseArgs(db,this,optsOrRev,opts);args.doc=docOrId}return callHandlers(handlers,args,function(){return remove.call(this,args.doc,args.options)})}};wrapperBuilders.bulkDocs=function(db,bulkDocs,handlers){return function(docs,options,callback){var args=parseBaseArgs(db,this,options,callback);if("new_edits"in docs){args.options.new_edits=docs.new_edits}args.docs=docs.docs||docs;return callHandlers(handlers,args,function(){return bulkDocs.call(this,args.docs,args.options)})}};wrapperBuilders.allDocs=function(db,allDocs,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(allDocs,args))}};wrapperBuilders.changes=function(db,changes,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(changes,args))}};wrapperBuilders.sync=function(db,replicate,handlers){return function(url,options,callback){var args=parseBaseArgs(db,this,options,callback);args.url=url;return callHandlers(handlers,args,function(){return replicate.call(this,args.url,args.options)})}};wrapperBuilders["replicate.from"]=wrapperBuilders.sync;wrapperBuilders["replicate.to"]=wrapperBuilders.sync;wrapperBuilders.putAttachment=function(db,putAttachment,handlers){return function(docId,attachmentId,rev,doc,type,options,callback){var args;if(typeof type==="string"){args=parseBaseArgs(db,this,options,callback);args.rev=rev;args.doc=doc;args.type=type}else{args=parseBaseArgs(db,this,type,options);args.rev=null;args.doc=rev;args.type=doc}args.docId=docId;args.attachmentId=attachmentId;return callHandlers(handlers,args,function(){return putAttachment.call(this,args.docId,args.attachmentId,args.rev,args.doc,args.type)})}};wrapperBuilders.getAttachment=function(db,getAttachment,handlers){return function(docId,attachmentId,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docId=docId;args.attachmentId=attachmentId;return callHandlers(handlers,args,function(){return getAttachment.call(this,args.docId,args.attachmentId,args.options)})}};wrapperBuilders.removeAttachment=function(db,removeAttachment,handlers){return function(docId,attachmentId,rev,options,callback){var args=parseBaseArgs(db,this,options,callback);args.docId=docId;args.attachmentId=attachmentId;args.rev=rev;return callHandlers(handlers,args,function(){return removeAttachment.call(this,args.docId,args.attachmentId,args.rev)})}};wrapperBuilders.query=function(db,query,handlers){return function(fun,options,callback){var args=parseBaseArgs(db,this,options,callback);args.fun=fun;return callHandlers(handlers,args,function(){return query.call(this,args.fun,args.options)})}};wrapperBuilders.viewCleanup=function(db,viewCleanup,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(viewCleanup,args))}};wrapperBuilders.info=function(db,info,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCall(info))}};wrapperBuilders.compact=function(db,compact,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(compact,args))}};wrapperBuilders.revsDiff=function(db,revsDiff,handlers){return function(diff,options,callback){var args=parseBaseArgs(db,this,options,callback);args.diff=diff;return callHandlers(handlers,args,function(){return revsDiff.call(this,args.diff)})}};wrapperBuilders.list=function(db,orig,handlers){return function(path,options,callback){var args=parseBaseArgs(db,this,options,callback);args.path=path;return callHandlers(handlers,args,function(){return orig.call(this,args.path,args.options)})}};wrapperBuilders.rewriteResultRequestObject=wrapperBuilders.list;wrapperBuilders.show=wrapperBuilders.list;wrapperBuilders.update=wrapperBuilders.list;wrapperBuilders.getSecurity=function(db,getSecurity,handlers){return function(options,callback){var args=parseBaseArgs(db,this,options,callback);return callHandlers(handlers,args,makeCallWithOptions(getSecurity,args))}};wrapperBuilders.putSecurity=function(db,putSecurity,handlers){return function(secObj,options,callback){var args=parseBaseArgs(db,this,options,callback);args.secObj=secObj;return callHandlers(handlers,args,function(){return putSecurity.call(this,args.secObj)})}};var staticWrapperBuilders={};staticWrapperBuilders["new"]=function(PouchDB,construct,handlers){return function(name,options,callback){var args;if(typeof name==="object"){args=parseBaseArgs(PouchDB,this,name,options)}else{args=parseBaseArgs(PouchDB,this,options,callback);args.options.name=name}return callHandlers(handlers,args,function(){return construct.call(this,args.options)})}};staticWrapperBuilders.destroy=function(PouchDB,destroy,handlers){return function(name,options,callback){var args;if(typeof name==="object"){args=parseBaseArgs(PouchDB,this,name,options)}else{args=parseBaseArgs(PouchDB,this,options,callback);args.options.name=name}if(args.options.internal){return destroy.apply(PouchDB,arguments)}return callHandlers(handlers,args,function(){var name=args.options.name;delete args.options.name;return destroy.call(this,name,args.options)})}};staticWrapperBuilders.replicate=function(PouchDB,replicate,handlers){return function(source,target,options,callback){var args=parseBaseArgs(PouchDB,this,options,callback);args.source=source;args.target=target;return callHandlers(handlers,args,function(){return replicate.call(this,args.source,args.target,args.options)})}};staticWrapperBuilders.allDbs=function(PouchDB,allDbs,handlers){return function(options,callback){var args=parseBaseArgs(PouchDB,this,options,callback);return callHandlers(handlers,args,makeCall(allDbs))}};function parseBaseArgs(thisVal1,thisVal2,options,callback){if(typeof options==="function"){callback=options;options={}}return{base:thisVal1||thisVal2,db:thisVal1||thisVal2,options:options||{},callback:callback}}function callHandlers(handlers,args,method){var callback=args.callback;delete args.callback;method=method.bind(args.base);for(var i=handlers.length-1;i>=0;i-=1){method=handlers[i].bind(null,method,args)}var promise=method();nodify(promise,callback);return promise}function makeCall(func){return function(){return func.call(this)}}function makeCallWithOptions(func,args){return function(){return func.call(this,args.options)}}exports.uninstallWrapperMethods=function(db,handlers){uninstallWrappers(db,handlers)};exports.uninstallStaticWrapperMethods=function(PouchDB,handlers){uninstallWrappers(PouchDB,handlers)};function uninstallWrappers(base,handlers){for(var name in handlers){if(!handlers.hasOwnProperty(name)){continue}var info=getBaseAndName(base,name);var wrapper=info.base[info.name];if(typeof wrapper==="undefined"){continue}var idx;try{idx=wrapper._handlers.indexOf(handlers[name])}catch(err){idx=-1}if(idx===-1){throw new Error("Wrapper method for '"+name+"' not installed: "+handlers[name])}wrapper._handlers.splice(idx,1);if(!wrapper._handlers.length){delete info.base[info.name];if(info.base[info.name]!==wrapper._original){info.base[info.name]=wrapper._original}}}}},{"promise-nodify":23}],23:[function(require,module,exports){"use strict";module.exports=function nodify(promise,callback){if(typeof callback==="function"){promise.then(function(resp){callback(null,resp)},function(err){callback(err,null)})}}},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/package.json b/package.json index 0d0a91ae..7c618210 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "http-pouchdb", - "version": "1.1.1", + "version": "1.1.2", "description": "Access remote CouchDB databases like you would access your local PouchDB ones.", "main": "index.js", "scripts": { @@ -11,7 +11,7 @@ "collect-coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha", "check-coverage": "./node_modules/.bin/istanbul check-coverage --statement 100 --branch 100 --function 100", "build": "npm run build-js && ./node_modules/.bin/uglifyjs dist/http-pouchdb.js -o dist/http-pouchdb.min.js", - "build-js": "mkdir -p dist && ./node_modules/.bin/browserify index.js -s buildHTTPPouchDB -o dist/http-pouchdb.js" + "build-js": "mkdir -p dist && ./node_modules/.bin/browserify -g es3ify index.js -s buildHTTPPouchDB -o dist/http-pouchdb.js" }, "repository": { "type": "git", @@ -31,11 +31,6 @@ "bugs": { "url": "https://github.com/marten-de-vries/http-pouchdb/issues" }, - "browserify": { - "transform": [ - "es3ify" - ] - }, "browser": { "xhr2": false }, From 6180f326126fe9446c12536aa4881355f8f0cfb2 Mon Sep 17 00:00:00 2001 From: Marten de Vries Date: Thu, 22 Oct 2015 12:22:50 +0200 Subject: [PATCH 05/23] Fixes #3 and #4 by including own getHost() impl; some dependency updates & tests cleanup; 1.1.3 --- README.md | 6 ++--- gethost.js | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ index.js | 12 +++++----- package.json | 25 ++++++++++---------- test/test.js | 21 +++++++++-------- 5 files changed, 98 insertions(+), 32 deletions(-) create mode 100644 gethost.js diff --git a/README.md b/README.md index 52b21691..7c4f0157 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ http-pouchdb ============ -[![Build Status](https://travis-ci.org/marten-de-vries/http-pouchdb.svg?branch=master)](https://travis-ci.org/marten-de-vries/http-pouchdb) -[![Dependency Status](https://david-dm.org/marten-de-vries/http-pouchdb.svg)](https://david-dm.org/marten-de-vries/http-pouchdb) -[![devDependency Status](https://david-dm.org/marten-de-vries/http-pouchdb/dev-status.svg)](https://david-dm.org/marten-de-vries/http-pouchdb#info=devDependencies) +[![Build Status](https://travis-ci.org/pouchdb/http-pouchdb.svg?branch=master)](https://travis-ci.org/pouchdb/http-pouchdb) +[![Dependency Status](https://david-dm.org/pouchdb/http-pouchdb.svg)](https://david-dm.org/pouchdb/http-pouchdb) +[![devDependency Status](https://david-dm.org/pouchdb/http-pouchdb/dev-status.svg)](https://david-dm.org/pouchdb/http-pouchdb#info=devDependencies) Access remote CouchDB databases like you would access your local PouchDB ones. Tested support for ``new PouchDB('name')``, diff --git a/gethost.js b/gethost.js new file mode 100644 index 00000000..ba679db2 --- /dev/null +++ b/gethost.js @@ -0,0 +1,66 @@ +// all code in this file is copied from PouchDB + +/* istanbul ignore next */ + +'use strict'; + +// Get all the information you possibly can about the URI given by name and +// return it as a suitable object. +module.exports = function getHost(name) { + // Prase the URI into all its little bits + var uri = parseUri(name); + + // Store the user and password as a separate auth object + if (uri.user || uri.password) { + uri.auth = {username: uri.user, password: uri.password}; + } + + // Split the path part of the URI into parts using '/' as the delimiter + // after removing any leading '/' and any trailing '/' + var parts = uri.path.replace(/(^\/|\/$)/g, '').split('/'); + + // Store the first part as the database name and remove it from the parts + // array + uri.db = encodeURIComponent(parts.pop()); + + // Restore the path by joining all the remaining parts (all the parts + // except for the database name) with '/'s + uri.path = parts.join('/'); + + return uri; +}; + +// originally parseUri 1.2.2, now patched by us +// (c) Steven Levithan +// MIT License +var keys = ["source", "protocol", "authority", "userInfo", "user", "password", + "host", "port", "relative", "path", "directory", "file", "query", "anchor"]; +var qName ="queryKey"; +var qParser = /(?:^|&)([^&=]*)=?([^&]*)/g; + +// use the "loose" parser +/* jshint maxlen: false */ +var parser = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/; + +/* istanbul ignore next */ +function parseUri(str) { + var m = parser.exec(str); + var uri = {}; + var i = 14; + + while (i--) { + var key = keys[i]; + var value = m[i] || ""; + var encoded = ['user', 'password'].indexOf(key) !== -1; + uri[key] = encoded ? decodeURIComponent(value) : value; + } + + uri[qName] = {}; + uri[keys[12]].replace(qParser, function ($0, $1, $2) { + if ($1) { + uri[qName][$1] = $2; + } + }); + + return uri; +} diff --git a/index.js b/index.js index 5208c81e..31880a43 100644 --- a/index.js +++ b/index.js @@ -6,9 +6,10 @@ var XHR = global.XMLHttpRequest; if (typeof XHR === "undefined") { XHR = require('xhr2'); } -var Promise = require('pouchdb-promise'); +var Promise = require('pouchdb/extras/promise'); var extend = require('extend'); var wrappers = require('pouchdb-wrappers'); +var getHost = require('./gethost'); module.exports = function (PouchDB, url, opts) { var api = {}; @@ -39,13 +40,12 @@ module.exports = function (PouchDB, url, opts) { return name; } - var getHost = new PouchDB('test', {adapter: 'http'}).getHost; - var HTTPPouchDB = PouchDB.defaults({ + var HTTPPouchDB = PouchDB.defaults(extend({}, opts, { adapter: 'http', - getHost: function (name, specificOpts) { - return getHost(getName(name), extend({}, opts, specificOpts)); + getHost: function (name) { + return getHost(getName(name)); } - }); + })); // https://github.com/marten-de-vries/http-pouchdb/issues/1 HTTPPouchDB.adapters.http.use_prefix = false; diff --git a/package.json b/package.json index 7c618210..f1cb50f3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "http-pouchdb", - "version": "1.1.2", + "version": "1.1.3", "description": "Access remote CouchDB databases like you would access your local PouchDB ones.", "main": "index.js", "scripts": { @@ -35,19 +35,18 @@ "xhr2": false }, "devDependencies": { - "browserify": "^7.0.3", - "chai": "^1.10.0", - "es3ify": "^0.1.3", - "istanbul": "^0.3.5", - "jshint": "^2.5.11", - "mocha": "^2.0.1", - "pouchdb": "^3.2.0", - "uglify-js": "^2.4.16" + "browserify": "^11.2.0", + "chai": "^3.4.0", + "es3ify": "^0.1.4", + "istanbul": "^0.4.0", + "jshint": "^2.8.0", + "mocha": "^2.3.3", + "uglify-js": "^2.5.0" }, "dependencies": { - "extend": "^2.0.0", - "pouchdb-promise": "0.0.0", - "pouchdb-wrappers": "^1.3.0", - "xhr2": "^0.1.0" + "pouchdb": "^5.0.0", + "extend": "^3.0.0", + "pouchdb-wrappers": "^1.3.6", + "xhr2": "^0.1.3" } } diff --git a/test/test.js b/test/test.js index c35606d1..2fae0f6f 100644 --- a/test/test.js +++ b/test/test.js @@ -1,6 +1,7 @@ "use strict"; /* global describe, it */ +/*jshint expr: true*/ var PouchDB = require('pouchdb'); //var buildHTTPPouchDB = require('http-pouchdb'); @@ -9,11 +10,11 @@ var should = require('chai').should(); var HTTPPouchDB = buildHTTPPouchDB(PouchDB, 'http://localhost:5984/'); var XMLHttpRequest = require('xhr2'); -var Promise = require('pouchdb-promise'); +var Promise = require('pouchdb/extras/promise'); describe('isHTTPPouchDB', function () { it('should be set on the HTTPPouchDB object', function () { - HTTPPouchDB.isHTTPPouchDB.should.be.ok(); + HTTPPouchDB.isHTTPPouchDB.should.be.ok; }); it('should not be set on the PouchDB object', function () { should.not.exist(PouchDB.isHTTPPouchDB); @@ -21,12 +22,12 @@ describe('isHTTPPouchDB', function () { }); describe('constructor', function () { - it('should create remote databases for normal db names', function (done) { + it('should create remote databases for normal db names', function () { var users = new HTTPPouchDB('_users'); - users.info().then(function (info) { + return users.info().then(function (info) { // a couchdb-only property. Even pouchdb-size doesn't provide it. info.should.have.property('data_size'); - }).then(done); + }); }); it('should still accept http urls', function (done) { @@ -45,7 +46,7 @@ describe('constructor', function () { describe('destroy', function () { it("should be possible using the 'class method'", function (done) { new HTTPPouchDB('test'); - PouchDB.destroy('test', done); + HTTPPouchDB.destroy('test', done); }); it('should be possible using the method', function (done) { var db = new HTTPPouchDB('test'); @@ -54,16 +55,16 @@ describe('destroy', function () { }); describe('replicate', function () { - it('should work', function (done) { + it('should work', function () { HTTPPouchDB.replicate('test-a', 'test-b').on('complete', function (resp) { resp.status.should.equal('complete'); - dbShouldExist('test-a').then(function () { + return dbShouldExist('test-a').then(function () { return dbShouldExist('test-b'); }).then(function () { - return HTTPPouchDB.destroy('http://localhost:5984/test-a'); + return new PouchDB.destroy('http://localhost:5984/test-a'); }).then(function () { - HTTPPouchDB.destroy('test-b', done); + return new PouchDB('test-b').destroy(); }); }); }); From 746f8637ab864287c7f2dd0f8a8261a36f98ff5e Mon Sep 17 00:00:00 2001 From: Marten de Vries Date: Thu, 22 Oct 2015 12:25:03 +0200 Subject: [PATCH 06/23] Container-based Travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 58c5363e..db17c977 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,3 +3,4 @@ node_js: - "0.10" services: - couchdb +sudo: false From 59e3ab9973c0d934721e6d0087140f608c836923 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Fri, 5 Feb 2016 12:18:47 +0100 Subject: [PATCH 07/23] chore(package): update dependencies http://greenkeeper.io/ --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f1cb50f3..3306b0fa 100644 --- a/package.json +++ b/package.json @@ -35,9 +35,9 @@ "xhr2": false }, "devDependencies": { - "browserify": "^11.2.0", + "browserify": "^13.0.0", "chai": "^3.4.0", - "es3ify": "^0.1.4", + "es3ify": "^0.2.0", "istanbul": "^0.4.0", "jshint": "^2.8.0", "mocha": "^2.3.3", From 71a9d623b09c5a54680b23478fa1d54f07dae406 Mon Sep 17 00:00:00 2001 From: zizai Date: Wed, 14 Dec 2016 21:03:21 +0800 Subject: [PATCH 08/23] keep up with pouchdb api --- dist/http-pouchdb.js | 1374 +++++++++++++++++--------------------- dist/http-pouchdb.min.js | 2 +- gethost.js | 66 -- index.js | 11 +- test/test.js | 8 +- 5 files changed, 626 insertions(+), 835 deletions(-) delete mode 100644 gethost.js diff --git a/dist/http-pouchdb.js b/dist/http-pouchdb.js index 09b3a4f9..84fa0afa 100644 --- a/dist/http-pouchdb.js +++ b/dist/http-pouchdb.js @@ -1,4 +1,4 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.buildHTTPPouchDB=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1) { + base = base[name.shift(0)]; } + return { + base: base, + name: name[0] + }; } -},{"./resolveThenable":13,"./states":14,"./tryCatch":15}],8:[function(require,module,exports){ -module.exports = exports = require('./promise'); -exports.resolve = require('./resolve'); -exports.reject = require('./reject'); -exports.all = require('./all'); -},{"./all":6,"./promise":9,"./reject":11,"./resolve":12}],9:[function(require,module,exports){ -'use strict'; +exports.createStaticWrapperMethod = function (name, original, handler, PouchDB) { + //PouchDB is optional + return createWrapper(name, original, handler, staticWrapperBuilders, PouchDB); +}; -var unwrap = require('./unwrap'); -var INTERNAL = require('./INTERNAL'); -var resolveThenable = require('./resolveThenable'); -var states = require('./states'); -var QueueItem = require('./queueItem'); +exports.createWrapperMethod = function (name, original, handler, db) { + //db is optional + return createWrapper(name, original, handler, wrapperBuilders, db); +}; -module.exports = Promise; -function Promise(resolver) { - if (!(this instanceof Promise)) { - return new Promise(resolver); - } - if (typeof resolver !== 'function') { - throw new TypeError('reslover must be a function'); - } - this.state = states.PENDING; - this.queue = []; - this.outcome = void 0; - if (resolver !== INTERNAL) { - resolveThenable.safely(this, resolver); +function createWrapper(name, original, handler, theWrapperBuilders, thisVal) { + //thisVal is optional + var buildWrapper = theWrapperBuilders[name]; + if (typeof createWrapper === "undefined") { + throw new Error("No known wrapper for method name: " + name); //coverage: ignore } + var handlers = [handler]; + var wrapper = buildWrapper(thisVal, original, handlers); + wrapper._original = original; + wrapper._handlers = handlers; + return wrapper; } -Promise.prototype['catch'] = function (onRejected) { - return this.then(null, onRejected); -}; -Promise.prototype.then = function (onFulfilled, onRejected) { - if (typeof onFulfilled !== 'function' && this.state === states.FULFILLED || - typeof onRejected !== 'function' && this.state === states.REJECTED) { - return this; - } - var promise = new Promise(INTERNAL); - - - if (this.state !== states.PENDING) { - var resolver = this.state === states.FULFILLED ? onFulfilled: onRejected; - unwrap(promise, resolver, this.outcome); - } else { - this.queue.push(new QueueItem(promise, onFulfilled, onRejected)); - } +var wrapperBuilders = {}; - return promise; -}; - -},{"./INTERNAL":5,"./queueItem":10,"./resolveThenable":13,"./states":14,"./unwrap":16}],10:[function(require,module,exports){ -'use strict'; -var handlers = require('./handlers'); -var unwrap = require('./unwrap'); - -module.exports = QueueItem; -function QueueItem(promise, onFulfilled, onRejected) { - this.promise = promise; - if (typeof onFulfilled === 'function') { - this.onFulfilled = onFulfilled; - this.callFulfilled = this.otherCallFulfilled; - } - if (typeof onRejected === 'function') { - this.onRejected = onRejected; - this.callRejected = this.otherCallRejected; - } -} -QueueItem.prototype.callFulfilled = function (value) { - handlers.resolve(this.promise, value); -}; -QueueItem.prototype.otherCallFulfilled = function (value) { - unwrap(this.promise, this.onFulfilled, value); -}; -QueueItem.prototype.callRejected = function (value) { - handlers.reject(this.promise, value); -}; -QueueItem.prototype.otherCallRejected = function (value) { - unwrap(this.promise, this.onRejected, value); -}; -},{"./handlers":7,"./unwrap":16}],11:[function(require,module,exports){ -'use strict'; - -var Promise = require('./promise'); -var INTERNAL = require('./INTERNAL'); -var handlers = require('./handlers'); -module.exports = reject; - -function reject(reason) { - var promise = new Promise(INTERNAL); - return handlers.reject(promise, reason); -} -},{"./INTERNAL":5,"./handlers":7,"./promise":9}],12:[function(require,module,exports){ -'use strict'; - -var Promise = require('./promise'); -var INTERNAL = require('./INTERNAL'); -var handlers = require('./handlers'); -module.exports = resolve; - -var FALSE = handlers.resolve(new Promise(INTERNAL), false); -var NULL = handlers.resolve(new Promise(INTERNAL), null); -var UNDEFINED = handlers.resolve(new Promise(INTERNAL), void 0); -var ZERO = handlers.resolve(new Promise(INTERNAL), 0); -var EMPTYSTRING = handlers.resolve(new Promise(INTERNAL), ''); - -function resolve(value) { - if (value) { - if (value instanceof Promise) { - return value; - } - return handlers.resolve(new Promise(INTERNAL), value); - } - var valueType = typeof value; - switch (valueType) { - case 'boolean': - return FALSE; - case 'undefined': - return UNDEFINED; - case 'object': - return NULL; - case 'number': - return ZERO; - case 'string': - return EMPTYSTRING; - } -} -},{"./INTERNAL":5,"./handlers":7,"./promise":9}],13:[function(require,module,exports){ -'use strict'; -var handlers = require('./handlers'); -var tryCatch = require('./tryCatch'); -function safelyResolveThenable(self, thenable) { - // Either fulfill, reject or reject with error - var called = false; - function onError(value) { - if (called) { - return; - } - called = true; - handlers.reject(self, value); - } - - function onSuccess(value) { - if (called) { - return; - } - called = true; - handlers.resolve(self, value); - } - - function tryToUnwrap() { - thenable(onSuccess, onError); - } - - var result = tryCatch(tryToUnwrap); - if (result.status === 'error') { - onError(result.value); - } -} -exports.safely = safelyResolveThenable; -},{"./handlers":7,"./tryCatch":15}],14:[function(require,module,exports){ -// Lazy man's symbols for states - -exports.REJECTED = ['REJECTED']; -exports.FULFILLED = ['FULFILLED']; -exports.PENDING = ['PENDING']; -},{}],15:[function(require,module,exports){ -'use strict'; - -module.exports = tryCatch; - -function tryCatch(func, value) { - var out = {}; - try { - out.value = func(value); - out.status = 'success'; - } catch (e) { - out.status = 'error'; - out.value = e; - } - return out; -} -},{}],16:[function(require,module,exports){ -'use strict'; - -var immediate = require('immediate'); -var handlers = require('./handlers'); -module.exports = unwrap; - -function unwrap(promise, func, value) { - immediate(function () { - var returnValue; - try { - returnValue = func(value); - } catch (e) { - return handlers.reject(promise, e); - } - if (returnValue === promise) { - handlers.reject(promise, new TypeError('Cannot resolve promise with itself')); - } else { - handlers.resolve(promise, returnValue); - } - }); -} -},{"./handlers":7,"immediate":17}],17:[function(require,module,exports){ -'use strict'; -var types = [ - require('./nextTick'), - require('./mutation.js'), - require('./messageChannel'), - require('./stateChange'), - require('./timeout') -]; -var draining; -var currentQueue; -var queueIndex = -1; -var queue = []; -var scheduled = false; -function cleanUpNextTick() { - draining = false; - if (currentQueue && currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - nextTick(); - } -} - -//named nextTick for less confusing stack traces -function nextTick() { - scheduled = false; - draining = true; - var len = queue.length; - var timeout = setTimeout(cleanUpNextTick); - while (len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - currentQueue[queueIndex].run(); - } - queueIndex = -1; - len = queue.length; - } - queueIndex = -1; - draining = false; - clearTimeout(timeout); -} -var scheduleDrain; -var i = -1; -var len = types.length; -while (++i < len) { - if (types[i] && types[i].test && types[i].test()) { - scheduleDrain = types[i].install(nextTick); - break; - } -} -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -module.exports = immediate; -function immediate(task) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(task, args)); - if (!scheduled && !draining) { - scheduled = true; - scheduleDrain(); - } -} - -},{"./messageChannel":18,"./mutation.js":19,"./nextTick":2,"./stateChange":20,"./timeout":21}],18:[function(require,module,exports){ -(function (global){ -'use strict'; - -exports.test = function () { - if (global.setImmediate) { - // we can only get here in IE10 - // which doesn't handel postMessage well - return false; - } - return typeof global.MessageChannel !== 'undefined'; -}; - -exports.install = function (func) { - var channel = new global.MessageChannel(); - channel.port1.onmessage = func; - return function () { - channel.port2.postMessage(0); - }; -}; -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],19:[function(require,module,exports){ -(function (global){ -'use strict'; -//based off rsvp https://github.com/tildeio/rsvp.js -//license https://github.com/tildeio/rsvp.js/blob/master/LICENSE -//https://github.com/tildeio/rsvp.js/blob/master/lib/rsvp/asap.js - -var Mutation = global.MutationObserver || global.WebKitMutationObserver; - -exports.test = function () { - return Mutation; -}; - -exports.install = function (handle) { - var called = 0; - var observer = new Mutation(handle); - var element = global.document.createTextNode(''); - observer.observe(element, { - characterData: true - }); - return function () { - element.data = (called = ++called % 2); - }; -}; -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],20:[function(require,module,exports){ -(function (global){ -'use strict'; - -exports.test = function () { - return 'document' in global && 'onreadystatechange' in global.document.createElement('script'); -}; - -exports.install = function (handle) { - return function () { - - // Create a